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
中读取的所有单个数字,然后将 even 和 odd[=110 分开=] 以非常简单的方式打印数字(注意: 不需要 stdlib.h
或 math.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
系列函数或使用面向行的 fgets
或 getline
并用 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
查看新示例,如果您还有其他问题,请告诉我。
我的程序有问题。它的目的是读取用户输入的数字,当他们停止输入数字(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
中读取的所有单个数字,然后将 even 和 odd[=110 分开=] 以非常简单的方式打印数字(注意: 不需要 stdlib.h
或 math.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
系列函数或使用面向行的 fgets
或 getline
并用 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
查看新示例,如果您还有其他问题,请告诉我。