簡體   English   中英

fscans()之后fgets()不起作用

[英]fgets() not working after fscanf()

我正在使用fscanf讀取日期,然后使用fgets讀取便箋。 但是,在第一次迭代之后,fscanf返回值-1。

我使用GDB逐步調試程序。 在首次使用fgets之前,它可以正常工作。 當我嘗試打印出fgets在第一次迭代中讀取的行時,它給了我這個:

(gdb) print line
$6 = "\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000\000\000\000q\352\261\a\370\366\377\267.N=\366\000\000\000\000\003\000\000\000\370xC\000\000\000\000\000\000\000\000\000\001\000\000\000\227\b\000\000\070\367\377\267H\364\377\267\362\202\004\bdoD\000\354\201\004\b\001\000\000\000\304oC\000p\363\377\277\260zC\000D\363\377\277\n!B\000\064\363\377\277\354\201\004\b(\363\377\277TzC\000\000\000\000\000\070\367\377\267\001\000\000\000\000\000\000\000\001\000\000\000\370xC\000\001\000\000\000\000\000\312\000\000\000\000\000\377\260\360\000\001\000\000\000\277\000\000\000\364\317\000\000\344\261\\\000\000\000\000\000p\363\377\277|\233\004\b\350\362\377\277 \204\004\b\005\000\000\000|\233\004\b\030\363\377\277"

看起來fgets讀取剩余的條目,然后將它們全部存儲在單個字符串中。

我不確定為什么要這樣做。

這是主要代碼:

int main(int argc, char* argv[]) {
    FILE* file;
    int numEntries, i = 0;
    int index = atoi(argv[1]);
    char line[SIZE];
    JournalEntry *entry;

    /*argument provided is the entry user wants to be displayed*/
    if (argc > 2) {
        perror("Error: Too many arguments provided");
    }
    file = fopen("journalentries.txt", "r");
    if (file == NULL) {
        perror("Error in opening file");
    }

    if (fscanf(file, "%d", &numEntries) != 1) {
        perror("Unable to read number of entries");
    }

    entry = (JournalEntry*)malloc(numEntries  * sizeof(JournalEntry));
    if (entry == NULL) {
        perror("Malloc failed");
    }

    for (i = 0; i < numEntries; i++) {
        if (fscanf(file, "%d/%d/%d", &entry[i].day, &entry[i].month, &entry[i].year) != 3) {
            perror("Unable to read date of entry");
        }

        if (fgets(line, sizeof(line), file) == NULL) {
            perror("Unable to read text of entry");
        }
    }

    printf("%d-%02d-%02d %s: ", entry[index].year, entry[index].month, entry[index].day, entry[index].text);

    if(ferror(file)) {
        perror("Error with file");
    }

    fclose(file);
    free(entry);

    return 0;
}

我必須讀取的文件:第一行包含要讀取的條目數

4
12/04/2010
test
18/04/2010
test2
03/05/2010
test3
05/08/2009
test4

頭文件中的struct JournalEntry結構:

typedef struct {
    int day;
    int month;
    int year;
    char text[250];
} JournalEntry;

看起來fgets讀取剩余的條目,然后將它們全部存儲在單個字符串中。

是的, '\\r'不是行終止符。 因此,當fscanf在第一個無效字符處停止解析並將它們留在緩沖區中時, fgets會讀取它們直到行尾。 並且由於文件中沒有有效的行終止符,所以直到文件結束。

您可能應該修復文件,使其具有有效的(Unix?)行尾,例如使用合適的文本編輯器即可。 但這是另一個問題,之前已經有人問過(如此 ),具體取決於您的問題中未包含的細節。

此外,您需要仔細檢查fscanf返回值。 僅當返回值為-1時才使用perror ,否則錯誤消息將與該錯誤完全無關。 如果返回值>=0但與所需值不同,則打印自定義錯誤消息“無效的輸入語法”或其他內容(並可能使用fgets從緩沖區中讀取其余行)。

另外,為了可靠地混合scanffgets ,我需要在fscanf格式字符串中添加空格,以便它會讀取行尾的所有空格(也包括下一行的開頭和任何空行),因此請小心如果重要的話),就像這樣:

int items_read = scanf("%d ", &intvalue);

如另一個答案所述,最好只讀取帶有fgets行,然后逐行用sscanf解析它們。

不要混合使用fscanf()fgets() ,因為前者可能會將內容留在流的緩沖區中。

對於面向行的格式,請使用fgets()讀取整行,然后使用例如sscanf()解析已閱讀的內容。

運行GDB時看到的字符串實際上以第一個空字符結尾:

"\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000"

之后的其他數據將被忽略(使用普通str函數時);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM