前言
从语言对字符和字符串的处理时很频繁的,但是C语言本身是没有字符串类型的,字符串通常放在字符串常量中或者字符数组中,字符串常量适用于那些对它不做修改的字符串函数
1.求字符串长度
1.1 strlen
size_t strlen(const char* str);
size_t 就是 unsigned int 类型。
注意:
- 字符串已经'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
- 参数指向的字符串必须要以‘\0'结束。
- 注意函数的返回值为size_t,是无符号的(易错)
示例:
#include<stdio.h> #include<string.h> int main() { int len = strlen("abcedf"); printf("%d\n", len);//6 char arr[] = "abc\0def"; len = strlen(arr); printf("%d\n", len);//3 char arr1[3] = { 'a','b','c' };//没有 '\0' len = strlen(arr1); printf("%d\n", len);//随机值 return 0; }
返回值是 size_t 类型
#include<stdio.h> #include<string.h>//VS不写头文件,会把返回值当为int类型 int main() { //strlen函数的返回值是size_t - 无符号整形 if (strlen("abc") - strlen("abcdef") > 0) { printf(">\n");//输出 } else { printf("<=\n"); } return 0; }
自己模拟实现strlen函数,3种方法
1.计数器
2.递归
3.指针-指针
#include<stdio.h> #include<assert.h> //1.计数器 int my_strlen1(const char* arr) { assert(arr != NULL); int count = 0; while (*arr) { count++; arr++; } return count; } //2.递归 int my_strlen2(const char* arr) { if (*arr != '\0') { return my_strlen2(arr + 1) + 1; } else { return 0; } } //3.指针-指针 int my_strlen3(const char* arr) { char* start = arr; while (*arr != '\0') { arr++; } return arr - start; } int main() { char arr[] = "bit"; int ret = my_strlen3(arr); printf("%d\n", ret); return 0; }
2.长度不受限制的字符串函数
2.1 strcpy 字符串拷贝函数
char* strcpy(char* destination, const char* source);
把 source 处的字符串拷贝到 destination 处。
注意:
- 源字符串必须以'\0'结束。
- 会将源字符串中的'\0'拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
示例:
#include<stdio.h> #include<string.h> int main() { char arr1[] = "abcdef"; char arr2[20] = { 0 }; strcpy(arr2, arr1);//arr2是目的地,拷贝到'\0',并且把'\0'拷贝过去 输出abcdef printf("%s\n", arr2); char arr3[] = "abc\0def"; strcpy(arr2, arr3);//拷贝到'\0',并且把'\0'拷贝过去 输出abc printf("%s\n", arr2); //目标空间必须可变 //char* p = "abcdefghi"; //char arr4[20] = "hehe"; //strcpy(p, arr4);//错误,p指向的是常量字符串,不能被修改 return 0; }
自己模拟实现 strcpy 函数
#include<stdio.h> #include<assert.h> //返回是目标空间的起始地址 char* my_strcpy(char* destination, const char* source) { assert(destination && source);//不能为空 int start = destination; while (*destination++ = *source++); return start; } int main() { char arr1[] = "abcdef"; char arr2[20] = "0"; my_strcpy(arr2,arr1); printf("%s\n", arr2); printf("%s\n", my_strcpy(arr2, arr1)); return 0; }
2.2 strcat 字符串追加函数
char* strcat(char* destination, const char* source);
将 source 处字符串追加到 destination 处
注意:
- 源字符串必须以‘\0'结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 字符串自己不能给自己追加。
示例:
#include<stdio.h> #include<string.h> int main() { char arr1[20] = "hello "; char arr2[] = "world"; //追加 strcat(arr1, arr2);//从字符串的'\0'开始追加 printf("%s\n", arr1); //输出 hello world return 0; }
我们通过自己模拟实现,就可以理解为什么不可以自己给自己追加:
#include<stdio.h> #include<assert.h> char* my_strcat(char* desination, const char* source) { assert(desination && source); char* start = desination; while (*desination)//找到目标空间的第一个'\0' { desination++; } while (*desination++ = *source++);//拷贝字符串 return start; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; my_strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
自己给自己追加,desination 和 source 相同,会修改自己最后的'\0',使得拷贝遍历的时候找不到自己的'\0'。
2.3 strcmp
int strcmp( const char* str1, const char* str2);
注意:
C语言标准规定
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
如何比较两个字符串:
比较的是相同位置上字符的ASCII码值,相等比较下一位,如果比到'\0'都相等,返回0。否则第一个ASCII码值大则返回大于0的数字,则小返回小于0的数字。
示例:
#include<stdio.h> int main() { if ("abcdef" == "cdefg");//可以比较,比较的是两个常量字符串的首字符地址 //比较两个字符串的内容的时候,应该使用strcmp char arr1[] = "abcdef"; char arr2[] = "cdefg"; int ret = strcmp(arr1, arr2);//比较的是对应位置上字符的ASCII码值, //相等比较下一位,如果比到'\0'都相等,返回0 //arr1的ASCII码值大,返回大于0的数字, //arr1的ASCII码值小,返回小于0的数字 printf("%d\n", ret); return 0; }
自己模拟实现:
#include<stdio.h> #include<assert.h> int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2) { if (*str1 == '\0') { return 0; } str1++; str2++; } //return *str1 - *str2;//没有说必须返回-1,或1 if (*str1 > *str2) { return 1; } else return -1; } int main() { char arr1[] = "qwer"; char arr2[] = "asdf"; int ret = my_strcmp(arr1, arr2); printf("%d\n", ret); return 0; }
3.长度受限制的字符串函数介绍
3.1 strncpy
char* strncpy(char* destination, const char* source, size_t num);
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
示例:
#include<stdio.h> #include<string.h> int main() { char arr1[] = "abcdef"; char arr2[5] = "xxxx"; //数字大于arr1长度是会补\0的 strncpy(arr2, arr1, 3);//abcx printf("%s\n", arr2); return 0; }
3.2 strncat
char* strncat (char* destination, const char* source, size_t num);
将 source 处的前num的字符追加到destination字符串后面'\0'处。
#include<stdio.h> #include<string.h> int main() { char arr1[20] = "hello "; char arr2[] = "world"; //数字大于arr2长度 不会再补多余的'\0' strncat(arr1, arr2, 3);//追加完后面会补'\0' printf("%s\n", arr1);//输出hello wor return 0; }
strncmp可以自己给自己追加。num写成自身长度。
3.3 strncmp
int strncmp(const char* str1,const char* str2, size_t num);
比较到出现一个字符不一样或者一个字符串结束或者num个字符全部比较完。
返回值:
示例:
#include<stdio.h> #include<string.h> int main() { char arr1[] = "abcdef"; char arr2[] = "abc"; //输入要比较几个字符 int ret = strncmp(arr1, arr2, 3); printf("%d\n", ret); return 0; }
4.字符串查找
4.1 strstr
char* strstr(const char* str1, const char* str2);
在str1中找str2首次出现的地址 ,没有找到返回空指针
示例:
#include<stdio.h> #include<string.h> int main() { char arr1[] = "abcdef"; char arr2[] = "bcd"; char* p = strstr(arr1, arr2); if (p == NULL) { printf("没有找到\n"); } else { printf("%s\n", p);//bcdef } return 0; }
自己模拟实现
#include<stdio.h> char* my_strstr(const char* str1, const char* str2) { while (*str1!='\0') { const char* p1 = str1; const char* p2 = str2; while (*p1 == *p2) { if (*(p2+1) == '\0') { return (char*)str1; } p1++; p2++; } str1++; } return NULL; } int main() { char arr1[] = "abcdef"; char arr2[] = "bcd"; char* p = my_strstr(arr1, arr2); if (p == NULL) { printf("没有找到\n"); } else { printf("%s\n", p);//cdef } return 0; }