C 拆分字符串并显示它

C 拆分字符串并显示它,c,C,实际上,下面的程序是分割字符串并显示输出。我已经完成了我的程序,它给出了所需的输出。但是,最后它给出了分段错误。我也尝试了调试器。但是,我找不到问题。有人能帮我吗 输入文件: 维韦克|拉杰| 20 阿比|尼拉| 20 预期产出: Vivek姓Raj,20岁。 Abi姓Nila,年龄20岁。 #包括 #包括 #包括 结构人{ charfirstname[30]; char lastname[30]; 智力年龄; }; int main(int args,char*argv[]) { 结构人员列

实际上,下面的程序是分割字符串并显示输出。我已经完成了我的程序,它给出了所需的输出。但是,最后它给出了分段错误。我也尝试了调试器。但是,我找不到问题。有人能帮我吗

输入文件: 维韦克|拉杰| 20 阿比|尼拉| 20

预期产出: Vivek姓Raj,20岁。 Abi姓Nila,年龄20岁。
#包括
#包括
#包括
结构人{
charfirstname[30];
char lastname[30];
智力年龄;
};
int main(int args,char*argv[])
{
结构人员列表[30];
inti,n;
字符*ch、*ch1、*ch2、*ch3;
char-buf[256];
文件*fp;
fp=fopen(argv[1],“r”);
如果(fp==NULL){
printf(“无法打开文件%s\n”,argv[1]);
出口(0);
}
i=0;
fgets(buf,256,fp);
而(!feof(fp)){
ch=strchr(buf,'\n');
如果(ch!=NULL)*ch='\0';
否则就断了;
ch=strchr(buf,“|”);
ch2=strrchr(buf,“|”);
如果(ch!=NULL)
{
*ch='\0';ch1=++ch2;
}
否则就断了;
ch++;
strcpy(ch3,ch);
ch2=strchr(ch3,“|”);
*ch2='\0';
strcpy(列表[i]。名字,buf);
strcpy(列表[i]。姓氏ch3);
列表[i]。年龄=atoi(ch1);
i++;
fgets(buf,256,fp);
}
n=i;
对于(i=0;i
首先,你的阅读是错误的。您应该在
fgets()
上循环,因为失败时它返回
NULL
(通常,这意味着您已到达文件末尾):


代码可能崩溃的原因有很多

1) 在我看来,ch3根本没有初始化。因此,它可能包含垃圾并(偶然)指向可写内存(可能是堆栈?)。在使用ch3之前,您应该为它分配一个指向有效缓冲区的指针。我认为这次坠机是由于这个问题。一个可能的修正(并非最好的修正)是:

2) 顺便说一句,您根本不需要第二个缓冲区:您可以查找两个分隔符,用终止字符替换它们,并直接从原始缓冲区获取指向三个字符串的指针:

            ch = strchr(buf,'|');
            if (ch == NULL) 
            {
            // INPUT MALFORMED
                    break;
            }
            *ch = '\0'; // This splits first and second+third
            ++ch;
            // Now ch points to the second+third field!
            ch2 = strrchr(ch,'|');
            if(ch2 == NULL)
            {
            // INPUT MALFORMED
                    break;
            }
            *ch2 = '\0'; // split second and third
            ++ch2;
            // Now ch2 points to the third field!
            //
            printf("First name=%s Last name=%s age=%s\n",buf,ch,ch2);
3) 程序限制为30个项目,但实际插入的元素数量不会在任何地方进行检查(类似于

//...
++i;
if (i >= 30) {
  break;
}
当然,如果“列表”数组的大小是通过宏参数化的,那就更好了

4) “firstname”和“lastname”是char[SOME_SIZE]。是否所有的输入字段都适合某种大小的大小

通常,程序会丢失一些“限制”和“输入验证”控件(例如,如果数字字段格式不正确怎么办?好的,它不会崩溃,但是…嗯…)

我希望这能有所帮助


关于

您的printf声明不正确:

for (i = 0; i < n; i++)
        printf("%s's last name %s and age.\n",list[i].firstname,list[i].lastname,list[i].age);
return 0;
(i=0;i printf(“%s的姓氏%s和年龄。\n”,列表[i]。名字,列表[i]。姓氏,列表[i]。年龄); 返回0; 最后一个参数缺少%d。应该是:

for (i = 0; i < n; i++)
        printf("%s's last name %s and age is %d.\n",list[i].firstname,list[i].lastname,list[i].age);
return 0;
(i=0;i printf(“%s的姓氏%s,年龄为%d。\n”,列表[i]。名字,列表[i]。姓氏,列表[i]。年龄); 返回0;
你正在做strcpy(ch3,ch);如果ch3没有分配任何内存,因为它也没有分配给NULL,那么代码会覆盖一些未知内存,导致内存损坏并最终导致崩溃。

您没有显示足够的代码。具体来说,您没有显示“list”的声明。我通过将该文件作为可执行代码的参数来运行程序。对于ex,./a.out inputfile,输入文件的内容如下所示。Vivek | Raj | 20 Abi | Nila | 20对于firstname和
lastname
来说太多了!我执行了你的程序,没有出现任何分段错误。但如果我在终端中执行,就会出现分段错误。因此您可以退出(0),因为shell需要退出状态。更好的是可以使用FFECK检查而不是FEF条件。考虑使用<代码> Strutok < /C> >而不是<代码> STRCHR 和<代码> SSTRCHR 。另外,
strncpy
而不是
strcpy
,这样就不会溢出.firstname和.lastname。事实上,这不会是一个问题。在我更改了它之后,它也会出现同样的错误。@vivekguna:即使它按照您编写的方式工作,一个调用也比两个(相同)调用加上第三个要好。:)
 char tmp[256];
 char *ch3;

 // Make ch3 point to a valid buffer
 ch3 = tmp;

 // ...
     // Here ch3 must point to a valid location!!!
     strcpy(ch3,ch);
            ch = strchr(buf,'|');
            if (ch == NULL) 
            {
            // INPUT MALFORMED
                    break;
            }
            *ch = '\0'; // This splits first and second+third
            ++ch;
            // Now ch points to the second+third field!
            ch2 = strrchr(ch,'|');
            if(ch2 == NULL)
            {
            // INPUT MALFORMED
                    break;
            }
            *ch2 = '\0'; // split second and third
            ++ch2;
            // Now ch2 points to the third field!
            //
            printf("First name=%s Last name=%s age=%s\n",buf,ch,ch2);
//...
++i;
if (i >= 30) {
  break;
}
for (i = 0; i < n; i++)
        printf("%s's last name %s and age.\n",list[i].firstname,list[i].lastname,list[i].age);
return 0;
for (i = 0; i < n; i++)
        printf("%s's last name %s and age is %d.\n",list[i].firstname,list[i].lastname,list[i].age);
return 0;