本篇文章的疑惑之处 1:当键盘输入abcd^z并且按回车键时,为什么终端显示的结果没有体现出'\n'?(一直没有弄清楚)
2.EOF 是宏定义,不存放在 缓冲区,那么,我想问:宏定义 是不是 都不存放在 缓冲区?

文章目录

  • 前言
  • 一、while 循环
    • (1) 定义
    • (2) while 语句中的 break 和 continue
      • 1、break
      • 2、continue
        • 1. 补充:system(“pause”)
          • (1) 具体分析
          • (2) 例子
        • 2. getchar 和 putchar 以及 MSDN 相关的知识点
          • (1)getchar ——— " ctrl + z ":使 getchar 读取结束
          • 1、详解 getchar() 、EOF 和 ctrl + Z
            • EOF
            • getchar( )
            • Ctrl + Z 和 Ctrl + D
            • 网上查的关于 Ctrl + Z 和 Ctrl + D 的解释:
          • 2、" ctrl + z ":使 getchar 读取结束
          • (2) putchar

前言


循环语句:while、 for、 do while


一、while 循环

(1) 定义

while(表达式)
循环语句;

(2) while 语句中的 break 和 continue

1、break

总结:break 在while 循环中的作用:break 是用于永久的终止循环
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while 中的 break 是用于永久终止循环的

int main()
{int i = 1;while (i <= 10){if (5 == i)break;printf("%d\n", i);i += 1;}return 0;                   输出结果:1 2 3 4
}

上面这段代码中的
if( 5==i )
break;
可以写的更规范些,如下
if(5= =i)
{
break ;
}

int main()
{int i = 1;while (i <= 10){if (5 == i){break;              这么写才规范!}printf("%d\n", i);i += 1;}return 0;                   输出结果:1 2 3 4
}

以上代码解释:
当 i=5 时,经过 break 后,不执行”printf(“%d”,i); i += 2“.

2、continue

continue 是用于终止本次循环的,也就是本次循环中 continue 后边的代码不会执行,而是直接跳转到 while 语句的判断部分。进行下一次循环的入口判断。

int main()
{int i = 1;while (i <= 10){if (5 == i){continue;}printf("%d\n", i);i += 1;}return 0;                   输出结果:1 2 3 4 然后一直死循环下去
}

C语言中的 while 循环-编程知识网
输出结果:1,2,3,4,然后一直死循环下去

原因:当 i == 5 时,执行完” continue “之后,
跳过 ”printf(“%d”,i);“
“i += 1;”
直接回到” while(i <= 10) “进行执行判断,此时 ”i ==5 ”是真,又执行到 continue.
然后,一直死循环下去。

int main()
{int ch = 0;while ((ch = getchar()) != EOF){if (ch < '0' || ch>'9')               输出 0~9continue;putchar(ch);}return 0;
}

C语言中的 while 循环-编程知识网

1. 补充:system(“pause”)

在c++中 system(“pause”); 用来暂停黑窗口

在c++程序中,窗口有时会一闪就消失,如果不想消失,需添加

system(“pause”);

但要注意在return 语句之前添加,并且要头文件#include<stdlib.h>

(1) 具体分析

system()就是调用(DOS)系统命令(和shell命令)

pause,就是DOS命令集合中的暂停命令

当程序中有system(“pause”);语句时,从该程序里调用了“pause"命令,让操作系统暂停该程序进程的执行,同时程序运行到该语句时,会在窗口上显示"Pree any key to continue…"当用户按下任意键,程序继续往后执行。

(2) 例子
#include <stdlib.h>int main()
{printf("hello world");system("pause");            //暂停printf("你好");return 0;
}

C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

2. getchar 和 putchar 以及 MSDN 相关的知识点

(1)getchar ——— " ctrl + z ":使 getchar 读取结束
int main()
{int ch = 0;while ((ch = getchar()) != EOF)putchar(ch);return 0;
}

解释代码:
通过 MSDN 理解 getchar 和 putchar
EOF :end of file "文件结束"标志

C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

理解:int getchar(void);
我们在键盘中输入的是:a b c d \n (回车键也被 getchar ( ) 转换成字符了,毕竟回车键就是换行符 )
我们在电脑上看到的就是 abcd 到了第二行, 第三行 出现了 光标,这个 第三行的光标 就是 回车键(换行符)的体现
C语言中的 while 循环-编程知识网
以下的例子,也能很好的解释 回车键 ‘\n’ 也转换成了 相应的字符(就是光标到了第4行)

#include<stdlib.h>
int main()
{int ch = 0;while ((ch = getchar()) != EOF){printf("%d  ,%c  ,", ch, ch);}system("pause");return 0;
}

C语言中的 while 循环-编程知识网

#include<stdlib.h>
int main()
{int ch = 0;while ((ch = getchar()) != EOF){printf("%d  ,%c  ,", ch, ch);}system("pause");printf("\n");printf("此语句用来说明 system(pause) 的暂停程序的功能");putchar('\n');return 0;
}

C语言中的 while 循环-编程知识网

C语言中的 while 循环-编程知识网
int getchar(void);

Each of these functions returns the character read. To indicate an read error or end-of-file condition, getc and getchar

return EOF

, and getwc and getwchar return WEOF. For getc and getchar, use ferror or feof to check for an error or for end of file.

这些函数都返回已读字符。要指示读错误或文件结束条件,getc和getchar返回EOF, getwc和getwchar返回WEOF。对于getc和getchar,使用ferror或feof检查错误或文件结束。

C语言中的 while 循环-编程知识网

Each of these routines reads a single character from a file at the current position and increments the associated file pointer (if defined) to point to the next character. In the case of getc and getwc, the file is associated with stream (see Choosing Between Functions and Macros). Routine-specific remarks follow.

这些例程中的每一个都从文件的当前位置读取一个字符,并将相关的文件指针(如果已定义)加1以指向下一个字符。在getc和getwc的情况下,文件与流相关联(参见在函数和宏之间的选择)。Routine-specific讲话。

1、详解 getchar() 、EOF 和 ctrl + Z

当初学C语言的时候,都知道 EOF 是文件结束符,end of file 的意思,一般通过 EOF 来标识输入的结束或文件的结束(终端输入的话windows系统中是Ctrl + Z 键,Linux系统是 Ctrl + D 键),如上面那段代码所示,以前一直以为是不断读入终端输入的字符,一直读到 ^Z 为止,但是现在发现却不是这么简单的。
一个小例子

#include<stdlib.h>
int main()
{int ch = 0;while ((ch = getchar()) != EOF){printf("%d %c\n", ch, ch);}system("pause");return 0;
}

简单运行一下这个小程序,如果输入 abcd^Z ,然后回车,程序运行结果如下:
C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

可以看到程序此时并没有结束,需要再键入 Ctrl + Z,回车,才会结束;
C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网
这是为什么呢?这得讲讲 EOF 和 getchar( )。

EOF

EOF 如字面意思,就是文件结尾(End of File),是操作系统无法从数据源读取更多数据的情形。数据源通常为 文件或流。
EOF 的真实值与不同的平台有关(但通常是 -1,比如在 glibc 中),并且不等于任何有效的字符代码。
一般在 c/c++ 中 EOF 是个 宏定义,其值为 -1,也就是说,EOF 并不是个字符,没有什么特殊的结构,只是一个值为 -1 的 宏定义 而已。
C语言中的 while 循环-编程知识网
右击–> 转到定义–> 发现 EOF 的 宏定义 为 -1
C语言中的 while 循环-编程知识网

getchar( )

定义:int getchar(void)
作用:从 stdin 读取下一个字符,等价于 getc(stdin)
返回值:成功时为获得的字符,失败时为 EOF

上面说到 EOF 其实只是 -1,并不是一个字符,这里的 getchar( ) 函数返回的其实也不是字符,而是一个 int 整形。当 getchar( ) 读取字符成功时,其返回的就是字符的 ASCII 值,失败时返回 EOF,即 -1,那怎么样读取失败呢?这里需要讲讲 ^Z 这个字符。

Ctrl + Z 和 Ctrl + D

大一刚开始学 C 的时候,只知道 windows 通过 Ctrl + Z 来终止上面的 while 循环输入,Linux 通过 Ctrl + D ,当时以为键入 Ctrl + Z,那个 ^Z 字符就是 EOF,getchar( ) 得到EOF自然就终止了,现在看来,EOF 并不是一个字符,而 getchar( ) 成功时也不可能返回 EOF 。其实如上面的运行结果所示, ^Z 字符的 ASCII 值是 26 ,也就是说键入 Ctrl + Z 后,其实输入的是一个 ASCII值为 26 的字符。

那如果 Ctrl + Z 输入是一个字符的话,getchar( ) 怎么会返回 EOF 呢?

因为输入缓冲是行缓冲,在windows 系统下按下回车后,才会送到输入缓冲区中存储。每当按下回车键后,就会检测输入缓冲区中是否有了可读的数据以及 Ctrl + Z 这样的流结束的标志。如上面运行结果所示,当 Ctrl + Z 前面有其他字符时,此时系统认为缓冲区中有可读的数据,系统不会检测Ctrl + Z ( 因为有要读的数据,还不能认为到了流的末尾 );而当 Ctrl + Z 前面没有其他字符时,系统此时会检测到 Ctrl + Z,此时 getchar( ) 就会读取失败,返回 EOF。**所以如果需要终端输入 Ctrl + Z 终止输入,需要另起一行输入 Ctrl + Z 才行。

网上查的关于 Ctrl + Z 和 Ctrl + D 的解释:

输入缓冲 是 行缓冲。当从键盘上输入一串字符并按回车后,这些字符会首先被送到输入缓冲区存储。每当按下回车键后,就会检测输入缓冲区中是否有了可读的数据。还会对键盘上是否有作为流结束标志的Ctrl + Z ( windows ) 或者 Ctrl + D 键 按下作出检查,其检查方式有两种:阻塞式 以及 非阻塞式

阻塞式检查方式 指的是只有在回车键按下之后才对此前是否有 Ctrl + Z 组合键按下进行检查,非阻塞式指的是按下 Ctrl + D 之后立即响应的方式。如果在按 Ctrl +D 之前已经从键盘输入了字符,则Ctrl + D 的作用就相当于回车(但是回车自己也会进入缓冲),即把这些字符送到输入缓冲区供读取使用,此时 Ctrl + D 不再起流结束符的作用。如果按 Ctrl + D 之前没有任何键盘输入,则 Ctrl + D 就是流结束的信号。

Windows 系统中一般采用 阻塞式检查 Ctrl + Z、Unix \ Lunix 系统下一般采用非阻塞式的检查 Ctrl + D 。楼主是在 Windows 系统下,因此使用阻塞式的 Ctrl + Z 来标识流的结束。
这种阻塞式的方式有一个特点:

只有按下回车之后
才有可能检测在此之前是否有 Ctrl + Z 按下。
还有一个特点就是:如果输入缓冲区中有可读的数据 则不会检测 Ctrl + Z (因为有要读的数据,还不能认为到了流的末尾)。

还有一点需要知道:Ctrl + Z 产生的不是一个普通的 ASCII 码值,也就是说它产生的 不是一个字符,EOF如上图知,EOF是一个宏定义, 所以不会跟其他从键盘上输入的字符一样 能够存放在输入缓冲区 中。
C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

#include<stdlib.h>
int main()
{int ch = 0;while ((ch = getchar()) != EOF){printf("%d  ,%c  ,", ch, ch);}system("pause");return 0;
}

C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

^Z :的ASCII 值 为 26
即:Ctrl + Z 的ASCII 值 为 26

int main()
{int a = 26;printf("%c\n", a);return 0;
}

C语言中的 while 循环-编程知识网
’ \n ’ :的ASCII值 是 10
即:回车键 的 ASCII 值为 10

int main()
{char a = '\n';printf("%d\n", a);return 0;
}

C语言中的 while 循环-编程知识网

//测试getchar()读取问题 
#include <stdio.h>
int main()
{int ch = 0;int i = 0;while ((ch = getchar()) != EOF){printf("int ch:%d\n", ch);i++;}printf("int ch:%d\n", ch);printf("scanf()读取次数:%d", i);
}

或者

#include <stdio.h>
int main()
{int ch = 0;int i = 0;while ((ch = getchar()) != EOF){putchar(ch);               两个代码,也就这点区别i++;}printf("int ch:%d\n", ch);printf("scanf()读取次数:%d", i);
}

C语言中的 while 循环-编程知识网

C语言中的 while 循环-编程知识网
C语言中的 while 循环-编程知识网

C语言中的 while 循环-编程知识网

2、" ctrl + z ":使 getchar 读取结束
(2) putchar

定义:int putchar(int c);

int main()
{int a = getchar();printf("printf输出:%c\n", a);printf("putchar输出:");putchar(a);putchar('\n');return 0;
}

C语言中的 while 循环-编程知识网

C语言中的 while 循环-编程知识网
Each of these functions returns the character written. To indicate an error or end-of-file condition, putc and putchar return EOF; putwc and putwchar return WEOF. For all four routines, use ferror or feof to check for an error or end of file.

这些函数都返回写入的字符。要指示错误或文件结束条件,putc和putchar返回EOF;putwc和putwchar返回WEOF。对于这四个例程,使用ferror或feof检查错误或文件结束。

C语言中的 while 循环-编程知识网

The putc routine writes the single character c to the output stream at the current position. Any integer can be passed to putc, but only the lower 8 bits are written. The putchar routine is identical to putc( c, stdout ). For each routine, if a read error occurs, the error indicator for the stream is set. putc and putchar are similar to fputc and _fputchar, respectively, but are implemented both as functions and as macros (see Choosing Between Functions and Macros). putwc and putwchar are wide-character versions of putc and putchar, respectively.

putc例程将单个字符c写入当前位置的输出流。任何整数都可以传递给putc,但只写入较低的8位。putchar例程与putc(c, stdout)相同。对于每个例程,如果发生读错误,则设置流的错误指示符。putc和putchar分别类似于fputc和_fputchar,但同时作为函数和宏实现(参见在函数和宏之间的选择)。Putwc和putwchar分别是putc和putchar的宽字符版本。