字符串函数
<string.h>
strlen
size_t strlen ( const char * str );
作用:计算字符串中’\0’之前的字符个数
返回:类型为size_t(无符号类型),返回’0’之前的字符个数
int main()
{
char arr[] = "abcde";
int st = strlen(arr);
printf("%d\n", st);
return 0;
}
长度不受限制函数
strcat
字符串追加
<string,h>
char * strcat ( char * destination, const char * source );
在destination字符串’\0’的位置开始追加source字符串(destination字符串的 '\0’会被覆盖)
需要注意的是目标字符串必须确保有足够的空间能够容纳追加的字符
当字符串给自己追加时可能会出现问题,因为会把’\0’给覆盖掉,从而变成死循环
int main()
{
char c1[30] = { "abcde" };
char c2[] = { "fghij" };
strcat(c1, c2);
printf("%s\n", c1);
return 0;
}
strcpy
字符串拷贝
char * strcpy ( char * destination, const char * source )
将source字符串复制到目标空间,并在复制’\0’后停止
需要确保目标有充足的空间容纳字符串
返回值为目标空间首地址
int main()
{
char c1[20] = { 0 };
char c2[] = { "abcdef" };
strcpy(c1, c2);
printf("%s\n", c1);
return 0;
}
strcmp
int strcmp ( const char * str1, const char * str2 );
将str1与str2以字节为单位进行比较
ptr2小于ptr1返回小于零的数
ptr1等于ptr2返回等于零的数
ptr2大于ptr1返回大于零的数
在vs中大于返回 1,等于返回 0,小于返回 -1
在 Linux-gcc 中,大于返回正数,等于返回0,小于返回负数
所以需要注意判断的写法
int main()
{
char c1[] = "abcde";
char c2[] = "abcdf";
int a = strcmp(c1, c2);
if(a<0)
{
printf("c1<c2\n");
}
else if (a > 0)
{
printf("c1>c2\n");
}
else
{
printf("c1=c2\n");
}
return 0;
}
由于这三个函数使用时,空间使用可能会出现问题从而报错
所以又出现了长度受限制的函数
长度受限制函数
strncat
<string.h>
char * strncat ( char * destination, const char * source, size_t num );
在这里新增了num,控制追加字符数量
int main()
{
char c1[20] = "abcde";
char c2[] = "feghijk";
char* c3=strncat(c1, c2, 4);
printf("%s\n", c3);
return 0;
}
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
将num个字符拷贝到目标字符串中,当num大于字符个数拷贝完后会在后面补零
int main()
{
char c1[10] = "XXXXXXXXXX";
char c2[] = "abc";
strncpy(c1, c2, 5);
return 0;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
较到出现另个字符不一样或者一个字符串结束或者 num 个字符全部比较完
int main()
{
char c1[] = "abcdef";
char c2[] = "abcdee";
int n=strncmp(c1, c2, 5);
printf("%d\n", n);
return 0;
}
发现c1和c2最后一个字符是不同的,但是由于只比较了前五个字符刚好没有比较最后一个所以判断相等
字符串查找函数
strstr
char * strstr ( char * str1, const char * str2 );
返回字符串中首次出现子串的地址
如果str1中有str2的字符串,返回str1中这个字符串的首地址
如果没有,返回NULL
int main()
{
char c1[] = { "abccde" };
char c2[] = { "cde" };
char* cc=strstr(c1, c2);
printf("%s\n", cc);
return 0;
}
strtok
char *strtok(char*str,const char*sep)
sep是一个字符串,定义了分隔符的集合
str指定一个字符串,它包含多个sep字符串中的多个或一个分隔符
把分隔符替换成\0;
会改变字符串(一般使用临时内容)
int main()
{
char arr[] = "zhang@san.";
char* p = "@.";
char buf[20] = { 0 };
strcpy(buf, arr);
//拷贝到可修改的数组里
//第一个不能传空指针
//但是之后传入空指针后,从上一次保留的位置向后找找分隔符
strtok(buf, p);//找'@'
strtok(NULL, p);//找'.'
//优化
char* ret = NULL;
for (ret = strtok(buf, p); ret != NULL; ret = strtok(NULL, p))
{
//初始化部分执行一次,判断,打印,再次执行,判断,打印直到返回NULL;
printf("%s\n", ret);
}
return 0;
}
strerror
<string.h>
char * strerror ( int errnum );
c语言的库函数,在运行时发生错误,就会将错误码存在一个变量中,这个变量是errno,错误码是一些数字。
返回错误码所对应信息,将错误码翻译成错误信息,返回cahr*,错误信息的首地址
#include<errno.h>
//strerror
//把错误码翻译成错误信息
#include<string.h>
int main()
{
//strerror
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("%s\n", strerror(4));
return 0;
}
int main()
{
// fopen//打开文件
// FILE*fopen(const char *filename,const char*mode)
// FILE*指针 文件名 打开方式
//打开成功返回有效指针
//失败返回NULL指针
FILE* pf=fopen("test.txt","r");
if(pf==NULL)
{ //空指针失败
//没有写路径,默认在当前工程文件中寻找
//打印错误信息,errno错误码变量
//多次错误,使用多次
printf("%s\n",strerror(errno));
—————————;
//void perror (const char*str);
perror("fopen");
//可以认为==printf("%s\n",strerror(errno))
//直接打印错误信息,在打印错误信息前,会先打印自定义信息
return 1;
}
//打开成功,读取文件.......
//关闭文件
fclose(pf);
return 0;
}
函数 | 符合条件返回真 |
---|---|
iscntrl | 判断 所有控制字符 |
isspace | 判断 空白字符如:空格,换行符,制表符,回车… |
isdigit | 判断 十进制 数字 0-9 |
isxdigit | 判断 十六进制 数字,包括所有 十进制数,小写字母,大写字母 |
islower | 判断 小写字母 范围 a~z |
isupper | 判断大写字母 |
isalpha | 判断 大写字母A~Z 或 小写字母 a~z |
isalnum | 判断 字母(大小写) 或 数字 0~9 |
ispunct | 判断 标点符号,不属于数字或字母的 图形字符可以打印 |
isgraph | 判断 图形字符 |
isprint | 判断 可打印字符,包括图形字符,空白字符 |
//<string.h>
//islower,判断小写字母
//int islower(int c);
//a~z
//是小写返回非零,不是小写返回零
int main()
{
char ch = 'A';
char cc = 'a';
printf("ch=> %s\n", islower(ch) > 0 ? "yes" : "no");
printf("cc=> %s\n", islower(cc) > 0 ? "yes" : "no");
return 0;
}
//<ctype.h>
//isdigit,判断字符是否为十进制数字
//int isdigit (int c);
//0~9
//是小写返回非零,不是小写返回零
#include<ctype.h>
int main()
{
printf(" 1=> %s\n", isdigit(2) > 0 ? "yes" : "no");
printf("'1'=> %s\n", isdigit('1') > 0 ? "yes" : "no");
return 0;
}
//<ctype>
//tolower
//int tolower (int c); 字符,Ascll 皆可
//A~Z
//把大写字符转换为小写
#include<ctype.h>
int main()
{
char cc = 'A';
for (cc = 'A'; cc <= 'Z'; cc++)
{
printf("%c ", tolower(cc));
}
return 0;
}
//<ctype>
//int toupper(int c);字符,Ascll 皆可
//a~z
//把小写转换为大写
int main
{
char cc = 'a';
for (cc = 'a'; cc <= 'z'; cc++)
{
printf("%c ", toupper(cc));
}
return 0;
}
字符操作函数
memcpy(模拟)
<string,h>
void * memcpy ( void * destination, const void * source, size_t num );
将num个字节的值从source拷贝到destination,尽量不重叠拷贝
voidmemcpy(voiddestination,const coidsource,size_t num);
void 接受各种内型 目标数组 拷贝源数据 拷贝字节数
在这里插入代码片void* My_memcpy(void* a,const void* b, size_t c)
{
void* ret = a;
assert(a && b);
while (c--)
{
//一字节一字节交换
*(char*)a = *(char*)b;
//(char*)a++;
//(char*)b++;//不可取,强制类型转换是临时的,加加后不再是char*类型了
a = (char*)a + 1;
b = (char*)b + 1;
//++(char*)a;
//++(char*)b;但是前置加加是可以的
}
return ret;
}
int main()
{
int aa[] = { 1,2,3,4,5,6,7,8,9,10 };
int ab[20] = { 0 };
//My_memcpy(ab, aa, 15);
//但是,把数组自身1,2后复制成1,2,3,4......
//重叠会出现问题
//可以使用memmove
My_memcpy(ab, aa, 15 );
return 0;
}
memmove(模拟)
<string.h>
void * memmove ( void * destination, const void * source, size_t num );
voidmemmove(voiddestination,constvoidsource,size_tnum)
void 接受各种内型 目标数组 拷贝源数据 拷贝字节
将num字节个值从source拷贝到destination,允许源与目标重叠
void* My_memmove(void* a, const void* b, size_t c)
{
void* ret = a;//返回首地址
assert(a && b);
//从前向后
if (a < b)
{
while (c--)
{
//从源头一个字节一个字节的拷贝
*((char*)a) = *((char*)b);
a = (char*)a + 1;
b = (char*)b + 1;
}
}
//从后向前
else
{
//把地址加上拷贝字节数就是从后拷贝
//假如a=0,c=15,真实地址是16的位置
while (c--)
//但是经过c--后,就是从第15个字节向前拷贝了,同时a+c和b+c都会向前进
{
*((char*)a + c) = *((char*)b + c);
}
}
return ret;
}
int main()
{
int aa[] = { 1,2,3,4,5,6,7,8,9,10 };
My_memmove(aa, aa+2, 15);
return 0;
}
memcmp(模拟)
<string.h>
int memcmp(const void*ptr1,const void* ptr2,size_t num);
memcmp,内存块比较
int memcmp(const voidptr1,const void ptr2,size_t num);
ptr1和ptr2比较num个字节数
ptr2小于ptr1返回小于零的数
ptr1等于ptr2返回等于零的数
ptr2大于ptr1返回大于零的数
int main()
{
int arr[] = { 1,2,1 };
int aar[] = { 1,2,3 };
int ret = memcmp(arr, aar, 12);
if (ret>0)
{
printf("arr>aar\n");
}
else if(ret<0)
{
printf("arr<aar\n");
}
else
{
printf("arr=aar\n");
}
}
//<string.h>
//memset
//void*memset(void*ptr,int value,size_t num);
//内存设置函数
//以字节为单位设置内存中的值
int main()
{
char ch[] = "abcde";
memset(ch, 'x', 5);
//但是!!!
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
memset(arr, 1, 40);
//此函数设置值是以字节为单位,在int函数中会使每个字节为1
return 0;
}