簡體   English   中英

無限循環fscanf字符串textfile c編程

[英]infinite loop fscanf string textfile c programming

為什么當我掃描文本文件中的字符串時,它總是陷入無限循環?

while(val = fscanf(stdin,"%lf%c",d,c) != EOF)
{if(val==0){//error}
else if(c='\n'){//error print char}
else{//print double}
}

文本文件:

4.5
r5
23
s

我想要的是打印所有內容,但是當我到達字符串時,它總是給我一個無限循環。

scanf()系列函數是一種折磨測試,對新手程序員不應進行。 准確地使用它們非常困難。

分析

甚至忽略代碼布局(完全令人震驚-這是一種專業的評估),並假設您具有以下變量聲明:

double  value;
double *d = &value;
char    newline;
char   *c = &newline;
int     val;

而不是更合理:

double d;
char   c;
int    val;

您的片段中充滿了數不勝數的問題。

while(val = fscanf(stdin,"%lf%c",d,c) != EOF)
{if(val==0){//error}
else if(c='\n'){//error print char}
else{//print double}
}

您已將比較結果分配給val ,而不是將fscanf()的返回值分配給val並將其與EOF進行比較。

while ((val = fscanf(stdin, "%lf%c", d, c)) != EOF)

現在代碼只是錯誤的; fscanf()可以返回EOF(通常是,但不保證, -1 ),或0 ,或12 ,而其中只有2就是你要找的答案。 因此,循環條件應為:

while ((val = fscanf(stdin, "%lf%c", d, c)) == 2)

或者,如果您有更簡單的定義,則應為:

while ((val = fscanf(stdin, "%lf%c", &d, &c)) == 2)

現在您知道讀取了兩個值。 現在,循環內的if (val == 0)檢查是多余的; 僅當val == 2時才輸入循環體。

您可以檢查*c的值是否是進行比較而不是賦值的換行符:

    if (*c == '\n')

(或if (c == '\\n') ;讓我們假設您使用了簡單的聲明,而忘記了原始代碼中的&字符。)但是,如果c不是換行符,則會出現錯誤,因此實際上它應該是一個!=測試。

while ((val = fscanf(stdin, "%lf%c", &d, &c)) == 2)
{
    if (c != '\n')
        ...print error...
    else
        printf("Number = %g\n", d);
}

循環之后,您可以測試val == EOF vs val == 0 vs val == 1 第一個表示您已達到EOF或發生了錯誤; 第二個字母表示輸入的下一個字符既不是空格也不是有效數字的一部分(例如, .+-以外的字母或標點符號)。 val == 1情況深奧; 它要求文件的末尾出現在后面沒有換行符(或其他任何字符)的數字之后。

無限循環

順便說一句,最有可能導致無限循環的原因是輸入中的字符無效(非數字,非空格)。 而且,仔細檢查后,我發現第二行輸入中有一個r 這將觸發代碼無限循環。 fscanf()始終返回0,而不是EOF,因此循環繼續。 (它無法用%c讀取r ,因為它必須先成功讀取一個數字。)

合成

%lf格式將跳過任何前導空格,包括換行符,因此您的代碼試圖確保每行有一個數字,且沒有尾隨空格。 在這種情況下,使用fgets()strtod()可能會做得更好,盡管完全正確地使用strtod()並非完全無關緊要。 以下代碼忽略了strtod()優點。

char line[4096];
double d;

while (fgets(line, sizeof(line), stdin) != 0)
{
    char *end;
    d = strtod(line, &end);
    if (end == line || *end != '\n')
        ...incorrect format...
    else
        printf("Number = %g\n", d);
}

fgets()返回空指針的唯一原因是您已達到EOF或發生了錯誤。 您可能要設置errno = 0; 在調用strtod()之前,然后檢查其值以發現超出范圍的數字。

代碼進入無限循環,因為fscanf(stdin,"%lf%c",d,c)試圖讀取一個數字並找到一個字母: r5r 如果無法掃描任何內容,它將返回0 0 != EOF為true,並且true分配給val 並且while (val)重復。 問題是r未被任何東西消耗,因此下一個`fscanf()會重復重復嘗試,結果相同。

推薦

if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
  result = sscanf(buffer, "%lf %c", &d, &c);
  if (result != 1) ; //handle error
}

一個問題是您不應嘗試掃描換行符。 另一個問題是,不等於運算符!=具有更高的 優先級比分配,這意味着val是比較的結果。 第三個錯誤是您沒有提供將值讀入的指針(導致未定義的行為)。

我建議這樣改變:

while (scanf("%lf", &d) == 1)
{
    printf("You have read %f\n", d);
}

只要輸入是浮點,上述循環就會循環。

暫無
暫無

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

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