strlen
声明
size_t strlen(const char*str);
函数的返回值为无符号整型
形参为字符串的地址,用const修饰防止修改该地址内的内容
实现
size_t my_strlen(const char* str)
{
assert(str);//断言防止传参为NULL
size_t count = 0;
while (*s++)
{
count++;
}
return count;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* c = "abcdef";
size_t a = strlen(c);
printf("%zu", a);//6
return 0;
}
注意
strlen函数在遇到’\0’时停止,结果并不会包括’\0’
strcpy
声明
char * strcpy ( char * destination, const char * source );
函数的返回值为目标字符串的首地址
形参为字符串的地址,用const修饰防止修改该地址内的内容
实现
char* my_strcpy(char* destination, const char* source)
{
assert(source);
char* p = destination;
while (*destination++ = *source++);
return p;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char*a="abcdef";
char b[10]={0};
char*c=NULL;
c=strcpy(b,a);
printf("%s\n",b);//abcdef
printf("%s\n",c);//abcdef
}
注意
strcpy以’\0’为标志,将源地址处第一个’\0’及之前的字符全部复制到目标地址处,但strcpy并不会完全覆盖目标字符串。
请不要复制大于目标字符串的源字符串
strcpy_s
strcpy的升级版,更安全。。。。。。
声明
errno_t strcpy_s(char *strDestination , size_t numberOfElements , const char *strSource);
返回一个整数,0表示复制成功,返回非0值代表复制不成功,不同的值表示不同的错误,具体内容可以查阅MSDN手册。
与strcpy不同的是中间多了一个形参来设置目标缓冲区大小,并非原始缓冲区大小。
实现
errno_t my_strcpy_s(char* strDestination, size_t numberOfElements, const char* strSource)
{
assert(strSource);
int count = 1;
char* p = strDestination;
while (*strDestination++ = *strSource++)
{
if (++count > numberOfElements)
{
p[0] = '\0';
return -1;
}
}
return 0;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcdef";
char b[10] = { 0 };
int ret=strcpy_s(b, sizeof(b)/sizeof(b[0]), a);
//错误写法
//strcpy_s(b, sizeof(a) / sizeof(a[0]), a);
printf("%s\n", b);//abcdef
printf("%d", ret);//0
return 0;
}
注意
与strcpy一样在遇到’\0’时停止复制,连同’\0’及之前的字符复制到目标地址处,不要复制过长字符,会报Debug(自测),但strcpy在dev上测试不会报错,会照常打印。
strncpy
声明
char *strncpy(char *dest, const char *src, size_t n);
函数的返回值为目标字符串的首地址
形参为字符串的地址,用const修饰防止修改该地址内的内容,相较于strcpy,在末尾多一个形参,表明最大拷贝长度。
实现
char* my_strncpy(char* dest, const char* src, size_t n)
{
assert(src);
char* p = dest;
int count = 0;
while (n&& (*dest++ = *src++))n--;
if (n)
{
while (--n) *dest++ = '\0';
}
return p;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcdef";
char b[10] = { 0 };
char *c=strncpy(b,a, 3);
printf("%s\n", b);//abc
printf("%s", c);//abc
return 0;
}
注意
strncpy拷贝指定长度的源字符串,若指定长度小于源字符串长度,则不会拷贝’\0’,只拷贝指定长度字符串;若指定长度大于源字符串长度,则拷贝’\0’来凑够指定长度。若指定长度或源字符串长度长于目标空间长度,编译器不会报错,会照常打印。
strncpy_s
相较于strncpy,它在第一个参数后面多一个形参表示目标空间的大小,以此来防止溢出。
但在vs测试中,若指定长度小于源字符串长度,则于strncpy不同,strncpy_s会在最后主动添加一个’/0’,而strncpy不会。若指定长度大于源字符串长度,则不会添加多余的’\0’。
strcat
声明
char * strcat(char * dst,const char * src);
函数的返回值为目标字符串的首地址
形参为字符串的地址,用const修饰防止修改该地址内的内容
实现
char* my_strcat(char* dst, const char* src)
{
assert(src);
char* p = dst;
while (*dst++);
dst--;
while (*dst++ = *src++);
return p;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abc\0def";
char b[10] = {0};
char*c=strcat(b,a);
printf("%s", b);//abc
printf("%s",c);//abc
}
注意
strcat会在目标字符串中第一个出现’\0’的位置开始追加源字符串,直到源字符串出现第一个’\0’为止,并将’\0’一同拷贝进去。
strcat_s
声明
errno_t strcat(char * dst,size_t SizeInBytes,const char * src);
函数的返回值:正确连接返回0,错误返回非零
形参为字符串的地址,用const修饰防止修改该地址内的内容。相较于strcat,中间多了一个参数来说明最大目标空间,防止溢出。在测试中,strcat_s会对溢出报错,但strcat不会。
实现
errno_t my_strcat_s(char* dst, size_t SizeInBytes, const char* src)
{
assert(src);
size_t count = 1;
while (*dst++) count++;
dst--;
while (*dst++ = *src++)
{
if (++count > SizeInBytes)
{
*(--dst) = '\0';
return -1;
}
}
return 0;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abc\0def";
char b[10] = {0};
int ret=strcat_s(b, sizeof(b) / sizeof(b[0]), a);
printf("%s\n", b);//abc
printf("%d", ret);//0
}
注意
strcat_s会在目标字符串中第一个出现’\0’的位置开始追加源字符串,直到源字符串出现第一个’\0’为止,并将’\0’一同拷贝进去。
strncat
声明
char * strncat (char * front, const char * back,size_t count);
函数的返回值:目标字符串的首地址
形参为字符串的地址,用const修饰防止修改该地址内的内容。相较于strcat,最后多了一个参数来说明最大链接长度。
实现
char* my_strncat(char* front, const char* back, size_t count)
{
assert(back);
char* p = front;
while (count && (*front++ = *back++)) count--;
if (count == 0)*front = '\0';
if (count)
while (--count)
*front++ = '\0';
return p;
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcdefghijklmn";
char b[10] = { 0,'#','#','#','#','#','#' ,'#','#',0};
char* c = strncat(b,a,10);
printf("%s\n", b);//abcdefghij,这里存在越界访问
printf("%s\n",c);//abcdefghij
return 0;
}
注意
strncat会在目标字符串第一个’\0’处开始链接源字符串,若指定长度小于源字符串长度,则将指定长度源字符串链接过去,并主动添加一个’/0’,这点与strncpy_s相似,与strncpy不同,但它缺少判断越界访问的条件,故当strncpy_s报错的情况下,strncat不会报错。若指定长度大于源字符串长度,则不足的用’\0’补齐。
strncat_s
相较于strncat,这个函数在第一个参数后面多一个参数表明目标字符串的长度,以此来防止越界访问。这个函数在防止越界访问的同时还会在链接时,若指定字符串小于源字符串长度主动添加’\0’;若指定字符串大于源字符串长度则不会添加多余的’\0’。
strcmp
声明
int strcmp(const char*src,const char*dst);
函数的返回值:>0:src>dst <0:src<dst 0:src=dst
形参为字符串的地址,用const修饰防止修改该地址内的内容。
实现
int my_strcmp(const char* src, const char* dst)
{
assert(src && dst);
while (*src == *dst && *dst!='\0')
{
src++;
dst++;
}
return (*src - *dst);
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcdefgi";
char* b = "abcdefg";
int ret=strcmp(a, b);//1
printf("%d", ret);
return 0;
}
注意
字符串的比较与双方的长度没有关系,在第一个不相等的地方就比较出了结果。双方比较的是第一个’\0’及以前的字符串。
strncmp
声明
int strncmp(const char*src,const char*dst,size_t n);
函数的返回值:>0:src>dst <0:src<dst 0:src=dst
形参为字符串的地址,用const修饰防止修改该地址内的内容。
实现
int my_strncmp(const char* src, const char* dst, size_t n)
{
assert(src && dst);
while (n != 0 && *src == *dst && *dst != '\0' )
{
src++;
dst++;
n--;
}
if (n > 0)
return (*src - *dst);
else
return(*(--src) - *(--dst));
}
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcd\0fgihij";
char* b = "abcdf\0hij";
int ret=strncmp(a, b, 8);
printf("%d", ret);//-1
return 0;
}
注意
字符串的比较与双方的长度没有关系,在第一个不相等的地方就比较出了结果。双方比较的是第一个’\0’及以前的字符串和指定比较长度中比较小的那一段字符串。
strstr
声明
const char * strstr ( const char * str1, const char * str2 );
函数的返回值:若能在str1中找到str2,则返回找到的位置地址;
若不能在str1中找到str2,则返回空指针。
形参为字符串的地址,用const修饰防止修改该地址内的内容。
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "abcdef";
char* b = "a\0e";
char* c = strstr(a, b);
printf("%s", c);//abcdef
return 0;
}
注意
该函数使用的是str1和str2中第一个’\0’之前的字符进行匹配查找。
strtok
声明
char * strtok ( char * str, const char * delimiters );
以delimitres内的字符为分隔符,将const划分为更小的字符串。
函数的返回值:该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
形参为字符串的地址,用const修饰防止修改该地址内的内容。
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abcde-fhijk^lmn*opq-rst uvw\0xyz";
char b[10] = "-^* ";
char* c=strtok(a,b);//第一次划分要传字符串首地址
while (c != NULL)
{
printf("%s\n", c);
c = strtok(NULL, b);//后面的划分传NULL
}
for(int i=0;i<35;i++)
{
printf("%c",a[i]);
}
return 0;
}
注意
该函数是对str1中第一个’\0’之前的字符串进行切割,每次找到分割符后会将源字符串中的分割符替换成’\0’。空格也能当分割符,最后一次切割是遍历到str1中第一个’\0’为止,此时返回最后一个子字符串,下一次切割直接返回NULL。
iscntrl
声明
int iscntrl(int n);
函数的返回值:若是控制字符则返回非0值,若不是则返回0.
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "k \n \a \t";
for (int i = 0; i < strlen(a); i++)
{
printf("%d ", iscntrl(a[i]));
}
return 0;
}
注意
该函数查找字符串中’\0’之前的控制字符。
isspace
声明
int isspace(int c);
函数的返回值:若是空白字符则返回非0值,若不是则返回0.
如空格’ ‘,换页’\f’,换行’\n’,回车’\r’,制表符’\t’,垂直制表符’\v’
使用
#include<stdio.h>
#include<string.h>
int main()
{
char* a = "k \n\a\t\v\r\f\0\t";
for (int i = 0; i < 20; i++)
{
printf("%d ", isspace(a[i]));
}
return 0;
}
注意
'\0’不是空白字符。
isdigit
声明
int isdigit(int c);
函数的返回值:若是数字字符则返回非0值,若不是则返回0.
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[13] = "012345\0 6789";
for (int i = 0; i < 12; i++)
{
printf("%d ", isdigit(a[i]));
}
return 0;
}
注意
只能判断一个字符。
isxdigit
声明
int isxdigit(int c);
函数的返回值:若是十六进制字符则返回非0值,若不是则返回0.
0~9,abcdef,ABCDEF
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[] = "0123456789abcdefABCDEF";
for (int i = 0; i < strlen(a); i++)
{
printf("%d ", isxdigit(a[i]));
}
return 0;
}
注意
只能判断一个字符。
islower
声明
int islower(int c);
函数的返回值:若是小写字母字符则返回非0值,若不是则返回0.
a~z
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[27] = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < 27; i++)
{
printf("%d ", islower(a[i]));
}
return 0;
}
注意
只能判断一个字符。
isupper
声明
int isupper(int c);
函数的返回值:若是大写字母字符则返回非0值,若不是则返回0.
A~Z
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < 27; i++)
{
printf("%d ", isupper(a[i]));
}
return 0;
}
注意
只能判断一个字符。
isalpha
声明
int isalpha(int c);
函数的返回值:若是大写字母字符或小写字母字符则返回非0值,若不是则返回0.
A~Z,
a~z
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[27] = "ABC abc\t\n\a";
for (int i = 0; i < strlen(a); i++)
{
printf("%d ", isalpha(a[i]));
}
return 0;
}
注意
只能判断一个字符。
isalnum
声明
int isalnum(int c);
函数的返回值:若是大写字母字符或小写字母字符或数字字符则返回非0值,若不是则返回0.
0~9,
A~Z,
a~z
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[27] = "ABC abc 123\t\n\a";
for (int i = 0; i < strlen(a); i++)
{
printf("%d ", isalnum(a[i]));
}
return 0;
}
注意
只能判断一个字符。
ispunct
声明
int ispunct(int c);
函数的返回值:若是非字母和数字的可打印图形符则返回非0值,若不是则返回0.
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[27] = "ABC abc 123\t\n\a^!*,.@#";
for (int i = 0; i < strlen(a); i++)
{
printf("%d ", ispunct(a[i]));
}
return 0;
}
注意
只能判断一个字符。
isgraph
声明
int isgraph(int c);
函数的返回值:若是图形符则返回非0值,若不是则返回0.
! " # $ % & ’ ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 { | } ~
注意
只能判断一个字符。
tolower
声明
int tolower(int c);
函数的返回值:如果 c 有相对应的小写字母,则该函数返回 c 的小写字母,否则 c 保持不变。返回值是一个可被隐式转换为 char 类型的 int 值。
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[30] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@!#";
for (int i = 0; i < strlen(a); i++)
{
printf("%c ", tolower(a[i]));
}
return 0;
}
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 @ ! #
注意
只能判断一个字符。
toupper
声明
int toupper(int c);
函数的返回值:如果 c 有相对应的大写字母,则该函数返回 c 的小写字母,否则 c 保持不变。返回值是一个可被隐式转换为 char 类型的 int 值。
使用
#include<stdio.h>
#include<string.h>
int main()
{
char a[30] = "abcdefghijklmnopqrstuvwxyz@!#";
for (int i = 0; i < strlen(a); i++)
{
printf("%c ", toupper(a[i]));
}
return 0;
}
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 @ ! #
注意
只能判断一个字符。