入门学习计算机第十七天—字符串函数使用和剖析
编译器:Microsoft Visual Studio 2019
前言:
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 或者 字符数组中,字符串常量适用于那些对它不做修改的字符串函数。
字符函数介绍 :
strlen: 字符串长度
size_t strlen (const char* str)
//typedef unsigned int size_t
- 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’ 前面出现的字符个数。
- 参数指向的字符串必须要以’\0’结束。
- 注意函数的放回值为size_t ,是无符号的(易错)
int main()
{
if (strlen("abc") - strlen("abcdef") > 0)
{
printf("hehe");
}
else
{
printf("haha");
}
return 0;
}
输出的结果是 “hehe”
strlen 返回值的类型是无符号数,两个无符号数相减,得到的结果依然是无符号数
不创建临时变量,求字符串长度
int my_strlen(char* a)
{
if (*a != 0)
return 1 + my_strlen(a + 1);
else
return 0;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", my_strlen(arr));
return 0;
}
输出的结果是6。
strcpy 字符串拷贝
char* strcpy(char* destination ,const char* source);
- 原字符串以’\0’结束
- 会将字符串中的’\0’拷贝到目标空间
- 目标空间必须足够大,以确保能存放原字符串
- 目标空间必须可变
模拟实现strcpy
char* my_strcpy(char* dest, const char* src)
{
assert(dest != NULL);
assert(src != NULL);
char* ret = dest;
//拷贝src指向的字符串到dest指向的空间,包含'\0'
while (*dest++ = *src++)
{
;
}
//返回目的空间的起始地址
return ret;
}
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "bit";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcat 字符串追加
char* strcat (char* destnation, const char* source);
- 原字符串以’\0’结束
- 目标空间必须足够大,以确保能容纳原字符串的内容
- 目标空间必须可修改
- 字符串自己给字节追加?
模拟实现 strcat
char* my_strcat(char* dest, const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
//1.找到目的字符串的'\0'
while (*dest != '\0')
{
dest++;
}
//2.追加
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[50] = "hello";
char arr2[] = "world";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
strcmp 字符串比较
int strcmp(const char *str1 , const char * str2)
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,返回0
- 第一个字符串小于第二个字符串,返回小于0的数字
int main()
{
const char* p1 = "chen";
const char* p2 = "wen";
int rent = (strcmp(p1, p2));
printf("%d\n", rent);
return 0;
}
输出的值是 -1
模拟实现strcmp
int my_strcmp(const char* a1, const char* a2)
{
while (*a1 ==*a2)
{
if (*a1 == '\0')
{
return 0;//相等
}
a1++;
a2++;
}
if (*a1 > *a2)
return 1;//
else
return -1;
}
int main()
{
const char* p1 = "chen";
const char* p2 = "when";
printf("%d\n", my_strcmp(p1, p2));
return 0;
}
strncpy 长度受限制的字符拷贝
char* strncpy(char* strDest, const* strSource , size_t count) //count 的单位是字节
- 拷贝num个字符从原字符串到目标空间
- 如果原字符串的长度小于num,则拷贝完原字符串之后,在目标的后边追加0,直至num个
int main()
{
char arr1[10] = "abcdefgh";
char arr2[] = "hello bit";
strncpy(arr1, arr2, 5);
printf("%s\n", arr1);
return 0;
}
输出的结果是
模拟实现strncpy
char* my_strncpy(char* arr1, char* arr2, int count)
{
char* start = arr1;
while (count && (*arr1++ = *arr2++))
{
count--;
}
if (count)
{
while (--count)
{
*arr1++ = '\0';
}
}
return start;
}
int main()
{
char arr1[10] = "ab";
char arr2[] = "hello bit";
my_strncpy(arr1, arr2, 10);
printf("%s\n", arr1);
return 0;
}
strncat 长度受限制的字符追加
char* strncat(char* strDest, const char* strSource, size_t count)
int main()
{
char arr1[30] = "hello\0XXXXXXX";
char arr2[] ="world";
strncat(arr1,arr2,3);//strncat会主动补\0
printf("%s\n",arr1);
}
模拟实现strncat
char* my_strncat(char* front, const char* back, size_t count)
{
char* start = front;
while (*front++)
{
;
}
front--;
while (count--)
{
if (!(*front++ = *back++))
{
return start;
}
}
*front = '\0';
return start;
}
int main()
{
char arr1[30] = "hello";
char arr2[]= "world";
my_strncat(arr1, arr2, 3);//strncat会主动补\0
printf("%s\n", arr1);
}
strncmp 长度受限制的字符比较
int strncmp(const char* str1 , const char* str2 ,size_t num);
- 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
int main()
{
char arr1[30] = "hello";
char arr2[]= "helle";
int ret = strncmp(arr1, arr2, 4);//strncat会主动补\0
printf("%d\n",ret );
return 0;
}
输出的结果是0
模拟实现strncmp
strstr 寻找子字符串
char* strstr(const char* string, const char * strCharSet)
int main()
{
char* p1 = "abcdef";
char* p2 = "def";
char* ret = strstr(p1,p2);
if(ret == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s\n",ret);
}
return 0;
}
模拟实现
char* my_strstr(const char* str1, const char* str2)
{
assert(str1);
assert(str2);
const char* s1 = str1;
const char* s2 = str2;
const char* cur = str1;
if (*str2 == '\0')
{
return (char*)str1;
}
while (*cur)
{
s1 = cur;
s2 = str2;
while ((*s1!='\0') && (*s2 != '\0') && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cur;
}
if (*s1 == '\0')
{
return NULL;
}
cur++;
}
return NULL;//找不到子串
}
int main()
{
char arr1[30] = "abcdefgih";
char arr2[]= "defasdawrawra";
const char* len = my_strstr(arr1, arr2);
printf("%s\n",len );
return 0;
}
strtok 提取被符号分割的字符串
char* strtok(char* str ,const char* sep)
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串一个或者多个分隔符分割的标记
- strtok 函数找到了str中的下一个标记,并将其用\0结尾 ,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串找到str中的下一个标记,所以使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
- strtok函数的第一个参数不为NULL,函数将找到str第一个标记,strtok函数将保存它在字符串中的位置
- strtok函数的第一个参数为NULL,函数将同一个字符串中被保存的位置开始,查找下一个标记
- 如果字符串不存在更多的标记,则返回NULL指针
函数的基本使用
int main()
{
char arr[] = "abcd.ad.w@er";
const char* p = "@.";
char* len = NULL;
for (len = strtok(arr, p); len != NULL; len = strtok(NULL, p))
{
printf("%s\n", len);
}
return 0;
}
strerror 错误信息函数 需要引头文件<errno.h>
char* strerror(int errnum);
//返回错误码,所对应的错误信息
errno 是一个全局的错误码变量
当C语言的库函数在执行过程中,发生了错误,将会把对应的错误码,赋值到errno中
函数使用:打开text.txt文件
int main()
{
FILE* pf = fopen("text.txt", "r");//打开文件
if (pf == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
printf("open file success\n");
}
return 0;
}
当code文件夹下没有text.txt文件时:
没有该文件或者目录
当文件下有text.txt文件时
字符转换:需要引头文件 <ctype.h>
int tolower(int c);//大写转小写
int toupper(int c);//小写转大写
int main()
{
char arr = tolower("Q");
putchar(arr);
}
输出的结果是q
将一个字符串全部打印成小写
int main()
{
char arr[] = "I Am A Student";
int i = 0;
while (arr[i])
{
if (isupper(arr[i]))//判断是否为大写
{
arr[i] = tolower(arr[i]);
}
i++;
}
printf("%s\n", arr);
return 0;
}
输出的结果为:
内存函数
memmove: 内存移动函数
void* memmove(void* destination ,const void* soure,size_t num);
- 和mencpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
memcpy: 内存拷贝函数
void* memcpy(void* destination , const void* source, size_t num)
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
- 这个函数在遇到’\0’的时候并不会停下来
- 如果source和destination有任何的重叠,复制的结果都是未定义的
int main()
{
int arr1[] = {1,2,3,4,5,6};
int arr2[] = {0};
memcpy(arr2,arr1,6);
}
模拟实现memcpy函数:
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest);
assert(src);
void* ret = dest;
while(num--)
{
*(char*)dest = *(char*)src;
++(char*)dest;
++(char*)src;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1,sizeof(arr1));
return 0;
}
计算机知识/代码知识(零碎)
阅读文档的时候:
NULL - 空指针
NUL / Null - ‘\0’