簡體   English   中英

C讀取一個文本文件,該文件用單詞大小不受限制的空格分隔

[英]C reading a text file separated by spaces with unbounded word size

我有一個文本文件,其中包含用空格分隔的單詞(字符串)。 字符串的大小不受限制,字數也不受限制。 我需要做的是將文件中的所有單詞放在列表中。 (假設列表工作正常)。 我無法弄清楚如何克服無限的字長問題。 我已經試過了:

FILE* f1;
f1 = fopen("file1.txt", "rt");
int a = 1;

char c = fgetc(f1);
while (c != ' '){
    c = fgetc(f1);
    a = a + 1;
}
char * word = " ";
fgets(word, a, f1);
printf("%s", word);
fclose(f1);
getchar();

我的文本文件如下所示:

 this is sparta

請注意,我所能得到的只是第一個字,甚至我做錯了,因為我得到了錯誤:

Access violation writing location 0x00B36860.

有人可以幫幫我嗎?

從上面的評論者那里獲取建議,只要內存不足或顯然足夠,它就會重新分配內存。

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

void fatal(char *msg) {
    printf("%s\n", msg);
    exit (1);
    }

int main() {
    FILE* f1 = NULL;
    char *word = NULL;
    size_t size = 2;
    long fpos = 0;
    char format [32];

    if ((f1 = fopen("file1.txt", "rt")) == NULL)        // open file
        fatal("Failed to open file");
    if ((word = malloc(size)) == NULL)                  // word memory
        fatal("Failed to allocate memory");
    sprintf (format, "%%%us", (unsigned)size-1);        // format for fscanf

    while(fscanf(f1, format, word) == 1) {
        while (strlen(word) >= size-1) {                // is buffer full?
            size *= 2;                                  // double buff size
            printf ("** doubling to %u **\n", (unsigned)size);
            if ((word = realloc(word, size)) == NULL)
                fatal("Failed to reallocate memory");
            sprintf (format, "%%%us", (unsigned)size-1);// new format spec
            fseek(f1, fpos, SEEK_SET);                  // re-read the line
            if (fscanf(f1, format, word) == 0)
                fatal("Failed to re-read file");
        }
        printf ("%s\n", word);
        fpos = ftell(f1);                               // mark file pos
    }

    free(word);
    fclose(f1);
    return(0);
}

程序輸入

this   is  sparta
help 30000000000000000000000000000000000000000
me

程序輸出:

** doubling to 4 **
** doubling to 8 **
this
is
sparta
help
** doubling to 16 **
** doubling to 32 **
** doubling to 64 **
30000000000000000000000000000000000000000
me

您在哪個平台上?

如果您使用的是POSIX平台,則考慮使用getline()讀取無限制大小的行,然后使用strcspn()strpbrk()strtok_r()或(如果您確實確定要編寫代碼, (不可重用) strtok()獲取單詞的邊界,最后使用strdup()創建單詞的副本。 strdup()返回的指針將存儲在通過realloc()管理的char *數組中。

如果您沒有使用足夠的POSIX平台,則需要使用fgets()進行檢查以查看您是否實際讀取了整行-如果您的起始行不在,請使用realloc()分配更多空間足夠長了。 一旦有了一行,就可以像以前一樣拆分它。

您可能會getdelim()於POSIX getdelim() ,只需要一個定界符,並且您可能希望用空格和換行符來標記單詞的結尾(可能還有制表符),而這是無法處理的。

而且,如果您使用的是足夠現代的POSIX系統,則可以考慮使用m修飾符對scanf()

char *word = 0;

while (scanf("%ms", &word) == 1)
    …store word in your list…

如果可用,這甚至更簡單。

暫無
暫無

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

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