今天在写代码的时候碰到了getchar()函数,以前学c的时候没学好,现在来重新学习一下,查阅了一些资料,终于有点弄清getchar()函数了。以下均为copy.
--------------------------------------------------------------------------------------
一,getchar(),putchar()
二,gets(),puts()
三,字符串处理函数
-------------------------------------------------------------------------------------
关于getchar()函数
一,作用
简单来说,getchar() 用于读取用户从键盘输入的单个字符(包括空格、回车和Tab) 。
它有一个整型的返回值,当发生读取错误的时候,返回整型值-1,当读取正确的时候,它会返回用户从键盘输的第一个字符的ASCII码。
当程序调用getchar时.运行程序时就等着用户从按键输入,用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中),当用户键入回车之后,getchar才开始从输入流中每次读入一个字符。
输入的字符不只一个的时候,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完之后,才等待用户按键,getchar函数输入数字也按字符处理,单个的getchar函数输入多于一个字符时,只接收第一个字符
二,缓冲区
首先,用getchar()函数进行字符的输入,并不是直接从键盘这个硬件中读取输入的字符,而是从“输入缓冲区”中得到的字符。
输入缓冲区是一个字符的队列,其中存储了所有你尚未读取的字符。
每次调用getchar函数,它就会从输入缓冲区中读出第一个字符,并把这个字符从输入缓冲区中清除。
然而,这个输入缓冲区的设计,是把所有从键盘上输入的东西都放进去的,包括你每次按的回车符‘\n’,
而getchar函数只读走了你在回车前输入的那个字符,而将回车符保留在了输入缓冲区中。
于是,第二次调用getchar时,函数就从输入缓冲区中读出了'\n'。
要解决这个问题,有两种可行的途径。
一是多加一个getchar(),过滤掉回车,但是这种方法有不足,就是如果你在调用第一个getchar时输入了多个字符,
那么,加入一个getchar并不能把所有未读取的字符过滤。如果你的本意是重新从“键盘”读取的话,最好是加一个
fflush(stdin);
清除输入缓冲区
如何清除回车
解决方法:
(1)使用下面的语句清除回车:
while(getchar()!='\n');
(2)用getche()或getch()代替getchar(),其作用是从键盘读入一个字符(不用按回车),注意要包含头文件<conio.h>
关于putchar()函数
putchar()向终端输出一个字符。
格式为putchar(ch),其中ch可以是被单引号(英文状态下)引起来的一个字符,
可以是介于0~127之间的一个十进制整型数(包含0和127)(超过127就不是ASCII码了),
也可以是事先用char定义好的一个字符型变量当c为一个被单引号(英文状态下)引起来的字符时,输出该字符(注:该字符也可为转义字符),当c为一个介于0~127(包括0及127)之间的十进制整型数时,它会被视为对应字符的ASCII代码,输出该ASCII代码对应的字符;当c为一个事先用char定义好的字符型变量时,输出该变量所指向的字符。
note:当整型变量ch超出8位变量的范围时,ch则会变强制转化为8位变量(即取其低八位传过去输出),当为负数的时候,由于计算机存储负数是用补码表示的,所以传过去的二进制补码也被当做正数处理,也是取其低八位
------------------------------------------------------------------------------------
先写这些,有空再补充
今天学习数组的时候看到了字符串的输入输出,本来想把他归纳到数组那一部分的的,想了想还是接着这个往下写。
另外,我觉得markdown编辑器不好用,还是用富文本编辑器吧。
------------------------------------------------------------------------------------
字符串的输出(puts()与printf())
在C语言中,有两个函数可以在控制台(显示器)上输出字符串,它们分别是:
- puts():输出字符串并自动换行,该函数只能输出字符串。
- printf():通过格式控制符
%s
输出字符串,不能自动换行。除了字符串,printf() 还能输出其他类型的数据。
例如:
#include <stdio.h>
int main(){
char str[] = "http://c.biancheng.net";
printf("%s\n", str); //通过字符串名字输出
printf("%s\n", "http://c.biancheng.net"); //直接输出
puts(str); //通过字符串名字输出
puts("http://c.biancheng.net"); //直接输出
return 0;
}
运行结果:
http://c.biancheng.net
http://c.biancheng.net
http://c.biancheng.net
http://c.biancheng.net
注意,输出字符串时只需要给出名字,不能带后边的[ ]
,例如,下面的两种写法都是错误的:
printf("%s\n", str[]);
puts(str[10]);
字符串的输入(gets()与scanf())
在C语言中,有两个函数可以让用户从键盘上输入字符串,它们分别是:
- scanf():通过格式控制符
%s
输入字符串。除了字符串,scanf() 还能输入其他类型的数据。 - gets():直接输入字符串,并且只能输入字符串。
但是,scanf() 和 gets() 是有区别的:
- scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。
- gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以,不管输入了多少个空格,只要不按下回车键,对 gets() 来说就是一个完整的字符串。换句话说,gets() 用来读取一整行字符串。
请看下面的例子:
#include <stdio.h>
int main(){
char str1[30] = {0};
char str2[30] = {0};
char str3[30] = {0};
//gets() 用法
printf("Input a string: ");
gets(str1);
//scanf() 用法
printf("Input a string: ");
scanf("%s", str2);
scanf("%s", str3);
printf("\nstr1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
return 0;
}
运行结果:
Input a string: C C++ Java Python↙
Input a string: PHP JavaScript↙
str1: C C++ Java Python
str2: PHP
str3: JavaScript
分析:
第一次输入的字符串被 gets() 全部读取,并存入 str1 中。第二次输入的字符串,前半部分被第一个 scanf() 读取并存入 str2 中,后半部分被第二个 scanf() 读取并存入 str3 中。
注意,scanf() 在读取数据时需要的是数据的地址,这一点是恒定不变的,所以对于 int、char、float 等类型的变量都要在前边添加&
以获取它们的地址。但是在本段代码中,我们只给出了字符串的名字,却没有在前边添加&
,这是为什么呢?因为字符串名字或者数组名字在使用的过程中一般都会转换为地址,所以再添加&
就是多此一举,甚至会导致错误了。
(数组名或者数组的第一个元素都指向数组的首地址。如:str[]=&str[0];)到数组与指针的时候再细细讨论,现在仅需知道,输入一个数组时前面不要加&。
就目前学到的知识而言,int、char、float 等类型的变量用于 scanf() 时都要在前面添加&
,而数组或者字符串用于 scanf() 时不用添加&
,它们本身就会转换为地址。读者一定要谨记这一点。
其实 scanf() 也可以读取带空格的字符串
以上是 scanf() 和 gets() 的一般用法,很多教材也是这样讲解的,所以大部分初学者都认为 scanf() 不能读取包含空格的字符串,不能替代 gets()。其实不然,scanf() 的用法还可以更加复杂和灵活,它不但可以完全替代 gets() 读取一整行字符串,而且比 gets() 的功能更加强大。比如,以下功能都是 gets() 不具备的:
- scanf() 可以控制读取字符的数目;
- scanf() 可以只读取指定的字符;
- scanf() 可以不读取某些字符;
- scanf() 可以把读取到的字符丢弃。
先写这些。
好吧我真香了,觉得富文本不好用了,每次标注还要划上去。还是用Markdown吧。
---------------------------------------------------------------------------
第三次修改。
本来只想写一写getchar(),putchar(),没想到写了这么多,感觉已偏题了,索性改个题目吧。
---------------------------------------------------------------------------
C语言字符串处理函数
用于输入输出的字符串函数,例如printf
、puts
、scanf
、gets
等,使用时要包含头文件stdio.h
,而使用其它字符串函数要包含头文件string.h
。string.h
是一个专门用来处理字符串的头文件,它包含了很多字符串处理函数,由于篇幅限制,只能讲解几个常用的。
(1)字符串连接函数 strcat()
功能:把两个字符串拼接在一起,语法格式为:
strcat(arrayName1, arrayName2);
strcat() 将把 arrayName2 连接到 arrayName1 后面,并删除原来 arrayName1 最后的结束标志'\0'
。这意味着,arrayName1 必须足够长,要能够同时容纳 arrayName1 和 arrayName2,否则会越界(超出范围)。
strcat() 的返回值为 arrayName1 的地址。
#include <stdio.h>
#include <string.h>
int main(){
char str1[100]="The URL is ";
char str2[60];
printf("Input a URL: ");
gets(str2);
strcat(str1, str2);
puts(str1);
return 0;
}
运行结果:
Input a URL: http://c.biancheng.net/cpp/u/jiaocheng/↙
The URL is http://c.biancheng.net/cpp/u/jiaocheng/
(2)字符串复制函数 strcpy()
功能:字符串复制,也即将字符串从一个地方复制到另外一个地方,语法格式为:
strcpy(arrayName1, arrayName2);
strcpy() 会把 arrayName2 中的字符串拷贝到 arrayName1 中,字符串结束标志'\0'
也一同拷贝。将 arrayName2 复制到 arrayName1 后,arrayName1 中原来的内容就被覆盖。这也要求 arrayName1 要有足够的长度,否则不能全部装入所拷贝的字符串。
#include <stdio.h>
#include <string.h>
int main(){
char str1[50] = "《C语言变怪兽》";
char str2[50] = "http://c.biancheng.net/cpp/u/jiaocheng/";
strcpy(str1, str2);
printf("str1: %s\n", str1);
return 0;
}
运行结果:
str1: http://c.biancheng.net/cpp/u/jiaocheng/
(3)字符串比较函数 strcmp()
功能:字符串比较,
语法格式为:strcmp(arrayName1, arrayName2);
arrayName1 和 arrayName2 是需要比较的两个字符串。
字符本身没有大小之分,strcmp() 以各个字符对应的 ASCII 码值进行比较。strcmp() 从两个字符串的第 0 个字符开始比较,如果它们相等,就继续比较下一个字符,直到遇见不同的字符,或者到字符串的末尾。
返回值:若 arrayName1 和 arrayName2 相同,则返回0;若 arrayName1 大于 arrayName2,则返回大于 0 的值;若 arrayName1 小于 arrayName2,则返回小于0 的值。
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "aBcDeF";
char b[] = "AbCdEf";
char c[] = "aacdef";
char d[] = "aBcDeF";
printf("a VS b: %d\n", strcmp(a, b));
printf("a VS c: %d\n", strcmp(a, c));
printf("a VS d: %d\n", strcmp(a, d));
return 0;
}
运行结果:
a VS b: 32
a VS c: -31
a VS d: 0
----------------------------------------------------------------------------