2014-10-09 78 views
2

我有一個make[]數組輸出問題給我帶來了問題。因此,我首先標記名爲Carss.txt的文件,只抓取第三列&,並分別將結果存儲在make[]數組和year[]數組中。c中的輸出問題

我測試了make[]數組,看它是否會輸出我想要的結果。它在while(fgets)循環內完成,但是當我在while(fgets)的外部測試它時,它正在重複。

我不明白是什麼問題。我的程序和文本文件在下面提供。

while(fgets)循環,並使陣列的輸出:(我想要),並使陣列的

FORD 
FORD 
JAYCO 

輸出外while(fgets)循環:(不是我想要的)

JAYCO 
JAYCO 
JAYCO 

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

int main() { 
    FILE * fp; 
    char * filename = "Carss.txt"; 
    char lines[100000], blank[100000]; 
    char * token, * del = " "; 
    int i = 0, c, d = 0, j; 
    char * make[10000]; 
    char * year[10000]; 
    if ((fp = fopen(filename, "r")) == NULL) /* Opens the file */ { 
     printf("can't open %s\n", filename); 
     exit(1); 
    } 
    c = 0; 
    while (fgets(lines, sizeof(lines), fp) != NULL) { 
     token = strtok(lines, "\t"); 
     i = 1; 
     while (i < 5) { 
      token = strtok(NULL, "\t"); 
      if (i == 2) { 
       make[c] = token; 
      } 
      if (i == 4) { 
       year[c] = token; 
      } 
      i++; 
     } 
     printf("%s\n", make[c]); /* OUTPUT OF THE ARRAY HERE IS WHAT I WANTED */ 
     c++; 
    } 
    c = 0; 
    while (c < 3) { 
     printf("%d\n", c); 
     printf("%s\n", make[c]); 
     c++; 
    } 
} 

我標記的文本文件:Carss.txt

1 02V288000 FORD FOCUS 2001 02S41 ELECTRICAL SYSTEM:BATTERY:CABLES FORD MOTOR COMPANY 19990719 20010531 V 291854 20030210 ODI Ford Motor Company 20021106 20021106   CERTAIN PASSENGER VEHICLES EQUIPPED WITH ZETEC ENGINES, LOOSE OR BROKEN ATTACHMENTS AND MISROUTED BATTERY CABLES COULD LEAD TO CABLE INSULATION DAMAGE. THIS, IN TURN, COULD CAUSE THE BATTERY CABLES TO SHORT RESULTING IN HEAT DAMAGE TO THE CABLES. BESIDES HEAT DAMAGE, THE "CHECK ENGINE" LIGHT MAY ILLUMINATE, THE VEHICLE MAY FAIL TO START, OR SMOKE, MELTING, OR FIRE COULD ALSO OCCUR. DEALERS WILL INSPECT THE BATTERY CABLES FOR THE CONDITION OF THE CABLE INSULATION AND PROPER TIGHTENING OF THE TERMINAL ENDS. AS NECESSARY, CABLES WILL BE REROUTED, RETAINING CLIPS INSTALLED, AND DAMAGED BATTERY CABLES REPLACED. OWNER NOTIFICATION BEGAN FEBRUARY 10, 2003. OWNERS WHO DO NOT RECEIVE THE FREE REMEDY WITHIN A REASONABLE TIME SHOULD CONTACT FORD AT 1-866-436-7332. ALSO CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015339000215022000000202 
2 02V288000 FORD FOCUS 2000 02S41 ELECTRICAL SYSTEM:BATTERY:CABLES FORD MOTOR COMPANY 19990719 20010531 V 291854 20030210 ODI Ford Motor Company 20021106 20021106   CERTAIN PASSENGER VEHICLES EQUIPPED WITH ZETEC ENGINES, LOOSE OR BROKEN ATTACHMENTS AND MISROUTED BATTERY CABLES COULD LEAD TO CABLE INSULATION DAMAGE. THIS, IN TURN, COULD CAUSE THE BATTERY CABLES TO SHORT RESULTING IN HEAT DAMAGE TO THE CABLES. BESIDES HEAT DAMAGE, THE "CHECK ENGINE" LIGHT MAY ILLUMINATE, THE VEHICLE MAY FAIL TO START, OR SMOKE, MELTING, OR FIRE COULD ALSO OCCUR. DEALERS WILL INSPECT THE BATTERY CABLES FOR THE CONDITION OF THE CABLE INSULATION AND PROPER TIGHTENING OF THE TERMINAL ENDS. AS NECESSARY, CABLES WILL BE REROUTED, RETAINING CLIPS INSTALLED, AND DAMAGED BATTERY CABLES REPLACED. OWNER NOTIFICATION BEGAN FEBRUARY 10, 2003. OWNERS WHO DO NOT RECEIVE THE FREE REMEDY WITHIN A REASONABLE TIME SHOULD CONTACT FORD AT 1-866-436-7332. ALSO CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015339000215021000000202 
3 02V236000 JAYCO FT EAGLE 10 SG 2003  EQUIPMENT:OTHER:LABELS JAYCO, INC. 20020730 20020813 V 86 20020923 MFR Jayco, Inc. 20020904 20020912   ON CERTAIN FOLDING TENT CAMPERS, THE FEDERAL CERTIFICATION (AND RVIA) LABELS HAVE THE INCORRECT GROSS VEHICLE WEIGHT RATING, TIRE SIZE, AND INFLATION PRESSURE LISTED. IF THE TIRES WERE INFLATED TO 80 PSI, THEY COULD BLOW RESULTING IN A POSSIBLE CRASH. OWNERS WILL BE MAILED CORRECT LABELS FOR INSTALLATION ON THEIR VEHICLES. OWNER NOTIFICATION BEGAN SEPTEMBER 23, 2002. OWNERS SHOULD CONTACT JAYCO AT 1-877-825-4782. ALSO, CUSTOMERS CAN CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015210000106403000000349 

回答

3

當你這樣做:

token = strtok(NULL, "\t"); 
if(i==2) 
{ 
    make[c] = token; 
} 

你不採取串的副本,只有指針引用。然後在下次您撥打fgets時,字符串被覆蓋,並且所有引用都指向新字符串。所以,當你到達程序結尾時,你所有的指針都指向最後的寫入該內存的東西。

試試這個:

make[c] = strdup(token); 

這將分配新的內存,複製字符串,返回新的指針。副本不會被覆蓋。 strdup在內部調用malloc,所以當你完成它時你應該記住free的內存。

1

在循環中,make[c] = token記錄裏面char lines[]地址。由於該緩衝區在下一次迭代時被覆蓋,因此您需要將您的令牌複製到其他地方以保證它們的安全。

只需使用make[c] = strdup(token)(年份相同)即可完成此操作 - 但請記住,在任何真正的程序中,您現在應該使用free所有制作和年份字符串。

0

您正在使用錯誤的數據結構來存儲結果。

make數組是一個指針數組。這意味着您存儲的所有內容都有一個內存地址,在您的情況下,在strtok操作期間使用的指針的內存地址。這不是你想要的,因爲你不知道事後會發生什麼,在這種情況下,看起來在每次連續調用函數時都會被覆蓋。

您必須要麼使用多維數組或使用malloc()strdup()通過strtok()返回的創建char *值的副本。和strtok的只有一個靜態緩衝區 - - 所以每次while循環迭代

0

的strtok的靜態緩衝

當你寫

strtok(lines, "\t"); 

lines緩衝區拷貝到內部靜態緩衝區操作,新的內容被放入靜態緩衝區,使任何以前的指針失效,即make []和year []。

爲了保留令牌,您需要爲它們分配單獨的內存,這些內存在循環結束時不會被銷燬。這可以通過幾種方式來完成,比如像其他海報中提到的那樣,在每個字符串上使用strdup,雖然會有很多簿記,然後釋放這些東西。你也可以使用另一個數據結構,例如鏈表存儲,而不必大量指針的值:

typedef struct record 
{ 
    char make[32]; // lets say the max length of make is 32 
    char year[10]; 
    struct record* next; 
} record; 

每當你從文件中讀取一個新行創建一個新的紀錄:

record* first = NULL; 
record* last = NULL; 

while (fgets(lines, sizeof(lines), fp) != NULL) 
{ 
    // first create the record 
    record* newRecord = malloc(sizeof(record)); 
    newRecord->next = NULL; 

    // parse the line 
    int column = 0; 
    for (char* token = strtok(lines,"\t"); token != NULL; token = strtok(NULL, "\t"), ++column) 
    { 
    switch(column) 
    { 
    case 2: 
     strncpy(newRecord->make, token, sizeof(newRecord.make)); 
     break; 
    case 4: 
     strncpy(newRecord->year, token, sizeof(newRecord.year)); 
     break; 
    default: // ignore 
     break; 
    } 
    } 
    // put in the list 
    if (first == NULL) 
    { 
    first = last = newRecord; 
    } 
    else 
    { 
    last->next = newRecord; 
    last = newRecord; 
    } 
} 

現在你有部分你有興趣在一個列表中。你可以打印出列表

for (record* rec = first; rec != NULL; rec = rec->next) 
{ 
    printf("%s, %s\n", rec->make, rec->year); 
} 

//免責聲明,沒有編譯過這個。