字符函数和字符串函数
在编程中,我们经常要处理字符和字符串,为了方便操作字符和字符串,C语言标准库中提供了一系列库函数。 C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。这些函数的使用都需要包含一个头文件 例如 在之前,要一个字符大小写转换打印,用的是 C语言提供了2个字符转换函数: 举个例子: 含 示意图: 另,字符串匹配算法——KMP算法。 举个例子: 在不同的系统和C语言标准库的实现中都规定了一些错误码,一般是放在 除此之外,还有一个函数 举个例子:1 字符函数
1.1 字符分类函数
ctype.h。islower、isupper等,以islower为例:int islower (int c);islower能够判断参数部分的c是否是小写字母。通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。关于(int c),要注意到字符的本质是一个ASCII码值,这样的写法并没有问题。1.2 字符转换函数
字符+/-32来实现的,例如:大写转小写就加上32、小写转大写就减去32(参见ASCII码相关知识)。现在,我们可以用以下库函数来更简洁的解决。int tolower (int c);//将参数传进去的大写字母转小写
int toupper (int c);//将参数传进去的小写字母转大写#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <ctype.h>
int main()
{
char i = 'a';
//i = i - 32;
i = toupper(i);
printf("%c\n", i);
return 0;
}2 字符串函数
1
strlen的使用和模拟实现size_t strlen ( const char * str );'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包'\0')。'\0'结束。size_t,是无符号的(⭐)。strlen的使用需要包含头文件string.h。strlen的模拟实现:#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include <stdio.h>
#include <assert.h>
//模拟实现strlen
size_t my_strlen1(const char* str)
{
assert(str != NULL);
size_t n = 0;
while (*str != '\0')
{
n++;
str++;
}
return n;
}
size_t my_strlen2(const char* str)
{
assert(str != NULL);
char* p = str;
while (*p)
{
p++;
}
return p - str;
}
size_t my_strlen3(const char* str)
{
assert(str != NULL);
if (*str)
{
return 1 + my_strlen3(str + 1);
}
else
{
return 0;
}
}
int main()
{
char arr[] = { "abcdef" };
size_t r = strlen(arr);
size_t r1 = my_strlen1(arr);
size_t r2 = my_strlen2(arr);
size_t r3 = my_strlen3(arr);
}2
strcpy的使用和模拟实现char * strcpy ( char * destination, const char * source );'\0'结束。'\0'拷贝到目标空间。strcpy的模拟实现:#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include <stdio.h>
#include <assert.h>
//模拟实现strcpy
//char* my_strcpy(char* des, const char* src)
//{
// assert(des != NULL && src != NULL);
// char* ret = des;
// while (*src)
// {
// *des = *src;
// des++;
// src++;
// }
// *des = '\0';
// return ret;
//}
char* my_strcpy(char* des, const char* src)
{
assert(des != NULL && src != NULL);
char* ret = des;
while (*des++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = { "abcdef" };
char arr2[20] = {"xxxxxxxxxxxxxxxx"};
my_strcpy(arr2, arr1);
}3
strcat的使用和模拟实现char * strcat ( char * destination, const char * source );'\0'结束。'\0',否则没办法知道追加从哪里开始。strcat模拟实现:#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* des, const char* src)
{
assert(des && src);
char* ret = des;
while (*des != '\0')
{
des++;
}
while (*des++ = *src++)
{
;
}
return ret;
}
int main()
{
char a[20] = { "Hello \0xxxxxxxxxxx" };//目标字符串要有足够位置
char b[10] = { "world" };
//strcat(a, b);
my_strcat(a, b);
printf("%s\n", a);
}4
strcmp的使用和模拟实现int strcmp ( const char * str1, const char * str2 );
strcmp模拟实现:#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp1(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return (*str1 - *str2);
}
int my_strcmp2(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
return 1;
else
return -1;
}
int main()
{
char a1[] = { "abcdef" };
char a2[] = { "abq" };
int r = strcmp(a1, a2);
int r1 = my_strcmp1(a1, a2);
int r2 = my_strcmp2(a1, a2);
return 0;
}strcpy、strcat、strcmp三个函数有对应的更安全的版本(要多传一个参数),它们分别是strncpy、strncat和strncmp。5
strncpy函数char * strncpy ( char * destination, const char * source, size_t num );num个字符从源字符串到目标空间。num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。6
strncat函数char * strncat ( char * destination, const char * source, size_t num );source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加一个\0字符)。source指向的字符串的长度小于num的时候,只会将字符串中到\0的内容追加到destination指向的字符串末尾)。7
strncmp函数int strncmp ( const char * str1, const char * str2, size_t num );str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不一样,就提前结束。返回值标准参照strcmp函数。8
strstr的使用和模拟实现const char * strstr ( const char * str1, const char * str2 );str2在字符串str1中第一次出现的位置)。\0字符,以\0作为结束标志)。strstr模拟实现:#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* cur = str1;//记录比较的起始位置
const char* s1 = NULL;//用s1在str1中遍历
const char* s2 = NULL;//用s2在str2中遍历
//特殊情况:str2是一个空字符串
if (*str2 == '\0')
return str1;
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return (char*)cur;
cur++;
}
return NULL;//找不到
}
int main()
{
char a[] = { "abbbcdef" };
char b[] = { "bbc" };
//char* r = strstr(a, b);
char* r = my_strstr(a, b);
printf("%s\n", r);
}str1、str2分别记录字符串a、b的起始位置;cur记录比较的起始位置;s1、s2用于遍历,完成一次比较后分别靠cur、str2复位。
9
strtok函数的使用char * strtok ( char * str, const char * sep );sep参数指向一个字符串,定义了用作分隔符的字符集合。sep字符串中一个或者多个分隔符分割的标记。strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。NULL指针。#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "zpw@bitedu.net.hehe";
char buf[20] = {0};//可以修改
strcpy(buf, arr);
//zpw\0bitedu\0net
const char* p = "@.";
char* r = NULL;
for (r = strtok(buf, p); r != NULL; r = strtok(NULL, p))
{
printf("%s\n", r);
}
//这样用是不合适的
//char* r1 = strtok(buf, p);
//printf("%s\n", r1);//zpw
//r1 = strtok(NULL, p);
//printf("%s\n", r1);//bitedu
//r1 = strtok(NULL, p);
//printf("%s\n", r1);//net
return 0;
}
10
strerror与perror函数的使用strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。char * strerror ( int errnum );errno.h这个头文件中说明的,C语言程序启动的时候就会使用一个全局变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每一个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。perror,它不需要传入错误码,会直接将错误信息打印出来。void perror ( const char * str );perror函数打印完参数部分的字符串后,再打印一个冒号和一个空格,再打印错误信息。#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");//以读的形式打开test.txt文件,如果文件不存在,则打开失败。
if (pf == NULL)
{
//打开文件失败了
perror("错误信息是");//: xxxx
printf("错误信息是: %s\n", strerror(errno));
return 1;
}
//往下走了
//...
return 0;
}