字符输入输出和输入验证

字符输入/输出

  了解C语言的输出输入首先要了解几个概念,输入输出,标准文件,缓冲等。

I/O(输入/输出)

  • 输入(input):向程序填充一些数据。
  • 输出(output):在屏幕上、打印机上或任意文件中显示一些数据。

标准文件

  文件是存储器中储存信息的区域。通常,文件都保存在某种永久存储器中(如,硬盘、U盘或DVD等)。

  C 语言把所有的设备都当作文件。所以设备被处理的方式与文件相同。

  从较低层面上,C可以使用主机操作系统的基本文件工具直接处理文件,这些直接调用操作系统的函数被称为底层 I/O。

  从较高层面上,C还可以通过标准I/O包来处理文件。

  从概念上看,C程序处理的是流而不是直接处理文件。流是一个实际输入或输出映射的理想化数据流。这意味着不同属性和不同种类的输入,由属性更统一的流来表示。于是,打开文件的过程就是把流与文件相关联,而且读写都通过流来完成。

  • stdin流:标准输入流,一般默认对应键盘设备文件。
  • stdout流:标准输出流,一般默认对应显示器设备文件。它从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件。
  • stderrr流:标准错误流,一般默认对应显示器设备文件。它将错误信息输出到对应的标准错误文件。

缓冲

  • 无缓冲输入:回显用户输入的字符后立即重复打印该字符属于无缓冲输入。
  • 缓冲输入:大部分系统在用户按下Enter键之前不会重复打印刚输入的字符,这种输入形式属于缓冲输入。

  1. 虽然大部分情况下都用缓冲输入,但是无缓冲输入也是必要的,毕竟你也不希望你玩游戏或者看电视的时候,按一个按键没反应吧。
  2. ANSI没有提供调用无缓冲输入的标准方式,这意味着是否能进行无缓冲输入取决于计算机系统。

缓冲分为两类:

  • 完全缓冲:完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区(内容被发送至目的地),通常出现在文件输入中。
  • 行缓冲:在出现换行符时刷新缓冲区。键盘输入通常是行缓冲输入,所以在按下Enter键后才刷新缓冲区。

缓冲区(buffer)

  用户输入的字符被收集并储存在一个被称为缓冲区的临时存储区,按下Enter键后,程序才可使用用户输入的字符。

作用

  1. 把若干字符作为一个块进行传输比逐个发送这些字符节约时间。
  2. 如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。

I/O函数

scanf()和printf()

  printf()是输出函数,scanf()是输入函数,两个函数都使用格式字符串和参数列表。前面有文章专门介绍了这两个函数,这里不展开。

单字符I/O:getchar()和putchar()

  • getchara(): 函数从键盘读取下一个可用的字符。这个函数在同一个时间内只会读取一个单一的字符。可以在循环内使用这个方法,以便从屏幕上读取多个字符。
  • putchar():函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。可以在循环内使用这个方法,以便在屏幕上输出多个字符。

  由于这些函数只处理字符,所以它们比更通用的scanf()和printf()函数更快、更简洁。而且,注意 getchar()和 putchar()不需要转换说明,因为它们只处理字符。这两个函数通常定义在 stdio.h头文件中。

示例
#include <stdio.h>
#define SPACE ' ' 
int main(void)
{
char ch;
ch = getchar(); 
while (ch != '\n') 
{
if (ch == SPACE) 
putchar(ch); 
else
putchar(ch + 1); 
ch = getchar(); 
}
putchar(ch); 
return 0;
}
解释

  ch=getchar();读取一个字符并赋值给ch变量,利用while循环不断读取字符,如果读入的字符是一个空格,那么将会保留这个空格(putchar()将读到的ch输出),否则输出此字符下一个字符。

gets( )和puts()函数

  • gets():从键盘上输入字符,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。
  • puts():函数将字符输出到屏幕。

注意:gets函数由于没有指定输入字符大小,所以会无限读取,一旦输入的字符大于数组长度,就会发生内存越界,从而造成程序崩溃或其他数据的错误。

注意混用问题

  假设程序要求用 getchar()处理字符输入,用 scanf()处理数值输入,这两个函数都能很好地完成任务,但是不能把它们混用。因为 getchar()读取每个字符,包括空格、制表符和换行符;而 scanf()在读取数字时则会跳过空格、制表符和换行符。

#include <stdio.h>
void display(char cr, int lines, int width);
int main(void)
{
int ch; 
int rows, cols; 
printf("Enter a character and two integers:\n");
while ((ch = getchar()) != '\n')
{
scanf("%d %d", &rows, &cols);
display(ch, rows, cols);
printf("Enter another character and two integers;\n");
printf("Enter a newline to quit.\n");
}
printf("Bye.\n");
return 0;
}
void display(char cr, int lines, int width)
{
int row, col;
for (row = 1; row <= lines; row++)
{
for (col = 1; col <= width; col++)
putchar(cr);
putchar('\n');
}
}
解释

  该程序开始时运行良好。但当输出完第一组数据时,程序直接退出了,这是输入行中紧跟在 后面的换行符。scanf()函数把这个换行符留在输入队列中。和 scanf()不同,getchar()不会跳过换行符,所以在进入下一轮迭代时,你还没来得及输入字符,它就读取了换行符,然后将其赋给ch。而ch是换行符正式终止循环的条件。

解决方法
while (getchar() != '\n')
continue;

  可以使用while循环处理掉scanf()输入后面所有字符,为循环的下一轮读取做好了准备。

改正后,如下:

#include <stdio.h>
void display(char cr, int lines, int width);
int main(void)
{
int ch; 
int rows, cols;
printf("Enter a character and two integers:\n");
while ((ch = getchar()) != '\n')
{
if (scanf("%d %d", &rows, &cols) != 2)
break;
display(ch, rows, cols);
while (getchar() != '\n')
continue; //处理scanf剩余字符,包括换行符
printf("Enter another character and two integers;\n");
printf("Enter a newline to quit.\n");
}
printf("Bye.\n");
return 0;
}
void display(char cr, int lines, int width)
{
int row, col;
for (row = 1; row <= lines; row++)
{
for (col = 1; col <= width; col++)
putchar(cr);
putchar('\n'); 
}
}
}
void display(char cr, int lines, int width)
{
int row, col;
for (row = 1; row <= lines; row++)
{
for (col = 1; col <= width; col++)
putchar(cr);
putchar('\n'); 
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值