字符函数和字符串函数
(本章重点)
1.求字符长度
1.strlen
2.长度不受限制的字符串函数
2.strcpy 3.strcat 4.strcmp
3.长度受限制的字符串长度介绍
5.strncp 6.strncat 7.strncm
4.字符串查找
8.strstr 9.strtok
5错误信息报告
10.streroor
6.字符操作
7.内存操作函数
11.memcpy 12.memmove 13.memset 14.memcmp
函数介绍
1.strlen
size_t strlen( const char * str); 1.字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数不包括('\0')。
2.参数指向的字符串必须要以'\0'结束。 3.注意函数的返回值为size_t,是无符号的(易错)
不使用变量的递归函数实现strlen
#include
unsigned int my_strlen(const char* p)
{
assert(p);
if (*p != '\0')
{
return (my_strlen(++p)+1);
}
else
{
return 0;
}
}
int main()
{
char arr[] = "abcdef";
my_strlen(arr);
printf("%d", my_strlen(arr));
}
2.strcpy
char *strcpy(char * destination(目的地),const char * source(源头)); 将源头拷贝到目的地
源字符串必须以'\0'结束。 会将源字符串中的'\0''拷贝到字符空间. 目标空间必须足够大,以确保能存放源字符串。 目标空间必须可变。 学会模拟实现。
#include
char * my_strcpy(char* p1, const char* p2)
{
assert(p1!=NULL);
assert(p2!=NULL);
char *ret=p1;
//拷贝p2指向的字符串到p1指向的空间,包含'\0'
while (*p1++ = *p2++);
return ret;//返回目的空间的起始地址
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bit";
//strcpy(arr1, arr2);
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
3.strcat
char* stract(char* destination, const char* source) 1.源字符串必须以'\0'结束 2.目标空间必须足够大能容纳下源字符串的内容。 3.目标空间必须可以修改。 4.字符串自己给自己追加如何? 5.自己实现strcat
//实现strcat
char* my_strcat(char* p1, const char* p2)
{
char* p3 = p1;
while (*p1++);
p1--;
while (*p1++ = *p2++);
return p3;
}
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "love";
char *p = my_strcat(arr1, arr2);
printf("%s\n",p);
return 0;
}
4.strcmp
int strcmp ( const char * str1, const char * str2 ); 比较两个字符串 将 C 字符串 str1 与 C 字符串 str2 进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或达到终止空字符。
此函数执行字符的二进制比较。有关考虑特定于区域设置的规则的函数,请参阅 strcoll。 标准规定: 1.第一个字符串大于第二个字符串,则返回大于0(>0)的数字 2第一个字符串等于第二个字符串则返回0 3.第一个字符串小于第二个字符串则返回小于0(<0)的数 4.那么如何判断两个字符串 用函数实现strcmp
//自己实现strcmp
int my_strcmp(const char* p1,const char* p2)
{
assert(p1 && p2);
while (*p1 == *p2)//判断是否相等相等就能进去
{
if (*p1 == '\0')
return 0;
p1++;
p2++;
}
if (*p1 > *p2)
return 1;
else if (*p1 < *p2)
return -1;
}
int main()
{
char* p1 = "abcdefgh";
char* p2 = "abcdefgh";
int ret = my_strcmp(p1, p2);
printf("%d", ret);
return 0;
}
5.strncpy
char * strncpy ( char * destination, const char * source, size_t num ); 1.拷贝num个字符从源字符到目标空间 2.如果源字符串的长度小于num,则拷贝完源字符串后在后面追加0,知道追加到sum个 3.实例
//自己实现strncpy
char* my_strncpy(char* p1, const char* p2, int k)
{
assert(p1 && p2);
int a = 0;
char* p3 = p1;
for (a = 0; a < k; a++)
{
if (*p2 == '\0')
{
while (a++ < k && (*p1++ = '\0'))
return p3;
}*p1++ = *p2++;
}
return p3;
}
int main()
{
char arr1[30] = " zhangyanshu";
char arr2[] = "love";
int k = 0;
scanf_s("%d", &k);
char* p = my_strncpy(arr1, arr2, k);
printf("%s\n", p);
return 0;
}
6.strncat
char * strncat ( char * destination, const char * source, size_t num ); 1.从字符串追加字符 2.将源的第一个字符追加到目标,以及终止空字符。
3.如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。 4.实现strncat(自己实现的和库函数好相似)
//自己实现strncat
char* my_strncat(char* p1, const char* p2, unsigned int k)
{
char* p3 = p1;
assert(p1 && p2);
while (*p1++);
--p1;
while (k-- && (*p1++ = *p2++))
if (*p1 == '\0')
return p3;
*p1 = '\0';
return p3;
}
int main()
{
char arr1[30] = "I LOVE YOU ";
char arr2[] = "zhangyanshu";
int k = 0;
scanf_s("%d", &k);
char *ret=my_strncat(arr1, arr2, k);
printf("%s\n", ret);
return 0;
}
7.strncmp
int strncmp ( const char * str1, const char * str2, size_t num ); 比较两个字符串的字符 将 C 字符串 str1 的数目与 C 字符串 str2 的数目进行比较。 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止空字符,或者直到两个字符串中的数字字符匹配,以先发生者为准。 实例
//自己实现strncmp
int my_strncmp(const char* p1, const char* p2, size_t p)
{
assert(p1 && p2);
--p1,--p2;
while (p--&&( *p1++ == *p2++))
{
if (*p1 != *p2)
if (*p1 > *p2)
return 1;
else
return -1;
}
return 0;
}
int main()
{
const char *arr1 = "abcdef";
const char *arr2 = "abcdxyz";
int k = 0;
scanf_s("%d", &k);
int ret=my_strncmp(arr1, arr2, k);
if (ret == 0)
printf("相等\n");
else if (ret == 1)
printf("上面字符大于下面字符");
else
printf("下面字符大于上面字符");
return 0;
}
8.strstr
const char * strstr ( const char * str1, const char * str2 );
查找子字符串 返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回空指针。
匹配过程不包括终止空字符,但它止步于此。 实例
//自己实现strstr重点!!!
char* my_strstr(const char* p1, const char* p2)
{
assert(p1 && p2);
if (*p2 == '\0')
return(char*) p1;
const char* m = NULL;
const char* n = NULL;
while (*p1++)
{
m = p1,n = p2;
while (m && n && !( * m - *n))//如果相减为0,感叹号则为真继续执行
{
m++,n++;
if (*n == '\0')
return (char*)p1;
if (*m == '\0')
return NULL;
}
}
return NULL;
}
int main()
{
const char* arr1 = "abc";
const char* arr2 = "abcdef";
const char* p = my_strstr(arr1, arr2);
if (p == NULL)
printf("没找到了\n");
else
printf("找到了%s\n", p);
return 0;
}
9.strtok
char * strtok ( char * str, const char * delimiters );
段落引用 将字符串拆分为标记 对此函数的一系列调用将 str 拆分为标记,这些标记是由作为分隔符一部分的任何字符分隔的连续字符序列。 段落引用 在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,其第一个字符用作扫描令牌的起始位置。在后续调用中,该函数需要一个空指针,并将紧跟在最后一个令牌结束之后的位置用作扫描的新起始位置。 段落引用 若要确定令牌的开头和结尾,该函数首先从起始位置扫描分隔符中未包含的第一个字符(该字符将成为令牌的开头)。然后从令牌的开头开始扫描分隔符中包含的第一个字符,该字符将成为令牌的结尾。如果找到终止空字符,扫描也会停止。 段落引用 令牌的此末尾将自动替换为空字符,令牌的开头由函数返回。 段落引用 在对 strtok 的调用中找到 str 的终止空字符后,对此函数的所有后续调用(以空指针作为第一个参数)将返回空指针。 段落引用 找到最后一个令牌的点由函数在内部保留,以便在下一次调用时使用(不需要特定的库实现来避免数据争用)。 用法
//strtok
int main()
{
char arr[] = "w18602600146@163.com";
char p[] = "@.";
char buf[1024] = { 0 };
strcpy(buf, arr);
//切割buf中的字符
char* ret=NULL;
for (ret=strtok(buf,p); ret != NULL; ret = strtok(NULL, p))
{
printf("%s ", ret);
}
return 0;
}
10.strerror
char * strerror ( int errnum );
errnum 错误号。 返回值 指向描述错误错误的错误字符串的指针。
11.字符分类函数
字符转换函数 tolower 将大写字母转换为小写字母 如果 c 是大写字母并且具有等效的小写字母,则将 c 转换为其小写等效项。如果无法进行此类转换,则返回的值为 c 不变。
请注意,什么被认为是字母可能取决于所使用的区域设置;在默认的“C”语言环境中,大写字母是以下任何一个:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z,分别翻译为:a b c d e f g h i j k l m n o p q r s t u v w x y z。
在其他区域设置中,如果一个大写字符具有多个对应的小写字符,则此函数始终为相同的 c 值返回相同的字符。
在 C++ 中,此函数的特定于区域设置的模板版本(tolower)存在于标头
12.memcpy
- memcpy
- void * memcpy ( void * destination, const void * source, size_t num );
- 复制内存块
- 将 num 字节值从源指向的位置直接复制到目标指向的内存块。
- 为避免溢出,目标参数和源参数所指向的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。 自己实现memcpy
#include
void* my_memcpy(void* dest, const void* src, size_t p)
{
assert(dest && src);
void* arr = dest;
if (dest < src)
{
while (p--)
{
* (char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
else
while (p--)
*((char*)dest + p) = *((char*)src + p);
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
my_memcpy(arr1, arr1 + 3, 20);
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
13.memcmp
memcmp int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 比较两个内存块 将 ptr1 所指向的内存块的前 num 个字节与 ptr2 指向的第一个字节数进行比较,如果它们都匹配,则返回零,或者如果不匹配,则返回与零不同的值,表示哪个值更大。
请注意,与 strcmp 不同,该函数在找到空字符后不会停止比较。
14.memset
void * memset ( void * ptr, int value, size_t num ); 填充内存块 将 ptr 所指向的内存块的前一个字节数设置为指定值(解释为无符号字符)。
//memset
int main()
{
char arr[10] = "";
memset(arr, '#', 10);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%c", arr[i]);
}
return 0;
}