2016-01-13 117 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