[英]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.