繁体   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