C语言day9 输入输出


我很震惊第八章还要学习输入输出,因为前面几章一上来就在讲输入输出,而且每一个程序都要用到输入输出,所以我以为输入输出就告一段落了·····
是我想太多
这一章是专门讲输入输出,涉及一些更深层次的概念,比如有无缓冲的输入,重定向的具体含义,文件,有些知识点从来没有听说过,有些却虽然听说过还小小接触过但是仍然不明内里,所以还是静下心来探索一番,有些知识或者视角真的很振奋人心,比如键盘输入和屏幕显示实际上都是文件(对于程序而言是这样)

之前接触过的执行I/O任务的函数有4个:printf(),scanf(),putchar(),getchar(),但是我刚知道,后两个实际上并不是函数,而是宏!!!用于预处理器使用的!!!!他俩在用法上很像函数,一直不懂宏是什么,很激动,thrilled

ANSI C定义了标准(不同系统通用)的I/O函数

在这里插入图片描述

输入验证(用户交互更友好)

以前没把输入验证当回事,写程序遇到过一次要求验证输入的,觉得有点用,但是还没养成习惯
在这里插入图片描述

单字符I/O getchar() putchar() (宏)

在这里插入图片描述

这两个宏和stdio.h关联的

有缓冲输入(C语言标准) VS 无缓冲输入

之前完全不知道输入还有缓冲的概念,不过还比较好理解,也挺有意思,很好奇无缓冲输入的用武之地(一些实时的交互式程序)到底是怎么样使用
在这里插入图片描述
总之buffer是一段内存区域,键盘输入的字符先放在那里,而不是直接发给程序使用,像是一个中间站,键盘输入和程序的中间站,等buffer满了再一次性发给程序,两个好处:

  • 减少发送次数,节约时间,提高效率
  • 如果写错了字符,可以删除重写,那么重写的是buffer的内容,buffer内容是正确的才发送给程序,降低了错误率

在这里插入图片描述
ANSI C没有提供无缓冲输入的标准方式

完全缓冲I/O VS 行缓冲I/O

在这里插入图片描述
在这里插入图片描述

突然觉得,word好像用的就是和缓冲区类似的机制实现保存内容的。用户对文件进行编辑和修改,这些输入先存在缓冲区,只有CTRL+S保存或者缓冲区满或者word自动保存的计时到了时,才刷新缓冲区,即把新编辑和新的修改存储到文件上,文件在硬盘中。这样可以减少和硬盘的交互次数。

好多概念实际上本质上都是一段内存区域

最近的学习中发现好多概念实际上本质上都是一段内存区域,比如变量实际上代表的就是内存,变量只是提供了一种用符号表示内存的方式;文件也是内存,这个我还挺震惊了,毕竟一说文件,想到的就是纸质的····(我好low),很难联想到他实际是内存区域,不管是什么后缀的,存了什么内容,本质上在计算机里都是占用了一段内存,我们看的时候用屏幕和友好的界面显示出来了而已,实际上他们只是磁盘里的一段内存;

怎么结束键盘和文件的输入 & 流

之前几章的编程示例都是用一个特殊字符标志着输入的结束,常常使用#或者q,通过while语句

while((ch=getchar())!='#')

这是一种结束键盘输入的方式,但是这样子井号这个字符就不能出现在我的输入字符中了,显然不是一个通用的好办法

一般程序有两种输入数据的来源:键盘输入和文件输入。但是这两种情况,实际上又是同一种情况,因为C程序实际上处理的是流·······不管你是键盘来的字符流,还是问价来的字符流,程序并不关心,C程序只是把他们当做流做统一处理就好了。有两个流:stdin流(键盘输入),stdout流(屏幕输出)

键盘输入

C程序其实把键盘输入和屏幕输出也是当做文件的。所以只需要研究文件如何结束输入就好了。

文件输入

在这里插入图片描述

文件就是内存。文件就是内存。文件是内存。

现在知道为啥本科学Linux时候文件系统要讲那么久了,但是当时还是觉得很难听懂,大概就是没有理解这个关键概念:文件实际上是内存。

关于文件的操作就四个:打开,读取,写入,关闭

在这里插入图片描述

这段话只能理解60%,灵活性是说实现方法多种多样,办法多的意思;直接调用操作系统软件的函数是比较底层的I/O,而不和操作系统打交道的,就是较高层面的,
但我不懂为什么标准I/O函数包可以屏蔽掉OS,不需要和OS互动,那么他和OS之间的转换和沟通是不是还需要谁来完成呢?
我也不明白C如何处理不同系统的差异以让用户享受一致统一的UI?
希望以后能渐渐明白

在这里插入图片描述
好像是I/O函数在处理,即使我输入的只是换行符,I/O函数会自动给我转换为回车符加换行符的组合,以使得OS知道我到底想做啥。平时编程很难想到底层的有关OS的东西诶,基本都只管自己的程序的输入输出对不对,想都没想全都是OS在做事。

那么不同OS都有哪些差异呢?举个栗子?
都是一些很具体的处理方式,OS的任务是一样的,但是不同OS的办法不太一样而已
在这里插入图片描述在这里插入图片描述

键盘输入和屏幕输出都是文件,但C程序处理的是流而不是文件

在这里插入图片描述

如何标志文件的结束?

用特殊字符标记 (CRTL+Z ,EOF)

像之前我们编程用#一样一样的,但是CRTL+Z是在文本中绝不会使用的字符,EOF是一个值,文本中只会用字符,不会用到值,所以这两种方法都不会遇到我们之前担心的那种问题:文本中要用这个特殊字符咋整?
在这里插入图片描述
上图可以清晰说明文件是内存区域存储的信息。

在这里插入图片描述在这里插入图片描述

#include <stdio.h>
int main(void)
{
    int ch;
    while((ch=getchar())!=EOF)
        putchar(ch);
    return 0;
}

在这里插入图片描述

qwehhinn
qwehhinn
EOF
EOF
-1
-1
^Z

实际上使用CTRL+Z产生EOF仍然是操作系统大哥在帮助我们,看来我们这些在APP层写程序的仔还是要更加深入的了解操作系统大哥到底为我们做了多少默默无闻的事情啊
在这里插入图片描述

重定向

重定向实际上还是说的输入输出流,和输入流,输出流两个关键概念联系密切。流就是程序查找输入和输出的位置,把stdin流和stdout流赋给文件则用文件输入或输出,赋给标准输入输出则用键盘屏幕。

Unix,Linux,Windows系统都支持重定向,没有重定向的系统还会用C去模仿重定向。
在这里插入图片描述

重定向运算符 < >

在这里插入图片描述
C语言把文件和IO设备当在一个层次哦!!!
在这里插入图片描述在这里插入图片描述

重定向示例 Windows 命令行

程序源代码

#include <stdio.h>
int main(void)
{
    int ch;
    while((ch=getchar())!=EOF)
        putchar(ch);
    return 0;
}

编译生成exe文件后,从命令行进入exe文件的路径,新建了一个txt文件,写了一些字符作为程序的文件输入,然后在命令行使用组合

C:\Users\wulimmya>cd C:\Users\wulimmya\Documents\MyCCode\MyC

C:\Users\wulimmya\Documents\MyCCode\MyC>bin
'bin' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

C:\Users\wulimmya\Documents\MyCCode\MyC>cd bin

C:\Users\wulimmya\Documents\MyCCode\MyC\bin>cd Debug

C:\Users\wulimmya\Documents\MyCCode\MyC\bin\Debug>MyC < input > output
系统找不到指定的文件。

C:\Users\wulimmya\Documents\MyCCode\MyC\bin\Debug>MyC < input.txt > output

C:\Users\wulimmya\Documents\MyCCode\MyC\bin\Debug>

新建的文件没有后缀,用记事本打开看到了正确输出
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

更友好的用户界面设计(交互式程序)

示例 猜数字(本例的算法很烂)

#include <stdio.h>
int main(void)
{
    int num, guess=1;
    char ch;
    printf("Enter an integer from 1 to 100. I will try to guess.\n"
           "Respond with a y if my guess is right and a n if I'm wrong.\n");
    scanf("%d", &num);
    printf("Is your number %d?\n", guess);
    while((ch=getchar())!='y')
    {
        if(ch=='\n')
            continue;//如果不加这句,则换行符字符也会让程序输出一句猜测,结果就是每输入一个字符会导致两次猜测
        printf("Is your number %d?\n", ++guess);
    }
    printf("I know I can do it!\n");
    return 0;
}
Enter an integer from 1 to 100. I will try to guess.
Respond with a y if my guess is right and a n if I'm wrong.
5
Is your number 1?
n
Is your number 2?
n
Is your number 3?
n
Is your number 4?
n
Is your number 5?
y
I know I can do it!

但是如果回应时多敲一个字符就不行了,多敲几个就会得到多几个猜测,明显这种跳过换行符的做法是不太好的,下面我们跳过所有字符,只根据换行符来执行猜测就好了

Enter an integer from 1 to 100. I will try to guess.
Respond with a y if my guess is right and a n if I'm wrong.
4
Is your number 1?
no
Is your number 2?
Is your number 3?
no sir
Is your number 4?
Is your number 5?
Is your number 6?
Is your number 7?
Is your number 8?
Is your number 9?

也可以写为下面这样,上面是跳过换行符,实际上上面的方法是不合乎原理的,因为输入换行符就是为了告诉程序我输入结束了,该程序采取动作了,所以更好地方法是跳过非换行符

#include <stdio.h>
int main(void)
{
    int num, guess=0;
    char ch;
    printf("Enter an integer from 1 to 100. I will try to guess.\n"
           "Respond with a y if my guess is right and a n if I'm wrong.\n");
    scanf("%d", &num);

    while((ch=getchar())!='y')
    {
        if(ch!='\n')
            continue;
        printf("Is your number %d?\n", ++guess);
    }
    printf("I know I can do it!\n");
    return 0;
}
Enter an integer from 1 to 100. I will try to guess.
Respond with a y if my guess is right and a n if I'm wrong.
5
Is your number 1?
n
Is your number 2?
n
Is your number 3?
n
Is your number 4?
n
Is your number 5?
y
I know I can do it!

看,已经克服了刚才的问题,新问题来了,由于只用了字符y和输入的第一个!!(getchar只考虑第一个字符)字符作对比,如果交互者灵活应答,程序就出错了,因为程序把首字母y当做对,其他不管什么字母都是错,所以在改进一下

Enter an integer from 1 to 100. I will try to guess.
Respond with a y if my guess is right and a n if I'm wrong.
5
Is your number 1?
n
Is your number 2?
no
Is your number 3?
no no no
Is your number 4?
oh no
Is your number 5?
it is!
Is your number 6?

原来我上面写错了一点,就是不需要用户输入数字

#include <stdio.h>
int main(void)
{
    int num, guess=1;
    char ch;
    printf("Pick an integer from 1 to 100. I will try to guess.\n"
           "Respond with a y if my guess is right and a n if I'm wrong.\n");
    printf("Is your number %d?\n", guess);
    while((ch=getchar())!='y')
    {

        if(ch=='n')
            printf("Is your number %d?\n", ++guess);
        else
            printf("I only understand y and n.\n");
        while(getchar()!='\n')
            continue;

    }
    printf("I know I can do it!\n");
    return 0;
}
Pick an integer from 1 to 100. I will try to guess.
Respond with a y if my guess is right and a n if I'm wrong.
Is your number 1?
no
Is your number 2?
no
Is your number 3?
no sir
Is your number 4?
sir no
I only understand y and n.
n
Is your number 5?
it is
I only understand y and n.
yes
I know I can do it!

混合字符和数字输入

在这里插入图片描述

示例

/*输入一个字符c和两个整数(m,n),显示出m行n列这个字符*/
#include <stdio.h>
void display(char, int, int);
int main()
{
    int ch;
    int row, col;
    printf("Enter a character and two integers.\n");
    while((ch=getchar())!='\n')
    {
        scanf("%d %d", &row, &col);
        display(ch, row, col);
        printf("Enter another character and two integers.\n");
        printf("Enter a newline to quit.\n");
    }
    printf("Bye!\n");
    return 0;
}

void display(char ch, int row, int col)
{
    for(int i=1;i<=row;i++)
    {
        for(int j=1;j<=col;j++)
            putchar(ch);
        putchar('\n');
    }
}
Enter a character and two integers.
c 2 3
ccc
ccc
Enter another character and two integers.
Enter a newline to quit.
Bye!

在这里插入图片描述

我是想不出来办法解决了,整个脑袋晕晕的,什么也没法思考,只想叹气,全是疲惫和皱眉,

在这里插入图片描述

修改上面换行符的问题

/*输入一个字符c和两个整数(m,n),显示出m行n列这个字符*/
#include <stdio.h>
void display(char, int, int);
int main()
{
    int ch;
    int row, col;
    printf("Enter a character and two integers.\n");
    while((ch=getchar())!='\n')
    {
        scanf("%d %d", &row, &col);
        display(ch, row, col);
        while(getchar()!='\n')
            continue;
        printf("Enter another character and two integers.\n");
        printf("Enter a newline to quit.\n");
    }
    printf("Bye!\n");
    return 0;
}

void display(char ch, int row, int col)
{
    for(int i=1;i<=row;i++)
    {
        for(int j=1;j<=col;j++)
            putchar(ch);
        putchar('\n');
    }
}
Enter a character and two integers.
q 2 3
qqq
qqq
Enter another character and two integers.
Enter a newline to quit.
s 2 4 5
ssss
ssss
Enter another character and two integers.
Enter a newline to quit.

Bye!

但是如果不小心输入了浮点数,即输入错误
如果输入不到2个整数,scanf会继续等你输入
如果一开始输入了一个浮点数和一个整数,程序不会打印
但是如果开始是对的,程序就会打印之那两个整数

Enter a character and two integers.
q 1

2
qq
Enter another character and two integers.
Enter a newline to quit.
e 2.1 3
ee
ee
Enter another character and two integers.
Enter a newline to quit.
q 1.2 2
qq
Enter another character and two integers.
Enter a newline to quit.
Enter a character and two integers.
w 1.2 2

Enter another character and two integers.
Enter a newline to quit.
a 4 5
aaaaa
aaaaa
aaaaa
aaaaa
Enter another character and two integers.
Enter a newline to quit.
Enter a character and two integers.
q 2 3
qqq
qqq
Enter another character and two integers.
Enter a newline to quit.
w 2.3 4
www
www
Enter another character and two integers.
Enter a newline to quit.

继续改进,在这里插入图片描述

/*输入一个字符c和两个整数(m,n),显示出m行n列这个字符*/
#include <stdio.h>
void display(char, int, int);
int main()
{
    int ch;
    int row, col;
    printf("Enter a character and two integers.\n");
    while((ch=getchar())!='\n')
    {
        if(scanf("%d %d", &row, &col)!=2)
            break;
        display(ch, row, col);
        while(getchar()!='\n')
            continue;
        printf("Enter another character and two integers.\n");
        printf("Enter a newline to quit.\n");
    }
    printf("Bye!\n");
    return 0;
}

void display(char ch, int row, int col)
{
    for(int i=1;i<=row;i++)
    {
        for(int j=1;j<=col;j++)
            putchar(ch);
        putchar('\n');
    }
}
Enter a character and two integers.
Q 3 2
QQ
QQ
QQ
Enter another character and two integers.
Enter a newline to quit.
E 3.1 2
Bye!

输入验证

x是long类型,输入3.4,scanf("%ld", &x)==1的值竟然是是true!!!

所以 while(scanf("%ld", &x)!=1)是拦不住浮点数输入的,只能挡住字符输入,即当你输入字符能够进入这个while循环,而输入浮点数不会进入这个循环

#include <stdio.h>
long get_long(void);
int main()
{
    long x;
    char ch;
    printf("Please enter a long variable.\n");
    while(scanf("%ld", &x)==1)
    {
        printf("x is %ld\n", x);
        while((ch=getchar())!='\n')
            putchar(ch);
        printf(" is not an integer.\n Please enter an ");
        printf("integer value, such as 23, -56 or 3:\n");
    }
    printf("Your input is %ld\n", x);
    return 0;
}

可以看到,输入的3被读取为整数,而后面的.4被留在缓冲流中

Please enter a long variable.
3.4
x is 3
.4 is not an integer.
 Please enter an integer value, such as 23, -56 or 3:
Please enter a long variable.
234
x is 234
 is not an integer.
 Please enter an integer value, such as 23, -56 or 3:

这说明scanf("%ld", &x)==1会把浮点数输入的整数部分读入,而小数点以及其后的数字被留在输入的缓冲流中,真是······
注释掉那句显示x的(那是为了测试上面的错误)

#include <stdio.h>
long get_long(void);
int main()
{
    long x;
    char ch;
    printf("Please enter a long variable.\n");
    while(scanf("%ld", &x)!=1)
    {
        //printf("x is %ld\n", x);
        while((ch=getchar())!='\n')
            putchar(ch);
        printf(" is not an integer.\n Please enter an ");
        printf("integer value, such as 23, -56 or 3:\n");
    }
    printf("Your input is %ld\n", x);
    return 0;
}

可以看到只有输入字符才会进入while循环以进行输入错误的处理,而输入浮点数不会进入,而是执行while后面的语句

Please enter a long variable.
a
a is not an integer.
 Please enter an integer value, such as 23, -56 or 3:
2.3
Your input is 2

示例 用户界面友好(主要是解决好输入的可能错误),模块化编程

用不同函数/模块实现输入验证和求和的功能

#include <stdio.h>
#include <stdbool.h>
const long MAX = +10000000L;
const long MIN = -10000000L;
long get_long(void);//验证输入是一个整数
bool bad_limits(long begin, long end, long low, long high);//验证范围上下限符合要求
long sum_squares(long a, long b);//求整数a,b之间的整数的平方和
int main()
{
    long start, stop, sum;//用户指定的范围
    printf("This program computes the sum of the squares of the integers in a range.\n"
           "The lower bound should not be less than %ld.\n"
           "The upper bound should not be greater than %ld\n"
           "Enter the limits( enter 0 for both limits to quit:)\n"
           "lower limit:\n", MIN, MAX);
    start = get_long();
    printf("upper limit:\n");
    stop = get_long();
    while(start!=0 || stop!=0)
    {
       if(bad_limits(start, stop, MIN, MAX))
        printf("Enter again!");
       else
       {
           sum = sum_squares(start, stop);
           printf("The sum of integers in the range of %ld and %ld is %ld\n\n", start, stop, sum);
       }
        printf("lower limit:\n");
        start = get_long();
        printf("upper limit:\n");
        stop = get_long();
    }
    printf("Done!\n");
    return 0;
}

long get_long(void)
{
    long x;
    char ch;
    //printf("Please enter a long variable.\n");
    while(scanf("%ld", &x)!=1)
    {
        while((ch=getchar())!='\n')
            putchar(ch);
        printf(" is not an integer.\n Please enter an ");
        printf("integer value, such as 23, -56 or 3:\n");
    }
    return x;
}

bool bad_limits(long begin, long end, long low, long high)
{
    bool not_good = false;
    if(begin>end)
    {
        printf("%ld isn't smaller than %ld.\n", begin, end);
        not_good = true;
    }
    if(low>high)
    {
        printf("%ld isn't smaller than %ld.\n", low, high);
        not_good = true;
    }

    if(begin<low || end<low)
    {
        printf("Values must be %ld or greater.\n", low);
        not_good = true;
    }

    if(begin>high || end>high)
    {
        printf("Values must be %ld or less.\n", high);
        not_good = true;
    }
        return not_good;
}
long sum_squares(long a, long b)
{
    long sum=0;
    for(long i=a;i<=b;i++)
        sum += i*i;
    return sum;
}
This program computes the sum of the squares of the integers in a range.
The lower bound should not be less than -10000000.
The upper bound should not be greater than 10000000
Enter the limits( enter 0 for both limits to quit:)
lower limit:
1
upper limit:
3
The sum of integers in the range of 1 and 3 is 14

lower limit:
10
upper limit:
100
The sum of integers in the range of 10 and 100 is 338065

lower limit:
0
upper limit:
0
Done!

输入是多个字符组成的字节流

在这里插入图片描述

厉害的scanf 转换小能手

把字符根据转换说明转换为各种数据类型,棒棒的
在这里插入图片描述

菜单(UI的不可或缺的一部分)

在这里插入图片描述
在这里插入图片描述

以后用C++和Java写点图形界面的菜单玩玩

我还没做过这种类似的分析,写出伪代码,想到什么事情适合用什么语句

在这里插入图片描述

换行符 kind of a pain in the ass(成功分析并解决了换行符带来的麻烦,呼呼,好有成就感!)

在这里插入图片描述在这里插入图片描述

本示例gets me so high (这局和换行符终于玩清楚了)

有一周多没有这样的成就感了,通过自己努力分析,调试,找到问题并解决,这是一种真正的开心,嘴角上扬的毫无阻力,内心和表情高度愉悦的一致,头也不晕了,心情无比轻松,比看剧什么的都有意思多了!解决了一个工作和学习的难题所带来的的成就感简直太治愈了!!我要继续攻坚克难,追求被虐后才能获得的这种很high high的feel!被虐很久才会有这么一次放松,并且虐的越惨,就越放松!我的喜好真表态。

#include <stdio.h>
char get_choice();
char get_first();
void count(int i);
int get_integer();
int main()
{
    char ch;
    int i;
    while((ch = get_choice())!='q')
    {
        switch(ch)
    {
    case 'a':
        printf("Buy low, sell high.\n");break;
    case 'b':
        putchar('\a');break;
    case 'c':
        printf("Count how far? Enter an integer.\n");
        i = get_integer();
        count(i);
        break;
    default:
        printf("\\n is like a pain in the ass.\n");break;
    }
    }
    if(ch=='q')
        printf("Bye!\n");
    return 0;
}

char get_choice()
{
    char choice;
    printf("Enter the letter of your choice:\n");
    printf("a. advice       b. bell\nc. count        q. quit\n");
    while(((choice=get_first()) != 'a') && (choice!='b') && (choice!='c') && (choice!='q'))
        {
            printf("Please respond with a, b, c or q.\n");
            printf("Enter the letter of your choice:\n");
            printf("a. advice       b. bell\nc. count       q. quit\n");
        }
    return choice;
}

char get_first()
{
    char first;
    first=getchar();
    while(getchar()!='\n')
        continue;
    return first;
}
void count(int i)
{
    for(int j=1;j<=i;j++)
        printf("%d\n", j);
}
int get_integer()
{
    int i;
    char ch;
    while(scanf("%d", &i)!=1)
    {
        while((ch=getchar())!='\n')
            putchar(ch);
        printf(" is not an integer. Please enter an integer, such as 3, -4, 80:\n");
    }
    getchar();//输入整数后的换行符必须清理掉,不然后面get_choice会get换行符
    return i;
}

完全正确的菜单

Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
a
Buy low, sell high.
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
b
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
c
Count how far? Enter an integer.
2
1
2
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
a
Buy low, sell high.
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
b
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
c
Count how far? Enter an integer.
3
1
2
3
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
c
Count how far? Enter an integer.
3
1
2
3
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
q
Bye!

遇到的几个问题及其解决

  • 1.菜单显示后输入a没问题,但是输入b,c,q都完全没反应,调试的时候输入b,c,q还无法return回去,我一脸蒙蔽不知为何一度十分痛苦,多按几次换行符还输出了Please respond with a, b, c or q
    如下:
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
a
Buy low, sell high.
Enter the letter of your choice:
a. advice       b. bell
c. count        q. quit
b
c
q


Please respond with a, b, c or q.
Enter the letter of your choice:
a. advice       b. bell
c. count       q. quit








Please respond with a, b, c or q.
Enter the letter of your choice:
a. advice       b. bell
c. count       q. quit

经过思索,原来这是因为我犯了一个巨大的错误!
我把while的表达式写成了

//最终正确版本
while(((choice=get_first()) != 'a') && (choice!='b') && (choice!='c') && (choice!='q'))
//原始错误版本
while(((choice=get_first()) != 'a') || ((choice=get_first())!='b') || ((choice=get_first())!='c') || ((choice=get_first())!='q'))

原始错误版本有两个巨大错误:一是竟然写的或???很低级的错误,就不说了;上面的现象是我把或改为与后,出现的错误现象。

二是我他妈竟然调用了4次get_first函数······what the fuck???我在想什么???难怪输入几次换行符才进入到while语句里输出Please respond with a, b, c or q,因为人家调用了4次函数。所以后面三个字符根本不用再调用了···
由于菜单显示后我输入a,while(((choice=get_first()) != ‘a’) && ((choice=get_first())!=‘b’) && ((choice=get_first())!=‘c’) && ((choice=get_first())!=‘q’))中的第一个表达式就是false了,&&是短路运算符,所以不会再判断后面的,直接把整个表达式判定为false,所以就跳过了这个while,把字符a传回了main程序进了switch,得到了正确的反应

    1. 上面的big mistake改好后,程序正常多了,但是我发现输入c后由于需要再输入一个整数,于是整数输入结束后的换行符遗留在了输入流中,于是本次输入c得到正确响应后再输入不管什么选项,都会被提示Please respond with a, b, c or q.,这是因为换行符被返回去了,所以在get_integer程序末尾特地加了一个getchar()把换行符吸收掉·····
      ==注意输入a, b,c, q选项时换行符为什么没捣乱,那是因为get_first函数的末尾的while代码把输入选项时的第一个字符外的字符包括换行符都吸收掉了!!!!==哈哈哈哈哈哈哈
while(getchar()!='\n')
        continue;

上面的get_choice函数还可以这么写,简单点:
注意choice变量生命为int才可以比较大小哦

char get_choice()
{
    int choice;
    printf("Enter the letter of your choice:\n");
    printf("a. advice       b. bell\nc. count        q. quit\n");
    choice=get_first();
    while((choice<'a' || choice>'c') && (choice!='q'))
        {
            printf("Please respond with a, b, c or q.\n");
            printf("Enter the letter of your choice:\n");
            printf("a. advice       b. bell\nc. count       q. quit\n");
            choice=get_first();
        }
    return choice;
}

总结

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值