1

我正在尝试用结构和文件制作一个程序。以下只是我的代码的一部分(它不是整个程序)。我想要做的是:要求用户编写他的命令。例如。删除约翰,例如。输入 John James 5000 ipad 购买。

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

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

因为是时候将短名称保存在结构的第一个元素中了。但是如果文件被写入了,那会发生什么呢?第一个元素存在,所以如果我写 ..[0] 我会写吗?我应该怎么办?提前感谢您的帮助!: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]);


}

结果,在运行程序后,我得到了一个 Segmentation Fault... 的行:

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

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

4

4 回答 4

4

您有 2 个错误:

  1. 您的catalog[MAX]数组包含MAX指向您的指针struct catalogue,但它们都没有被初始化。解决这个问题的方法是要么不将它们声明为指针,要么malloc根据需要声明它们,例如catalog[0] = (struct catalogue *)malloc(sizeof(struct catalogue));

  2. 你的args变量不好。首先,我不认为您打算创建一个长度为命令字符串长度的字符串数组。这意味着如果您键入“sort1”,您将创建args[5]. 这是荒谬的,因为你的命令的长度与它应该有多少参数无关。

    但是假设您真的想这样做,您正在为数组创建空间,而不是为数组中的字符串创建空间。无论如何,你最终都会得到一个段错误(尽管你得到的那个是由于上面的#1)因此。您需要在args使用时为每个元素分配空间。

代码可能如下所示:

for (n = 0; temp != NULL; ++n)
{
   args[n] = (char *)malloc((strlen(temp) + 1) * sizeof(char));
   strcpy(args[n], temp);
   // and so on
}
于 2010-05-14T14:14:14.267 回答
1

您的目录数组是指针数组,而不是对象数组,但这些指针未初始化为任何内容,因此出现 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]); 
于 2010-05-14T14:13:27.950 回答
1

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

该警告是由于另一个错误。您不能只将指针分配给这样的数组。改为使用strcpy()

于 2010-05-14T13:17:55.223 回答
1

这段代码有很多问题。

首先,您将输入行上的参数数量与目录中的条目数量混淆了。在一种情况下,您n用于计算 args 的数量,但在另一种情况下,您使用它来索引catalog数组。

您在不需要的地方制造内存管理难题。该args变量是完全没有必要的,无论如何您都在为它错误地分配内存。您基本上是在说,“为 char 中的每个字符分配一个指针,command这可能不是您想要的。

完全输args了;你不需要它。

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

我不确定你认为你在做什么

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

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

无论如何,这些都不重要,因为catalog[n]还没有被初始化为指向任何有意义的地方;段错误来自尝试访问该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];tostruct catalog {...} catalog[MAX]更改->.

于 2010-05-14T14:43:29.450 回答