簡體   English   中英

讀取String中的fscanf問題

[英]fscanf problem with reading in String

我正在讀一個.txt文件。 我正在使用fscanf來獲取格式化的數據。 我遇到問題的這條線是這樣的:

result = fscanf(fp, "%s", ap->name);

這是好的,直到我有一個空格的名稱,例如:St Ives所以我用這個來讀取空白區域:

result = fscanf(fp, "%[^\n]s", ap->name);

但是,當我嘗試讀取第一個名稱(沒有空白區域)時,它只是不起作用並且弄亂了其他的fscanf。

但我使用[^ \\ n]它在我正在使用的不同文件中工作正常。 不確定發生了什么。

如果我在fscanf的位置使用fgets,我會在變量中得到“\\ n”。

編輯//

好的,所以如果我使用:

result = fscanf(fp, "%s", ap->name);
result = fscanf(fp, "%[^\n]s", ap->name);

這允許我讀入沒有空格的字符串。 但是當我得到一個帶有空格的“名字”時它不起作用。

這有一個問題:

result = fscanf(fp, "%[^\n]s", ap->name);

是你的格式說明符末尾有一個額外的s 整個格式說明符應該只是%[^\\n] ,它表示“讀取一個字符串,該字符串由不是換行符的字符組成”。 額外的s不是格式說明符的一部分,因此它被解釋為文字:“從輸入中讀取下一個字符;如果它是”s“,則繼續,否則失敗。”

但是額外的s實際上並沒有傷害到你。 您確切知道輸入的下一個字符:換行符。 它不匹配,輸入處理在那里停止,但它並不重要,因為它是格式說明符的結尾。 但是,如果在同一格式字符串之后有其他格式說明符,則會導致問題。

真正的問題是你沒有使用換行符:你只讀取換行符之前的所有字符,而不是換行符本身。 要解決這個問題,你應該這樣做:

result = fscanf(fp, "%[^\n]%*c", ap->name);

%*c說明符表示讀入字符( c ),但不將其分配給任何變量( * )。 如果省略了* ,則必須傳遞fscanf()另一個包含指向字符( char* )的指針的參數,然后它將存儲它讀入的結果字符。

您也可以使用%[^\\n]\\n ,但這也會在新行后面的任何空格中讀取,這可能不是您想要的。 fscanf在其格式說明符(空格,換行符或制表符)中找到空格時,它會消耗盡可能多的空格(即您可以認為它消耗了與正則表達式匹配的最長字符串[ \\t\\n]* ) 。

最后,您還應指定最大長度以避免緩沖區溢出。 您可以通過將緩沖區長度放在%[之間[ 例如,如果ap->name是256個字符的緩沖區,則應該這樣做:

result = fscanf(fp, "%255[^\n]%*c", ap->name);

這適用於靜態分配的數組; 不幸的是,如果數組在運行時具有動態大小,那么將緩沖區大小傳遞給fscanf並不容易。 您必須使用sprintf創建格式字符串,例如:

char format[256];
snprintf(format, sizeof(format), "%%%d[^\n]%%*c", buffer_size - 1);
result = fscanf(fp, format, ap->name);

Jumm寫道:

如果我在fscanf的位置使用fgets,我會在變量中得到“\\ n”。

這是一個更容易解決的問題,所以順其自然:

fgets( ap->name, MAX, fp ) ;
nlptr = strrchr ( ap->name, '\n' ) ;
if( nlptr != 0 )
{
    *nlptr = '\0' ;
}

我不確定你的意思是[^ \\ n]假設工作。 []是一個修飾符,表示“接受一個字符, 除了該塊內的任何字符”。 ^反轉條件。 使用fscanf的%s僅在讀取分隔符時才會讀取。 對於包含空格和換行符的字符串,請改為使用fgets和sscanf的組合,並指定長度限制。

沒有這樣的東西,我收集到你試圖在fscanf函數中暗示一個不存在的正則表達式,不是我所知道的,也沒有在任何地方看到它 - 啟發我這一點。

讀取字符串的格式說明符是%s ,可能需要這樣做, %s\\n將獲取換行符。

但是對於皮特來說,不要使用 Clifford上面的答案所規定 的標准舊的gets家庭功能 因為這是緩沖區溢出發生的地方,並且被用於1990年代的一個臭名昭着的蠕蟲 - 莫里斯蠕蟲,更具體地說是在fingerd守護進程中使用的打電話gets那造成混亂。 幸運的是,現在已經修補了。 此外,許多程序員已經深入研究了不使用該功能的心態。

即使微軟已經采取了安全版本的gets家庭的功能,即指定一個參數來表示緩沖區的長度來代替。

編輯我的壞 - 我沒有意識到Clifford確實指定了輸入的最大長度......哎呀! 抱歉! 克利福德的答案是對的! 所以+1來克利福德的回答。

謝謝尼爾指出我的錯誤......

希望這會有所幫助,最好的問候,湯姆。

我發現了這個問題。

正如Paul Tomblin所說,我在上面的領域有一個額外的新線字符。 所以用tommieb75說我用過的:

result = fscanf(fp, "%s\n", ap->code);
result = fscanf(fp, "%[^\n]s", ap->name);

這固定了!

謝謝你的幫助。

暫無
暫無

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

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