从零开始学编程---第一步-C语言(四)

时间:2014-03-03 22:29    点击:

大家还记得这个程序吧

#include <stdio.h>
main()
{
    
        char a[50];
        printf("请输入一个字符串\n");
        scanf(" %s",a);
        printf("字符串为:%s\n",a);


}    

输入hello 结果显示字符串为:hello

但如果我们输入hello world 结果也显示字符串为:hello

原因不用我多说了吧,那么怎么用数组来输出hello world


第一种方法,定义两个数组分别存放hello和 world(注意前面有空格)
char a[20]="hello";    长度尽可能大,因为将要存放数组b的字符串
char b[7]=" world"; 因为前面有个空格,后面有个NULL零,所以长度是7,7个字符

然后用strcat()函数连接,strcat()代表字符串连接(string concatenation)
用strcat()需要用 #include <string.h> 头文件
strcat() 把一个字符串附加或加到另一个字符串的末尾
就是这样
strcat(a,b) 理解为数组b的内容存放到数组a里,而且连在后面
b数组里的内容没有丢失也没有修改,还是原来一样,存放着" world"
反过来也可以,strcat(b,a) 就是a数组存放到b数组里面,但b数组长度要足够大, 结果也会反过来,变成" worldhello"

程序就是这样
#include <stdio.h>
#include <string.h>
main()
{
        char a[20]="hello";
        char b[7]=" world";
    
        strcat(a,b);
        printf("字符串为:%s\n",a);


}   

显示结果为:字符串为:hello world

还可以不要第2个数组,直接用字面上的
main()
{
        char a[20]="hello";
        
        strcat(a,“world”);
        printf("字符串为:%s\n",a);


}   

但如果你想自己输入,像这样
#include <stdio.h>
#include <string.h>

main()
{
    
        char a[50],b[50];
        printf("请输入第一个字符串\n");
        scanf(" %s",a);
        printf("请输入第二个字符串\n");
        scanf(" %s",b);
        strcat(a,b);
        printf("字符串为:%s\n",a);


}    

也有中种方法就是设两个数组,在打印两个数组
a[]="hello";b[]=" world"
printf("%s%s",a,b); 就OK了

结果不是你想要的,会是helloworld,那个空格你没办法打印出来,因为scanf() %S格式遇到空格会被忽略不被打印出来


以上没看懂完全没关系,因为基本不用,下面才是重要的


接下来我们学习puts()和gets()输出输入函数,这两个函数提供了一种更容易的方法来打印和获取字符串

下面定义一个字符数组

char a[50];
用gets()获取字符串 get(a);
然后用puts()打印字符串 puts(a);

get是获取的意思,从键盘获取值,get()既能获取一个字符也能获取多个字符,也就是字符串,它能获取到带空格的字符串,自动在末尾加上NULL零,这都正是我们想要的
puts()能打印一个字符也能打印字符串,而且在打印后面会自动换行(加个'\n',不过你看不到)
puts()也能直接打印 puts("hello world"); 并且自动换行,不需要打'\n'

下面这个程序
#include <stdio.h>
main()
{
    
        char a[50];
        puts("请输入一个字符串");
        gets(a);
        puts(a);     


}    
输入hello world就能顺利输出hello world了 


gets()既能获取单个字符,又能获取到带空格的字符串,并且自动在字符串末尾加上NULL零
puts()既能打印单个字符,又能直接输出任何字符格式,并且自动换行

这两个是不是很强大?

有了puts(),gets()我们是不是可以抛弃printf() scanf() putchar() getchar()?
答案是否定的,这就需要介绍3者各自的功能
printf()和scanf()是格式输出输入函数,最后的f是format(格式)的意思

putchar() getchar() 输出输入函数只针对单个字符的操作

puts(),gets() 输出输入函数可以单个字符操作(但是功能有限的),主要是针对字符串操作


下面我们定义
int a

用scanf("%d",a)可以获取整型a的值,a=getchar(),gets(a)无法从键盘获取数字
用printf("%d",a)可以打印数字a的值,putchar(a),puts(a)没法打印
数字方面:printf()和scanf()胜

char a
用scanf("%c",&a) 可以获取字符a的值,用a=getchar()能获取a的值,用gets(a)不能获取
用printf("%c",a)可以打印字符a的值 用a=getchar()可以打印a的值,用puts(a)不能打印

字符方面:getchar()和putchar()第1 scanf()和printf()第2 gets和puts()败

补充:puts()和gets()能接收和打印单个字符只限制变量是数组变量
例如 char a[50];
      gets(a);
      put(a);
你输入一个字符就会打印一个字符

但如果是字符变量
    char a='x';          char a;
     puts(a);       或       gets(a);
                        puts(a);

就无法运行


char a[50]

用scanf("%s",a)能获取数组a的值,用a=getchar()无法获取,用gets(a)能获取a的值
用printf("%s",a)能打印数组a的值 用putchar(a)无法打印,用puts(a)能打印a的值

字符串(数组)方面:gets()和puts()第一,scanf()和printf()第2,getchar()和putchar()败

可见scanf()和printf()什么都能实现,但对字符和字符串操作没有其他两种好
getchar()和putchar()对字符操作优势明显,但不能操作数字变量,字符数组变量
gets()和puts()对字符串操作优势明显,但也不能操作数字变量,字符变量

scanf()和printf()格式输入输出能同时按格式一起输入输出字符,数字,字符串
这是其他两种不能比的

所以程序以scanf()和printf()为主,其他两种作为辅助,发挥各自的长处
如果大家还对这些感到晕的话,也不要急,它们各自的功能将会在以后的程序中完全体现出来,你也会更容易理解

另外我在说一下缓冲区的问题,是针对scanf()的

首先是
#include <stdio.h>
main()
{
   
     char a, b,c;
     scanf("%c",&a);
   
     scanf("%c",&b);
  
     scanf("%c",&c);


     printf("%c,%c,%c",a,b,c);


}    

%c是能接收空格和回车(既是确定又是字符)的
当输入x 回车 两个同时被释放,被变量a,b分别获取
输入y 回车    y被释放,回车准备释放状态,y被c获取

和getchar()缓冲区原理一样把
scanf()怎么去掉回车?前面很早就说过了,在%前面加个空格

#include <stdio.h>
main()
{
   
     char a, b,c;
     scanf("%c",&a);
   
     scanf(" %c",&b);
  
     scanf(" %c",&c);


     printf("%c,%c,%c",a,b,c);


}    
上面输入x 回车 两个同时被释放 x被a获取 回车到了第2个scanf的那个空格里
输入y 回车 y被b获取 回车到了第3个scanf那个空格里
输入z 回车 z被c获取 回车则是准备释放状态中

因为scanf()是格式输入函数,还记得我说过scanf("\n%c",&a),前面那个\n你可以忽略吧
scanf(" %c",&a)有scanf("%c ",&a)有什么不同
空格在前你可以忽略空格直接打x, 也可以按空格 x或者回车 x 你一开始打空格或回车就在那个空格里了,不会再跑进缓冲区,你直接忽略那个空格打x,x进入缓冲区被释放的时候会直接进到%c里,无视前面的空格

空格在后,它就不再无视了,你输入x 回车 两个同时释放 x进了%c 回车到了那个空格 此时缓冲区是空的,等待着你的输入,直到你输入一个值,回车之后,才算结束,似乎缓冲器总是要至少留一个准备释放状态的值,它才可以结束输入

其实空格在后也可以实现,像这样
#include <stdio.h>
main()
{
   
     char a,b,c;
     scanf("%c ",&a);
   
     scanf("%c ",&b);
  
     scanf("%c",&c);


     printf("%c,%c,%c",a,b,c);


}    


以上输入x-回车-y-回车-z-回车和输入xyz-回车结果一样的

下面再来个缓冲区问题,看程序

#include <stdio.h>
main()
{
  
     char a[20], b[20],c[20];
     scanf("%s",a);
   
     scanf("%s",b);
  
     scanf("%s",c);
  

     printf("%s,%s,%s",a,b,c);


}    

输入abc 回车 def 回车 ghi 回车
结果是abc,def,ghi

在scanf()%s格式中,scanf会按照%s的格式对缓冲区按字节顺序扫描,当扫描到回车或空格时,结束扫描,然后在扫描到的数据(不含回车空格)发送数组a里,
此时,缓冲区为空,继续等待输入,输入def 同样是除去回车 发送到数组b里
缓冲区为空,继续等待输入,输入ghi 回车 ghi发送到数组c里 但最后一个回车留到缓冲区作为准备释放状态,输入结束

无论你在开始输入前打多少空格或回车,都不会留到缓冲区,直到你开始输入数据后,回车或空格,sacnf()%s格式会认为输入结束,且不让回车和空格进缓冲区,但是最后输入完成的那个回车会留到缓冲区等待释放(因为后面没%s了),输入结束

scanf("%c%c%c",a,b,c);
这个缓冲原理应该理解了吧
输入x 回车 两个同时释放 到了 ab里
输入y 回车 同时释放 y到了 c里 回车为准备释放状态

如果输入xyz 回车 都释放出来 xyz依次被abc获取 回车为准备释放状态

scanf()%d格式同样也有缓冲原理,但是对回车空格免疫,道理很简单,数字格式拒绝字符格式

最后一个关于缓冲问题,针对gets()
看程序
#include <stdio.h>
main()
{
     char a[20],b[20];
     printf("请输入第一组字符串:\n");
     scanf("%s",a);
     puts("请输入第二组字符串");
     gets(b);
   
     printf("%s,%s",a,b); 
   
}    
这个程序不是我们想要的结果
我们输入hello 回车 此时hello和回车同时从缓冲区里被释放,hello被数组a获取,回车为准备释放状态,等回车到了gets()那里,由于gets()碰到回车会认为输入结束,所以还没等你输入,gets()就已完成输入,则数组b为空,程序结束

gets()的缓冲原理,假设gets(b),当我们输入hello 此时hello在缓冲区,再输入回车,gets()遇到回车会认为输入结束,但它不会让回车进入缓冲区,回车没进入缓冲区,也就谈不上释放,也就不会在进入以后的scanf()或者getchar(),这里的回车只有确定功能没有字符功能,当打完回车 hello会被释放,被b获取,如果包含空格,也会连同空格,存到数组b里(空格占一个字符),此时的缓冲区完全是空,没有准备释放的值,不会继续等待你的输入(gets是这样),除非下面程序还要输入。
gets()取值是字符串(字符串也可以是一个字符),所以gets(b),而非b=gets()

所以程序这样就可以
#include <stdio.h>
main()
{
      char a[20],b[20];
      puts("请输入第一组字符串");
      gets(a);
   
      printf("请输入第二组字符串:\n");
      scanf("%s",b);
  
      printf("%s,%s",a,b); 

  
}    


scanf("%s",a);,gets(a)遇到回车和空格

scanf("%s",a);以遇到空格为输入结束的标志(前提是缓冲区有值),值还在缓冲区等回车来确定释放,但%s格式不会让回车和空格进入缓冲区,也不会让空格和回车存入%s格式的a里
scanf("%s",a);遇到回车结束和释放同时进行,回车不进入缓冲区

gets(a),以遇到回车为结束的标志,不管缓冲区有没有值,遇到回车马上结束,回车不进入缓冲区
gets(a);遇到空格等于遇到字符,没特殊含义

scanf("%c",&a);,a=getchar()遇到回车和空格

scanf("%c",&a);,遇到空格会直接被a获取,然后进入缓冲区等待回车,回车也进入缓冲区和缓冲区的值一起释放
scanf("%c",&a);,遇到回车也会直接被a获取,且同时和回车一起从缓冲区释放

a=getchar()原理和scanf("%c",&a);,一样 因为scanf("%c",&a)等于a=getchar()

还有这种
#include <stdio.h>
main()
{
      char a;
      int b;


      scanf("%c",&a);
      scanf("%d",&b);
      printf("%c,%d",a,b);



  
}    

输入a1b4,在缓冲区是怎样的,首先a1b4先进入缓冲区,再按回车 a1b4和回车一起释放,scanf()函数本质上是一种"模式匹配"函数,首先第一个 scanf()读取缓冲区里的数据 %c格式只能保存一个字符,所以a被第一个scanf()拿走了,1b4继续留在缓冲区,接着第2个scanf()读取,%d格式获取1成功,但获取到b时,由于格式不匹配,放弃b ,由于%d已经获取了一个数字,所以4也放弃了, b4和回车就继续留到缓冲区里准备释放中

好了,缓冲区内容告一段落!

来源:幻想编程//所属分类:站长原创/更新时间:2014-03-03 22:29
顶一下
(29)
93.5%
踩一下
(2)
6.5%
上一篇:从零开始学编程---第一步-C语言(三)
下一篇:从零开始学编程---第一步-C语言(五)
相关内容