简体   繁体   English

C程序的奇怪输出随重定向而改变

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

I write a program to solve Exercise 2-2 of K&R. 我编写了一个程序来解决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;
}

This program is wrong...in a weird way. 该程序是错误的……很奇怪。 I run this code with redirection like 我像重定向那样运行此代码

./2-2 <in

with the in file in文件

Get this line. 得到这条线。

Then the output to the screen is countless 然后输出到屏幕上的无数

G length: 1 G长:1

It looks like the program stuck in a loop. 程序似乎陷入了循环。 But when I stop using redirection and just type Get this line. 但是当我停止使用重定向时,只需键入Get this line。 to the terminal, though it is still wrong, the countless output disappeared. 到终端,尽管仍然错误,但无数的输出消失了。 Why? 为什么?

The problem is here: 问题在这里:

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

Instead of incrementing in a for-loop, only increment after inserting a new element. 代替在for循环中递增,仅在插入新元素后递增。 Like 喜欢

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

Instead of a for-loop, you could use a while loop, like: 可以使用while循环代替for循环,例如:

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

The next step is to get rid of the flag and use break insted. 下一步是摆脱标记并使用break insted。 Like: 喜欢:

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

    ...
}

Your code will be much shorter and easier to read. 您的代码将更短并且更易于阅读。

You have also complicated your function quite a bit. 您还使功能复杂了很多。 If you simply want to get the line redirected from the file, store it in line and insure it is nul-terminated (and without the trailing '\\n' - which you shouldn't leave dangling off strings you store), you could do something quite simple like: 如果您只是想从文件中重定向该行,将其存储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 */
}

( note: from your comment about not having used break before, then a simple goto works just as well) 注意:从您关于以前没有使用过break评论来看,简单的goto效果也一样)

Example Use/Output 使用/输出示例

Given your file containing the line "Get this line." 给定您的文件包含"Get this line."

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

(note: if you store the newline, then the length would be 15 and that output would be on the next line) (注意:如果存储换行符,则长度将为15,并且输出将在下一行上)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM