分割字符串并显示它

时间:2010-03-10 10:53:56

标签: c

实际上,下面的程序是分割字符串并显示输出。我已经完成了我的程序并且它提供了所需的输出。但是,最后它给出了分段错误。我也尝试使用调试器。但是,我无法找到问题。任何人都可以帮助我吗?

输入文件:

 
  Vivek|Raj|20
  Abi|Nila|20 
  

预期产出:

  Vivek's last name Raj and age is 20.
  Abi's last name Nila and age is 20.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct person{
        char firstname[30];
        char lastname[30];
        int age;
};
int main(int args, char *argv[])
{
        struct person list[30];
        int i,n;
        char *ch,*ch1,*ch2,*ch3;
        char buf[256];
        FILE *fp;

        fp = fopen(argv[1],"r");
        if(fp == NULL){
                printf("Cannot open file %s\n", argv[1]);
                exit(0);
        }
        i=0;
        fgets(buf,256,fp);
        while(!feof(fp)){
                ch = strchr(buf,'\n');
                if(ch != NULL) *ch = '\0';
                else break;
                ch = strchr(buf,'|');
                ch2 = strrchr(buf,'|');
                if(ch != NULL)
                {
                        *ch = '\0';ch1 = ++ch2;
                }
                else break;
                ch++;
                strcpy(ch3,ch);
                ch2=strchr(ch3,'|');
                *ch2='\0';
                strcpy(list[i].firstname,buf);
                strcpy(list[i].lastname,ch3);
                list[i].age = atoi(ch1);
                i++;
                fgets(buf,256,fp);
        }
        n = i;

        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;
}

4 个答案:

答案 0 :(得分:1)

作为第一点,你读错了。您应该循环fgets(),因为它在失败时返回NULL(通常,这意味着您已到达文件末尾):

char buf[256];

while(fgets(buf, sizeof buf, fp))
{
  /* process each line here */
}

答案 1 :(得分:1)

你正在做一个strcpy(ch3,ch);其中ch3没有被分配任何内存,因为它也没有被分配给NULL,你的代码会覆盖一些未知的内存,导致内存损坏并最终导致崩溃。

答案 2 :(得分:0)

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

1)在我看来,ch3根本没有初始化。所以它可能包含垃圾和点(偶然)到可写内存(可能是堆栈?)。在使用之前,应该将指向有效缓冲区的指针分配给ch3。我认为崩溃是由于这个问题。可能的纠正(不是最好的纠正)是:

 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);

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;
}

当然,如果“list”数组的大小是通过宏参数化的话会很好。

4)“firstname”和“lastname”是char [SOME_SIZE]。所有输入字段是否都适合SOME_SIZE-1?

一般来说,程序错过了一些“限制”和“输入验证”控件(例如,如果数字字段格式不正确怎么办?好吧,它不会崩溃,但是......嗯......)

我希望这可能有所帮助。

此致

答案 3 :(得分:0)

您的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;

你错过了最后一个参数的%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;