C语言字符串知识点全解

基础知识

字符串常量

定义

字符串常量是指用双引号括起来的内容(不包含双引号本身)。

双引号是用来告知编译器它括起来的是字符串。——《C Primer Plus》

性质

  1. 字符串常量是储存在静态空间里的静态数组,拥有静态变量所拥有的性质:只被储存一次、存在于整个生命周期。
    在定义相同内容的字符串常量时,可能只为其分配一次存储空间,也可能分配多次
  2. 字符串常量(包括双引号及其括起来的内容)代表该字符串存储空间的首地址——类似数组名。
  3. 定义时在内存中储存的内容是双引号括起来的内容+结尾的空字符。

字符串数组

  1. 指针存储
int main()
{
	char string1[3] = "Hi";
	char string2[6] = "Hello";
	char string3[7] = "hahaha";
	char* StringPtr[3]; //建立一个含三个类型为指向字符的指针的元素的数组
	StringPtr[0] = string1;
	StringPtr[1] = string2;
	StringPtr[2] = string3;
/*再依次让三个指针指向不同的字符串首元素的地址(即字符串的首地址)*/
}
  1. 数组存储
int main()
{
	char stringss[3][7] = {"Hi","Hello","hahaha"};//建立一个二维数组
}
  1. 两者的差别
  • 二维数组的储存方式更直观,但占用了更多不必要的空间(当字符串长度差别很大时,这种劣势会更明显),指针的储存方式则相反。
  • 在做排序时,直接排序指针比对数组的直接排序(利用strcpy函数)内容简单,而且保留了数组中字符串的原始顺序。见代码:
#include <string.h>
int main()
{
	char stringss[3][7] = {"Hi","Hello","hahaha"};
	for( int i = 0; i < 3; i++ )
	{
		StringPtr[i] = stringss[i];
	}
	/*按字典顺序排序指针*/
	for( int i = 0; i < 3; i++ )
	{
		for( int k = i+1; k < 3; i++ )
		{
			if( strcmp( StringPtr[i], StringPtr[k]) > 0 )
			{
				char* TempPtr = StringPtr[i];
				StringPtr[i] = StringPtr[k];
				StringPtr[k] = TempPtr;
			}  
		}
	}
	/*此时stringss中的元素均没有发生改变*/
	/*直接按字典顺序排序数组内容*/
	for( int i = 0; i < 3; i++ )
	{
		for( int k = i+1; k < 3; k++ )
		{
			if( strcmp( stringss[i], stringss[k]) > 0 )
			{
				char TempPtr[7];
				strcpy(TempPtr,stringss[i]);
				strcpy(stringss[i] ,stringss[k]);
				strcpy(stringss[k] ,TempPtr);
			}  
		}
	}
	/*此时stringss中原来的顺序无法找到*/
}

空字符vs空指针

  • 相同点:空字符和空指针都可用数值0来表示
  • 不同点:空字符代表的0是指ASCII码表上0对应的空字符’\0’,空指针(NULL)代表的0是指的是一个地址,该地址不会与任何数据的有效地址对应。

定义和初始化

用数组储存字符串(3种方式)

第一种:

char str[] = "Hello"; //用字符串常量初始化

第二种:

char str[6] = {'H''i''\0'};//省略括号中的无语法问题,但数组大小只有3
char str[] = {'H''i''\0'};

第三种:

#include <stdio.h>
char str[10];
scanf("%s", str);
  1. 在初始化数组时,若指定了数组大小,所有未被使用的元素都被自动初始化为’\0’。
    因此如上方法2的第一种,初始化的结果是’H’ ‘i’ ‘\0’ ‘\0’ ‘\0’ ‘\0’
  2. 字符串常量之间没有空格或用空白字符分隔,等价于其串连起来的字符串。
char str[] = "Hello " "wor""ld";
char str1[] = "Hello world";

这里str和str1的内容是一样的。

用指针访问字符串

char *str = "Hello"; //名为str的指针指向字符串常量所在的首地址

不同指针指向相同内容的字符串常量,编译器可能只给该字符串常量分配1次,(也可能分配多次)储存空间。

二者的对比

  1. 数组有顶层const,因此数组不是可被赋值的左值。数组名代表的地址不可改变。而指针指向的地址可以改变(但其指向的字符串地址无法改变)。
  2. 定义时,字符串被储存在静态存储区中。
    用数组存储字符串时,是将静态存储区中的字符串拷贝到数组中;
    而指针未为字符串的存储分配具体空间,用指针定义字符串时,实则是让指针访问该静态变量所储存的地址。这也就导致此时不能用scanf对字符串进行输入,用指针修改字符串中元素的值时,可能导致其它指向相同内容字符串的指针指向的值发生改变(而相同内容的数组之间是独立的)。

建议在把指针初始化为字符串字面量时使用const限定符。
如果不修改静态存储的字符串本身,不要使用指针指向字符串字面量。
——《C Primer Plus》

字符串函数

输入与输出(头文件stdio.h)

字符串的输入

调用格式读取时的停止标识符读取方式是否导致越界优势特点
getsgets(StringName);换行符整行读入,丢弃末尾换行符可能优势,可能c99建议不用,c11废除此函数方便,但容易产生不可预判的结果
fgetsfgets(StringName, StringLength, stdin);return键整行读入(会保留末尾的换行符)或读入了StringLength-1个字符避免越界,还可以读取文件中的字符所有输入的文字留在缓冲区,若不清理则可能被下一个字符数组读取
gets_sgets_s(StringName, StringLength);换行符整行读入(丢弃末尾的换行符)或读入了StringLength-1个字符避免越界越界时会丢弃该输入行的其他内容,程序将中止或退出,若想程序继续运行,需要另外写“处理函数”
sprintf与printf基本相同,除左括号后的第一个量是被填入的字符串名后引号可能将本应打印于电脑屏幕的字体储存在字符串中,变量的内容应预先输入好
scanfscanf("%s", StringName);空白字符:空格、tab、enter按单词读入,丢弃末尾空白符可能能读取不同种类的数据详情见数据类型、转换符及标准化输入输出

字符串的输出

调用格式是否额外添加换行符备注
putsputs(StringName);一直打印直至遇到’\0’,已经被废弃
fputsfputs(StringName, FileName);将字符串的内容写入文件,若要打印在屏幕上,FileName位置写stdout
printfprintf("%s", StringName);可以输出不同类型的变量,详情见数据类型、转换符及标准化输入输出

常用函数(头文件string.h)

strlenstrcat(strncat)strcmp(strncmp)strcpy(strncpy)
作用计算字符串(不算结尾空字符)长度将字符串2拼接到字符串1后面比较两字符串的的机器排序序列(一般是ASCII码表),str2位于str1前返回正数,位于其后返回负数,二者相等返回0用第二个字符串的内容等位地覆盖第一个字符串
调用格式strlen(StringName);strcat(str1,str2);strcmp(str1,str2);strcpy(str1,str2);
特点/局限性暂无不能检查组合后的字符串是否越界比较的是字符串而非字符str1未必指向字符串的开始。若字符串2过短,会保留字符串1的部分内容。
是否改变字符串str1改变,str2不变str1改变,str2不变
改变结果str1变为原str1除去空字符后接上整个str2从str1指向的地址开始,被str2的内容覆盖
加n与原函数的区别可控制连接后字符串(不包括空字符)的总长度不超过n只比较前n个字母的机器排序序列只覆盖从str1到str1+n指向的地址中间的区域
带n函数的调用格式strncat(str1,str2,n);strncmp(str1,str2,n);strncpy(str1,str2,n);

函数原型

size_t strlen(const char*);
char* strcmp(const char*, const char*);
char* strncmp(const char*, const char*, size_t);
char* strcat(char*, const char*);
char* strcpy(char*, const char*);
char* strncat(char*, const char*, size_t);
char* strncpy(char*, const char*, size_t);

较常用函数

/*调用函数strrchr和strchr时,第二个实参可以是字符。*/
/*虽然函数原型中第二个参数的类型是int,但字符在计算机中的储存形式是其ASCII码,因此可直接用int类型进行读取。*/
char* strrchr(const char* s, int c); //查找字符串s中是否有字符c,若有则返回该字符最后一次出现的地址,若无则返回空指针
char* strchr(const char* s, int c); //查找字符串s中是否有字符c,若有则返回该字符首次出现的地址,若无则返回空指针
char* strstr(const char* s1, const char* s2);//查找字符串s1中是否有字符串s2,若有则返回该字符串首次出现的首地址,若无则返回空指针
char* strpbrk(const char* s1, const char* s2);//查找字符串s1中是否有字符串s2中的部分内容,若有则返回该部分字符串在s1中首次出现的首地址,若无则返回空指针

与字符相关的函数(头文件ctype.h)

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值