目录
一、实验环境
Windows 10 系统
Visual Studio Community 2019
二、简介C语言字符
1、字符常量
“字符常量”通过在单引号 (''
) 内包含单个字符来构成。例如:‘a’, ‘1’, ‘!’。字符可以是字符集中的任何元素。
字符常量具有整数类型(integer type)。每个字符常量都被解释为其对应的ASCII码,如'a'
在十进制和十六进制下分别为 97 和 61。
常用的几个ASCII码:
字符值 | ASCII码 (十进制下 ) |
---|---|
‘0’ | 48 |
‘9’ | 57 |
‘A’ | 65 |
‘Z’ | 90 |
‘a’ | 97 |
‘z’ | 122 |
2、字符变量
字符变量的类型说明符是char
。每个字符变量占用一个字节的内存空间,存储字符常量的值(即ASCII码)。例如:
char ch = 'a';//ch是字符变量,'a'是字符常量
char型和int型可以相互转换。当int型的变量转换成char型时,只取int型变量的低八位;当char型变量转换成int型时,以符号位的值补足成int型。
三、字符输入输出函数
1、使用scanf() 和 printf()
强大的格式化输入输出函数,可以用于字符的输入和输出。需要加入头文件#include<stdio.h>。
#define _CRT_SECURE_NO_WARNINGS//VS里不加这个会对scanf报错,说scanf涉及安全问题,我没有细看了
#include<stdio.h>
int main(void)
{
char ch;
scanf("%c",&ch);//用%c
printf("ch = '%c'",ch);//用%c
return 0;
}
输出:
a //输入的字符
ch = 'a'
2、使用getchar() 和 putchar()
作为知识补充,首先我们来看这样一个问题:getchar() 和 putchar()是宏还是函数?
C陷阱与缺陷 139页:
函数调用需要花费较长的程序执行时间,因此getchar经常被实现为宏。这个宏在stdio.h中定义,因此如果一个程序没有包含stdio头文件,编译器对getchar的定义一无所知。在这种情况下,编译器会假定getchar是一个返回类型为整型的函数。
实际上,很多C语言实现在库文件中都包括有getchar函数,忘记在程序中包含stdio头文件的效果就是在所有出现getchar宏的地方都用getchar函数调用来替换getchar宏。
总之我们需要知到:
1、getchar()和putchar() 比 scanf()和printf()函数实现简单,效率更高;
2、为了额外的效率提升,通常getchar()和putchar()都是作为宏来实现的。
当我们使用getchar()和putchar()的时候,通常需要包含头文件#include<stdio.h>。在stdio.h中有如下声明:
_Check_return_ _ACRTIMP int __cdecl getchar(void);
_Check_return_opt_ _ACRTIMP int __cdecl putchar(_In_ int _Character);
虽然看不懂,但还是能理解意思的,意思大概就是:
int getchar(void);
int putchar(int _Character);
1、getchar()
功能:从输入缓冲区读取一个字符,输入有回显。不需要提供参数,返回值是读取字符的ASCII码。
2、putchar()
功能:输出指定字符。需要提供一个参数,返回值是接收参数的ASCII码。
注意到这里putchar()接收参数的类型是int,而不是char,为什么呢?getchar()和putchar()返回值类型为什么是int而不是char呢?网上有说是为了兼容文件结束符EOF,有说是为了兼容ASCII码以外的字符,我就知到这么多了。😜
在平时的使用中,如果使用putchar()输出一个ASCII码编码的字符,那么给定参数可以是一个字符变量、字符常量(如’a’)、ASCII码值(0~127)。
#include<stdio.h>
int main(void)
{
char ch;
ch = getchar();//接收字符
putchar(ch);//字符变量
printf("\n");
putchar('b');//字符常量
printf("\n");
putchar(99);//ASCII码值
return 0;
}
输出:
a //输入的字符,这里把输入的字符a显示出来,称为回显(敲击键盘上的字符a后,还要敲击Enter键)
a //字符变量
b //字符常量
c //ASCII码值(99)
3、使用getche()
功能:输入一个字符后会立即读取,不用等待用户按下回车键,输入有回显。
使用getche()需要加入头文件#include<conio.h>,在conio.h中有如下声明:
_Check_return_ _CRT_NONSTDC_DEPRECATE(_getche)
_DCRTIMP int __cdecl getche(void);
然而事情并非如同想象的一样顺利,在VS中,加入头文件conio.h后,getche()编译都过不去,代码如下:
#include<stdio.h>
#include<conio.h>
int main(void)
{
char ch;
ch = getche();
printf("\n");//用回车换行将回显和输出分开
putchar(ch);
return 0;
}
报错如下:
error C4996: 'getche': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _getche. See online help for details.
意思是getche()被弃用了,要使用C和C++里都一致的名字_getche()。
将上面代码中getche()改成_getche()就好了。(被弃用了怎么还有getche()的声明存在?原因我也没明白,下面将会更迷惑)
_getche()在头文件conio.h里的声明:
_Check_return_ _DCRTIMP int __cdecl _getche(void);
将上面代码getche()修改为_getche()后的输出:
a //输入回显
a //输出(当在键盘上敲击字符a后,立即输出)
让人更迷惑的是,不加头文件conio.h,使用getche()或者_getche()都可以过编译,也都可以正常运行。(上面不是说getche()被弃用了吗…)
#include<stdio.h>
//#include<conio.h>
int main(void)
{
char ch;
ch = getche();
//或者ch = _getche();
printf("\n");
putchar(ch);
return 0;
}
编译器会给出warning:
'getche'未定义,假设外部返回int
运行正常(将getche()换成_getche()运行也一样):
a //输入回显
a //输出
我有限的知识与理解
:C里面不声明函数的话,会有一个默认调用约定,返回值为int型的默认声明,所以编译能过,但是有warning。在链接阶段,链接器默认链接libc,在libc里能找到相应函数就能通过链接。如果不包含头文件conio.h,就没有getche()(或_getche())函数的声明。编译器会默认其有一个返回值为int的默认声明,在链接时,从libc中可以找到函数getche()(或_getche()),故最终代码可以运行。
(为什么在加了头文件conio.h后,getche()反而不能用了?)
4、使用getch()和putch()
在头文件conio.h中声明。
1、getch()
声明:
_Check_return_ _CRT_NONSTDC_DEPRECATE(_getch)
_DCRTIMP int __cdecl getch(void);
功能:getch()与getche()功能相同,只是前者输入没有回显。
2、putch()
声明:
_Check_return_opt_ _CRT_NONSTDC_DEPRECATE(_putch)
_DCRTIMP int __cdecl putch(_In_ int _Ch);
功能:输出指定字符。需要提供一个参数,返回值是接收参数的ASCII码。
在上面的问题一样,当加入头文件conio.h时,编译器会报错提醒使用_getch()和_putch()。当不加入头文件conio.h时,编译器只会报warning,并且程序运行正常。
#include<stdio.h>
#include<conio.h>
int main(void)
{
char ch;
ch = _getch();
printf("\n");//用回车换行将回显和输出分开
_putch(ch);
return 0;
输出:
//我敲击了字符a,但没有回显,这里是printf函数打印的\n
a //输出
四、总结
函数 | 功能 | 头文件 | 平台 |
---|---|---|---|
getchar() | 有回显,输入需要敲击Enter键 | stdio.h | 可跨平台 |
getche() | 有回显,输入无需敲击Enter键 | conio.h | Windows |
getch() | 无回显,输入无需敲击Enter键 | conio.h | Windows |
putchar() | 输出字符 | stdio.h | 可跨平台 |
putch() | 输出字符 | conio.h | Windows |
putchar()和putch()的区别尚不清楚。