结构,strtok,分段错误

时间:2010-05-14 13:12:45

标签: c struct command-line-arguments strtok

我正在尝试使用结构和文件创建程序。以下只是我的代码的一部分(它不是整个程序)。 我要做的是:要求用户写下他的命令。例如。删除约翰 例如。输入约翰詹姆斯5000 ipad购买。

问题是我想拆分命令以保存结构元素的'args'。这就是我使用strtok的原因。但我面临的另一个问题是谁将这些“放”在结构上。 另外,对于我来说,如何以安全的方式将'args''传递给结构体似乎很奇怪,因为我保存所有进入(来自用户)二进制文件,可能会重新打开并重新编译,因此我无法使用:

strcpy(catalog[0]->short_name, args[1]); 

因为时间短名称将保存在结构的第一个元素中。但如果文件被写入会发生什么呢?第一个元素存在,所以如果我写.. [0]我会写上它吗? 我该怎么办? Thanx提前提供任何帮助! :d

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100

char command[1500]; 

struct catalogue                
{
        char short_name[50];
        char surname[50];
        signed int amount;
        char description[1000];
}*catalog[MAX]; 

int main ( int argc, char *argv[] )
{
    int i,n;
    char choice[3];

    printf(">sort1: Print savings sorted by surname\n");
    printf(">sort2: Print savings sorted by amount\n");
    printf(">search+name:Print savings of each name searched\n");
    printf(">delete+full_name+amount: Erase saving\n");
    printf(">enter+full_name+amount+description: Enter saving \n");
    printf(">quit:  Update + EXIT program.\n");

    printf("Choose your selection:\n>");
    gets(command);                     //it save the whole command

    /*in choice it;s saved only the first 2 letters(needed for menu choice again)*/
    strncpy(choice,command,2);      
    choice[2]='\0';                   

char** args = (char**)malloc(strlen(command)*sizeof(char*));
memset(args, 0, sizeof(char*)*strlen(command));

char* temp = strtok(command, " \t");

for (n = 0; temp != NULL; ++n)
{   
    args[n] = strdup(temp);
    temp = strtok(NULL, " \t");
    printf(" %s ",args[n]);
}

strcpy(catalog[0]->short_name, args[1]);         //segmentation fault
strcpy(catalog[0]->surname,args[2]);
catalog[0]->amount=atoi(args[3]);               //atoi doesn't work
strcpy(catalog[0]->description,args[4]);


}

因此,在运行程序后,我收到了分段错误... 对于该行:

strcpy(catalog[0]->short_name, args[1]); 

有任何帮助吗?有什么想法吗?

4 个答案:

答案 0 :(得分:4)

您有2个错误:

  1. 您的catalog[MAX]数组包含指向MAX的{​​{1}}个指针,但未对其进行初始化。修复此问题的方法是要么不将它们声明为指针,要么根据需要将它们声明为struct catalogue,例如malloc

  2. 您的catalog[0] = (struct catalogue *)malloc(sizeof(struct catalogue));变量很糟糕。首先,我认为您不打算创建一个长度为命令字符串长度的字符串数组。这意味着如果您键入“sort1”,您将创建args。这是荒谬的,因为你的命令长度与它应该有多少个参数无关。

    但假设您确实想要这样做,那么您将为数组创建空间,但不会为数组中的字符串创建空间。不管怎样,你最终会得到一个段错(尽管你得到的是#1),因为这样。在使用args[5]时,您需要为args中的每个元素分配空间。

  3. 代码可能如下所示:

    for (n = 0; temp != NULL; ++n)
    {
       args[n] = (char *)malloc((strlen(temp) + 1) * sizeof(char));
       strcpy(args[n], temp);
       // and so on
    }
    

答案 1 :(得分:1)

for循环一次分配一个参数(args[n] = ...),但随后会在每个传递中访问多个参数:*args[1]args[2]等,这些是第一遍未初始化。

警告是由于另一个错误。你不能只是像这样指定一个指向数组的指针。请改用strcpy()

答案 2 :(得分:1)

catalouge的数组是一个指针数组,而不是一个对象数组,但这些指针没有初始化为任何东西,因此seg错误

尝试:

struct catalogue                 
{ 
        char short_name[50]; 
        char surname[50]; 
        signed int amount; 
        char description[1000]; 
}catalog[MAX]; 



strcpy(catalog[0].short_name, args[1]);         //segmentation fault  
strcpy(catalog[0].surname,args[2]);  
catalog[0].amount=atoi(args[3]);               //atoi doesn't work  
strcpy(catalog[0].description,args[4]); 

答案 3 :(得分:1)

此代码中的问题很多

首先,您会混淆输入行中参数的数量,以确定目录中的条目数。在一个上下文中,您使用n来计算args的数量,但在另一个上下文中,您使用它来索引catalog数组。

您正在创建不需要的内存管理问题。 args变量是完全没必要的,无论如何你正在为它错误地分配内存。你基本上是在说,“为command中的每个角色分配一个指向char的指针,这可能不是你想要的。

完全失去args;你不需要它。

我意识到这不是你的整个程序,但是不清楚你为什么要创建catalog作为指向struct catalog的指针数组,而不仅仅是常规数组。

我不确定你认为你在线上做了什么

*catalog[n]->short_name=*args[1]; 

表达式catalog[n]->short_name的类型为char[50]。在此上下文中,数组类型被隐式转换(“衰减”)为指针类型char *。因此整个表达式*catalog[n]->short_name的类型是* (char *),或者只是普通char,这是一个整数类型。您实际上是在尝试将args[1]的第一个字符的值分配给catalog[n]->short_name的第一个字符。

无论如何这都不重要,因为catalog[n]尚未被初始化为指向任何有意义的地方; segfault来自尝试访问short_name成员,该成员隐式取消引用catalog[n],它指向某个随机位置。

接下来,您不能使用赋值运算符=来分配字符串数据;您必须使用strcpy()strncpy()来执行此操作。

最后,永远不会永远不会使用gets()在您的代码中引入故障点。它已在C99中正式弃用,不应再使用。请改用fgets()

if (fgets(command, sizeof command, stdin) != NULL)
{
  char *newline = strchr(command, '\n');
  if (newline != NULL)
    *newline = 0;
}

以下是解析命令字符串并将字段分配给结构成员的方法:

curToken = strtok(command, '\t');
if (curToken)
  strncpy(catalog[n]->short_name, curToken, sizeof catalog[n]->short_name);

curToken = strtok(NULL, '\t');
if (curToken)
  strncpy(catalog[n]->surname, curToken, sizeof catalog[n]->surname);

curToken = strtok(NULL, '\t');
if (curToken)
{
  char *chk;
  catalog[n]->amount = (int) strtol(curToken, &chk, 10);
  if (!isspace(*chk) && *chk != 0)
    fprintf(stderr, 
      "Warning: expected integer value for amount, received %s instead\n",
      curToken);
}

curToken = strtok(NULL, '\t');
if (curToken)
  strncpy(catalog[n]->description, curToken, sizeof catalog[n]->description);

此代码假定catalog仍被声明为指针的数组,每个元素已初始化为指向某个有意义的位置。否则,将声明从struct catalog {...} *catalog[MAX];更改为struct catalog {...} catalog[MAX],并将->更改为.