[英]C Program doesn't end after giving the correct output
所以我正在尝试做一个程序来读取由空格和新行分隔的数字序列。 输出应该是相同的序列,但删除不必要的零(字符序列 'EOF' 结束程序)。 每个例子
好吧,我已经实现了这个目的,但遇到了一个障碍。 除非我输入 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 + d
从stdin
(键盘)模拟。
#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;
}
getchar()
返回一个整数,而不是一个字符。 如果它只返回一个字符,它就没有办法返回一个指示文件结束的值,因为所有字符值都是有效的,不能用于其他目的。
十进制系统中的一个激励示例可能是:检查温度的函数返回一个两位数。 0 到 99 之间的任何温度都是有效的。 温度计断线时如何报错? 您必须返回一个具有更多位数的数字,并使用一个特殊值,例如UNPLUGGED = 100
。
但 int 是一种更广泛的类型:它比 char 具有更多的值,“额外”值可用于表示某些特殊情况,即“嘿,这不是一个有效字符,但我不得不告诉你的其他事情” .
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.