文档章节

C Primer Plus 第11章 字符串和字符串函数 11.2 字符串输入

idreamo
 idreamo
发布于 2016/08/19 05:36
字数 1995
阅读 23
收藏 0

11.2.1  创建存储空间

要做的第一件事是建立一个空间以存放读入的字符串。

最简单的办法就是在声明中明确指出数组的大小:

char name[81] ;

现在的name是一个已经分配81字节存储块的地址。另一个方法是使用C库里分配存储空间的函数,这一点会在第12章讨论。

为字符串预留空间后,就可以读取字符串了。C库提供了三个读取字符串的函数:scanf( )、gets( )和fgets( )。我们先讨论最常用的gets( )。

11.2.2  gets( ) 函数

它从系统的标准输入设备(通常是键盘)获取一个字符串。因为字符串没有预定的长度,所以gets( )需要知道何时结束。解决办法是读字符串直到遇到一个换行字符(\n),按回车键可以产生这个字符。它读取换行符(不包括换行符)之前的所有字符,在这些字符后添加一个空字符(\o),然后把这个字符串交给调用它的程序。它将读取换行符并将其丢弃,这样下一次读取就会在新一行开始。

程序清单11.4  name1.c程序

/*name1.c  读取一个名字*/
#include<stdio.h>
#define MAX 81
int main(void)
{
    char name[MAX];  /*分配空间*/
    printf("Hi,what's your name?\n");
    gets(name);  /*把字符串放进name数组*/
    printf("Nice name ,%s.\n",name);
    return 0;
}

程序清单11.4接受并存储最多80个字符(包括空格)的任何名字(记住为数组里的\o预留空间)。注意到希望gets( )改变调用函数中的某个变量(name),也就是说应当使用一个地址作为参数;当然,数组名正是一个地址。

get( )函数的使用可以比前的例子更为复杂,请参见程序清单11.5.

程序清单11.5 name2.c程序

/*name1.c  读取一个名字*/
#include<stdio.h>
#define MAX 81
int main(void)
{
    char name[MAX];  /*分配空间*/
    char * ptr;

    printf("Hi,what's your name?\n");
    ptr=gets(name);  /*把字符串放进name数组*/
    printf("Nice name, %s.\n",ptr);

    return 0;
}

get( )函数通过两种方式获取输入:

**它使用一个地址,把字符串赋给name;

**gets( )的代码使用return关键字返回字符串的地址,程序把这个地址分配给ptr。注意到ptr是一个char的指针,这意味着gets必须返回一个指向char的指针值。

ANSI C要求stdio.h头文件包括gets( )的函数原型。您不需要亲自声明这个函数,只须记住包含这个头文件即可。gets( )函数的构造如下:

char *gets(char *s)
{
    ...
    return (s);
}

这个函数头说明gets( )返回一个指向char的指针。请注意,gets( )返回的指针与传递给它的是同一个指针。输入字符串只有一个备份,它放在作为函数参数传递过来的地址,因此程序清单11.5中的ptr最后也指向name。gets( )函数实际的构造更复杂一点,因为它有两个可能的返回值:如果一切都顺利,它返回的是读入字符串的地址,正如上面所说的。如果出错或gets( )遇到文件结尾,它就返回一个空(0)地址。这个空地址被称为空指针,并用stdio.h中定义的常量NULL来表示。因此,gets( )中还加入了一些错误检测,这使它可以很方便的使用如下形式使用:

while (gets(name)!=NULL)

这个的指令使您即可以检查是否到了文件的结尾,又可以读取一个值。如果遇到了文件的结尾,name中什么也不会读入。这种一举两得的方法就比getchar( )函数所采用的方法简洁的多,getchar( )只返回一个值而没有参数。

while ((ch=getchar())!=EOF)

附带提一下,不要混淆空指针和空字符。空指针是一个地址,而空字符是一个char类型的数据对象,其值为0.数值上两者都可以用0表示,但是它们的概念不同:NULL是一个指针,而0是一个char类型的常量。

11.2.3  fgets( )函数

gets( )的一个不足是它不检查预留存储区是否能够容纳实际输入的数据。多出来的字符简单地溢出到相邻的内存区。fgets( )函数改进了这个问题,它让您指定最大读入字符数。由于fgets( )是为文件I/O设计的,在处理键盘输入时就不如gets()那么方便。fgets()和gets()有三方面不同:

1、它需要第二个参数来说明最大读入字符数。如果这个参数值为n,那么fgets( )就会读取最多n-1个字符或者读完一个换行符为止,由这二者中最先满足的那个来结束输入。

2、如果fgets( )读取到换行符,就会把它存放在字符串里,而不是像gets()那样丢弃;

3、它还需要第三个参数来说明读哪个文件。从键盘上读取输入时,可以使用stdin作为该参数,这个标识符在stdio.h中定义。

程序清单11.6使用了fgets( )代替了11.5里的gets( )。

程序清单11.6 name3.c 程序

/*name1.c  读取一个名字*/
#include<stdio.h>
#define MAX 81
int main(void)
{
    char name[MAX];  /*分配空间*/
    char * ptr;

    printf("Hi,what's your name?\n");
    ptr=fgets(name,MAX,stdin);  /*把字符串放进name数组*/
    printf("Nice name, %s.\n",ptr);

    return 0;
}

问题在于fgets( )把换行符存储到字符串里,这样每次显示字符串时就会显示换行符。本章后面“其他字符串函数”小节的结尾会介绍如何用strchr( )来定位和删除换行符。

对于重要的编程,应当使用fgets( )而不是gets( )。

11.2.4  scanf( )函数

scanf( ) 和get( )的主要差别在于它们如何决定字符串何时结束。

scanf()更基于如何获取单词(get word)而不是获取字符串(get string);而gets( )函数,正如您所看到的,会读取所有字符,直到遇到第一个换行符为止。

scanf( )使用两种方法来决定输入结束。无论哪种方法,字符串都是以遇到第一个非空白字符开始。如果使用%s格式,字符串读到下一个空白字符(但不包括)(比如空格、制表符和换行符)。如果指定了字段的宽度,比如%10s,scanf( )就会读入10个字符或直到遇到第一个空白字符,由二者中最先满足的那一个终止输入。

程序清单11.7举例说明了指定字段宽度时scanf( )的工作情况。

/*scan_str.c  使用scanf()*/
#include<stdio.h>
int main(void)
{
    char name1[11],name2[11];  /*分配空间*/
    int count;

    printf("Please inter 2 names.\n");
    count=scanf("%5s %10s",name1,name2);
    printf("I read the %d names %s and %s.\n",
           count,name1,name2);

    return 0;
}

第三个例子输出:

Please enter 2 names .
portensia callowit 
I read 2 names Porte and nsia.

portensia的后4个字母被读到name2中,这是因为第二次调用scanf( )时,它在第一个调用 结束的地方继续开始读取输入数据。

根据所需输入的特点,用gets()从键盘读取文本可能要更好。scanf()主要用于以某种标准形式输入的混合类型数据的读取和转换。例如,每一个输入行都包括一种工具名称、库存数量和单价,您就可以使用scanf();否则您必须在函数中自己处理输入错误的检测。如果希望一次只输入一个单词,最好使用scanf( )。

© 著作权归作者所有

idreamo
粉丝 18
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
C Primer Plus 第11章 字符串和字符串函数 11.5 字符串函数

C库提供了许多处理字符串的函数:ANSI C 用头文件string.h给出这些函数的原型。下面是一些最有用和最常用的函数:strlen() 、strcat()、strncat() 、strcmp() 、strncmp() 、strcpy()、 strn...

idreamo
2016/08/25
45
0
C Primer Plus 第11章 11.7 ctype.h字符函数和字符串

第7章“C控制语句 分支和跳转”介绍了ctype.h系列字符相关的函数。这些函数不能被 应用于整个字符串,但是可以被应用于字符串中的个别字符。程序清单11.26定义了一个函数,它把toupper( )函数...

idreamo
2016/08/27
52
0
C Primer Plus 第11章 11.9 把字符串转换为数字

数字即能以字符串形式也能 以数字形式存储。以字符串形式存储数字就是存储数字字符。例如,数字213即能以数字'2'、‘1’、‘3’、‘0’的形式存储在一个字符串数组中。以数字形式存储213意味...

idreamo
2016/08/29
43
0
C Primer Plus 第11章 字符串和字符串函数 11.3 字符串输出

11.3.1 puts( )函数 puts( )函数的使用很简单,只需要给出字符串参数的地址。程序清单11.8列出了输出字符串的多种方式。 程序清单11.8 put_out.c程序 输出如下: 注意,每个字符串都单行显示...

idreamo
2016/08/19
20
0
C Primer Plus 第11章 11.13 编程练习答案

1、设计并测试一个函数,可以从输入读取n个字符(包括空格、制表符和换行符),把结果存储在一个数组中,这个数组的地址通过参数来传递。 2、修改并测试练习1中的函数,使得可以在n个字符后,...

idreamo
2016/09/22
663
0

没有更多内容

加载失败,请刷新页面

加载更多

Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
47分钟前
15
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
今天
8
0
太全了|万字详解Docker架构原理、功能及使用

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpa...

Java技术剑
今天
21
0
Wifiphisher —— 非常非常非常流氓的 WIFI 网络钓鱼框架

编者注:这是一个非常流氓的 WIFI 网络钓鱼工具,甚至可能是非法的工具(取决于你的使用场景)。在没有事先获得许可的情况下使用 Wifiphisher 攻击基础网络设施将被视为非法活动。使用时请遵...

红薯
今天
82
1
MongoDB 4 on CentOS 7安装指南

本教程为CentOS x86_64 7.x操作系统下,MongoDB Community x86_64 4.2(GA)安装指南。 安装方式一:yum repo在线安装 [此方式较为简单,官方推荐] Step1:新建MongDB社区版Yum镜像源。 # vim ...

王焱君
今天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部