C编程中到达EOF时如何退出stdin

How to exit stdin when EOF is reached in C programming

我的程序有问题。它的目的是读取用户输入的数字,当他们停止输入数字(ctrl-d)时,它会收集输入的数字并打印出 'Odd numbers were: blah blah' 和 'Even numbers were: blah blah'.

我遇到了如何在 EOF 退出程序的问题,当我觉得我已经解决了这个问题时,出现了另一个问题,即我的程序没有打印数组中的数字。它只打印 'Odd numbers were:' 和 'Even numbers were:'.

感谢任何帮助。 谢谢

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void) {
int n, i, array[1000];
    i=0;
    while (i = getchar() !=EOF) {
        scanf("%d", &array[i]);
        i++;
    }   
    printf("Odd numbers were:");
    i=0 ;
    while(i = getchar() != EOF) { 
        if(array[i]%2!=0) {
            printf(" %d", array[i]);
            i++;
        }
    }
    printf("\nEven numbers were:");
    i=0 ;
    while(i = getchar() !=EOF) { 
        if (array[i]%2==0) {
            printf(" %d", array[i]);
            i++;
        } 
    }
        printf("\n");
return 0;
}

将输入循环更改为:

n = 0;

while ( 1 == scanf("%d", &array[n]) )
    ++n;

你真正想做的是继续读取数字,直到读取尝试失败;这个循环条件表达了那个逻辑。忘掉 EOF。 (添加逻辑以在 n 达到 1000 时停止也是一个好主意,以避免缓冲区溢出)。

在输出循环中,您不想做任何输入,因此调用 getchar() 不是一个好主意。相反,使用 "normal" 循环,for (i = 0; i < n; ++i).

执行个位数转换为 int

您可能会让自己的事情变得比需要的更难。虽然您可以使用 while (scanf ("%d", &array[i]) == 1) 读取 以空格分隔的整数 并避免执行手动转换,但如果您打算读取个位数,则使用 getchar()很好。 (就此而言,您可以使用 getchar() 读取任何多位整数,您只需提供从 ASCII 字符到最终数值的转换即可)

单个数字字符的手动转换很简单吗?当您将数字作为字符读取时,您不是在读取由数字 表示的 整数值,而是在读取表示每个数字 [=110] 的字符的 ASCII 值=].参见 ASCII Table and Description。为了将单个 ASCII 字符数字转换为其整数值,您必须减去 '0' 的 ASCII 值。 (注意: 单引号很重要)

比如你用int c = getchar();读取一个数字,那么你需要减去'0'得到个位数的整数值,例如int n = c - '0';

填充数组时,您必须始终防止超出数组范围的写入。如果您声明 int array[1000] = {0};(它具有 0-999 的可用的从零开始的数组索引),那么您必须验证您永远不会写超出索引 999 未定义行为 结果。为了保护您的数组边界,只需跟踪填充的索引数并测试它始终低于可用的数组元素数,例如

while (n < MAX && (c = getchar()) != EOF)   /* always protect array bounds */
    if ('0' <= c && c <= '9')               /* only handle digits */
        array[n++] = c - '0';               /* convert ASCII to int */

接下来,虽然您可以自由测试 n % 2(使用 modulo 运算符),但没有必要(小端)。由于任何奇数都会将其 ones-bit 设置为 1,您所需要的只是一个简单的按位比较,例如(7 在二进制中是 0111)。

    if (array[i] & 1)                       /* if ones-bit is 1, odd */
        printf (" %d", array[i]);

当然,对于偶数,个位会是0(比如8二进制就是1000),所以对应的测试可以是:

    if ((array[i] & 1) == 0)                /* if ones-bit is 0, even */
        printf (" %d", array[i]);

将所有部分放在一起,您可以存储在 array 中读取的所有单个数字,然后将 evenodd[=110 分开=] 以非常简单的方式打印数字(注意: 不需要 stdlib.hmath.h),

#include <stdio.h>

#define MAX 1000   /* define a constant rather than use 'magic' numbers in code */

int main (void)
{
    int array[MAX] = {0},
        c, i, n = 0;

    while (n < MAX && (c = getchar()) != EOF)   /* always protect array bounds */
        if ('0' <= c && c <= '9')               /* only handle digits */
            array[n++] = c - '0';               /* convert ASCII to int */

    printf ("\narray        : ");               /* output array contents */
    for (i = 0; i < n; i++)
        printf (" %d", array[i]);

    printf ("\narray - odd  : ");
    for (i = 0; i < n; i++)
        if (array[i] & 1)                       /* if ones-bit is 1, odd */
            printf (" %d", array[i]);

    printf ("\narray - even : ");
    for (i = 0; i < n; i++)
        if ((array[i] & 1) == 0)                /* if ones-bit is 0, even */
            printf (" %d", array[i]);

    putchar ('\n');                             /* tidy up w/newline */

    return 0;
}

启​​用警告的示例编译

$ gcc -Wall -Wextra -pedantic-std=gnu11 -Ofast -o bin/arrayevenodd arrayevenodd.c

示例Use/Output

$ echo "01234567890123456789" | ./bin/arrayevenodd

array        :  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
array - odd  :  1 3 5 7 9 1 3 5 7 9
array - even :  0 2 4 6 8 0 2 4 6 8

检查一下,如果您还有其他问题,请告诉我。


执行手动多位数转换为 int

如果您需要从字符转换多位整数,简单的方法是使用为您提供转换的函数(例如 scanf 系列函数或使用面向行的 fgetsgetline 并用 strtok 解析和转换数字串,然后 strtol,或用 sscanf 解析,等等)

但是,将 getchar() 读取的单个字符手动转换为多位整数是很简单的。您只需检查一个可以开始整数的有效字符(包括 +/- 的前缀),然后对每个数字求和,通过在添加之前将总和乘以 10 来为数字的位置提供适当的偏移量(或者如果为了编码效率目的将总和构建为 negative 总和,则实际减去)每个数字,直到到达下一个非数字,然后将最终总和添加到数组并前进数组索引。

在构建总和时,您需要在将最终总和添加到数组之前检查 整数溢出。 (你可以随心所欲地处理溢出情况,下面的例子只是抛出错误并退出)

手动转换大概会增加20行左右的代码,例如

#include <stdio.h>
#include <stdint.h> /* exact length types */
#include <limits.h> /* INT_X constants */

#define MAX 1000    /* define constant rather than use 'magic' number in code */

int main (void)
{
    int array[MAX] = {0},
        c, i, start = 0, sign = 1, n = 0;
    int64_t sum = 0;

    while (n < MAX && (c = getchar()) != EOF) { /* always protect array bounds */
        if (!start) {                           /* flag to start building int  */
            start = 1;                          /* flag - working on int */
            if (c == '+')                       /* handle leading '+' sign */
                continue;
            else if (c == '-')                  /* handle leading '-' sign */
                sign = -1;
            else if ('0' <= c && c <= '9')      /* handle digits */
                sum = sum * 10 - (c - '0');     /* note: sum always computed */
            else                                /*       as negative value   */
                start = 0;                      /* reset - char not handled  */
        }
        else if ('0' <= c && c <= '9') {        /* handle digits */
            sum = sum * 10 - (c - '0');         /* convert ASCII to int */
            if (sum < INT_MIN || (sign != -1 && -sum > INT_MAX))
                goto err;               /* check for overflow, handle error */
        }
        else {                          /* non-digit ends conversion */
            if (sum)                    /* if sum has value, add to array */
                array[n++] = sign != -1 ? -sum : sum;
            sign = 1;                   /* reset values for next conversion */
            start = 0;
            sum = 0;
        }
    }
    if (sum)    /* add last element to array on EOF */
        array[n++] = sign != -1 ? -sum : sum;

    printf ("\narray        : ");               /* output array contents */
    for (i = 0; i < n; i++)
        printf (" %d", array[i]);

    printf ("\narray - odd  : ");
    for (i = 0; i < n; i++)
        if (array[i] & 1)                       /* if ones-bit is 1, odd */
            printf (" %d", array[i]);

    printf ("\narray - even : ");
    for (i = 0; i < n; i++)
        if ((array[i] & 1) == 0)                /* if ones-bit is 0, even */
            printf (" %d", array[i]);

    putchar ('\n');                             /* tidy up w/newline */

    return 0;

    err:

    fprintf (stderr, "error: overflow detected - array[%d]\n", n);
    return 1;
}

示例Use/Output

$ echo "1,2,3,5,76,435" | ./bin/arrayevenodd2

array        :  1 2 3 5 76 435
array - odd  :  1 3 5 435
array - even :  2 76

带有“+/-”前缀的示例

$ echo "1,2,-3,+5,-76,435" | ./bin/arrayevenodd2

array        :  1 2 -3 5 -76 435
array - odd  :  1 -3 5 435
array - even :  2 -76

查看新示例,如果您还有其他问题,请告诉我。