【问题标题】:Structs, strtok, segmentation fault结构,strtok,分段错误
【发布时间】:2023-04-04 20:05:01
【问题描述】:

我正在尝试使用结构和文件制作程序。以下只是我的代码的一部分(它不是整个程序)。 我想要做的是:要求用户编写他的命令。例如。删除约翰 例如。输入 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]);


}

结果,运行程序后我得到一个分段错误... 换行:

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

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

【问题讨论】:

标签: c struct command-line-arguments strtok


【解决方案1】:

您有 2 个错误:

  1. 您的catalog[MAX] 数组包含指向您的struct catalogueMAX 指针,但它们都没有被初始化。解决这个问题的方法是要么不将它们声明为指针,要么根据需要将它们声明为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
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 是的,这是真的,我尝试使用 catalog[0]->short_name 将其排除在循环之外。 .但我得到了同样的警告
    • strcpy(catalog[0]->short_name, args[1]);再一次......分段错误如果'args'是一个数字怎么办? atoi 不起作用!
    【解决方案3】:

    您的目录数组是指针数组,而不是对象数组,但这些指针未初始化为任何内容,因此出现 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]); 
    

    【讨论】:

    • Thnx 墓地!这是一个很大的帮助! :D
    【解决方案4】:

    很多代码中的问题。

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

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

    彻底输掉args;你不需要它。

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

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

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

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

    反正这些都不重要,因为catalog[n] 还没有被初始化为指向任何有意义的地方;段错误来自尝试访问short_name 成员,该成员隐式取消引用catalog[n],它指向随机的某个地方。

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

    最后,NEVER NEVER NEVER NEVER NEVER 使用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] 并将-&gt; 更改为.

    【讨论】:

    • 使用此代码...在行中:curToken = strtok(c​​ommand, '\t'); curToken = strtok(NULL, '\t'); curToken = strtok(NULL, '\t'); curToken = strtok(NULL, '\t');有一个警告:警告:传递“strtok”的参数 2 从整数中生成指针,而无需强制转换 Thnx 无论如何都需要帮助
    • 使用这个: char *curToken = strtok(c​​ommand," ");行分割:strncpy(catalog[n]->short_name,curToken,sizeof(catalog[n]->short_name));
    • 废话;那应该是“\t”而不是“\t”;我有点睡不着觉。至于段错误,就像我上面所说的,这假设catalog[n] 已正确分配并指向有意义的地方。正如我所说,尚不清楚为什么将catalog 分配为struct catalog指针 数组,但我在编写示例时假设这是您想要的。如果不是,则将声明从struct ... *catalog[MAX]; 更改为struct ... catalog[MAX],并使用. 代替. 进行组件选择。
    • 嗯好的!是的,我明白了!我的错!现在我用了。而不是->还有一个问题,请在您的代码中使用例如目录[n]等这个“n”在哪里定义?你的意思是它;在for循环上?如果是,则该命令未正确保存。
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    相关资源
    最近更新 更多