字符串函数
strlen
函数原型:size_t strlen(const char* str);
字符串以’\0’作为结束标志,strlen()函数返回的是在字符串中’\0’之前出现的字符的个数,不包含’\0’
字符串必须要以’\0’结束
函数的返回值size_t是unsigned int,无符号数
#include<stdio.h>
#include<string.h>
int main(void)
{
//char arr[] = {'a', 'b', 'c', 'd', '\0'};//输出4.以{}表示的字符串,一定要在{}的最后加上'\0',不加的话,strlen求出的数字未知
char arr[] = "abcd";//常量字符串,会自动在末尾加'\0'
int len = strlen(arr);
printf("%d", len);
getchar();
return 0;
}
简单实现strlen()函数
int my_strlen(char* arr){
int count = 0;
assert(arr != NULL);
while(*arr != '\0'){//while中的条件也可以写成*arr,只要*arr不为0,*arr就一定大于0,就能进while循环,因为ASCII码中,0是最小的
count++;
arr++;
}
return count;
}
对strlen()的返回值size_t是unsigned int(无符号数)的理解
int main(void)
{
if(strlen("abc") - strlen("abcdef") > 0){
printf("abc");
}else{
printf("abcdef");
}
getchar();
return 0;
}
输出的是abc,因为两个无符号数相减的结果依然是无符号数,所以3-6=-3,这个-3要当做无符号数来看待,肯定大于0
strcpy
函数原型:char* strcpy(char* dest, const char* source);
源字符串必须以’\0’结束
会将源字符串中的’\0’拷贝到目标空间
目标空间必须足够大,保证能存储源字符串
目标空间必须可修改
返回值是目标空间的起始地址
#include<stdio.h>
#include<string.h>
int main(void)
{
char source[] = "test";
char dest[] = "abcdefg";
strcpy(dest, source);//从内存中看,可以发现dest数组中的值变为了test\0fg\0
getchar();
return 0;
}
简单实现strcpy()函数
char* my_strcpy(char* dest, const char* source){
assert(dest != NULL);
assert(source != NULL);
while(*source != '\0'){//
*dest = *source;
*dest++;
*source++;
}
*dest = '\0';
return dest;
}
简化写法
char* my_strcpy(char* dest, const char* source){
char * res = dest;
assert(dest != NULL);
assert(source != NULL);
//先赋值,后运算。*dest++ = *source++表达式的结果是*dest的值,所以只要*dest不为\0,while循环就不会退出
while(*dest++ = *source++){
}
return res;
}
strcat
函数原型:char* strcat(char* dest, const char* source);
源字符串必须以’\0’结束
目标空间必须足够大,能够容纳源字符串的内容
目标空间必须可修改
#include<stdio.h>
#include<string.h>
int main(void)
{
char source[] = "world";
char dest[30] = "hello\0xxxxxx";
//strcat函数是找到目标字符串中\0的位置,在\0的前面,追加整个源字符串
//如果目标字符串在非结尾处中有\0,则会在此\0的前面,追加整个源字符串
strcat(dest, source);
//dest变为helloworldx,world\0替换了6个x的位置
getchar();
return 0;
}
简单实现strcat()函数
char* my_strcat(char* dest, const char* source){
char * res = dest;
assert(dest != NULL);//也可以写成assert(dest);
assert(source != NULL);
while(*dest != '\0'){
*dest++;
}
while(*dest++ = *source++){
}
return res;
}
strcmp
函数原型:int strcmp(const char* str1, const char* str2);
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串小于第二个字符串,则返回小于0的数字
第一个字符串等于第二个字符串,则返回等于0的数字
#include<stdio.h>
#include<string.h>
int main(void)
{
char str1[] = "123457";
char str2[] = "123456";
//strcmp会逐个比较两个字符串中的每个char字符,一旦有某个char字符要小,则包含此char字符的字符串为较小的
int res = strcmp(str1, str2);
printf("%d", res);
getchar();
return 0;
}
简单实现strcmp()函数
int my_strcmp(char* str1, const char* str2){
assert(str1 != NULL);
assert(str2 != NULL);
while(*str1 == *str2){
if(*str1 == '\0'){
return 0;
}
*str1++;
*str2++;
}
if(*str1 < *str2 ){
return -1;
}else{
return 1;
}
}
strcpy,strcat,strcmp都是字符串长度不受限制的字符串函数
strncpy,strncat,strncmp都是字符串长度受限制的字符串函数
strncpy
函数原型:char* strncpy(char* dest, const char* source, size_t num);
从源字符串拷贝num个字符至目标空间
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加’\0’,直到总长度达到num个字符
#include<stdio.h>
#include<string.h>
int main(void)
{
char str1[10] = "abcde";
char str2[] = "de";
//str1的内容就会变成de\0de\0\0\0\0\0
strncpy(str1, str2, 3);
getchar();
return 0;
}
简单实现my_strncpy()
char* my_strncpy(char* str1, const char* str2, int num){
int flag = 0;
char* res = str1;
assert(str1 && str2);
while(flag < num){
if(*str2 != '\0'){
*str1 = *str2;
str1++;
str2++;
flag++;
continue;
}
*str1 = '\0';
*str1++;
flag++;
}
return res;
}
strncpy的源码更简洁
char* my_strncpy(char* str1, const char* str2, int num){
char* res = str1;
while(num && (*str1++ = *str2++)){//*str1++ = *str2++的结果就是*str1的值
num--;
}
if(num){
while(num--){
*str1++ = '\0';
}
}
return res;
}
strncat
函数原型:char* strncat(char* dest, const char* source, size_t num);
目标空间必须足够大,能够容纳源字符串的内容
目标空间必须可修改
如果源字符串的长度要小于num,则只会拷贝源字符串到目标空间,不会额外补’\0’
拷贝字符串的最后,会拼接一个’\0’
#include<stdio.h>
#include<string.h>
int main(void)
{
char str1[20] = "abcde\0xxxxxx";
char str2[] = "def";
//str1的内容就会变成abcdedef\0xxx
strncat(str1, str2, 5);
getchar();
return 0;
}
strncmp
函数原型:char* strncmp(char* str1, const char* str2, size_t count);
比较两个字符串中count个字符的大小
strstr
函数原型:char* strstr(const char* str1, const char* str2);
在str1中寻找str2是否存在,如果存在,则返回str1中str2首次出现的首字符地址,如果不存在,则返回空指针
库函数strstr的实现(const类型的指针到非const类型的指针要强制类型转化)
char * __cdecl strstr (
const char * str1,
const char * str2
)
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
strtok
函数原型:char* strtok(char* str, const char* seq);
seq参数是个字符串,定义了用作分隔符的字符集合
str是一个字符串,包含了若干个seq字符串中的分隔符。strtok函数会改变被操作的字符串,所以使用strtok函数切分的字符串一般都是临时拷贝的内容并且可以修改
#include<stdio.h>
#include<string.h>
int main(void)
{
char arr[] = "abc@def.zxc";
char seq[] = "@.";
char copy[20] = {0};
char* res = NULL;
strcpy(copy, arr);
//第一次分割的时候,会找到字符串中的@,将@替换为\0,同时返回分割的前一段的字符串的首地址,即abc中a字符的地址
//同时strtok会记录此时@出现的位置,再次调用时,只需要传一个NULL作为被分割的字符串参数
res = strtok(copy, seq);
printf("%s\n", res);
//第二次分割的时候,会找到字符串中的.,将.替换为\0,同时返回分割的前一段的字符串的首地址,即def中d字符的地址
//同时strtok会记录此时.出现的位置,再次调用时,只需要传一个NULL作为被分割的字符串参数
res = strtok(NULL, seq);
printf("%s\n", res);
//第三次分割的时候,字符串中已经没有需要分割的字符了,返回字符串分割的最后一段的首地址,即zxc中z字符的地址
//如果再分割,字符串中没有需要分割的字符,则返回空指针
res = strtok(NULL, seq);
printf("%s\n", res);
getchar();
return 0;
}
for循环的方式进行分割
#include<stdio.h>
#include<string.h>
int main(void)
{
char arr[] = "abc@def.zxc";
char seq[] = "@.";
char copy[20] = {0};
char* res = NULL;
strcpy(copy, arr);
for(res = strtok(copy, seq); res != NULL; res = strtok(NULL, seq)){
printf("%s\n", res);
}
getchar();
return 0;
}
strerror
函数原型:char* strerror(int errnum);
根据传入的数字,返回对应的错误信息
#include<stdio.h>
#include<string.h>
int main(void)
{
//输入0 输出No error
//输入1 输出Operation not permitted 等等
//传给strerror的数字,就是错误码,返回的就是错误信息
char* res = strerror(1);
printf("%s\n", res);
getchar();
return 0;
}
实际点的用法
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main(void)
{
//errno 是一个全局的错误码变量
//当库函数在执行过程中,发生了错误,就会把对应的错误码,赋值到errno中
FILE* file = fopen("test.txt", "r");
if(file == NULL){
printf("%s\n", strerror(errno));//会输出No such file or directory
}
getchar();
return 0;
}