第11章 字符串和字符串函数


——《C Primer Plus》的搬运工,仅记录自己觉得重要的内容,方便以后参考

11.1表示字符串和字符串I/O

puts()函数只显示字符串,而且自动在显示的字符串末尾加\n

11.1.1在程序中定义字符串

  • 字符串常量,“串”,编译器自动补\0,存储在内存中

字符串常量属于静态存储类别,字符串只会被存储一次,直到整个程序的声明周期
%p-printf,打印字符串首字符的地址>> *'串'

  • char arr[40]="串" == char arr[40]={‘字符’,‘字符’,'\0'};//必须加\0,自动变为串

未被赋值的元素,自动补0,实际上是补\0

arr=&arr[0];
*arr='首字符';
  • char* pt="串";== char arr[40]="串" ; ==char arr[40]={‘字符’,‘字符’,'\0'};
  • 自动计算大小 char arr[]="串"
  • 这种方式不允许const char arr[] ; arr = "hello";
  • 这种方式是允许的const char* arr; arr = "hello world";

数组与指针

  • 数组形式
    在这里插入图片描述
    编译器将数组名识别为数组首元素地址的别名,但是数组名为常量,不能更改
  • 字符形式
    在这里插入图片描述
#define MSG "hello world";
char arr[]=MSG;
char* pt=MSG;
(%p MSG) == (%p pt) != (%p arr);//因为arr为MSG的拷贝,所以地址不一样

字符串数组

  • 指向字符串的指针数组
    这里不同于二维数组的表现形式(定义方式)
const char* arr1[N]={"串1""串2",...,"串N"};
printf("%s",arr1[i]);//0<=i<N
  • char类型数组的数组
const char arr2[M][40]={"串1""串2",...,"串M"};
printf("%s",arr2[i]);//0<=i<M
  • 二者区别
    arr1数组是一个内含5个指针的数组,共占N·(1个指针类型所占字节数)个字节
    arr2是一个内含5个数组的数组,每个数组含有40个char类型的值,共M·40个字节arr1中的指针指向初始化时所用的字符串字面量的位置,这些字面量(字符串常量)被存储在静态内存中
    arr2中的数组存储的是字符串常量的副本,所以每个字符串都存储了两次,与上面介绍的字符串的解释一样
    arr1数组的指针元素所指向的字符串不必存储在连续的内存中

11.1.2指针和字符串

char* pt="串"*"hello world "==h;//说明"表示的是一个地址"

11.2.2不幸的gets()函数

gets()用于读取一行字符(串),知道遇到换行符,然后丢弃换行符,存储其余字符,并在末尾自动添加一个空字符 ‘\0’

puts()函数用于显示字符,遇到空字符 '\0’停止输出,并在末尾自动添加换行符 ‘\n’

缺点:无法检查数组时候装得下输入行。gets()只知道数组的开始处,不知道数组中有多少个元素

gets()函数遇到文件结尾返回空指针NULL或0

11.2.2gets()的替代品

C11中可以用gets_s() 函数代替gets() 函数

fgets()函数和fputs()函数

fgets() 函数通过第2个参数限制读入的字符数来解决字符数溢出的问题。
在这里插入图片描述

fgets() -> \n\0

fgets()函数,当时输入字符比定义的要长时,只放\0,没有\n
fputs()函数不再末尾加\n
fputs()函数遇到文件结尾返回NULL指针,或为0

如果不想修改字符常量,那么就最好不要用指针。

gets_s()函数

在这里插入图片描述

11.2.4scanf()函数

scanf()函数从第一个非空白符作为字符串的的开始
用%s转换说明,下一个空白字符(空行、空格、制表符、换行符)作为字符串的结束标志,输入的结果字符不包含空白字符
%10s可以限定读入的次数
scanf()函数返回一个整数值,该值等于成功读取的项数或EOF(表示文件的结尾),即可以一次性读入多个字符

11.3字符串输出

11.3.1puts()函数

puts(字符串的地址);
输出字符串直到\0位置,即遇到空字符停止,并为每行末尾添加一个\n

字符串常量被认为该字符串的地址

11.3.2fputs()函数

fputs()函数的第二个参数指明要写入数据的文件,或stdout表示打印在显示器上
fputs()函数不会在末尾自动添加\n

11.3.3printf()函数

printf()函数不会自动在字符串的末尾添加一个\n

11.4自定义输入输出函数

*string++;
等价于
*string;
string++;

11.5字符串函数

11.5.2strcat()函数

用于拼接字符串,接受两个字符串作为参数,把第2个字符串的备份附加在第一个字符串的结尾,并把拼接后形成的新字符串作为第一个字符串,第二个字符串不变

char arr[100] = "hello";
const char* arr2 = "world";
strcat(arr, arr2);

//错误示范
char* arr = "hello";
const char* arr2 = "world";
strcat(arr, arr2);

strcat()函数返回char*类型,返回第一个拼接后形成的新字符串的地址
strcat()函数第一个数组必须有足够的空间
覆盖第一个字符串的\0

11.5.3strncat()函数

strncat()函数,中的第三个参数指定了最大添加字符数

  • 时刻注意末尾\0的问题
  • 不会拷贝第二个字符中空字符和其后的字符,但是对新拼接的字符后面自动加上一个空字符\0

11.5.4strcmp()函数

用于字符串比较

strcmp(str1,str2);

直接比较字符串的时候,比较的是两个字符串的地址是否相同,不能直接比较
strcmp()函数可以比较不同大小的字符串(存储在不同大小数组中),逐次比较每个字符
参数相同返回0,不相同返回非零值,即小则返回复数,大则返回正数
strncmp()函数中第三个参数指定要比较的字符个数

11.5.5strcpy()函数和strncpy()函数

strcpy()接受两个字符串指针作为参数
可以把指向源字符串的第二个指针声明为指针、数组名、或字符串常量
把指向源字符串副本的第一个指针参数指向一个数据对象(数组)

char arr1[M][N];
char arr2[N];
gets(arr2);//scanf("%s",arr2);
strcpy(arr[i],arr2);//拷贝字符串

//==//
char arr3[N];
strcpy(arr3,"hello world");//N要大于都等于strlen("hello world")+'\0'

//错误示范
char* str;
strcpy(str,"hello world");
  • strcpy()函数的返回类型为char*,返回的是第一个参数的地址,即一个字符的地址。拷贝之后两个指针指向的地址不一样
  • 第一个参数不必指向数组的开始,可用于拷贝数组的一部分
  • strcpy()函数把源字符串中的空字符也拷贝进去,
  • 函数返回值为char*

strcncpy()函数中的第3个参数指明要拷贝的最大字符数
注意部分拷贝的情况可能没有\0,需要自己添加
函数返回值为char*

11.5.6sprintf()函数

把数据写入字符串,而不是打印在显示器中
第一个参数是目标字符串的地址,其余参数与printf()相同
本质上与printf()函数相同,只是将输出转移到数组(字符串中)

char formal[M];
sprintf(formal, "%s,%s\n", "hello", "world");//\n也会存储在formal中

11.5.7其他字符串函数

  • strchr
char* strchr(const char* s,int c);
如果s字符串中包含c字符,该函数返回s字符串首位置的指针(末尾的空字符也是字符串的一部分,所以在查找范围内);如果未找到,该函数返回NULL
  • strrchr
char* strrchr(const char* s,int c);
该函数返回s字符串中c字符的最后一次出现的位置,末尾的空字符也是字符串的一部分,在查找范围内,未找到则返回NULL
  • strpbrk
 char* strpbrk(const char* s1,const char* s2);
如果s1字符中包含s2字符串中的任意字符,该函数返回指向s2,如果在s1字符串中未找到任何s2字符串中的字符,返回NULL
  • strstr
char* strstr(const char* s1,const char* s2);
该函数返回指向s1字符串中s2字符串出现的首位置,如果没找到则返回NULL

11.6字符串示例:字符串排序

11.6.1排序指针而非字符串

排序指针而非排序原来的数组

11.6.2选择排序算法

见其他算法

11.7 cytype.h字符函数和字符串

7.2.2ctype.h系列的字符函数

isalnum();//字母或数字
isalpha();//字母
isblank();//标准的空白字符(空格、水平制表符、换行符)
iscntrl();//控制字符
isdigit();//数字
isgraph();//除空格外的任意可打印字符
islower();//小写字母
isprint();//可打印字符
ispunct();//标点符号
isspace();//空白字符(空格、换行符、换页符、回车符、垂直制表符、水平制表符)
isupper();//大写字符
isxdigit();//十六进制数字符

tolower();//如果参数是大写字符,返回小写字符,否则不动
toupper();//如果参数是小写字符,返回大写字符,否则不动

11.8命令行参数

int main(int argc,char* argv[]);
argc表示命令行中的字符串数量,系统用空格表示一个字符串的结束和下一个字符串的开始
把命令行字符串存储在内存中,并把每个字符串的地址存储在指针数组中
argv存储数组的地址,argv是一个指向指针的指针(相当于字符串数组),一把argv[0]表示可执行程序的名称
等价于
int main(int argc,char** argv);

11.9把字符串转换为数字

  • atio()
    将字母数字转换为整数
    参数不是数字则返回0

  • atof()
    将字符串转换为double类型的值

  • atol()
    函数把字符串转换成long类型的值

其他智能转换函数,书P366

——所有代码仅表示关键步骤,可能无法正常运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值