2017-04-24 108 views
-2

我一直在使用文本文件,但不知何故,我一直在收到一個奇怪的錯誤。當我嘗試獲取字符串的第1,第2,第4和第5部分時(':'是分隔符),我得到一個奇怪的響應。這是我想讀: 1000:產品:0.75:5:0C:字符串從緩衝區被錯誤複製

而且我得到這種答案:

8   |X  |0 
75(

下面是代碼:

int main(){ 
char c,buff[100],prod[30],id[8],stock[8],vendas[8]; 
int i=0,n=0,num=0; 
FILE *fp; 
fp=fopen("products.txt","r+"); 
printf("Lista de produtos(Num |Produto |Stock |Vendas)\n"); 
while(fgets(buff,100,fp)){ 
for(n=0;n<strlen(buff);n++){ 
    if(buff[n]==':'){ 
    num++; 
    i=0; 
    }  
    else if((buff[n]!=':')&&(num==0)){ 
    id[i]=buff[n]; 
    i++; 
    } 
    else if((buff[n]!=':')&&(num==1)){ 
    prod[i]=buff[n]; 
    i++; 
    } 
    else if((buff[n]!=':')&&(num==3)){ 
    stock[i]=buff[n]; 
    i++; 
    } 
    else if((buff[n]!=':')&&(num=4)){ 
    vendas[i]=buff[n]; 
    i++; 
    }  
    } 
i=0; 
num=0; 
printf("%s |%s    |%s  |%s\n",id,prod,stock,vendas);  
memset(id,0,8); 
memset(prod,0,30); 
memset(stock,0,8); 
memset(vendas,0,8); 
} 
printf("Prima qualquer tecla para sair"); 
getchar(); 
return 0; 
} 

任何幫助,將不勝感激。對不起,如果這個問題或我的代碼不是最好的。 祝您有美好的一天!

+3

'%s'格式說明符期望以null爲終點的stirng作爲參數 –

+1

當您從一種狀態切換到另一種狀態時,可能要考慮終止這些字符串。 – WhozCraig

+0

您也可以考慮使用strtok將字符串拆分爲多個部分。 – Gerhardh

回答

0
  • 如果格式字符串沒有以:開頭,則永遠不會初始化i
  • 如果確實以:開頭,那麼num==0將永遠不會執行。
  • 你永遠不會終止字符串。
  • if(buff[n]==':') ... else if((buff[n]!=':'是多餘的。
  • num=4是一個錯誤,啓用編譯器警告或獲得更好的編譯器。
  • 您從不檢查文件是否正確打開,也不檢查是否到達文件末尾。
+0

*如果格式字符串沒有以:開始,你永遠不會初始化I. *他在while循環的開始和結束處初始化'I'。 –

+0

'i'在聲明時被初始化。 – JeremyP

+0

嗯沒關係。爲什麼在3個不同的位置初始化一個變量,儘管......它是爲了最大程度的混淆而設計的 – Lundin

0

最適合的時間是通過調用未定義的行爲,因爲您尚未初始化每個字段緩衝區的內容。

您還在填充字段時不檢查的緩衝區溢出。如果一個字段是不是你把它在陣列一樣長或更長的時間,會出現緩衝區溢出並沒有終止\0

而且在每個else if中,您不需要(buff[n]!=':')條件。

另外,最後的else if在條件n = 4中有一個賦值(儘管這實際上不影響結果)。

+0

@AjayBrahmakshatriya我想你發佈了你的評論錯誤的答案。 – JeremyP

0

至少有兩個錯誤:

首先嚐試使用它們之前,初始化你的陣列...

while(fgets(buff,100,fp)){ 
    memset(id,0,8); 
    memset(prod,0,30); 
    memset(stock,0,8); 
    memset(vendas,0,8); 
    for(n=0;n<strlen(buff);n++){ 

分配在測試中,將:

if((buff[n]!=':')&&(num=4)){ 

if((buff[n]!=':')&&(num==4)){ 
         ^
+0

謝謝大家如此快速的幫助!我會記住所有的提示。我希望你們都有美好的一天。 –

0

你可能會讓邏輯變得更加困難。當你必須根據分隔符將一行文本分成單詞時,你應該考慮strtokstrsepstrtok是用於標記化的正常例程定界符上的一行文本,將行劃分爲單個單詞。(strsep主要用於存在遇到空字段的機會,如在大的.csv文件中)。

您的代幣很簡單,':' char和'\n'最後。您可以簡單地聲明char *delim = ":\n";並予以報道。

雖然您可以自由將菊花鏈if, then, else if, ....放在一起,但計數器上的switch可能使生活更輕鬆,代碼更具可讀性。

把這些作品放在一起,你可以這樣做以下:

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

enum { ISV = 8, PROD = 30, BUFF = 100 }; /* constants */ 

int main (int argc, char **argv) { 

    char buff[BUFF] = "", prod[PROD] = "", id[ISV] = "", 
     stock[ISV] = "", vendas[ISV] = "", *delim = ":\n"; 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* validate file open for reading */ 
     fprintf (stderr, "error: file open failed.\n"); 
     return 1; 
    } 

    while (fgets (buff, sizeof buff, fp)) { /* for each line of input */ 
     int i = 0, n = 0; /* tokenize buff into words */ 
     for (char *p = strtok (buff, delim); p; p = strtok (NULL, delim)) { 
      switch (i) { 
       case 0: strncpy (id, p, ISV);  /* handle id */ 
         if (strlen (p) >= ISV) 
          id[ISV-1] = 0; 
          i++; 
         break; 
       case 1: strncpy (prod, p, PROD); /* handle prod */ 
         if (strlen (p) >= PROD) 
          prod[PROD-1] = 0; 
          i++; 
         break; 
       case 2: strncpy (stock, p, ISV); /* handle stock */ 
         if (strlen (p) >= ISV) 
          stock[ISV-1] = 0; 
          i++; 
         break; 
       case 3: strncpy (vendas, p, ISV); /* handle vendas */ 
         if (strlen (p) >= ISV) 
          vendas[ISV-1] = 0; 
          i++; 
         break; 
       default: break; 
      } 
     } 
     n++; 

     printf ("id: %s, prod: %s, stock: %s, vendas: %s\n", 
       id, prod, stock, vendas); 

     if (fp != stdin) fclose (fp); /* close file */ 
    } 
    return 0; 
} 

例輸入文件

$ cat dat/prod.txt 
1000:Product1:0.75:5:0 
1001:Product2:0.90:2:0 
1002:Product3:0.55:8:0 

示例使用/輸出

$ ./bin/prod dat/prod.txt 
id: 1000, prod: Product1, stock: 0.75, vendas: 5 
id: 1001, prod: Product2, stock: 0.90, vendas: 2 
id: 1002, prod: Product3, stock: 0.55, vendas: 8 

看THI如果你還有其他問題,請告訴我。

+0

謝謝你的幫助!完全理解它。將來會記住這些提示。 –