本文将简要介绍这些常用的C语言字符串函数,包括它们的基本功能和使用方法。通过具体的代码示例,我们将展示如何在实际编程中运用这些函数来处理字符串。
注:使用库函数里的字符串,就需要包含头文件string.h,也就是#include<string.h>
strlen函数使用及实现
strlen - C++ 参考 (cplusplus.com)
函数声明 size_t strlen ();
主要就是求出指定字符串,或者字符串数组的元素个数,见代码:
#include<stdio.h>
#include<string.h>
int main()
{
const char* arr = "This is string";
printf("字符串长度为%d\n", strlen(arr));
return 0;
}
但这个函数存在错误的使用方法,
这次的结果就跟正确的答案差太远了,是因为函数strlen的测量长度的时候碰到了‘\0’就会停下,而‘\0’就是字符数组结束标志,但在这里的数组没有'\0'符存在,strlen
函数会继续在内存中查找,直到它遇到一个偶然的零值(这可能是在其他内存位置上的),或者直到它访问到它不应该访问的内存区域(这可能导致未定义行为,如程序崩溃),就需要在最后一个字符位置加上一个'\0'。
接下来是C语言的实现:
size_t our_strlen(const char* str)
{
if (*str=='\0')
return 0;
else
return 1 + our_strlen(str+1);
}
这里使用了递归的方法,但是效率较低,所以存在另一个方法:
size_t our_strlen(const char* str)
{
size_t count = 0;
for (count = 0; *str; count++, str++)
;
return count;
}
用指针遍历,然后count跟着指针走,直至遇到‘\0’停止,因为‘\0’的ascll码值是0,相当于指针指向的地址存放的值不为0。strlen函数返回值是size_t,这里也采用同样的类型。
strcpy函数使用及实现
strcpy - C++ 参考 (cplusplus.com)
是将一个字符串尽数复制到另一个指定字符串中,返回值是char*类型,但是也可以不需要接收返回值。使用结构:strcpy(char* dest ,const char* source)后者复制到前者
#include <stdio.h>
#include <string.h> // 为了使用strcpy
int main()
{
char arr1[20]= "nihao hello";
char arr2[20] = "no helloaff";
char* p = arr1, *q = arr2;
strcpy(p,q); // 这会覆盖arr1的内容
// 打印修改后的arr1的内容
while (*p)
{
printf("%c",*(p++));
}
printf("\n");
return 0;
}
arr1中的元素都被arr2给覆盖了。但为避免溢出,指向的数组的大小应足够长,以包含与相同的 C 字符串(包括终止 null 字符),并且不应在内存重叠。
比如说
这样的结果是会出错误的 ,导致两个数组的内容都被改了。
接下来是代码的实现:
char* my_strcpy(char* det, const char* sou)//sou指针不能被改变
{
assert(det!=NULL);//设置两个宏防止报错
assert(sou!=NULL);//
char* ret = det;//记录指针原来的位置
while (( *det++=*sou++))
;
return ret;
}
在while语句中,执行的代码都是赋值,然后两个指针向后走,所以可以都放在判断条件中,是代码简便许多。
比较直观的代码就是这样:
char* my_strcpy(char* det, const char* sou)
{
char* ret = det;
while (*sou!='\0' || *det!='\0')
{
*det = *sou;
det++;
sou++;
}
return ret;
}
strcat函数使用及实现
strcat - C++ 参考 (cplusplus.com)
用于连接(拼接)两个字符串,这个函数将第二个字符串(即源字符串)添加到第一个字符串(即目标字符串)的末尾,同时假设第一个字符串有足够的空间来存储结果字符串:
函数声明:char *strcat(char *dest, const char *src);
代码的使用如下:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[40] = "Hello, ";
char arr2[] = "world!";
strcat(arr1, arr2);
// 打印连接后的字符串
printf("%s\n", arr1); // 输出:Hello, world!
return 0;
}
代码实现如下:
char* our_strcat(char* dest, const char* src)
{
char* ret = dest;
while (*dest != '\0')
dest++;
while (*src != '\0')
*dest++ = *src++;
*dest = *src;
return ret;
}
先让第一指针走到第一个字符串末尾,然后再追加字符串在其后,但在之前就要记录好指针的开头作为返回的值,结果就完成了。
简化了就是这样:
char* our_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest!=NULL);//设置宏防止报错
assert(src != NULL);
while (*dest)
dest++;
whlie(*dest++ = *src++)
;
return ret;
}
跟前面的strcpy代码有着相似的用法。
strcmp函数使用及实现
strcmp - C++ 参考 (cplusplus.com)
用于两个字符串的比较,函数格式:
int strcmp ( const char * str1, const char * str2 ); str2大于str1就返回大于0的数,如果两个字符串都相同,就返回0,如果小于就返回小于0的数。字符串的比较都是各个字符元素逐个比较,比较的是字符的ascll码值。这里就不示范使用方法了,直接实现:
int our_strcmp(const char* str1, const char* str2)
{
while (*str1==*str2)
{
if (*str1 == '\0'||*str2=='\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
写一个while语句,只要两个比较元素都相同,就一直向后走,如果任一字符串到最后都一样,就返回0,如果有了不同,就跳出循环,直接返回比较结果。
strstr函数使用及实现
strstr - C++ 参考 (cplusplus.com)
函数声明 char * strstr ( const char *str1, const char *str2 );
此函数比较两个字符串,返回str2首次出现在str1中的首位置,返回值为char*意味着返回值并不是数组下标,而是指针地址。以下是此函数的模拟实现:
char* Strstr( const char* src, const char* dest)
{
char* s = dest;//记录dest首地址
if (dest==NULL)//如果是空指针直接返回NULL
{
return NULL;//NULL值需要包含stdio.h头文集……
}
int c = 0;//用来计算dest指向字符串的长度,首先记为0
while (src!='\0')//也可以写成src
{
if (*dest==*src)
{
dest++;
src++;
c++; //dest指向的值与src指向的值相同,c开始计数
}
else
{
c = 0;//如果向后比较的值为开始不一样,c重新变为0,方便重新计数
src++;
dest = s;
}
if (*dest == '\0')//如果dest指向的字符串查找完成返回所需要的位置
return src-c;
}
return NULL;
}
我们可以用两个指针逐一元素比较,src指针一直向后查找,如果两个指针的值开始相同,就都向后比较,如果向后不同,dest就指向起始位置,在这里我指针的值建立了一个s指针(记录dest指向字符串的首地址并且用来让dest复位的指针)和一个int类型的c变量(用来记录dest指向字符串的长度),当dest查找完成,就返回用src地址减去c值而得到的dest第一个元素出现时的地址。
如果查找到src结束都没有找到,就返回空指针就会比较合理,如果dest本身就是空指针,就返回NULL也很合理。
函数投入使用:
#include<stdio.h>
char* Strstr( const char* src, const char* dest)
{
char* s = dest;
if (dest==NULL)
{
return NULL;
}
int c = 0;
while (src!='\0')
{
if (*dest==*src)
{
dest++;
src++;
c++;
}
else
{
c = 0;
src++;
dest = s;
}
if (*dest == '\0')
return src-c;
}
return NULL;
}
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = Strstr (str,"simple");
if (pch != NULL)
strncpy (pch,"sample",6);
puts (str);
return 0;
}
函数就是将字符串“sample”,替换其中的“simple”。
接下来再写几个我还没有实现的字符串函数。
strncpy函数使用
strncpy - C++ 参考 (cplusplus.com)
函数的声明:
char * strncpy ( char * destination, const char * source, size_t num );
此函数与前面strcpy功能相同,可以看见此函数相比较于strcpy函数多了一个size_t类型参数,意思就是规定了指定长度的字符。
#include <stdio.h>
#include <string.h>
int main()
{
char src[] = "Hello, world!";
char dest[20];
// 使用 strncpy 复制最多 11 个字符(包括空字符)到 dest
strncpy(dest, src, 11);
dest[10] = '\0';
printf("Source string: %s\n", src);
printf("Copied string: %s\n", dest);
return 0;
}
如果理解了strcpy函数,那么这个函数就简单了。
strncat函数使用
同样的,此函数和strcat功能相同,但规定了使用长度。
#include <stdio.h>
#include <string.h>
int main() {
char dest[50] = "Hello, ";
char src[] = "world!";
size_t dest_len = strlen(dest);
size_t src_len = strlen(src);
strncat(dest, src, sizeof(dest) - dest_len - 1);
printf("Concatenated string: %s\n", dest);
return 0;
}
strncmp函数使用
不用多说跟前两者相同的,在strncmp函数的基础上规定了指定长度,直接看代码:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "Hello, world!";
char str2[] = "Hello, universe!";
int result = strncmp(str1, str2, 5);
if (result < 0)
{
printf("The %zu characters of str1 are less than str2.\n", 5);
} else if (result > 0)
{
printf("The %zu characters of str1 are greater than str2.\n", 5);
} else
{
printf("The %zu characters of str1 are equal to str2.\n",5);
}
return 0;
}
此外还有一些字符分类函数:
函数名 | 描述 | 示例用法 |
---|---|---|
isalpha() | 判断字符是否为字母(包括大写和小写) | if (isalpha('A')) { ... } |
isupper() | 判断字符是否为大写字母 | if (isupper('A')) { ... } |
islower() | 判断字符是否为小写字母 | if (islower('a')) { ... } |
isdigit() | 判断字符是否为数字(0-9) | if (isdigit('5')) { ... } |
isalnum() | 判断字符是否为字母或数字 | if (isalnum('a')) { ... } <br>if (isalnum('5')) { ... } |
isspace() | 判断字符是否为空白字符(包括空格、制表符、换行符等) | if (isspace(' ')) { ... } <br>if (isspace('\t')) { ... } |
iscntrl() | 判断字符是否为控制字符(ASCII码在0-31之间,包括DEL字符) | if (iscntrl('\n')) { ... } (注意:换行符不是控制字符,这里仅为示例) |
ispunct() | 判断字符是否为标点符号 | if (ispunct('.')) { ... } <br>if (ispunct(',')) { ... } |
isxdigit() | 判断字符是否为十六进制数字(0-9, A-F, a-f) | if (isxdigit('A')) { ... } <br>if (isxdigit('f')) { ... } |
isgraph() | 判断字符是否为可打印的图形字符(不包括空格) | if (isgraph('+')) { ... } <br>if (isgraph('*')) { ... } |
isprint() | 判断字符是否为可打印字符(包括空格) | if (isprint(' ')) { ... } <br>if (isprint('+')) { ... } |
感谢您花时间阅读我的博客。我希望通过我的分享,能够为您带来一些帮助,如果您有任何疑问、建议或想要深入讨论的话题,请在评论区留言