[英]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.