2010-04-07 42 views
0

我不明白为什么atoi()对除第一个元素之外的每个项都有效。我有以下代码来解析一个简单的.csv文件:从文件中读取时,atoi()仅在第一个元素上返回零。

void ioReadSampleDataUsers(SocialNetwork *social, char *file) { 
    FILE *fp = fopen(file, "r"); 

    if(!fp) { 
     perror("fopen"); 
     exit(EXIT_FAILURE); 
    } 

    char line[BUFSIZ], *word, *buffer, name[30], address[35]; 
    int ssn = 0, arg; 

    while(fgets(line, BUFSIZ, fp)) { 
     line[strlen(line) - 2] = '\0'; 

     buffer = line; 
     arg = 1; 

     do { 
      word = strsep(&buffer, ";"); 

      if(word) { 
       switch(arg) { 
        case 1: 
         printf("[%s] - (%d)\n", word, atoi(word)); 
         ssn = atoi(word); 
         break; 
        case 2: 
         strcpy(name, word); 
         break; 
        case 3: 
         strcpy(address, word); 
         break; 
       } 

       arg++; 
      } 
     } while(word); 

     userInsert(social, name, address, ssn); 
    } 

    fclose(fp); 
} 

而且该.csv示例文件是这样的:

900011000;Jon Yang;3761 N. 14th St 
900011001;Eugene Huang;2243 W St. 
900011002;Ruben Torres;5844 Linden Land 
900011003;Christy Zhu;1825 Village Pl. 
900011004;Elizabeth Johnson;7553 Harness Circle 

但是,这是输出:

[900011000] - (0) 
[900011001] - (900011001) 
[900011002] - (900011002) 
[900011003] - (900011003) 
[900011004] - (900011004) 

什么我做错了吗?

+0

您还可以打印strlen(单词)吗? – 2010-04-07 16:43:08

+0

它为第一个和第九个打印出'12'... – 2010-04-07 16:47:48

回答

5

我猜你的CSV文件是以UTF-8格式保存的,并且在开始时有一个BOM(byte order mark),令人迷惑atoi。您可以通过在十六进制编辑器中查看文件或查看word的前几个字节来验证此情况。

UTF-8的BOM是三个字节,值为0xEF,0xBB和0xBF。

如果可能,请将文件另存为ASCII。如果不是,请添加代码以检测并跳过这些字节。

+0

特别可能一旦你考虑到strlen()的结果。 – 2010-04-07 16:49:09

+0

只需将该文件保存为ANSI,即可解决该问题。我不认为输入需要以UTF-8保存。 – 2010-04-07 16:53:52

+0

我想你是指utf-16。如果是utf8,那么当限制字节值0-127时它将是ascii,并且不需要字节排序代码。 – nategoose 2010-04-07 20:09:37

2

我的猜测是该文件以字节顺序标记开头。 atoi()将其视为非数字,因此返回0.

if (line[0] == 0xEF && line[1] == 0xBB && line[2] == 0xBF) { 
    /* byte order mark is present, so skip it somehow */ 
} 
相关问题