第四章 键盘输入和屏幕输出
1.字符常量:
把字符放在一对单引号内,适用于多数可打印字符
2.转义字符:
以反斜线(\)开头,也是放在一对单引号内,适用于控制字符(如回车符,换行符)
3.常用的转义字符:
1) '\n' — 换行 8) '\a' — 响铃报警提示音
2) '\r' — 回车(不换行) 9) '\"' — 一个双引号
3) '\0' — 空字符 10) '\'' — 一个单引号
4) '\t' — 水平制表 11) '\\' — 一个反斜线
5) '\v' — 垂直制表 12) '\?' — 问号
6) '\b' — 退格 13) '\ddd' —1到3位八进制ASCII码值所代表的字符
7) '\f' — 走纸换页 14) '\xhh' —1到2位十六进制ASCII码值所代表的字符
4.\n,是将光标移到下一行起始位置,\r是将光标移到当前行的起始位置
5.\t,是水平制表符,相当于按下Tab键,每次按下Tab键并不是从当前光标位置向后移动一个Tab宽度,而是移到下一个制表位
实际移动的宽度视当前光标位置距相邻的下一个制表位的距离而定
6.制表位,屏幕上的一行被分为若干个域,相邻域之间的交接点称为制表位,每个域的宽度就是一个Tab宽度,多数习惯上为4
7.当转义序列出现在字符串中时,是按单个字符计数的
8.一个整形数在内存中是以二进制形式存储的,而一个字符在内存中也是以其对应的ASCII码的二进制形式存储的,
但char型数据在内存中只占一个字节,而int型数据在16位系统中占2个字节,32位系统占4个字节
9.在ASCII码取值范围内,char型数据可以和int型数据进行混合运算,char型数据也能以int型输出,直接输出其对应的ASCII码的十进制值
10.字符的输入/输出:
1) getchar()和putchar()是C标准函数库中专门用于字符输入/输出的函数,功能是只能输入/输出一个字符
2) 例:从键盘输入一个大写英文字母,将其转换为小写字母显示在屏幕上
#include
void main()
{
char ch;
ch=getchar();//键盘输入一个字符,再按回车表示输入结束,字符存入变量ch,注意:getchar()没有参数,直接返回读入的字符
ch=ch+32;
putchar(ch);//第二次按回车,将显示转换后的结果
putchar('\n');//注意:putchar()内一定要有参数,参数就是待输出的字符,可以是可打印字符,也可是转义字符
}
11.数据的格式化屏幕输出:
1) 函数printf()的一般格式:printf(格式控制字符串);或者printf(格式控制字符串,输出值参数表);
2) 格式控制字符串包括:格式转换说明符,需要原样输出的普通字符
3) 函数printf()的格式转换说明符:
%d — 输出带符号十进制整数,整数符号省略
%u — 输出无符号十进制整数
%o — 输出无符号八进制整数,不输出前导符0
%x — 输出无符号十六进制整数(小写),不输出前导符0x
%X — 输出无符号十六进制整数(大写),不输出前导符0x
%c — 输出一个字符
%s — 输出字符串
%f — 以十进制小数形式输出实数,包含单,双精度,隐含6位小数,但并非全是有效数字,单精度有效7位,双精度16位
%e — 以指数形式输出实数(小写e表示指数部分),小数点前有且仅有一位非0数字
%E — 以指数形式输出实数(大写E表示指数部分)
%g — 自动选取f或e格式中宽度较小的一种使用,不输出无意义的0
%% — 输出%
%p — 输出地址
4) 输出值参数表:需要输出的数据项的列表,可以是变量或表达式,逗号隔开,类型与格式转换说明符相匹配
5) 每个格式转换说明符与输出值参数表中的输出值参数一一对应,没有输出值参数,格式控制字符串就不需要格式转换说明符
6) 例:从键盘输入一个大写英文字母,将其转换为小写字母和其十进制ASCII码值显示在屏幕上
#include
void main()
{
char ch;
printf("Please enter a key:");
ch=getchar();
ch=ch+32;
printf("%c,%d\n",ch,ch);//printf("%c",ch)<<=>>putchar(ch),printf("\n")<<=>>putchar('\n')
}
7) 函数printf()中的格式修饰符:在%和格式符中间插入格式修饰符,用于输出格式的微调,如:指定输出域宽、精度、左对齐等
英文字母l — 修饰格式符d,o,x,u时,用于输出long型数据
英文字母L — 修饰格式符f,e,g时,用于输出long double型数据
英文字母h — 修饰格式符d,o,x时,用于输出short型数据
输出域宽m — m为整数,输出时占m列,若m>0,当数据宽度小于m时,域内右靠齐,左补空格,当数据宽度大于m时,修饰符失效,按实际宽度输出,若m有前导符0,左边多余位补0;若m<0,输出数据在域内左靠齐
显示精度 .n — n为大于等于0的整数,精度修饰符位于最小域宽修饰符之后,由圆点和整数构成,对于浮点数,用于指定输出的浮点数小数位数;对于字符串,用于指定从字符串左侧开始截取的子串字符个数
8) 使用const常量定义pi,编程从键盘输入圆的周长和面积,使其输出数据保留两位小数
#include
void main()
{
const double pi=3.14159;
double r,circum,area;
printf("Please enter r:");
scanf("%lf",&r);
circum=2*pi*r;
area=pi*r*r;
printf("输出没有宽度和精度的值:");
printf("circum=%f,area=%f\n",circum,area);
printf("输出没有宽度和精度的值:");
printf("circum=%7.2f,area=%7.2f\n",circum,area);//域宽为7,占7个字符宽度,小数点也算一个字符,精度为2,小数点后保留2位
}
12.数据的格式化键盘输入:
1) 函数scanf()的一般格式:scanf(格式控制字符串,参数地址表);
2) 格式控制字符串:包括格式转换说明符,分隔符
3) 格式转换说明符以%开始,以格式字符结束,用于指定各参数的输入格式
4) 函数scanf()的格式转换说明符:
%d — 输入十进制整数
%o — 输入八进制整数
%x — 输入十六进制整数
%c — 输入一个字符,空白字符(包括空格、回车、制表符)也作为有效字符输入
%s — 输入字符串,遇到第一个空白字符(包括空格、回车、制表符)时结束
%f或%e — 输入实数,以小数或指数形式输入均可
%% — 输入一个%
5) 参数地址表:由若干变量的地址组成的列表,用逗号分隔
6) 函数scanf()中的格式修饰符:在%和格式符中间插入格式修饰符
英文字母l — 加在格式符d,o,x,u之前,用于输入long型数据;加在f,e之前,用于输入double型数据
英文字母L — 加在格式符f,e之前,用于输入long double型数据
英文字母h — 加在格式符d,o,x时,用于输入short型数据
输出域宽m — m为正整数,指定输入数据的宽度,系统自动按此宽度截取所需数据
显示精度 .n — n为0或正整数,scanf()没有精度格式修饰符,输入时不能规定精度
忽略输入修饰符* — 表示对应的输入项在读入后不赋给相应的变量
7) 函数scanf()输入数值型数据时,被认为输入结束的几种情况:遇空格符、回车符、制表符;达到输出域宽;遇非法字符输入
8) 如果函数scanf()的格式控制字符串中存在除格式转换说明符以外的其他字符,必须将这些字符原样输入
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b); //以空格作为分隔符,等价于scanf("%d%d",&a,&b),等价于scanf("%d %d",&a,&b),
printf("a=%d,b=%d\n",a,b);//实际输入时,空格、回车符、制表符都可作为分隔符,即输入:12空格34 12回车34 12制表符34均可,
}
#include
void main()
{
int a,b;
scanf("%d,%d",&a,&b);//输入时必须以逗号作为分隔符,即只能输入:12,34
printf("a=%d,b=%d\n",a,b);
}
#include
void main()
{
int a,b;
scanf("a=%d,b=%d",&a,&b);//输入时必须将"a="和"b="原样输入,即只能输入:a=12,b=34
printf("a=%d,b=%d\n",a,b);
}
#include
void main()
{
int a,b;
scanf("%2d%2d",&a,&b);//输入时将前两位数读入存到a中,接着两位存到b中,然后结束读取,即输入:1234,或123456结果一样
printf("a=%d,b=%d\n",a,b);
}
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("a=\"%d\",b=\"%d\"\n",a,b);//输出a="12",b="34"
}
#include
void main()
{
int a,b;
scanf("%d%*c%d",&a,&b);//任意字符都可作为分隔符,即输入:12,34或12?34或12+34结果都一样
printf("a=%d,b=%d\n",a,b);
}
#include
void main()
{
int a,b;
scanf("%2d%*2d%d",&a,&b);//忽略两位,输入123456
printf("a=%d,b=%d\n",a,b);//输出a=12,b=56
}
对于程序
#include
void main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("a=%d,b=%d\n",a,b);
}
如果输入12 34a回车,则结果a=12,b=3,程序在遇到非法字符a时,会导致程序输入终止,此时a会读入12,b会读入3
如果输入123a回车,则结果a=123,b=-858993460,程序在遇到非法字符a时,会导致程序输入终止,此时a会读入123,而b未能读入指定数据项数
如果在scanf()函数中忘记在变量前加取地址运算符&,会导致非法内存访问
13.%c格式符使用几种情况:
1) 用%c格式读入字符时,空格字符和转义字符(包括回车)都会被当做有效字符读入
例:键盘输入一个整数加法算式:操作数1+操作数2,输出:操作数1+操作数2=计算结果
#include
void main()
{
int data1,data2;
char op; //输入:12空格+空格3 回车//输出:12 -858993460=-858993448
printf("Enter data1+data2\n");//输入:12空格3 回车//输出:12 3=15
scanf("%d%c%d",&data1,&op,&data2);//输入:12+3 回车//输出:12+3=15
printf("%d%c%d=%d\n",data1,op,data2,data1+data2);
}
2) 先输入一个数据后再输入字符型变量时,输入一个数据后,输入的回车符将被当做有效字符读给字符型变量
例:编程从键盘先后输入int型、char型和float型数据,要求每输入一个数据就显示这个数据的类型和数据值
#include
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d\n",a);
//在输入一个整型数据后,输入的回车符被当做有效字符读给了字符型变量b了
printf("Please input a character:");
scanf("%c",&b);
printf("chracter:%c\n",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f\n",c);
}
14.%c格式符存在问题的解决方法
1) 用函数getchar()将数据输入时存入缓冲区中的回车符读入,以避免被后面的字符型变量作为有效字符读入
#include
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d\n",a);
getchar();//将存于缓冲区中的回车符读入,避免在后面作为有效字符读入
//函数getchar()的返回值是一个回车符,已经避免了错误,不需要再将其赋给字符型变量使用
printf("Please input a character:");
scanf("%c",&b);
printf("chracter:%c\n",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f\n",c);
}
2) 在%c前面加一个空格,将前面数据输入时存于缓冲区的回车符读入,避免被后面的字符型变量作为有效字符读入
#include
void main()
{
int a;
char b;
float c;
printf("Please input an integer:");
scanf("%d",&a);
printf("integer:%d\n",a);
printf("Please input a character:");
scanf(" %c",&b);//在%c前面加空格,将存于缓冲区中的回车符读入
printf("chracter:%c\n",b);
printf("Please input a float number:");
scanf("%f",&c);
printf("float:%f\n",c);
}
//解释:在%c前加空格为什么能将存于缓冲区中的回车符读入
因为如果函数scanf()的格式控制字符串中存在除格式转换说明符以外的其他字符,必须将这些
字符原样输入,所以在%c前加空格,就必须在输入字符型数据前先原样输入空格,而空格,回车符,制表符在
函数scanf()输入数值型数据时都代表输入结束,由实践可知,空格符、回车符、制表符在输入时等效
所以,缓冲区中的回车将代替需要原样输入的空格,因此,实际上,在%c前增加空格或者Tab键都可以完成,
并且与增加的数量无关,且可以混合增加
3)*经典例题:编程实现键盘任意输入字符,统计字母、数字、空格、其他字符数量
首选字符串的方法:
#include
#define N 100
int main()
{
char a[N];
int i,m=0,n=0,b=0,c=0;
printf("请输入字符:\n");
gets(a);
for(i=0;a[i]!='\0';i++)
{
if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z')) m++;
else if(a[i]>=0&&a[i]<=9) n++;
else if(a[i]==' ') b++;
else c++;
}
printf("字母个数:%d\n",m);
printf("数字个数:%d\n",n);
printf("空格个数:%d\n",b);
printf("其他字符个数:%d\n",c);
return 0;
}
单个字符输入的方法,但是要解决缓冲区的问题
#include
int main()
{
char ch;
int a,b,c,d;
a=b=c=d=0;
printf("请输入字符:\n");
do{
ch=getchar();
getchar();//清除缓冲区的回车键,不然会当做第二个字符读入
if(ch!=' ')//用Tab键控制输入结束,他在程序中只会出现一次并且统计一次,
{ //然后结束,所以要去掉它,可以使用if语句,也可在前面初始化为d=-1
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) a++;
else if(ch>='0'&&ch<='9') b++;
else if(ch==' ') c++;
else d++;
}
}while(ch!=' ');
printf("字母个数:%d\n",a);
printf("数字个数:%d\n",b);
printf("空格个数:%d\n",c);
printf("其他字符个数:%d\n",d);
return 0;
}
//解释:你可以把Tab控制结束改成其他任意字符,包括字母、数字、/;都可以,
就是不能直接使用回车控制结束,因为你在实际键盘输入时,需要打回车才能把前面的
字符读入,当你输完回车后,就已经换行了,再回车就达不到你要的效果了,不可能把
他读入,但是他会留在缓冲区下一次使用,所以说,理论上任意字符都可以控制结束,
但是不能直接使用回车再回车的方法,而getchar()函数一次只能读一个字符,当你回车
读入字符后,回车符就会留在缓冲区下一次使用,你可以试试,你把getchar()这行语句
注释,然后一次输入两个字符再回车的话,那么这时他也只能读入第一个字符,第二个
字符和回车就会计入第二次、第三次的结果。
总结:这种方式与用字符串的区别在于,字符串可以统计任何字符,但是这种方式不能统计
你用来控制结束的字符,比如说,你用/控制结束,那么就不能统计/的数量了,而且你要把
他去掉,因为在整个程序中/只会出现一次,然后就结束了
**当程序中出现两次或以上的键盘输入时,就有可能出现缓冲区的问题,只有一次输入,回车直接结束没有这种问题
15.考点题型:字符串常量的长度问题:
1)字符串常量"ab\\c\td\376"的长度是(A)
A) 7 B) 12 C) 8 D) 14
// a b \\ c \t d \376
2)语句printf("%d",strlen("abs\no12\1\\"));的输出结果是(C)
A) 11 B) 10 C) 9 D) 8
// a b s \n o 1 2 \1 \\
16.考点题型:赋值运算、关系运算的混合运算问题:
1)设m,n,a,b,c,d的值均为0,执行(m=a==b)||(n=c==d),m,n的值是(C)
A) 0,0 B) 0,1 C) 1,0 D) 1,1
// "=="是算术运算符,"="是赋值运算符,优先级:算术运算符>赋值运算符,先判断a==b?是否正确
正确则为真,把1赋给m,"||"是或运算,前面已经为真,所以||后面的就不会再运算了,结果就为真
所以m=1,n=0不变
2)int a,b,m,n;初值依次为4,3,2,1,经计算m=(a<=b)&&(n=m
A) 1,1 B) 1,0 C) 0,1 D) 0,0
// a<=b为假,&&是并,前面已经为假,后面就不会再运算了,结果就为假,把0赋给m,即m=0,n=1不变