user-0 提问: C primer plus 第8章编程练习第八题自己做的答案过于繁琐，求指教

回复:
user: user-1
content: 拜托，我最后发给你的代码，是测试过的。输入字符串"one"时不会出现无限循环了。我也拜托你先测试一下好不好； 对于帮助你的朋友，你全盘否定是不够尊重呢，还有不敢接受别人的批评，怎么能进步呢？

user: user-1
content: 引用 6 楼 sudo987 的回复:我费了半天劲让程序能在任何输入的地方输入文件结束符，都会优雅的退出，而你的改动又让程序回到了输入文件结束符就无限循环的情况，拜托自己测试一下再回复，okay？  [quote=引用 3 楼 cfjtaishan 的回复:] #include <stdio.h> #include <stdbool.h> #include <string.h> //#include <iso646.h> #include <ctype.h> #include <math.h>  #define ZERO 0 #define ADD 'a' #define SUB 's' #define MUL 'm' #define DIV 'd'   int get_operator(void); float get_num(void); float add(float a, float b); float sub(float a, float b); float mul(float a, float b); float div(float a, float b);  int main(void) {     int oper;     float first;     float second;     while ((oper = get_operator()) != 'q') {         if (EOF == oper) {             break;         }         if (oper != ADD && oper != SUB && oper != MUL && oper != DIV) {             printf("Invalid operator, try again.\n");             getchar();    /* '\n' */             continue;         }         printf("Enter first num:");         first = get_num();         printf("Enter second num:");         second = get_num();          while ((oper == DIV) && (ZERO == second)) {             printf("Enter a num other than 0:");             second = get_num();         }             switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }             getchar();    /* '\n' */      }     printf("Bye.\n");     return 0; }   int get_operator(void) {     int c;     printf("Enter the operation of your choice:\n");     printf("%-20s%-20s\n%-20s%-20s\n%-20s\n", "a. add", "s. substract", "m. multiply", "d. divide", "q. quit");     while ((c = getchar()) != EOF) {         if (islower(c))             return c;         else             printf("Invalid input, please try again!\n");         getchar();     }     return c; }  float get_num(void) {     int c;     float num;     int item = scanf("%f", &num);     while (item != 1) {         printf(" is not a num.\n");         printf("Please enter a num, such as 2.5, -1.78E8, or 3:");         /*这句还是必须的，因为输入one时，会导致死循环*/         while ((c = getchar()) != '\n') {             putchar(c);         }         item = scanf("%f", &num);     }      return num; }  float add(float a, float b) {     return a + b; }  float sub(float a, float b) {     return a - b; }  float mul(float a, float b) {     return a * b; }  float div(float a, float b) {     return a / b; }[/quote] 拜托，你的char类型和EOF比较，你感觉是对的吗？怎么只看到“要优雅的退出”，没看到自己的程序里存在的问题呢？也摆脱把别人花费时间和精力调试的代码看完好不好，别人也不是圣人，也可能犯错误，你是不是能看到别人的错误时，也同时看到自己的问题呢？自己学不精的情况下，不要马上嘲笑别人的错误； 如果想优雅的退出，建议你使用字符串，不用float类型

user: user-0
content: 引用 4 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。  你好赵4，我的代码特点是在任何可以输入的地方键入文件结束符，程序都会优雅的退出，你说的rewind(stdin);只会让程序吃掉文件结束符，在键入文件结束符的时候不会有任何反应。

user: user-0
content: 我费了半天劲让程序能在任何输入的地方输入文件结束符，都会优雅的退出，而你的改动又让程序回到了输入文件结束符就无限循环的情况，拜托自己测试一下再回复，okay？  引用 3 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdbool.h> #include <string.h> //#include <iso646.h> #include <ctype.h> #include <math.h>  #define ZERO 0 #define ADD 'a' #define SUB 's' #define MUL 'm' #define DIV 'd'   int get_operator(void); float get_num(void); float add(float a, float b); float sub(float a, float b); float mul(float a, float b); float div(float a, float b);  int main(void) {     int oper;     float first;     float second;     while ((oper = get_operator()) != 'q') {         if (EOF == oper) {             break;         }         if (oper != ADD && oper != SUB && oper != MUL && oper != DIV) {             printf("Invalid operator, try again.\n");             getchar();    /* '\n' */             continue;         }         printf("Enter first num:");         first = get_num();         printf("Enter second num:");         second = get_num();          while ((oper == DIV) && (ZERO == second)) {             printf("Enter a num other than 0:");             second = get_num();         }             switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }             getchar();    /* '\n' */      }     printf("Bye.\n");     return 0; }   int get_operator(void) {     int c;     printf("Enter the operation of your choice:\n");     printf("%-20s%-20s\n%-20s%-20s\n%-20s\n", "a. add", "s. substract", "m. multiply", "d. divide", "q. quit");     while ((c = getchar()) != EOF) {         if (islower(c))             return c;         else             printf("Invalid input, please try again!\n");         getchar();     }     return c; }  float get_num(void) {     int c;     float num;     int item = scanf("%f", &num);     while (item != 1) {         printf(" is not a num.\n");         printf("Please enter a num, such as 2.5, -1.78E8, or 3:");         /*这句还是必须的，因为输入one时，会导致死循环*/         while ((c = getchar()) != '\n') {             putchar(c);         }         item = scanf("%f", &num);     }      return num; }  float add(float a, float b) {     return a + b; }  float sub(float a, float b) {     return a - b; }  float mul(float a, float b) {     return a * b; }  float div(float a, float b) {     return a / b; }

user: user-2
content: 在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

user: user-1
content: #include <stdio.h> #include <stdbool.h> #include <string.h> //#include <iso646.h> #include <ctype.h> #include <math.h>  #define ZERO 0 #define ADD 'a' #define SUB 's' #define MUL 'm' #define DIV 'd'   int get_operator(void); float get_num(void); float add(float a, float b); float sub(float a, float b); float mul(float a, float b); float div(float a, float b);  int main(void) {     int oper;     float first;     float second;     while ((oper = get_operator()) != 'q') {         if (EOF == oper) {             break;         }         if (oper != ADD && oper != SUB && oper != MUL && oper != DIV) {             printf("Invalid operator, try again.\n");             getchar();    /* '\n' */             continue;         }         printf("Enter first num:");         first = get_num();         printf("Enter second num:");         second = get_num();          while ((oper == DIV) && (ZERO == second)) {             printf("Enter a num other than 0:");             second = get_num();         }             switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }             getchar();    /* '\n' */      }     printf("Bye.\n");     return 0; }   int get_operator(void) {     int c;     printf("Enter the operation of your choice:\n");     printf("%-20s%-20s\n%-20s%-20s\n%-20s\n", "a. add", "s. substract", "m. multiply", "d. divide", "q. quit");     while ((c = getchar()) != EOF) {         if (islower(c))             return c;         else             printf("Invalid input, please try again!\n");         getchar();     }     return c; }  float get_num(void) {     int c;     float num;     int item = scanf("%f", &num);     while (item != 1) {         printf(" is not a num.\n");         printf("Please enter a num, such as 2.5, -1.78E8, or 3:");         /*这句还是必须的，因为输入one时，会导致死循环*/         while ((c = getchar()) != '\n') {             putchar(c);         }         item = scanf("%f", &num);     }      return num; }  float add(float a, float b) {     return a + b; }  float sub(float a, float b) {     return a - b; }  float mul(float a, float b) {     return a * b; }  float div(float a, float b) {     return a / b; }

user: user-1
content: #include <stdio.h> #include <stdbool.h> #include <string.h> //#include <iso646.h> #include <ctype.h> #include <math.h>  #define ZERO 0 #define ADD 'a' #define SUB 's' #define MUL 'm' #define DIV 'd'   int get_operator(void); float get_num(void); float add(float a, float b); float sub(float a, float b); float mul(float a, float b); float div(float a, float b);  int main(void) {     int oper;     float first;     float second;     while ((oper = get_operator()) != 'q') {         if (EOF == oper) {             break;         }         if (oper != ADD && oper != SUB && oper != MUL && oper != DIV) {             printf("Invalid operator, try again.\n");             getchar();    /* '\n' */             continue;         }         printf("Enter first num:");         first = get_num();         printf("Enter second num:");         second = get_num();          while ((oper == DIV) && (ZERO == second)) {             printf("Enter a num other than 0:");             second = get_num();         }             switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }             getchar();    /* '\n' */      }     printf("Bye.\n");     return 0; }   int get_operator(void) {     int c;     printf("Enter the operation of your choice:\n");     printf("%-20s%-20s\n%-20s%-20s\n%-20s\n", "a. add", "s. substract", "m. multiply", "d. divide", "q. quit");     while ((c = getchar()) != EOF) {         if (islower(c))             return c;         else             printf("Invalid input, please try again!\n");         getchar();     }     return c; }  float get_num(void) {     float num;     int item = scanf("%f", &num);     while (item != 1) {         printf(" is not a num.\n");         printf("Please enter a num, such as 2.5, -1.78E8, or 3:");         item = scanf("%f", &num);     }      return num; }  float add(float a, float b) {     return a + b; }  float sub(float a, float b) {     return a - b; }  float mul(float a, float b) {     return a * b; }  float div(float a, float b) {     return a / b; } 代码里太多注释对于代码的可读性起反作用，所以注释不在多在于精。

user: user-1
content: #include <stdio.h> #include <stdbool.h> #include <string.h> //#include <iso646.h> #include <ctype.h> #include <math.h>  #define ZERO 0 #define ADD 'a' #define SUB 's' #define MUL 'm' #define DIV 'd'   int get_operator(void); float get_num(void); float add(float a, float b); float sub(float a, float b); float mul(float a, float b); float div(float a, float b);  int main(void) {     //    char operator;     //char oper;   /* oper是char类型，EOF是-1是int类型*/     int oper;     float first;     float second;     while ((oper = get_operator()) != 'q') {         if (EOF == oper) {             break;         }         if (oper != ADD && oper != SUB && oper != MUL && oper != DIV) {             printf("Invalid operator, try again.\n");             getchar();             continue;         }         printf("Enter first num:");         first = get_num();         /*         // get_num()出现的结束符在这里进行处理，但是结束符根本无法处理，所以只能break，直接结束程序。         if (getchar() == EOF) break;         */         printf("Enter second num:");         second = get_num();         /*         // get_num()出现的结束符在这里进行处理，但是结束符根本无法处理，所以只能break，直接结束程序。         if (getchar() == EOF) break;         */         while ((oper == DIV) && (ZERO == second)) {             printf("Enter a num other than 0:");             second = get_num();             /*             //同样也是结束符的处理，但是在这里break只能跳出本层while，之前second作为ZERO，现在还是0，0作为除法会进行计算             // 所以在switch前加了一层逻辑判断,如果second等于0且oper是DIV（相当于在"Enter a num other than 0:"处键入文件结束符）再次跳出最外层循环。             if (getchar() == EOF) break;             */             if (ZERO != second) {                 break;             }         }         /*         // 注意，用的是非逻辑操作符         if (!(ZERO == second && oper == DIV)) {              switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }         } else {             break;         }         */             switch (oper) {                 case ADD:                     printf("%.2f + %.2f = %.2f\n", first, second, add(first, second));                     break;                 case SUB:                     printf("%.2f - %.2f = %.2f\n", first, second, sub(first, second));                     break;                 case MUL:                     printf("%.2f * %.2f = %.2f\n", first, second, mul(first, second));                     break;                 case DIV:                     printf("%.2f / %.2f = %.2f\n", first, second, div(first, second));                     break;             }             getchar();      }     printf("Bye.\n");     return 0; }   //char get_operator(void) int get_operator(void) {     //char c;     int c;     printf("Enter the operation of your choice:\n");     printf("%-20s%-20s\n%-20s%-20s\n%-20s\n", "a. add", "s. substract", "m. multiply", "d. divide", "q. quit");     while ((c = getchar()) != EOF) {         if (islower(c))             return c;         else             printf("Invalid input, please try again!\n");         getchar();         /*         if (isspace(c)) {             continue;         }         while (getchar() != '\n') {             continue;         }         return c;         */     }     //return EOF;     return c; }  float get_num(void) {     float num;     //char c;     int item = scanf("%f", &num);     while (item != 1) {         /*         // 因为程序本身返回数字类型，所以不可以让他返回EOF,容易混淆，所以只能让文件结束符继续向上走，走到主调函数中。         if (EOF == item) {             break;         }         while ((c = getchar()) != '\n') {             putchar(c);         }         */         printf(" is not a num.\n");         printf("Please enter a num, such as 2.5, -1.78E8, or 3:");         item = scanf("%f", &num);     }     /*     if (1 == item) {         return num;     }     */      return num; }  float add(float a, float b) {     return a + b; }  float sub(float a, float b) {     return a - b; }  float mul(float a, float b) {     return a * b; }  float div(float a, float b) {     return a / b; } 有些代码是冗余，但是有些判断是不对的； 冗余的代码已经注释掉，不对的代码是EOF是int类型的，char类型表示不了EOF;

user: user-2
content: 不要企图优雅的结束（因为这是不可能办到的） 而要在烂的不能再烂的摊子上也能重整河山！  http://bbs.csdn.net/topics/390787357  按Ctrl+Break或cmd窗口右上角的×或在任务管理器中结束cmd.exe进程。

user: user-1
content: 引用 10 楼 sudo987 的回复:[quote=引用 9 楼 cfjtaishan 的回复:] 拜托，我最后发给你的代码，是测试过的。输入字符串"one"时不会出现无限循环了。我也拜托你先测试一下好不好； 对于帮助你的朋友，你全盘否定是不够尊重呢，还有不敢接受别人的批评，怎么能进步呢？  我先为我的态度道歉，我说话太冲，不管什么原因你愿意花时间看一遍我的代码已经很让人尊敬了。让我们讨论一下代码本身吧，EOF的值是-1，char的取值范围是-128~127，一个char是可以接受EOF的；再者，getchar()和scanf()遇到文件结尾的时候都会返回EOF，我不是专业程序员，但是我觉得从完成目标的角度看getchar()或者char和EOF做比较是可以行得通的，你说的这里的问题是指这里面的哪一个部分？；另一个地方，get_operator()函数，我的本意就是只接受首字母，比如输入abc，不算这样是错的，我只是要他的首字符；如果输入空白字符，我的写法是不做判断，即不输出错误，等待下一个有效的输入。[/quote] 但是EOF是(0xffffffff)，不能简单理解成-1,虽然0xffffffff是int类型的-1, 但是不是简单的-1；通过getchar的原型可知，它的返回值是int类型；

user: user-0
content: 引用 9 楼 cfjtaishan 的回复:拜托，我最后发给你的代码，是测试过的。输入字符串"one"时不会出现无限循环了。我也拜托你先测试一下好不好； 对于帮助你的朋友，你全盘否定是不够尊重呢，还有不敢接受别人的批评，怎么能进步呢？  我先为我的态度道歉，我说话太冲，不管什么原因你愿意花时间看一遍我的代码已经很让人尊敬了。让我们讨论一下代码本身吧，EOF的值是-1，char的取值范围是-128~127，一个char是可以接受EOF的；再者，getchar()和scanf()遇到文件结尾的时候都会返回EOF，我不是专业程序员，但是我觉得从完成目标的角度看getchar()或者char和EOF做比较是可以行得通的，你说的这里的问题是指这里面的哪一个部分？；另一个地方，get_operator()函数，我的本意就是只接受首字母，比如输入abc，不算这样是错的，我只是要他的首字符；如果输入空白字符，我的写法是不做判断，即不输出错误，等待下一个有效的输入。