求字符串长度:
strlen:
注意事项:
- 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为size_t,是无符号的
#include <stdio.h>
int main()
{ const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
模拟实现strlen的三种方法:
//计数器方式
int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//不能创建临时变量计数器
int my_strlen(const char * str)
{
if(*str == '\0')
{
return 0;
}
else return 1+my_strlen(str+1);
}
//指针-指针的方式
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
- 长度不受限制的字符串函数
strcpy
注意事项:
-
源字符串必须以 ‘\0’ 结束。
-
会将源字符串中的 ‘\0’ 拷贝到目标空间。
-
目标空间必须足够大,以确保能存放源字符串。
-
目标空间必须可变
//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char*ret = dest;
while (*dest++ = *src++)//拷贝字符串 包括\0
{
;
}
return ret; //返回的是目标空间的起始地址
}
int main()
{
char arr1[20] = "***********";
char arr2[] = "nice guy";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat
注意事项:
- 源字符串必须以 ‘\0’ 结束
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
//模拟实现strcat 字符追加
#include<stdio.h>
#include<assert.h>
char* my_strcat(char*dest,const char*src)
{
assert(dest&&src != NULL);
char *ret = dest;
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "good ";
char arr2[] = "guy";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcmp
标准规定:
第1个字符串 > 第2个字符串, return大于0的数字
第1个字符串 = 第2个字符串, return 0
第1个字符串 < 第2个字符串, return 小于0的数字
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char*s1, const char*s2)
{
assert(*s1 && *s2 != NULL);
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
//int ret = strcmp("cd", "abcd");
int ret = strcmp("abcd", "cd");
//int ret = strcmp("abcd", "abcd");
printf("%d\n", ret);
return 0;
}
**
- 长度受限制的字符串函数介绍
strncpy
注意事项:
- 拷贝n 个字符从源字符串到目标空间。
如果源字符串的长度<n 则拷贝完源字符串之后,在目标的后边追加0,直到n个
strncpy
#include<stdio.h>
#include<assert.h>
char* my_strncpy(char*dest, const char*src)
{
assert(*dest&&*src);
char * cp = dest;
while (*cp)
{
cp++;
}
while (*cp++ = *src++)
{
;
}
return dest;
}
int main()
{
char arr1[20] = "*******";
char arr2[] = "abc";
my_strncpy(arr1, arr2, 5);
printf("%s\n", arr1);
return 0;
}
strncat
在字符串的结尾追加n个字符。
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[20];
char str2[20];
strcpy (str1,"To be ");
strcpy (str2,"or not to be");
strncat (str1, str2, 6);
puts (str1); return 0;
}
strncmp
#include <stdio.h>
#include <string.h>
int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
printf ("found %s\n",str[n]);
}
return 0;
}
- 字符串查找
strstr
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch; pch = strstr (str,"simple");
strncpy (pch,"sample",6);
puts (str);
return 0;
}
strtok
注意事项:
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
- 错误信息报告
strerror
返回错误码,所对应的错误信息。
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("Error opening file unexist.ent: %s\n",strerror(errno));
//errno: Last error number return 0;
}
- 字符操作
- 内存操作函数
memcpy
注意事项
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的
#include <stdio.h>
#include <string.h>
struct
{
char name[40];
int age;
} person, person_copy;
int main ()
{
char myname[] = "Pierre de Fermat";
memcpy ( person.name, myname, strlen(myname)+1 );
person.age = 46;
memcpy ( &person_copy, &person, sizeof(person) );
printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );
return 0;
}
//模拟实现
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
memmove
注意事项
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "memmove hahahahahahah yes";
memmove (str+20,str+15,11);
puts (str);
return 0;
}
//模拟实现
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count))
{
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else
{
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
memcmp
比较从ptr1和ptr2指针开始的num个字节
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
return 0;
}