每三个数换行 用C语言表示,关于换行符:使用fscanf()读取每行3个数字的文件,为什么“%d%d%d%* c”和“%d%d%d”一样好?...
我知道%d格式說明符,當(dāng)在fscanf()中使用時,會讀取一個整數(shù)并忽略其前面的空白,包括換行符(我已對其進(jìn)行了驗證)。但是在下面的程序中,我使用fscanf()來從多行(每個行包含3個整數(shù))的文件讀取時,格式字符串"%d%d%d%*c"與"%d%d%d"一樣好。
為什么會這樣呢?由于fscanf()與%d一起用作格式說明符字符串中的第一個格式說明符,所以忽略了整數(shù)前的任何空格,為什么用作最后一個說明符的額外%*c不會引起任何錯誤或側(cè)面錯誤-如果%d說明符在一行中每組3個數(shù)字之后都沒有忽略換行符,那么%*c就很有意義了,因為它會吃掉換行符。但是為什么即使沒有錯誤或副作用,它也能正常工作如果fscanf()默認(rèn)情況下忽略%d的空白?當(dāng)%* c找不到要吃的字符并且說明符和輸入之間不匹配時,fscanf()不應(yīng)該停止掃描嗎?不匹配時fscanf()是否應(yīng)該停止,就像scanf()一樣嗎?
編輯:即使我使用"%*c%d%d%d",它也能正常工作!一旦格式說明符和開頭的輸入之間不匹配,是否應(yīng)該停止后續(xù)字符的掃描和處理?
#include
#include
int main ()
{
int n1,n2,n3;
FILE *fp;
fp=fopen("D:\\\\data.txt","r");
if(fp==NULL)
{
printf("Error");
exit(-1);
}
while(fscanf(fp,"%d%d%d%*c",&n1,&n2,&n3)!=EOF) //Works as good as line below
//while(fscanf(fp,"%d%d%d",&n1,&n2,&n3)!=EOF)
printf("%d,%d,%d\",n1,n2,n3);
fclose(fp);
}
這是我的文件data.txt中數(shù)據(jù)的格式:
243 343 434
393 322 439
984 143 943
438 243 938
輸出:
243 343 434
393 322 439
984 143 943
438 243 938
請參閱與使用fscanf()關(guān)聯(lián)的注釋以從給定行讀取。 它恰好涵蓋了這種情況。
@JonathanLeffler是的,這就是我想問的。您說%d skips white space to the first digit。它證明了我最初在問題中說的話。%d應(yīng)該注意空格,包括換行符,所以為什么%*c不使用 格式說明符字符串的任何地方(甚至開頭)都會導(dǎo)致問題?
考慮問題中程序的這種變化:
#include
#include
int main(int argc, char **argv)
{
char *file ="D:\\\\data.txt";
FILE *fp;
char *formats[] =
{
"%d%d%d%*c",
"%d%d%d",
"%*c%d%d%d",
};
if (argc > 1)
file = argv[1];
for (int i = 0; i < 3; i++)
{
if ((fp = fopen(file,"r")) == 0)
{
fprintf(stderr,"Failed to open file %s\", file);
break;
}
printf("Format: %s\", formats[i]);
int n1,n2,n3;
while (fscanf(fp, formats[i], &n1, &n2, &n3) == 3)
printf("%d, %d, %d\", n1, n2, n3);
fclose(fp);
}
return 0;
}
重復(fù)打開效率不高,但是這里不必?fù)?dān)心。明確和顯示行為更為重要。
它被編寫為(a)使用在命令行上指定的文件名,因此我不必使用D:\\data.txt之類的名稱,它們在Unix系統(tǒng)上創(chuàng)建非常不便,并且(b)顯示了三種格式使用。
給定問題的數(shù)據(jù)文件:
243 343 434
393 322 439
984 143 943
438 243 938
該程序的輸出為:
Format: %d%d%d%*c
243, 343, 434
393, 322, 439
984, 143, 943
438, 243, 938
Format: %d%d%d
243, 343, 434
393, 322, 439
984, 143, 943
438, 243, 938
Format: %*c%d%d%d
43, 343, 434
393, 322, 439
984, 143, 943
438, 243, 938
請注意,當(dāng)%*c是格式的第一部分時,第一個數(shù)字的第一位將被使用。讀取前三個數(shù)字后,%*c讀取行中第三個數(shù)字之后的換行符,然后%d跳過其他空格(除非沒有空格)并讀取該數(shù)字。
否則,該行為將在下面的評論中進(jìn)行闡述,很大程度上是從另一個相關(guān)問題中提出的。
相關(guān)問題使用fscanf()從給定行讀取的一些正在討論的代碼是:
fscanf(f,"%*d %*d %*d%*c");
fscanf(f,"%d%d%d", &num1, &num2, &num3);
我注意到代碼應(yīng)該測試fscanf()的返回值。但是,對于三個%*d轉(zhuǎn)換規(guī)范,如果在到達(dá)指定行之前遇到了EOF,則可能會得到EOF的返回值。不幸的是,直到執(zhí)行第二個fscanf(),您才知道第一行包含字母而不是數(shù)字。您也應(yīng)該測試第二個fscanf()。您可能會得到EOF,或者0或1或2(所有這些都表示問題),或者您可能會得到3表示成功3次轉(zhuǎn)換。請注意,在格式中添加\意味著將跳過空白行,但是無論如何都會發(fā)生這種情況; %d將空格跳到第一位。
Is there any other way we can read but ignore entire lines like I clumsily did with fscanf(f,"%*d%*d%*d")?Is using %*[^\
] the nearest thing one can do for this?
跳過整行的最好方法是使用fgets(),如我答案中代碼的最新版本所示。顯然,如果這些行中的任何一個超過4095字節(jié),它就有可能誤計數(shù)行。太太,那是不可能的。
I have a confusion now and I don't want to put it in a question. So can you tell me this—fscanf() ignores whitespace automatically, so after the first line, when three integers are read and ignored according to my %*d%*d%*d specifier, I expect fscanf() to ignore the newline too when it starts reading in the next run of the loop. But why doesn't my additional %*c or \ cause problems and the program runs fine when I use %*d%*d%*d%*c or %*d%*d%*d\ in my code?
您無法確定這些格式在哪里出了問題;您可以檢測到EOF,否則,fscanf()將返回0。但是,由于%*d會跳過前導(dǎo)空格-包括換行符-您是否會在使用%*c的第三個數(shù)字之后讀取換行符并不重要是否存在,并且當(dāng)您有\(zhòng)時,這是一個空格,因此讀取將跳過換行符和任何尾隨或前導(dǎo)空格,并在到達(dá)非空格字符時停止。當(dāng)然,您也可以在三個數(shù)字中間添加換行符,或者一行中可以包含三個以上的數(shù)字。
請注意,當(dāng)用戶在終端上鍵入時,格式尾隨\尤其奇怪。用戶按下回車鍵,并繼續(xù)按下回車鍵,但是該程序直到用戶鍵入非空白字符后才繼續(xù)。這就是為什么fscanf()在數(shù)據(jù)不可靠時很難使用的原因。只要可靠,就很容易,但是如果出現(xiàn)任何問題,診斷和恢復(fù)將很痛苦。這就是為什么最好使用fgets()和sscanf()的原因;您可以控制要解析的內(nèi)容,可以根據(jù)需要使用其他格式重試,并且可以報告整行,而不僅僅是fscanf()無法解釋的內(nèi)容。
請注意,%c(和%*c)不會跳過空白。因此,格式末尾的%*c會讀取(并丟棄)讀取的數(shù)字后的字符。如果這是換行符,則表示已讀取并忽略了該字符。掃描集%[...]是另一個轉(zhuǎn)換規(guī)范,不會跳過空格。所有其他標(biāo)準(zhǔn)轉(zhuǎn)換規(guī)范都跳過前導(dǎo)空白。
很高興您加入了答案!!
讓我們在這里省略%*d部分,這與我們在使用%d%d%d無關(guān),而%*c在這里是真正的問題……就像它的存在不影響代碼的原因一樣。
是什么讓他放松了自己的答案?其中的討論有很多東西要存檔。
他獲得了兩次否決票(我都沒有),我還不清楚原因,但我可以同情刪除兩個否決票的答案。請注意,這個問題以及數(shù)十個相關(guān)問題明確說明了為什么處理scanf()和親屬的所有詳細(xì)信息如此困難。它們確實是向初學(xué)者教授的棘手功能!
@RppellsVulture我放棄了。 :)似乎我很想念這一點,就像喬納森(Jonathan)所說的那樣,我真的不在乎留下不贊成投票的答案,但不確定該如何解決。
@JonathanLeffler需要100k +聲譽的人投票否決另外100k +聲譽的人,所以既然這是關(guān)于我不屬于或不太可能屬于的俱樂部的全部,我應(yīng)該停止考慮。
@RppellsVulture嗯?我認(rèn)為沒有這樣的限制,我認(rèn)為(希望!)如果他們不同意我的回答,任何人都可以投票否決我。至少我不了解任何此類限制。
@unwind我的意思是,我在SO期間甚至還沒有投票贊成10k +的人,所以忘了100k +的人的答案。盡管我已經(jīng)看到50k +的人在指出時刪除了他們的錯誤或答案,但是同樣,它花費了50k +家伙首先發(fā)現(xiàn)他們的錯誤。
fscanf()成功時,該函數(shù)返回已成功填充的參數(shù)列表的項目數(shù)。 由于匹配失敗,讀取錯誤或文件結(jié)尾的范圍,此計數(shù)可以與預(yù)期的項目數(shù)匹配或更少(甚至為零)。
上面的段從不談?wù)撏V共黄ヅ涞那闆r,它也會嘗試使用額外的說明符,因為沒有輸入,所以它只會返回成功掃描的數(shù)字。如果格式說明的參數(shù)過多,則多余的參數(shù)將被忽略。 如果沒有足夠的參數(shù)用于格式說明,則結(jié)果不
總結(jié)
以上是生活随笔為你收集整理的每三个数换行 用C语言表示,关于换行符:使用fscanf()读取每行3个数字的文件,为什么“%d%d%d%* c”和“%d%d%d”一样好?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言第1章ppt,c语言第1章课件.p
- 下一篇: C语言函数到.h文件,求助C语言大佬 ,