C语言 – 字符函数和字符串函数 (一)
C语言中对字符和字符串的处理很是频繁,但C语言本身并没有字符串类型,字符串通常存放在常量字符串或字符数组中。
因C语言中有关字符函数和字符串函数内容较多,所以笔者想通过两篇博客对常用的几个字符函数和字符串函数进行简单的概括和总结。请见真章:
1. 求字符串长度
C语言中常用求长度的函数为:strlen()
size_t strlen ( const char * str);
注意:
a. 函数功能:求取字符串str的长度;
b. 字符串是以’\0’ 作为结束标志,strlen函数返回的是在字符串中’\0’ 前面出现的字符个数(不包含’\0’ );
c. 参数指向的字符串必须要以’\0’ 结束;
d. 注意函数的返回值为size_t,是无符号的( 易错)。
该函数的模拟实现如:
#include <stdio.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
2. 长度不受限制的字符串函数
该部分只对strcpy、strcat、strcmp进行讲解。
1). strcpy
char * strcpy(char * destination,const char * source);
注意:
a. 函数功能:将字符串source中的内容按顺序拷贝至字符串destination中;
b. 在使用该函数时,需检查该函数输入参数中相关字符串的合法性,并对其进行保护,以下函数模拟亦须如此;
c. 该函数返回为字符串;
d. 源字符串必须以’\0’ 结束,同时会将源字符串中的’\0’ 拷贝到目标空间;
e. 目标空间必须足够大且可变,以确保能存放源字符串。
该函数的模拟实现如:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *my_strcpy(char *dest, const char*src)
{
char *p1 = dest;
char *p2 = src;
assert(dest != NULL && src != NULL);
while(*p2)
{
*p1++ = *p2++;
}
*p1 = '\0';
return ret;
}
int main()
{
char str1[20] = "hello";
char *str2 = "bit";
printf("str1 = %s\n", str1);
char *ret;
ret = mystrcpy(str1, str2);
printf("str1 = %s\n", str1);
printf("ret = %s\n", ret);
system("pause");
return 0;
}
2). strcat
char * strcat(char * destination,const char * source);
注意:
a. 函数功能:将源字符串source追加到目标字符串destination之后;
b. 检查字符串合法性,并保护对应字符串;
c. 该函数返回为字符串;
d. 源字符串必须以’\0’结尾;
e. 目标空间必须足够大且可变,以确保能存放源字符串。
该函数模拟实现如:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *mystrcat(char *s1, char *s2)
{
assert(s1 != NULL && s2 != NULL);
char *p1 = s1;
const char *p2 = s2;
int n = strlen(p1);
int m = strlen(p2);
printf("%c", *(p1 + n-1));
for (int i = 0; i < m; i++)
{
*(p1 + n+i) = *(p2+i);
}
return s1;
}
int main()
{
char str1[20] = "hello";
char *str2 = "bit.";
printf("str1 = %s\n", str1);
char *ret;
ret = mystrcat(str1, str2);
printf("str1 = %s\n", str1);
printf("ret = %s\n", ret);
system("pause");
return 0;
}
3). strcmp
int strcmp(const char * destination,const char * source);
注意:
a. 函数功能:判断源字符串source与目标字符串destination之间大小,其对应标准规定:
(1)第一个字符串大于第二个字符串,则返回大于0的数字;
(2)第一个字符串等于第二个字符串,则返回0;
(3)第一个字符串小于第二个字符串,则返回小于0的数字。
b. 检查字符串合法性,并保护对应字符串;
c. 该函数返回为整型数;
d. 源字符串必须以’\0’结尾;
e. 目标空间必须足够大且可变,以确保能存放源字符串。
该函数模拟实现如:
int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL && dest != NULL);
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
{
++src, ++dst;
}
if ( ret < 0 )
{
ret = -1 ;
}
else if ( ret > 0 )
{
ret = 1 ;
}
return( ret );
}
3. 长度受限制的字符串函数
该部分只对strncpy、strncat、strncmp进行讲解。
1). strncpy
char * strncpy( char * destination, const char * source,size_t num);
注意:
a. 函数功能:将字符串source中前num个字符内容按顺序拷贝至字符串destination中;
b. 检查字符串合法性,并保护对应字符串;
c. 该函数返回为字符串;
d. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直至num个。
该函数的模拟实现如:
#include<stdlib.h>
#include<assert.h>
#include<string.h>
//模拟 strncpy()
char *my_strncpy(char *s1, char *s2,int n)
{
assert(s1 != NULL && s2 != NULL);//1\检查参数
char *p1 = s1;
char *p2 = s2; //2、保护参数
int m = strlen(p2);
if (n <= m)
{
while (*p2)
{
*p1++ = *p2++;
}
*p1 = '\0';
return s1;
}
else
{
while (*p2)
{
*p1++ = *p2++;
}
for (int i = 0; i < n - m; i++)
{
*p1++ = '0';
}
*p1 = '\0';
return s1;
}
}
int main()
{
char str1[20] = "hello";
char *str2 = "bit";
printf("str1 = %s\n", str1);
char *ret;
ret = my_strncpy(str1, str2, 5);
printf("str1 = %s\n", str1);
printf("ret = %s\n", ret);
system("pause");
return 0;
}
2). strncat
char * strncat ( char * destination, const char * source,size_t num);
注意:
a. 函数功能:将字符串source中前num个字符内容按顺序添加至字符串destination之后;
b. 检查字符串合法性,并保护对应字符串;
c. 该函数返回为字符串;
d. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直至num个。
该函数的模拟实现请结合 strncpy 函数和 strcat 函数对应的模拟实现程序进行编写,此处不再赘述。
3). strncmp
int strncmp ( const char * destination, const char * source,size_t num);
注意:
a. 函数功能:判断源字符串source的前num个字符内容与目标字符串destination之间大小;
b. 检查字符串合法性,并保护对应字符串;
c. 该函数返回为整型数;
d. 源字符串必须以’\0’结尾;
e. 目标空间必须足够大且可变,以确保能存放源字符串。
该函数的模拟实现程序不难,此处不再赘述,可结合以上函数的实现程序进行编写。
以上内容中所讲函数不多,总体内容多少会有点残缺,请见谅!
同时以上内容中对有关函数进行的模拟实现是用于帮助读者更好的了解对应函数的工作原理。又因为对应函数的正常调用格式与模拟实现中主函数中的调用形式大致相同,所以此处便不再进行赘述!