2016-01-13 84 views
2

我目前有一个从CSV文件读取数据的问题。C编程 - 读取CSV文件

我认为代码工作得很好。但是,打印的输出显示了一些怪异的字符(输出9-11)。

你对这里发生了什么有什么想法吗?我只是想摆脱这些奇怪的字符,以便我可以相应地处理导入的数据。

或者,如果您对我的编码风格有任何反馈,请与我分享,如果您不介意的话。

输出:

Obsns size is 150 and feat size is 4. 
1. 5.100000, 3.500000, 1.400000, 0.200000, Iris-setosa 
2. 4.900000, 3.000000, 1.400000, 0.200000, Iris-setosa 
3. 4.700000, 3.200000, 1.300000, 0.200000, Iris-setosa 
4. 4.600000, 3.100000, 1.500000, 0.200000, Iris-setosa 
5. 5.000000, 3.600000, 1.400000, 0.200000, Iris-setosa 
6. 5.400000, 3.900000, 1.700000, 0.400000, Iris-setosa 
7. 4.600000, 3.400000, 1.400000, 0.300000, Iris-setosa 
8. 5.000000, 3.400000, 1.500000, 0.200000, Iris-setosa 
9. 4.400000, 2.900000, 1.400000, 0.200000, ��L>-setosa 
10. 4.900000, 3.100000, 1.500000, 0.100000, Iris���=osa 
11. 5.400000, 3.700000, 1.500000, 0.200000, Iris-set��L> 
12. 4.800000, 3.400000, 1.600000, 0.200000, Iris-setosa 
13. 4.800000, 3.000000, 1.400000, 0.100000, Iris-setosa 
14. 4.300000, 3.000000, 1.100000, 0.100000, Iris-setosa 

代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int checkObsnsSize(char *dataFileName); 
void readIris(); 

int main() { 
    readIris(); 
    return 0; 
} 

void readIris() {  
    int featSize = 4; 
    char *dataFileName = "iris.data"; 
    int obsnsSize = checkObsnsSize(dataFileName); 
    float feat[featSize][obsnsSize]; 
    int label[obsnsSize]; 
    memset(feat, 0, featSize * obsnsSize * sizeof(float)); 
    memset(label, 0, obsnsSize * sizeof(int)); 

    printf("Obsns size is %d and feat size is %d.\n", obsnsSize, featSize); 

    FILE *fpDataFile = fopen(dataFileName, "r"); 
    if (!fpDataFile) { 
     printf("Missing input file: %s\n", dataFileName); 
     exit(1); 
    } 

    int index = 0; 
    while (!feof(fpDataFile)) { 
     char line[1024]; 
     char flowerType[20]; 

     fgets(line, 1024, fpDataFile); 

     sscanf(line, "%f,%f,%f,%f,%[^\n]", 
       &feat[1][index], &feat[2][index], 
       &feat[3][index], &feat[4][index], flowerType); 
     printf("%d. %f, %f, %f, %f, %s\n", ((int)index + 1), 
       feat[1][index], feat[2][index], 
       feat[3][index], feat[4][index], flowerType); 
     index++; 
    } 
    fclose(fpDataFile); 
} 

int checkObsnsSize(char *dataFileName) { 
    int obsnsSize = 0; 
    char line[1024]; 

    FILE *fpDataFile = fopen(dataFileName, "r"); 
    if (!fpDataFile) { 
     printf("Missing input file: %s\n", dataFileName); 
     exit(1); 
    } 
    while (!feof(fpDataFile)) { 
     fgets(line, 1024, fpDataFile); 
     obsnsSize++; 
    } 
    fclose(fpDataFile); 
    return obsnsSize; 
} 
+0

btw我在Linux上试过不同的编译器,我仍然遇到同样的错误。所以我不认为上面的问题与编译器的选择有关。 –

+1

阅读此帖http://stackoverflow.com/q/5431941/5339899 – JackVanier

+1

请提供您的CSV文件。我使用从输出创建的CSV文件运行了代码,程序似乎按预期运行。 – Chimera

回答

1
sscanf(line, "%f,%f,%f,%f,%[^\n]", &feat[1][index], &feat[2][index], 
     &feat[3][index], &feat[4][index], flowerType); 
printf("%d. %f, %f, %f, %f, %s\n", ((int) index+1), feat[1][index], feat[2][index], 
     feat[3][index], feat[4][index], flowerType); 

在这两行访问索引在这里&feat[4][index]界。这会导致未定义的行为

作为阵列的声明

float feat[featSize][obsnsSize];  //where featSize is 4 

所以,你可以从0(从0数组索引开始)访问索引34

+0

你是对的。我将您指定的值减1后问题就解决了。谢谢ameyCU! –

+0

@FrankPuk是的,那是因为你正在写入无效的内存位置。如果你声明一个大小为“n”的数组,你可以访问从“0”到“n-1”的索引。 – ameyCU

1

几件事情:

  • 请勿检查feof,检查返回值fgets()代替。

    while (!feof(fpDataFile)) { 
    
  • 总是检查返回值sscanf()

  • 你的指数应在0而不是1开始(索引4超出范围):

    sscanf(line, "%f,%f,%f,%f,%[^\n]", 
         &feat[0][index], &feat[1][index], 
         &feat[2][index], &feat[3][index], flowerType); 
    printf("%d. %f, %f, %f, %f, %s\n", ((int)index + 1), 
         feat[0][index], feat[1][index], 
         feat[2][index], feat[3][index], flowerType); 
    
  • 作为@chqrlie指出:使用%19[^\n]以避免溢出作为flowerType大小只有20

    sscanf(line, "%f,%f,%f,%f,%19[^\n]", 
         &feat[0][index], &feat[1][index], 
         &feat[2][index], &feat[3][index], flowerType); 
    
+0

@chqrlie - 添加到答案 - 谢谢。 –

1

所以把它放在一起,正确的代码如下所示:

1-使用fgets()返回值来确定文件何时被完全读取。
2-从索引0开始读入数组
3-检查sscanf()的返回值。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int checkObsnsSize(char * dataFileName); 
void readIris(); 

int main() { 
    readIris(); 
    return 0; 
} 

void readIris() { 

    int featSize = 4; 

    char *dataFileName = "iris.data"; 
    int obsnsSize = checkObsnsSize(dataFileName); 
    float feat[featSize][obsnsSize]; 
    int label[obsnsSize]; 
    memset(feat, 0, featSize*obsnsSize*sizeof(float)); 
    memset(label, 0, obsnsSize*sizeof(int)); 

    printf("Obsns size is %d and feat size is %d.\n", obsnsSize, featSize); 

    FILE *fpDataFile = fopen(dataFileName,"r"); 

    if (!fpDataFile) { 
     printf("Missing input file: %s\n", dataFileName); 
     exit(1); 
    } 

    int index = 0; 
    char line[1024]; char flowerType[20]; 

    while (fgets(line, 1024, fpDataFile)) 
    { 
     if(5 == sscanf(line, "%f,%f,%f,%f,%19[^\n]", &feat[0][index], &feat[1][index], &feat[2][index], &feat[3][index], flowerType)) 
     { 
      printf("%d. %f, %f, %f, %f, %s\n", ((int) index+1), feat[0][index], feat[1][index], feat[2][index], feat[3][index], flowerType); 
      index++; 
     } 
    } 
    fclose(fpDataFile); 
} 

int checkObsnsSize(char * dataFileName) { 

    int obsnsSize = 0; 
    char line[1024]; 

    FILE *fpDataFile = fopen(dataFileName,"r"); 
    if (!fpDataFile) { 
      printf("Missing input file: %s\n", dataFileName); 
      exit(1); 
     } 
    while (!feof(fpDataFile)) { 
     fgets(line, 1024, fpDataFile); 
     obsnsSize++; 
    } 
    fclose(fpDataFile); 
    return obsnsSize; 
} 
+0

为了防止缓冲区溢出,尽量不要使用'“%19 [^ \ n]”'尽管'%[^ \ n]'比'%[^ \ n]''尽管仍然没有检测到行中的额外文本。 – chux

+0

@chux啊好点! – Chimera

+0

也不要在'checkObsnsSize()'中使用'while(!feof(fpDataFile))',而应该使用'while(fgets(line,1024,fpDataFile))'。 – chqrlie