简体   繁体   English

C 程序在给出正确的输出后不会结束

[英]C Program doesn't end after giving the correct output

So I'm trying to do a program that reads a sequence of numbers separated by spaces and new lines.所以我正在尝试做一个程序来读取由空格和新行分隔的数字序列。 The output should be the same sequence, but erasing unnecessary zeros(The sequence of charachters 'EOF' ends the program).输出应该是相同的序列,但删除不必要的零(字符序列 'EOF' 结束程序)。 Per example每个例子

  1. 01492 102934 should come out as 1492 102934 01492 102934 应该是 1492 102934
  2. 9312 0 01923 should come out as 9312 0 1923 9312 0 01923 应该是 9312 0 1923
  3. 0001249 0000 should come out as 1249 0 0001249 0000 应该是 1249 0

Well I've achieved that purpose but have come across a roadblock.好吧,我已经实现了这个目的,但遇到了一个障碍。 The program doesn't exit unless I type the EOF sequence.除非我输入 EOF 序列,否则程序不会退出。 Maybe it's because I have a while(1) running that gives an infinite loop.也许是因为我有一段时间(1)在运行,导致无限循环。 But when I try to delete it the program doesn't even print at all.但是当我尝试删除它时,程序甚至根本不打印。 I'm still learning this is for a school project.我还在学习这是一个学校项目。 Any help would be apreciated!任何帮助将不胜感激!

Here's the code:这是代码:

#include <stdio.h>
int main(){
char c;
int i=0;
while(1){
    c=getchar();
    if (i==0){
        if(c=='0'){
            while (c=='0'){
            c=getchar();
            }
        }
        printf("%c",c);
        i=i+1;
    }
    else if (c==' '){
        printf("%c",c);
        c=getchar();
        if(c=='0'){
            while (c=='0'){
            c=getchar();
            }
        }
        printf("%c",c);
    }
    else if (c=='E'){
        c=getchar();
        if (c=='O'){
            c=getchar();
            if(c=='F'){
                printf("\n");
                return 0;
            }
        }
    }
    else{
        printf("%c",c);
    }
}

} }

The important stuff:重要的东西:

int c; // IMPORTANT, cannot be char
while (1) {
    c = getchar();
    if (c == EOF) break; // exit loop
    // ...
}

There has to be some way to tell the program to exit.必须有某种方式告诉程序退出。
With this, the program will exit on the letter x or two consecutive newlines or entering END .这样,程序将在字母x或两个连续的换行符处退出或输入END
getchar will return EOF when there is nothing left to read from a file.当没有任何东西可以从文件中读取时, getchar将返回EOF That can be simulated from stdin ( the keyboard) with ctrl + z on Windows or ctrl + d on Linux.这可以在 Windows 上使用ctrl + z或 Linux 上的ctrl + dstdin (键盘)模拟。

#include <stdio.h>
#include <string.h>

int main ( void) {
    char done[4] = "";
    int c = 0;
    int prior = 0;
    int reading = 0;
    int zero = 1;

    while ( EOF != ( c = getchar ( )) && 'x' != c) {
        if ( '\n' == c && '\n' == prior) {
            break;
        }
        if ( c >= '0' && c <= '9') {
            reading = 1;
            if ( '0' != c) {
                zero = 0;
            }
            if ( ! zero) {
                putchar ( c);
            }
        }
        else {
            if ( reading) {
                if ( zero) {
                    putchar ( '0');
                }
                if ( ' ' == c || '\n' == c) {
                    putchar ( c);
                }
                else {
                    putchar ( ' ');
                }
            }
            reading = 0;
            zero = 1;
        }
        prior = c;

        done[0] = done[1];
        done[1] = done[2];
        done[2] = c;
        done[3] = 0;
        if ( 0 == strcmp ( done, "END")) {
            break;
        }
    }
    putchar ( '\n');
    return 0;
}
  1. getchar() returns an int, not a char. getchar()返回一个整数,而不是一个字符。 If it only returned a char, there would be no way for it to return a value that indicates end of file, since all char values are valid and can't be used for another purpose.如果它只返回一个字符,它就没有办法返回一个指示文件结束的值,因为所有字符值都是有效的,不能用于其他目的。

    A motivating example in decimal system may be: A function checks the temperature returns a two-digit number.十进制系统中的一个激励示例可能是:检查温度的函数返回一个两位数。 Any temperature between 0 and 99 is valid. 0 到 99 之间的任何温度都是有效的。 How do you report errors when the thermometer is disconnected?温度计断线时如何报错? You have to return a number with more digits, and use a special value like UNPLUGGED = 100 .您必须返回一个具有更多位数的数字,并使用一个特殊值,例如UNPLUGGED = 100

    But int is a wider type: it has many more values than char, and the “extra” values can be used to indicate some special condition that means “hey, this is not a valid character, but something else I had to tell you”.但 int 是一种更广泛的类型:它比 char 具有更多的值,“额外”值可用于表示某些特殊情况,即“嘿,这不是一个有效字符,但我不得不告诉你的其他事情” .

  2. getchar() returns the EOF constant upon failure (any failure), for example if no more input is available. getchar()在失败(任何失败)时返回EOF常量,例如,如果没有更多输入可用。 There's nothing sensible you can do even if the reason for the failure other than end of input.即使失败的原因不是输入结束,你也无能为力。 You should end processing at the first EOF.您应该在第一个 EOF 处结束处理。

Thus, change the type of c to int, and every time you call getchar() , you must check that its value is not EOF, and return when you encounter it.因此,将c的类型更改为 int,并且每次调用getchar() ,必须检查其值是否为 EOF,并在遇到它时return

The nested structure of your loops means that EOF checking has to be repeated all over the place.循环的嵌套结构意味着必须在整个地方重复 EOF 检查。 There are other ways to structure the code to keep this check in one place, but, admittedly, the nested loops have at least the potential to exploit the branch predictor, whereas a single getchar followed by a state-machine style switch statement will make it perform potentially worse.有其他方法可以构造代码以将这个检查保存在一个地方,但是,无可否认,嵌套循环至少有利用分支预测器的潜力,而单个getchar后跟状态机样式的switch语句将使其成为可能表现可能更差。 None of this matters in a simple homework problem, but it's something to keep in mind.在一个简单的家庭作业问题中,这些都不重要,但需要牢记这一点。 In any case, performance has to be benchmarked - no other way around it.在任何情况下,都必须对性能进行基准测试——别无他法。

Try this code, I think it does what you requested:试试这个代码,我认为它符合你的要求:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int getLine(char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf("%s", prmpt);
        fflush(stdout);
    }
    if (fgets(buff, sz, stdin) == NULL)
        return -2;
    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff) - 1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? -1 : 0;
    }
    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff) - 1] = '\0';
    return 0;
}

int* convert2numbers(char* arr, int size) {
    int i;
    int j;
    int k;

    char token[100];
    int* numbers;
    int last_space = 0;
    int index = 1;
    int amount = 1;
    // Count the amount of tokens.

    for (i = 0; i < size; ++i) {
        if (arr[i] == ' ') {
            ++amount;
        }
    }
    numbers = (int *)malloc(amount * sizeof(int));
    numbers[0] = amount;

    for (j = 0; j <= size; ++j) {
        if (arr[j] == ' ' || arr[j] == '\0') {

            // Copy token from input string.
            for (k = 0; k < j; ++k) {
                token[k] = arr[k + last_space];
            }
            token[j] = '\0';
            numbers[index] = atoi(token);
            // Clear the token and continue.
            memset(token, '\0', sizeof(token));
            last_space = j;
            ++index;
        }
    }
    return numbers;
}

int main(void) {
    int i;
    int size;
    int* numbers;
    int amount;
    char input[100];
    char help[] = "Numbers> ";

    printf("Input numbers below or press enter to exit!\n");
    while (1) {
        getLine(help, input, sizeof(input));
        // If input is empty exit.
        if (input[0] == '\0') {
            break;
        }
        size = strlen(input);
        numbers = convert2numbers(input, size);
        amount = numbers[0];
        for (i = 1; i < amount + 1; ++i) {
            printf("%d ", numbers[i]);
        }
        printf("\n");
    }
    return 0;
}

When run with these inputs this code outputs:当使用这些输入运行时,此代码输出:

Input numbers below or press enter to exit!
Numbers> 01492 102934
1492 102934
Numbers> 9312 0 01923
9312 0 1923
Numbers> 0001249 0000
1249 0

Also if you press enter in console, it exits, as to escape the while(1) loop, easily.此外,如果您在控制台中按enter键,它会退出,以便轻松逃脱while(1)循环。

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

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