2016-01-23 116 views
-1

我正在使用此代碼加載文件,但它似乎也因爲某種原因刪除換行符,但刪除了第一行。從fread剝離換行符

void load_script(char* path) { 
    FILE* file; 
    char* script; 
    int filesize = 0; 

    file = fopen(path, "r"); 

    // determine file size 
    fseek(file, 0L, SEEK_END); 
    filesize = ftell(file); 
    fseek(file, 0L, SEEK_SET); 

    // allocate memory 
    script = malloc(filesize + 1); 

    // read script 
    size_t size = fread(script, 1, filesize, file); 
    script[size] = 0; 

    printf("Before stripping:\n%s\n", script); 

    // strip newlines 
    script[strcspn(script, "\n")] = 0; 

    printf("After stripping:\n%s\n", script); 

    fclose(file); 
    tokenize(script); 
} 

下面是輸出:

Before stripping: 
line 1 
line 2 
line 3 
After stripping: 
line 1 

我很想知道,從一個多字符串中去除換行的最佳方式。謝謝。

回答

2
script[strcspn(script, "\n")] = 0; 

這將終止第一個換行符後面的C字符串。您可能想循環使用字符串,並用' '代替\n'

喜歡的東西:

// strip newlines 
for(size_t i = 0; script[i]; i++) 
if (script[i] == '\n') script[i] = ' '; 

順便說一句,你應該使用off_t(POSIX定義)來存儲文件大小(截至filesize類型),而不是一個intint可能無法保存文件的大小。

+0

很好的解釋和修復,但你最後對文件大小類型的評論並不嚴格正確:'ftell()'被定義爲返回'long',而不是'lseek'這樣的'off_t'。類型'long'可能與'size_t'的大小不同,將其轉換爲'int'或'size_t'可能會截斷非常大的文件的值,而這個值甚至可能不是文件大小,所以確實存在問題在那裏。 – chqrlie

0

除了由L3X提供的解決方案,我要補充一點,使用的方法是不可靠的:

  • ftell可能會失敗,並在成功時,它的返回值是字節的文件,只有在數該文件以二進制模式打開。對於文本模式,標準不能保證除了可用作fseek的參數之外的任何內容。
  • 如果流沒有引用實際的文件,尋找文件結尾並返回到開頭將無法按預期工作:對於終端,字符設備或管道,它可能根本無法工作。

getc()的文件讀入緩衝區,可以按需重新分配,每次一個塊,這樣更可靠。