簡體   English   中英

C程序的奇怪輸出隨重定向而改變

[英]Weird output of a C program change with redirection

我編寫了一個程序來解決K&R的練習2-2。

#include<stdio.h>

#define MAXLINE 1000

/* write an equivalent loop without using && or || */
int Getline(char s[], int lim);

int main()
{
    int len;
    char line[MAXLINE];

    while ((len = Getline(line, MAXLINE)) > 0) {
        printf("%s%15s%d\n", line, "length: ", len);
    }

    return 0;
}

int Getline(char s[], int lim)
{
    int flag = 1;
    int i = 0, c = 0;

    for (i = 0; flag == 1; ++i) {
        if (i < lim - 1) {
            if ((c = getchar()) != '\n') {
                if (c != EOF) {
                    ;
                }
                else {
                    flag = 0;
                }
            }
            else {
                flag = 0;
            }
        }
        else {
            flag = 0;
        }
        if (flag == 1) {
            s[i] = c;
        }
    }

    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

該程序是錯誤的……很奇怪。 我像重定向那樣運行此代碼

./2-2 <in

in文件

得到這條線。

然后輸出到屏幕上的無數

G長:1

程序似乎陷入了循環。 但是當我停止使用重定向時,只需鍵入Get this line。 到終端,盡管仍然錯誤,但無數的輸出消失了。 為什么?

問題在這里:

for (i = 0; flag == 1; ++i) {
                       ^^^
                       i will always increment to at least 1
                       before the for-loop ends
                       so your function will never return 0

代替在for循環中遞增,僅在插入新元素后遞增。 喜歡

    if (flag == 1) {
        s[i] = c;
        ++i;
    }

可以使用while循環代替for循環,例如:

int i = 0;
while (flag == 1)
{
    ...
}

下一步是擺脫標記並使用break insted。 喜歡:

int i = 0;
while (1)
{
    if (i >= lim - 1) break;

    ...
}

您的代碼將更短並且更易於閱讀。

您還使功能復雜了很多。 如果您只是想從文件中重定向該行,將其存儲line並確保它是nul終止的 (並且沒有尾隨的'\\n' n'-您不應該讓懸掛的字符串脫離存儲的字符串),您可以這樣做很簡單的東西:

int Getline (char *s, int lim)
{
    int i = 0;              /* char count - length */
    while (i < lim - 1) {   /* loop while chars fit */
        int c = getchar();  /* getchar */
        if (c == EOF)       /* validate EOF? */
            goto done;
        if (c == '\n')      /* validate newline */
            continue;
        s[i++] = c;         /* good char, increment len */
    }
    done:;
    s[i] = 0;               /* nul-terminate */
    return i;               /* return length */
}

注意:從您關於以前沒有使用過break評論來看,簡單的goto效果也一樣)

使用/輸出示例

給定您的文件包含"Get this line."

$ ./bin/equivloop <dat/in
Get this line.       length: 14

(注意:如果存儲換行符,則長度將為15,並且輸出將在下一行上)

暫無
暫無

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

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