目录
C语言本身没有字符串类型,字符串存放在常量字符串或字符数组中。
strlen
求字符串长度
size_t strlen ( const char * str );
strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')
形参指向的字符串必须要以'\0'结束
函数的返回值是size_t,是unsigned int无符号整型
模拟实现:
用计数器模拟实现strlen
#include<assert.h>
size_t our_strlen(const char* p)
{
int count = 0;
assert(p != NULL);
while (*p!='\0')
{
*p++;
count++;
}
return count;
}
int main()
{
char* str = "Computer is very interesting!";
unsigned int ret = our_strlen(str);
printf("%d\n", ret);
return 0;
}
用函数递归实现strlen
size_t our_strlen(const char* p)
{
if (*p == '\0')
return 0;
else
return our_strlen(p+1) + 1;
}
int main()
{
char* str = "Computer is very interesting!";
unsigned int ret = our_strlen(str);
printf("%d\n", ret);
return 0;
}
用指针-指针的方式实现strlen
size_t our_strlen(const char* p)
{
char* init_p = p;
while (*p != '\0')
{
p++;
}
return p - init_p;
}
int main()
{
char* str = "Computer is very interesting!";
unsigned int ret = our_strlen(str);
printf("%d\n", ret);
return 0;
}
(特别说明一下指针-指针:当两个指针指向同一个数组中的元素时,才允许一个指针减去另一个指针,两个指针相减的结果类型是有符号整数,减法运算的值是两个指针在内存中的距离(该距离以间隔的单元格数为单位而不是字节)
strcpy
字符串复制
char * strcpy ( char * destination, const char * source );
源字符串必须以'\0'结束
会将源字符串中的'\0'拷贝到目标空间
目标空间必须足够大
目标空间必须可变
模拟实现:
#include<assert.h>
char* our_strcpy(char* destination, char* source)
{
char* ret = destination;
assert(destination && source);
while (*source)
{
*destination = *source;
*destination++;
*source++;
}
*destination = *source;
return ret;
}
int main()
{
char a[50] = { 0 };
char* b = "I want to get so much money.";
our_strcpy(a, b);
printf("%s\n", a);
return 0;
}
strcat
字符串追加
char * strcat ( char * destination, const char * source );
源字符串必须以'\0'结束
目标空间必须足够大
目标空间必须可修改
字符串自己给自己追加->死循环
模拟实现:
#include<assert.h>
char* our_strcat(char* destination, const char* source)
{
assert(destination && source);
char* ret = destination;
while (*destination)
{
destination++;
}
while (*destination++ = *source++)
{
;
}
return ret;
}
int main()
{
char a[50] = "I must get ";
char* b = "so much money.";
our_strcat(a, b);
printf("%s\n", a);
return 0;
}
strcmp
两个字符串比较相等(比较内容)
int strcmp ( const char * str1, const char * str2 );
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或达到终止空字符。比较的是ACSII码值大小。
模拟实现:
#include<assert.h>
int our_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1++==*str2++)
{
if (*str1 == '\0')
return 0;
}
return *str1 - *str2;
}
int main()
{
char a[] = "abc";
char b[] = "abd";
int ret = our_strcmp(a, b);
if (ret > 0)
printf(">\n");
else if (ret == 0)
printf("<\n");
else
printf("==\n");
return 0;
}
strncpy
字符串拷贝(长度受限制)
char * strncpy ( char * destination, const char * source, size_t num );
拷贝num个字符从源字符串到目标空间
如果源字符串长度小于num,则拷贝完源字符串后,在目标的后边追加0
应用举例:
#include<string.h>
int main()
{
char a[20] = "abcdefghigk";
char b[] = "xyz";
strncpy(a, b, 2);
printf("%s\n", a);
return 0;
}
strncat
字符串追加(长度受限制)
char * strncat ( char * destination, const char * source, size_t num );
应用举例:
#include<string.h>
int main()
{
char a[80];
char b[30];
strcpy(a, "I want to get so much ");
strcpy(b, "money.gogogo");
strncat(a, b, 6);
printf("%s\n", a);
return 0;
}
strncmp
两个字符串比较相等(长度受限制)
int strncmp ( const char * str1, const char * str2, size_t num );
num个字符全部比较完
应用举例:
#include<stdio.h>
#include<string.h>
int main()
{
char str[][5] = { "nbDS","yyds","yyss"};
puts("Looking for R2 astromech droids...");
for (int i = 0; i < 3; i++)
{
if (strncmp(str[i], "yyxx", 2) == 0)
printf("%s\n", *(str + i));
}
return 0;
}
strstr
查找子串的一个函数
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
应用举例:
int main()
{
char str[] = "I want to get so much money.";
char* p;
p = strstr(str, "money");
strncpy(p, "happy hahaha", 5);
puts(str);
return 0;
}
模拟实现:
#include<assert.h>
char* our_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* p1 = str1;
const char* p2 = str2;
const char* p = str1;
while (*p)
{
p1 = p;
p2 = str2;
while (*p1 != '\0' && p2 != '\0' && *p1 == *p2)
{
p1++;
p2++;
}
if (*p2 == '\0')
{
return (char*)p;
}
p++;
}
return NULL;
}
int main()
{
char str1[] = "The money is so difficult to get.";
char str2 = "difficult";
char* ret = our_strstr(str1, str2);
if (ret == NULL)
printf("子串不存在\n");
else
printf("%s\n", ret);
return 0;
}
strtok
切割字符串
char * strtok ( char * str, const char * delimiters );
delimiters参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由delimiters字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记,并将其用'\0'结尾,返回一个指向这个标记的指针
strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
如果字符串不存在更多的标记,则返回NULL指针
应用举例:
int main()
{
char str[] = "-This is,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
返回错误码所对应的错误信息
char * strerror ( int errnum );
应用举例:
#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;
}
字符分类函数(需引用头文件#include<ctype.h>)
函数 | 如果他的参数符合下列条件就返回真 |
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,a~z,A~Z,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
字符大小写转换
tolower
int tolower ( int c );
toupper
int toupper ( int c );
mencpy
内存拷贝(拷贝两块独立空间中的数据)
void * memcpy ( void * destination, const void * source, size_t num );
函数mencpy从source的位置开始向后复制num个字节的数据到destination的内存位置
这个函数在遇到'\0'的时候并不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的
模拟实现:
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
内存拷贝
void * memmove ( void * destination, const void * source, size_t num );
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
如果源空间和目标空间出现重叠,就应使用memmove函数处理
模拟实现:
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
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
将 ptr1 所指向的内存块的前 num 个字节与 ptr2 指向的第一个字节数进行比较,如果它们都匹配,则返回零,或者如果不匹配,则返回与零不同的值,表示哪个值更大。
分享到此结束,感觉后面的字符串越来越复杂~呜呜呜