文章目录
一、求字符串长度
二、长度不受限制的字符串函数
三、长度受限制的字符串函数
四、字符串查找
五、错误信息报告
六、字符分类函数 七、内存操作函数
一、求字符串长度
strlen
功能:获取字符串长度 参数:c字符串(str) 返回值:字符串长度(无符号整形size_t) 字符串将 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
const char * str1 = "abcdef" ;
const char * str2 = "bbb" ;
printf ( "%d\n" , strlen ( str1) ) ;
printf ( "%d\n" , strlen ( str2) ) ;
if ( strlen ( str2) - strlen ( str1) > 0 )
{
printf ( "str2>str1\n" ) ;
}
else
{
printf ( "srt1>str2\n" ) ;
}
return 0 ;
}
模拟实现
计数器方式
int my_strlen ( char * str)
{
int len = 0 ;
while ( * str)
{
str++ ;
len++ ;
}
return len;
}
不创建临时变量
int my_strlen ( const char * str)
{
if ( * str == '\0' )
return 0 ;
else
return 1 + my_strlen ( str + 1 ) ;
}
指针-指针
int my_strlen ( char * s)
{
char * p = s;
while ( * p!= '\0' )
{
p++ ;
}
return p - s;
}
二、长度不受限制的字符串函数
strcpy
功能:复制字符串 参数:目的字符串(destination)源字符串(source) 返回值:目的字符串 源字符串必须以 ‘\0’ 结束 会将源字符串中的 ‘\0’ 拷贝到目标空间 目标空间必须足够大,以确保能存放源字符串 目标空间必须可变
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str1[ ] = "Sample string" ;
char str2[ 40 ] ;
char str3[ 40 ] ;
strcpy ( str2, str1) ;
strcpy ( str3, "copy successful" ) ;
printf ( "str1: %s\nstr2: %s\nstr3: %s\n" , str1, str2, str3) ;
return 0 ;
}
模拟实现
char * my_strcpy ( char * dest, const char * src)
{
char * ret = dest;
assert ( src != NULL ) ;
assert ( dest != NULL ) ;
while ( * dest++ = * src++ )
{
}
return ret;
}
strcat
功能:连接字符串 参数:目的字符串(destination)源字符串(source) 返回值:目的字符串 将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。 目的地和来源不得重叠。
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str[ 80 ] ;
strcpy ( str, "these " ) ;
strcat ( str, "strings " ) ;
strcat ( str, "are " ) ;
strcat ( str, "concatenated." ) ;
puts ( str) ;
return 0 ;
}
模拟实现
char * my_strcat ( char * dest, const char * src)
{
char * ret = dest;
assert ( dest) ;
assert ( src) ;
while ( * dest)
{
dest++ ;
}
while ( * dest++ = * src++ )
{
}
return ret;
}
strcmp
功能:比较两个字符串 参数:要比较的字符串1(str1)要比较的字符串2(str2) 返回值:
返回值 表明 <0 第一个不匹配的字符在 PTR1 中的值低于 PTR2 中的值 0 两个字符串的内容相等 >0 第一个不匹配的字符在 PTR1 中的值大于在 PTR2 中的值
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续下一对,直到字符不同或达到终止空字符
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
int ret = strcmp ( "bbq" , "bcq" ) ;
if ( ret > 0 )
printf ( ">\n" ) ;
printf ( "%d\n" , ret) ;
return 0 ;
}
模拟实现
int my_strcmp ( const char * str1, const char * str2)
{
assert ( str1 && str2) ;
while ( * str1 == * str2)
{
if ( * str1 == '\0' )
return 0 ;
str1++ ;
str2++ ;
}
return ( * str1 - * str2) ;
}
三、长度受限制的字符串函数
strncpy
功能:从字符串中复制字符 参数:目的字符串(destination)源字符串(source)要从源中复制的最大字符数(num) 返回值:目的字符串 拷贝num个字符从源字符串到目标空间 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个 如果源长度超过 num,则不会在目标末尾隐式附加空字符。因此,在这种情况下,不应将目标视为以空结尾的 C 字符串(这样读取它会溢出) 目的地和来源不得重叠
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str1[ ] = "To be or not to be" ;
char str2[ 40 ] ;
char str3[ 40 ] ;
strncpy ( str2, str1, sizeof ( str2) ) ;
strncpy ( str3, str2, 5 ) ;
str3[ 5 ] = '\0' ;
puts ( str1) ;
puts ( str2) ;
puts ( str3) ;
return 0 ;
}
strncat
功能:从字符串追加字符 参数:目的字符串(destination)源字符串(source)要追加的最大字符数(num) 返回值:目的字符串 将源的第一个数字字符追加到目标,外加一个终止空字符 如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容 目标空间必须足够大以包含串联的结果字符串,包括其他 null 字符
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str1[ 20 ] ;
char str2[ 20 ] ;
strcpy ( str1, "To be " ) ;
strcpy ( str2, "or not to be" ) ;
strncat ( str1, str2, 6 ) ;
puts ( str1) ;
return 0 ;
}
strncmp
功能:比较两个字符串的字符 参数:要比较的字符串1(str1)要比较的字符串2(str2)要比较i的最大字符数(num) 返回值:
返回值 表明 <0 不匹配的第一个字符在 str1 中的值低于 str2 中的值 0 两个字符串的内容相等 >0 第一个不匹配的字符在 str1 中的值大于在 str2 中的值
将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的 num 字符匹配,以先发生者为准
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str[ ] [ 5 ] = { "R2D2" , "C3PO" , "R2A6" } ;
int n;
puts ( "Looking for R2 astromech droids..." ) ;
for ( n = 0 ; n < 3 ; n++ )
if ( strncmp ( str[ n] , "R2xx" , 2 ) == 0 )
{
printf ( "found %s\n" , str[ n] ) ;
}
return 0 ;
}
四、字符串查找
strstr
功能:查找子字符串 参数:要扫描的字符串(str1)包含要匹配的字符序列的字符串(str2) 返回值:指向 str1 中指定的整个字符序列在 str2 中首次出现的指针,如果序列在 str1 中不存在,则为 null 指针
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str[ ] = "This is a simple string" ;
char * pch;
pch = strstr ( str, "simple" ) ;
if ( pch != NULL )
strncpy ( pch, "sample" , 6 ) ;
puts ( str) ;
return 0 ;
}
模拟实现
char * my_strstr ( const char * str1, const char * str2)
{
char * cp= str1;
char * s1= str1;
char * s2= str2;
if ( * str2 == '\0' )
return str1;
while ( * cp)
{
s1 = cp;
s2 = str2;
while ( * s1 && * s2 && * s1 == * s2)
{
s1++ ;
s2++ ;
}
if ( * s2 == '\0' )
return cp;
cp++ ;
}
return NULL ;
}
strtok
功能:将字符串拆分为标记 参数:要截断的c字符串(str)包含分割字符的c字符串(delimiters) 返回值:如果找到令牌,则指向令牌开头的指针,否则为空指针。当在正在扫描的字符串中到达字符串的末尾(即空字符)时,始终返回空指针 strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改) strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置 strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str[ ] = "- This, 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
功能:获取指向错误消息字符串的指针 参数:错误号(errnum) 返回值:指向描述错误错误的字符串的指针 解释 errnum 的值,生成一个字符串,其中包含描述错误条件的消息,就像由库的函数设置为 errno 一样
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
int i = 0 ;
for ( i = 0 ; i < 10 ; i++ )
{
printf ( "%d: %s\n" , i, strerror ( i) ) ;
}
return 0 ;
}
六、字符分类函数
函数 如果他的参数符合下列条件就返回真 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 标点符号,任何不属于数字或者字母的图形字符(可打印) sgraph 任何图形字符 isprint 任何可打印字符,包括图形字符和空白字符
七、内存操作函数
memcpy
功能:复制内存块 参数:指向目标数组的指针(destinatiom)指向要复制的数据源的指针(source)要复制的字节数(num) 返回值:返回目标 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置 这个函数在遇到 ‘\0’ 的时候并不会停下来 如果source和destination有任何的重叠,复制的结果都是未定义的
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
int arr1[ ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ;
int arr2[ 20 ] = { 0 } ;
memcpy ( arr2, arr1, 40 ) ;
int i = 0 ;
for ( i = 0 ; i < 20 ; i++ )
{
printf ( "%d " , arr2[ i] ) ;
}
return 0 ;
}
模拟实现
void * my_memcpy ( void * dest, const void * src, size_t num)
{
void * ret = dest;
assert ( dest && src) ;
while ( num-- )
{
* ( char * ) dest = * ( char * ) src;
dest = ( char * ) dest + 1 ;
src = ( char * ) src + 1 ;
}
return ret;
}
memmove
功能:移动内存块 参数:指向目标数组的指针(destinatiom)指向要复制的数据源的指针(source)要复制的字节数(num) 返回值:返回目标 将字节数的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样,允许目标和源重叠 该函数不检查源中的任何终止空字符 - 它总是准确地复制字节数
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
char str[ ] = "memmove can be very useful......" ;
memmove ( str + 20 , str + 15 , 11 ) ;
puts ( str) ;
return 0 ;
}
模拟实现
void * my_memmove ( void * dest, const void * src, size_t num)
{
void * ret = dest;
assert ( dest && src) ;
if ( dest < src)
{
while ( num-- )
{
* ( char * ) dest = * ( char * ) src;
dest = ( char * ) dest + 1 ;
src = ( char * ) src + 1 ;
}
}
else
{
while ( num-- )
{
* ( ( char * ) dest + num) = * ( ( char * ) src + num) ;
}
}
return ret;
}
memcmp
功能:比较两个内存块 参数:指向内存块的指针1(str1)指向内存块的指针2(str2)要比较的字节数(num) 返回值:
返回值 表明 <0 两个内存块中不匹配的第一个字节在 PTR1 中的值低于 PTR2 中的值 0 两个内存块的内容相等 >0 两个内存块中不匹配的第一个字节在 PTR1 中的值大于在 PTR2 中的值
与 strcmp 不同,该函数在找到空字符后不会停止比较
例子
# include <stdio.h>
# include <string.h>
int main ( )
{
int arr1[ ] = { 1 , 2 , 1 , 4 , 5 , 6 } ;
int arr2[ ] = { 1 , 2 , 33 } ;
int ret = memcmp ( arr1, arr2, 10 ) ;
printf ( "%d\n" , ret) ;
return 0 ;
}