一.字符串长度

1.概述

strlen 是 C 语言中的一个标准库函数,用于计算一个字符串的长度(长度不包含\0)。它包含在 string.hcstring 头文件中。

2.使用

头文件:#include

函数的原型:

  • str:是要计算长度的字符串
size_t strlen(const char *str);

返回值:

strlen 函数返回字符串 str 的长度,不包括结尾的\0字符

3.示例

#include 
#include 

int main() {
	char str1[20] = "HelloWorld!";
	char* str2 = "HelloWorld!";

	printf("字符串1的长度是%zu\n", strlen(str1));//11,它不会例会字符数据的长度,只会关系字符串的长度
	printf("字符串2的长度是%zu\n", strlen(str2));//11,计算的不是指针的大小,而是其指向字符串的长度

}

二.字符串拷贝

不要试图将字符串复制到文字常量区,文字常量区是只读的

1.StrCpy

(1)概述

① 介绍

strcpy 是 C 语言中的一个标准库函数,用于复制字符串,不能指定要复制字符串的长度。

② 注意事项

需要注意要为终止符\0预留空间

  • **内存污染:**使用这个函数时,必须保证dest指向的内存空间足够承载拷贝过来的字符串,复杂它会强行占用dest后面其它程序使用的内存,造成内存污染
  • **源字符串的终止符:**使用这个函数复制字符串,其把字符串的终止符\0复制过来.

(2)使用

头文件:#include

**返回值:**目的内存的首地址

函数声明:

  • dest 是目标字符串的指针,strcpy 会将源字符串复制到这块内存中。
  • src 是源字符串的指针,即你想要复制的那个字符串。
char* strcpy(char* dest,const char* str);

(3)示例

代码:

#include   
#include   
  
int main() {  
    char src[] = "Hello, World!";  
    char dest[20]; // 确保目标数组足够大以容纳源字符串  
  
    // 使用strcpy复制字符串  
    strcpy(dest, src);  
  
    printf("Copied string: %s\n", dest);  
  
    return 0;  
}

输出:

Copied string: Hello, World!

2.Strncpy

(1)概述

① 介绍

**功能:**将 src 指向的字符串前 n 个字节,拷贝到 dest 指向的内存中

② 注意事项
  • strncpy拷贝\0

    • 复制完毕后要手动附加\0,确保字符串正确结束,避免未定义的出现
  • 如果n大于src指向的字符串中的字符个数,则在dest后面填充n-strlen(src)\0

    image-20240212080451450

(2)使用

头文件:#include

**返回值:**目的内存的首地址

函数原型:

  • dest:指向目标字符数组的指针,即复制到的位置。
  • src:指向源字符串的指针,即从哪里开始复制。
  • n:要复制的字符数。注意这里的n是指字节数,对于多字节字符集(如UTF-8编码的字符串),一个字符可能由多个字节组成。
char *strncpy(char *dest, const char *src, size_t n);

(3)示例

代码:

在这个例子中,strncpy 函数从 src 字符串中复制最多 5 个字符到 dest 字符串中。然后,我们手动在 dest 字符串的末尾添加一个空字符(\0),因为 strncpy 不会自动添加它。最后,我们使用 printf 函数输出源字符串和目标字符串。

#include   
#include   
  
int main() {  
    char src[] = "Hello, World!";  
    char dest[20];  // 确保目标数组足够大以容纳源字符串和空字符  
  
    // 使用 strncpy 复制最多 5 个字符(不包括空字符)  
    strncpy(dest, src, 5);  
  
    // 手动添加空字符,因为 strncpy 不一定会在末尾添加它  
    dest[5] = '\0';  
  
    printf("源字符串: %s\n", src);  
    printf("目标字符串: %s\n", dest);  
  
    return 0;  
}

三.字符串追加

1.StrCat

(1)概述

① 功能

**功能:**strcat函数追加src字符串到dest指向的字符串的后面。追加的时候会追加\0

② 注意
  • 要保证目标字符数组指向的内存空间足够大
  • 它追加以目标字符串dest\0为起点,追加字符串str\0为终点
    • 请确保目标字符串与追加字符串都是正确的结束

(2)使用

头文件:

函数声明:

  • dest:指向目标字符数组的指针,即要追加的位置
  • str:要追加的字符串
char* strcat(char *dest,const char *str);

(3)示例

\0是字符串的结尾,其后的字符不会被打印

从下面的例子可以得知,strcat的追加是在\0后的追加,且其追加也会将\0追加到字符串后面,从而导致str中Text被忽略。

#include 
#include 
#pragma warning(disable:4996)

int main() {
	char str[20] = "HelloWorld\0Text";
	char* strTemp = "你好";
	strcat(str,strTemp);
	printf("%s\n", str);//HelloWorld你好
}

2.StrnCat

(1)概述

① 功能

用于将源字符串(source)的前n个字符追加到目标字符串(destination)的末尾。

② 与strcat的区别

strcat 函数不同的是,strncat 会检查目标字符串是否有足够的空间来容纳要追加的字符,从而避免了缓冲区溢出的风险。

(2)使用

头文件:

函数声明:

  • dest:指向目标字符串的指针,该字符串应包含一个 C 字符串
    • 要确保其有足够的空间来容纳追加后的字符串,包括额外的空字符。
  • src:指向要追加的源字符串的指针
  • n:要追加的最大字符数
    • 大于源字符长度,仅会追加源字符长度的字符
    • 小于源字符长度,则会追加指定的字符长度
char *strncat(char *dest, const char *src, size_t n);

(3)示例

在目标字符串\0处追加

使用strncat追加zuiStr的前5个字符到str的后面(\0后面)

#include 
#include 
#pragma warning(disable:4996)

int main() {
	char str[] = "aaa\0aaaaaaaaaaaaa";
	char* zuiStr = "HelloWorld!";
	strncat(str, zuiStr, 5);//复制zuiStr的前5个字符
	printf("%s", str);//aaaHello
	
}

四.字符串比较

1.StrCmp

(1)概述

**比较规则:**根据ASCII,逐个字符去比较,一旦比较出大小就返回结果,后面的的不会继续比

注意:

  • 因为它是根据ASCII进行比较的,所以strcmp 函数对大小写敏感
    • 例如:Hellohello不被认为是一个字符串

(2)使用

函数声明:

  • str1:指向第一个要比较的字符串的指针。
  • str2:指向第二个要比较的字符串的指针
int strcmp(const char *str1, const char *str2);

返回值:

  • 如果 str1str2 是相同的,返回值为 0。
  • 如果 str1 在字典顺序上小于 str2,返回一个负数。
  • 如果 str1 在字典顺序上大于 str2,返回一个正数。

(3)示例

代码:

#include   
#include   
  
int main() {  
    const char *str1 = "Hello";  
    const char *str2 = "World";  
    const char *str3 = "Hello";  
    int result;  
  
    // 比较 str1 和 str2  
    result = strcmp(str1, str2);  
    if (result < 0) {  
        printf("str1 is less than str2\n");  
    } else if (result > 0) {  
        printf("str1 is greater than str2\n");  
    } else {  
        printf("str1 is equal to str2\n");  
    }  
  
    // 比较 str1 和 str3  
    result = strcmp(str1, str3);  
    if (result == 0) {  
        printf("str1 is equal to str3\n");  
    }  
  
    return 0;  
}

结果:

str1 is less than str2
str1 is equal to str3

2.StrnCmp

(1)概述

它同样用于比较两个字符串的大小,但其可以设置比较的多少个字符

(2)使用

函数声明:

  • str1:指向第一个要比较的字符串的指针
  • str2:指向第二个要比较的字符串的指针
  • n:要比较的字符的最大数量
int strncmp(const char *str1, const char *str2, size_t n);

返回值:

  • 如果 str1str2 的前 n 个字符相同,返回值为 0
  • 如果 str1 在字典顺序上小于 str2 的前 n 个字符,返回一个负数
  • 如果 str1 在字典顺序上大于 str2 的前 n 个字符,返回一个正数

(3)示例

下面的代码中设置了比较的字符数是5,即只比较二则的Hello部分,

结果显而易见就是相等的,故num的值为0,输出Str1等于str2"

#include 
#include 
#pragma warning(disable:4996)

int main() {
	char* str1 = "Hello C!";
	char* str2 = "Hello World!";

	int num = strncmp(str1, str2, 5);

	if (num > 0) {
		printf("str1大于str2");
	} else if (num < 0) {
		printf("str1小于str2");
	}else {
		printf("str1等于str2");//打印这个
	}

}

五.字符查找

1.Strchr

(1)概述

首次匹配原则,找到后就不会继续了

在字符指针指向的字符串中,找指定ASCII码的字符,并返回第一次出现的字符

(2)使用

头文件:

函数声明:

  • s:要查找的字符串
  • c:要查找字符的ASCII码
    • 可以直接使用''包裹,会自动转换成ASCII码
char *strchr(const char *s, int c);

返回值:

  • 找到返回第一个找到字符的地址(首次匹配)
  • 找不到就返回NULL

(3)示例

找到的是距离str1首地址5个元素的W,也就是第一个W了,即首次匹配

#include 
#include 
#pragma warning(disable:4996)

int main() {
	char* str1 = "HelloWorld,WoW!";
	char* p = strchr(str1, 'W');
	printf("str-p:%d\n", p - str1);//str-p:5,表示找到的是距离str1首地址5个元素W(首次匹配)
	return 0;
}

2.Strrchr

(1)概述

末次匹配原则,只会返回最后一个匹配到的字符

在字符指针指向的字符串中,找指定ASCII码的字符,并返回最后一次出现的字符

(2)使用

头文件:

函数声明:

  • s:要查找的字符串
  • c:要查找字符的ASCII码
char *strrchr(const char *s, int c);

返回值:

  • 找到返回最后一个找到字符的地址(末次匹配)
  • 找不到就返回NULL

(3)示例

找到的是距离str1首地址13个元素的W,也就是最后一个W,即末次匹配

#include 
#include 
#pragma warning(disable:4996)

int main() {
	char* str1 = "HelloWorld,WoW!";
	char* q = strrchr(str1, 'W');
	printf("str-q:%d\n", q-str1);//str-q:13,表示找到的是距离str1首地址13个元素的W(末次匹配)
	return 0;
}

六.字符串匹配-strstr

1.概述

**功能:**在传入的字符串中去查找第一次出现的指定字符串

2.使用

头文件:

函数声明:

  • str 要在其中搜索的字符串
  • substr 要查找的子字符串
char *strstr(const char *str, const char *substr);

返回值:

  • 找到,会返回substr第一次出现位置的指针
  • 找不到,会返回NULL

3.示例

代码:

#include 
#include 

int main() {
    char str[] = "Hello, World!";
    char substr[] = "World";
    char* result;

    result = strstr(str, substr);

    if (result != NULL) {
        printf("找到字符串的位置: %ld\n", result - str);
    }
    else {
        printf("Substring not found.\n");
    }

    return 0;
}

返回值:

找到字符串的位置: 7

七.空间设定

1.概述

概述:memset 是 C 语言中的一个库函数,用于设置内存区域的内容

**功能:**通常用于初始化内存区域或者将不需要的内存区域清零

2.使用

头文件:string.h>

函数原型:

  • str:指向要设置内存区域的指针。
  • c:要设置的值,这个值以 int 形式提供
  • 函数会按照 unsigned char来解析这个值,因此可以传入字符
  • n:要设置的字节数

返回值:

  • 目的内存的首地址,即str
void *memset(void *str, int c, size_t n);

3.示例

代码:

这个例子演示了memset的初始化内存的应用

  • 第一次printf在初始化内存的情况下读取该内存时,出现了随机字符
    • 这是因为printf在未初始化的空间中遇不到\0,然后一直往下读,直到遇到随机字符为止
  • 第二次prinft读取使用memset初始化后的内存后就是正常的空字符了
#include 
#include 
#include 
#pragma warning(disable:4996)

int main() {
	char * q =malloc(6*sizeof(char));
	if (q == NULL) {
		printf("申请失败");
		return 1;
	}
	printf("str = %s\n", q);//str = 屯屯妄?,尝试打印未初始化内存空间的结果,一串随机字符
	memset(q, '\0', 6 * sizeof(char));//使用memset对申请的空间进行初始化,可以避免这个问题
	printf("str = %s\n", q);//str =w
}

八.字符串转数值

1.概述

有点类似于Java的Integer.parseInt方法

**功能:**将指向字符串按数字进行解析成整数并返回

**注意:**传入的字符串的内容必须是数字,否则返回值会是0,即错误

2.使用

头文件:

函数原型:

  • str:要转换的字符串
int atoi(const char *str);

返回值:

  • 转换成功,返回解析出来的整数
  • str 的开始部分不包含可转换的数字或符号,atoi 会返回 0
  • 转换的值超出了 int 类型的表示范围,atoi 会返回 INT_MAXINT_MIN
    • 头文件中定义

3.示例

代码:

#include   
#include   
  
int main() {  
    char str[] = "12345";  
    int num;  
  
    num = atoi(str);  
    printf("这个整数的值是: %d\n", num);  
  
    return 0;  
}

返回值:

这个整数的值是12345

九.字符串切割函数

1.概述

strtok 是C标准库中的一个函数,用于将字符串分解成一系列子字符串。

2.使用

(1)注意事项

  • 这个函数要实现连续切割,必须先只在str传入要切割的字符串切一次,再传入NULL才能实现连续切割,而切割的结束条件,就是当且出来的值位NULL的时候

(2)语法

要分两次进行切割,先用要分解的字符串切一次,接着的就用NULL继续切

函数原型:

  • str:要分解的字符串

    • 第一次调用时传入待分解的字符串
    • 后续调用传入 NULL。
  • delim:分隔符,用于指定分解字符串的分隔符字符集

    • 会把""内任何一个字符都视为分隔符(无需,分隔)
char *strtok(char *str, const char *delim);

3.示例

(1)连续切割

① 步骤
  • 先用strtok传入要分解的字符串切割一次
  • 再传入NULL作要分解的字符串,循环切割
② 代码

打印的位置是有讲究的,放置在下一次切割的前面,保证了上面用str切割的字符能够被打印

#include 
#include 

int main() {
    char str[] = "apple,banana,orange";
    char *token = strtok(str, ",");
    while (token != NULL) {
        printf("%s\n", token);//第一个切出来的apple会在这里被打印,然后token的值才被处理
        token = strtok(NULL, ",");
    }
    return 0;
}
③ 输出
apple
banana
orange

(2)切割练习

切割通信模块返回的字符串,得到手机号、日期、时间、内容这些信息

#include 
#include 
#pragma warning(disable:4996)

/*
参数 1:待切割字符串的首地址
参数 2:指针数组:存放切割完字符串的首地址
参数 3:切割字符
返回值:切割的字符串总数量
*/
int msg_deal(char* msg_src, char* msg_done[], char* delStr) {
	int i = 0;
	msg_done[i] = strtok(msg_src, delStr);
	while (msg_done[i] != NULL) {
		i++;
		msg_done[i] = strtok(NULL, delStr);
	}
	return i;
}

int main() {
	char msg_src[] = "+CMGR:REC UNREAD,+8613466630259,98/10/01,18:22:11,ABCdefGHI";
	char  *msg_done[10];
	int num = msg_deal(msg_src, msg_done, ",");
	//printf("%d", num);
	printf("手机号:%s\n", msg_done[1]+3);//向前移动3个字符,去掉+86
	printf("日期:%s\n", msg_done[2]);
	printf("时间:%s\n", msg_done[3]);
	printf("内容:%s\n", msg_done[4]);
	
}

十.格式化字符串操作函数

1.格式化数据到字符串

类似于printf但这个不会进行打印,而是实质的写入缓冲区,可以理解为就是用来拼接参数组成一个字符串的函数

**过程:**参数 -融合-> 字符串

(1)概述

介绍:sprintfsnprintf都是标准C库函数,用于将格式化的数据写入一个字符串,其中,一个不可以指定字符串长度,一个可以。

**注意事项:**在使用 sprintf 时,务必确保目标缓冲区有足够的空间来存储格式化的字符串,否则可能会导致缓冲区溢出

(2)使用

① Sprintf

函数原型:

  • *buf:指向要写入的字符数组的指针

    大小必须足够容纳格式化后字符串,以及一个额外的\0

  • *format:一个C字符串,包含格式化标签,这些标签会被随后的参数替换

  • ...(可变参数):这些参数根据 format 字符串中的格式说明符来提供值。

int sprintf(char *buf, const char *format, ...);

返回值:

sprintf 函数返回写入 buf 的字符总数(不包括结尾的空字符)。如果发生错误,则返回一个负数。

② Snprintf

**优点:**可以避免sprintf导致的缓存区溢出问题

函数原型:

  • char *str:指向要写入的字符数组的指针

  • size_t size:这是目标缓冲区 str 的大小(以字节为单位)。

    snprintf 会确保不会写入超过 size - 1 个字符到缓冲区,以留出空间放置字符串的结束符 \0

  • const char *format:这是格式字符串,指定了如何格式化后续的参数。

  • ...(可变参数):这些参数根据 format 字符串中的格式说明符来提供值

int snprintf(char *str, size_t size, const char *format, ...);

**返回值:**返回实际写入缓存区的字符数

  • 大于或等于size则说明字符串被截断了

(3)示例

① sprintf
#include 
#pragma warning(disable:4996)

int main() {
	char buf[40];
	int year = 2024;
	int mon = 2;
	int day = 11;
	sprintf(buf, "今天是%d年%d月%d日,新年快乐!", year, mon, day);
	printf("%s\n", buf);//今天是2024年2月11日,新年快乐!
	return;
}
② snprintf

size设置为接受字符数组的长度,保证其不会溢出

#include   
  
int main() {  
    char buf[40]; // 缓冲区大小为40  
    int year = 2024;  
    int mon = 2;
    int day = 11;  
      
    // 使用snprintf确保不会溢出缓冲区  
    snprintf(buf, sizeof(buf), "今天是%d年%d月%d日,新年快乐!", year, mon, day);  
      
    printf("%s\n", buf); // 输出:今天是2024年2月11日,新年快乐!  
      
    return 0;  
}

2.从字符串读取信息

过程: 字符串 -读取-> 参数

(1)概述

sscanf 函数是 C 语言中用于从字符串中读取格式化输入的函数。

(2)使用

函数原型:

  • str 是要从中读取输入的字符串。
  • format 是一个字符串,指定要读取的输入的格式
  • ... 表示与格式字符串对应的附加参数,其中从字符串中读取的值将被存储。
int sscanf(const char *str, const char *format, ...);

返回值sscanf 函数的返回值是成功读取和转换的输入项的数量。如果转换失败,则返回值为负数。

(3)format的编写

① 格式说明符

遇到空格停止匹配,例如%s,遇到Hello Join,只会匹配到Join

  1. %d:读取一个十进制整数。
  2. %f:读取一个浮点数。
  3. %c:读取一个字符。
  4. %s:读取一个字符串(遇到空格或换行符停止)。
  5. %x:读取一个十六进制整数。
  6. %o:读取一个八进制整数。
  7. %u:读取一个无符号十进制整数。
  8. %lf:读取一个双精度浮点数。

运用:

#include 

int main() {
    char str[] = "John 25";
    char name[20];
    int age;

    // 从字符串中读取姓名和年龄
    sscanf(str, "%s %d", name, &age);

    // 打印姓名和年龄
    printf("Name: %s\n", name);
    printf("Age: %d\n", age);

    return 0;
}
② 修饰符

大体都是遇到空格停止匹配,取反符除外

  • %[...]:用于指定要匹配的字符集合。

    例如 %[a-zA-Z] 将匹配a-z以及A-Z的字母字符。

  • %*...:用于忽略输入中的某些数据

    例如:%*d将跳过一个整形,其它的也如此

  • %[width]...:只匹配前width个的字符

    例如:%4s,只获取前4个字符

  • %[^...],取非,匹配除这个外的所有,包括空格

    例如%[^aFc]匹配非aFc的任意字符,包括空格

运用:

#include 
#pragma warning(disable:4996)

int main() {
	char str[20];
	//跳过非#号的,再跳过一个字符,最后获取非@的字符,遇到@停下
	sscanf("abc#def@ghi", "%*[^#]%*c%[^@]", str);
	printf("%s", str);
}

十一.Const

1.概述

const 是C中的关键字,用于定义常量、指定常量指针、以及声明不可修改的变量。

2.使用

(1)定义常量

① 概述

const关键字修饰的变量将变成常量,创建时赋值,赋值后不允许修改

② 例子

创建一个名为 MAX_VALUE 的常量,其值为 100。在程序的其他部分中,不允许修改 MAX_VALUE 的值。

const int MAX_VALUE = 100;

(2)修饰指针

① 指定常量指针

**概述:**常量指针可以指向内存中的数据,但不能通过它来修改内存中的数据

const int *ptr;
② 指向字符常量的指针

**概述:**可以通过这个指针访问、修改其指向的只,但不能修改指针的指向

char * const str
③ 指向常量字符常量的指针

**概述:**指针本身是不可修改的,而且它所指向的字符串也是不可修改的

const char * const str
最后修改:2024 年 03 月 11 日
如果觉得我的文章对你有用,请随意赞赏