字符串和字符串函数
本章介绍内容
- 函数——gets()、gets_s()、fgets()、puts()、fputs()、strcat()、strncat()、strcmp()、strncmp()、strcpy()、strncpy()、sprintf()、strchr()
- 创建并使用字符串
- 使用C库中的字符和字符串函数,并创建自定义的字符串函数
表示字符串
- 字符串定义:字符串是以空字符(\0)结尾的char类型数组
- 定义字符串的几种方法
//使用数组
const char m1[40]="hello world";//定义一个字符串,const代表不会更改这个字符串
const char m1[40]={'h','e'.'l'.....'d','\0'};等同于上面,注意:如果没有最后的空字符,就不是一个字符串,而是一个字符数组。
//使用指针
const char *pt1="something is pointing at me."
//字符串常量:用双引号括起来的内容称为字符串常量,字符串常量属于静态存储类别,双引号括起来的内容被视为指向该字符串存储位置的指针
#define MSG "i am a symbolic string constant."
- 数组与指针
- 相同点
- 二者都可以用数组表示法
char heart[]="hello world";
const char *head="hello china";
putchar(heart[0]);
putchar(head[0]);//putchar()函数输出整型和字符型
- 都可以用指针加法操作
putchar(*(heart+1));
putchar(*(head+1));
- 区别:
- 数组名相当于常量,不能使用ar++,但可以ar+1,表示下一个元素的地址。指针ar是变量,可以使用递增操作。
- 定义字符串时,初始化数组把静态存储区的字符串拷贝到数组中,而初始化指针只把字符串的地址拷贝给指针。
字符串输入
- gets()函数 -----用于整行读取,直至遇到换行符,换行符一般不存储。函数参数是输入字符串的存储地址,如果写入成功,返回str地址,否则返回null,常与puts()函数配对使用
缺点:无法检查数组是否装得下输入行,会导致缓冲区溢出,一般不用。
int main()
{
char words[STLEN];
puts("Enter a string,please:");
gets(words);
puts("Enter a string,twice,please");
printf("%s\n", words);
puts(words);
}
- fgets()函数(和fputs())----专门解决溢出问题,替代gets()函数。如果一切正常,fgets()会返回与传入的第一个参数相同的地址,当fgets()遇到文件结尾和错误的时候,会返回一个空指针,在代码中也可以用数字0来代替
char world[STLEN];
puts ("enter a string");//输出字符串
fgets (world, STLEN, stdin);//第一个参数是输入的数组名,第二个参数是确定最大数量,,第三个参数指明要读入的文件,如果读入从键盘输入,则以stdin作为参数
//如果该参数是n,那么fgets将读到n-1,如果fgets()读到换行符会将他存储起来。
printf ("your string twice (puts(),the n fputs()):\n");
puts (world);//puts()会在带输出字符串末尾添加一个换行符,但fputs不会
fputs (world, stdout);//stdout标准输出,现实中在计算机显示屏上
- gets_s()函数:和fgets()函数类似,区别之一不需要第三参数,因为只从标准输入中读取数据。区别二读到换行符丢弃。区别三,当读到最大字符数还没读到换行符,会执行以下几步,首先把目标数组中的首字符设为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针,接着,调用依赖实现的“处理函数”,或者中止或退出程序。
- scanf()函数:遇到第一个空白字符(空格、换行符、制表符等)就读取缓冲区中的字符,因此无法连续读取数据。
- s_gets()函数:自定义输入函数,实现输入整行,并用空字符代替换行符,或者读取一部分输入并丢弃一部分
字符串输出
- puts()函数:直接将字符串地址作为参数传递,并且回自动在打印末尾添加换行符,puts()函数遇到空字符会停止输出。
- fputs():是puts()函数针对文件定制的版本,第二个输出的目的设备,可以是文件,也可以是系统标准输出,此时stdout作为该参数,且不会在输出的末尾添加换行符。
- printf()函数:支持多种类型数据的输出,可以通过转换说明符和修饰符来进行指定格式的输出。
**注意:**要配对使用
自定义输入/输出函数
例子:自定义puts()函数,但不会自动添加换行符
//用指针编写
#include<stdio.h>
void put1(const char * string)//不会改变字符串
{
while(*string!='\0')
putchar(*string++);//指针递增,打印的是指针指向的值
}
//用数组编写
#include<stdio.h>
int i=0;
while(string[i]='\0')
putchar(string[i++]);
//使用更加简洁的方式
while (*string);当string指向空字符时,*string的值是0,即测试条件为假,循环结束
字符串数组
字符串数组可以用二维数组和指针数组实现
字符串处理函数
C库中提供了很多处理字符串的函数,这些函数都放在string.h头文件中
- strlen()函数——统计字符串的长度
- strcat()函数——用于拼接字符串,接受两个字符串参数,拼接后形成的字符串作为第一个字符串,第二个字符串不变
int main()
{
char flower[SIZE];
char addon[] = "smell like shoes";
puts("what is your favouite");
if (s_gets(flower, SIZE))
{
strcat(flower, addon);
puts(flower);
puts(addon);
}
}
char* s_gets(char* st, int n)
{
char* ret_val;
int i=0;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
while (st[i] != '\n' && st[i] != '\0')//既没有换行也没结束
i++;
if (st[i] == '\n')//用空字符替代换行符
st[i] = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;//返回地址
}
- strncat()函数——拼接字符串,为了解决strcat()函数无法检查第一个参数是否能容纳第二个参数的问题,例如strncat(bugs,addon,13),在增加到第十三个字符或者遇到空字符自动停止,第三个参数指定最大添加字符数。**注意:**要给拼接后的字符串长度加1才能够空间存放末尾的空字符。
- strcmp()函数——比较两字符串是否相同,当两个字符串相同时,返回0,前一个字符串在前面返回-1,在后面返回一个正数
**注意:**strcmp()函数比较的是字符串而不是字符,所以参数应该是字符串 - strncmp()函数——在比较两字符串时,可以比较字符不同的地方,也可以只比较第三个参数指定的字符数
const char*list(LISTSIZE)={"astronomy","astounding","astrophysics","ostracize","asterism","astrophobia"};//定义一个不可变字符指针。
int count=0;
int i;
for(i=0;i<LISTSIZE;i++)
if(strncmp(list[i],"astro",5==0)//筛选出前五个单词为“astro”的项
{
printf("found:%s\n",list[i]);
count++;
}
printf("一共有%d个单词",count);
}
- strcpy()函数和strncpy()函数——复制字符串,strcpy和strcat有相同的问题,无法检查目标空间是否能容纳字符串副本,拷贝字符串用strncpy更安全,该函数的第三个参数指明课拷贝的最大字符数
- strcpy:
- 原型:char *strcpy(char *dest, char *src);
- 功能:把src所指由’\0’结束的字符串复制到dest所指的数组中。
- 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
- 返回指向dest的指针。
- 注意:当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。因此会导致dest栈空间溢出以致产生崩溃异常。如果不考虑src串的完整性,可以把dest数组最后一元素置为NULL,从dest串长度处插入NULL截取字串。
- strncpy:
- 原型:char * strncpy(char*dest, char *src, size_t n);
- 功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。
- sprintf()函数——和printf类似,但是是将数据写入到字符串,第一个参数是目标字符串的地址,其余参数和printf相同,即格式字符产和待写入的列表
例题:sprintf(formal,"%s",last);//将组合后的字符放在formal数组中