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

时间:2017-05-04 01:25:43

标签: c arrays stdin eof getchar

我的节目遇到了麻烦。它的目的是从用户读取数字输入,当他们停止输入数字(ctrl-d)时,它收集输入的数字并打印出'奇数是:blah blah' 并且'连数都是:等等等等。

我遇到了如何在EOF退出程序的问题,当我觉得我已经克服了这个问题时,又出现了另一个问题,那就是我的程序没有打印数组中的数字。它只打印'奇数是:'和'偶数是:'。

感谢任何帮助。 感谢

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

2 个答案:

答案 0 :(得分:0)

将输入循环更改为:

n = 0;

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

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

在输出循环中,您不想进行任何输入,因此调用getchar()不是一个好主意。相反,请使用“正常”循环for (i = 0; i < n; ++i)

答案 1 :(得分:0)

执行单数字转换 int

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

单位数字符的手动转换是直截了当的吗?当您将数字读取为字符时,您没有读取由数字表示的整数值,您正在读取代表每个数字的字符的 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,因此您只需进行简单的按位比较,例如(二进制70111)。

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

当然,对于偶数,1位将为0(例如二进制中的81000),因此相应的测试可以是:

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

将所有部分组合在一起,您可以存储在array中读取的所有单个数字,然后将偶数奇数数字分开,以便打印出来简单的方式(注意:既不需要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

示例使用/输出

$ 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函数族或使用{{1 }或fgets并使用getline然后strtok解析和转换数字字符串,或使用strtol解析等。)

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

在构建总和时,您可以在将最终总和添加到数组之前检查整数溢出。 (您可以根据需要处理溢出条件,下面的示例只会抛出错误并退出)

手动转换可能会增加大约20行代码,例如

10

示例使用/输出

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

示例&#39; + / - &#39;前缀

$ 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

查看新示例,如果您有任何其他问题,请与我们联系。