繁体   English   中英

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

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

所以我正在尝试做一个程序来读取由空格和新行分隔的数字序列。 输出应该是相同的序列,但删除不必要的零(字符序列 'EOF' 结束程序)。 每个例子

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

好吧,我已经实现了这个目的,但遇到了一个障碍。 除非我输入 EOF 序列,否则程序不会退出。 也许是因为我有一段时间(1)在运行,导致无限循环。 但是当我尝试删除它时,程序甚至根本不打印。 我还在学习这是一个学校项目。 任何帮助将不胜感激!

这是代码:

#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);
    }
}

}

重要的东西:

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

必须有某种方式告诉程序退出。
这样,程序将在字母x或两个连续的换行符处退出或输入END
当没有任何东西可以从文件中读取时, getchar将返回EOF 这可以在 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()返回一个整数,而不是一个字符。 如果它只返回一个字符,它就没有办法返回一个指示文件结束的值,因为所有字符值都是有效的,不能用于其他目的。

    十进制系统中的一个激励示例可能是:检查温度的函数返回一个两位数。 0 到 99 之间的任何温度都是有效的。 温度计断线时如何报错? 您必须返回一个具有更多位数的数字,并使用一个特殊值,例如UNPLUGGED = 100

    但 int 是一种更广泛的类型:它比 char 具有更多的值,“额外”值可用于表示某些特殊情况,即“嘿,这不是一个有效字符,但我不得不告诉你的其他事情” .

  2. getchar()在失败(任何失败)时返回EOF常量,例如,如果没有更多输入可用。 即使失败的原因不是输入结束,你也无能为力。 您应该在第一个 EOF 处结束处理。

因此,将c的类型更改为 int,并且每次调用getchar() ,必须检查其值是否为 EOF,并在遇到它时return

循环的嵌套结构意味着必须在整个地方重复 EOF 检查。 有其他方法可以构造代码以将这个检查保存在一个地方,但是,无可否认,嵌套循环至少有利用分支预测器的潜力,而单个getchar后跟状态机样式的switch语句将使其成为可能表现可能更差。 在一个简单的家庭作业问题中,这些都不重要,但需要牢记这一点。 在任何情况下,都必须对性能进行基准测试——别无他法。

试试这个代码,我认为它符合你的要求:

#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;
}

当使用这些输入运行时,此代码输出:

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

此外,如果您在控制台中按enter键,它会退出,以便轻松逃脱while(1)循环。

暂无
暂无

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

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