与字符串与内存相关的库函数

本次博客写的是关于几个库函数的实现的使用,这些函数都是提前包含在标准库中的,不需要我们自己定义,我们要学的是关于它们的使用。
在使用库函数是应当注意两点问题:

  1. 要包含库函数所在的头文件
  2. 要注意参数合法性检验
    这两点问题在下面我们会提到。

参数合法性检验

当使用库函数时,要注意参数的合法性检验,以免传入错误参数而导致BUG的出现。
参数合法性检验的两种风格:

1.if else;

2.assert (表达式);断言,写一个表达式,如果表达式为真,断言没有任何效果,代码继续执行;如果表达式为假,程序就会直接崩溃。使用的时候要包含<assert.h>头文件。

参数合法性判定的注意事项:

1.一般拿参数和空指针判定,虽然没啥卵用,但是聊胜于无。(有些合法性检验没啥用,但是必须写,要让别人知道你有参数合法性检验这个意识)。

2.判定的时候有两种风格,该怎么选?

assert:是一种比较严厉的处理方式,一旦触发,程序就会崩溃,如果当前场景是比较严重的问题,适合使用assert;例如:服务器启动,加载数据发现数据丢失了;在进行金钱结算的时候出现的问题等等。

if:如果当前场景没那么严重的问题,就不应该使用assert,而应该使用if,来自行定义问题处理方式。

字符串函数

   下面介绍一些关于字符串操作的库函数,使用这些库函数会大大提高我们写代码的效率,将许多复杂的循环和过程在这些这些库函数里实现,这些库函数同时需要包含头文件 <string.h>,

下面将来一一介绍

1. strlen
描述:

C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。
声明:

下面是 strlen() 函数的声明。

size_t strlen(const char *str)

参数:

str -- 要计算长度的字符串。

返回值:

该函数返回字符串的长度。
实例:

下面的实例演示了 strlen() 函数的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char str[50];
   int len;

   strcpy(str, "This is runoob.com");

   len = strlen(str);
   printf("|%s| 的长度是 |%d|\n", str, len);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

|This is runoob.com| 的长度是 |18|

模拟strlen的实现

int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//不能创建临时变量计数器
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;
}

2.  strcpy()
描述:

C 库函数 char *strcpy(char *dest, const char *src) 把 src 所指向的字符串复制到 dest。

需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。
声明

下面是 strcpy() 函数的声明。

char *strcpy(char *dest, const char *src)

参数:

dest -- 指向用于存储复制内容的目标数组。
src -- 要复制的字符串。

返回值:

该函数返回一个指向最终的目标字符串 dest 的指针。
实例

下面的实例演示了 strcpy() 函数的用法。
实例:

#include <stdio.h>
#include <string.h>
 
int main()
{
   char src[40];
   char dest[100];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strcpy(dest, src);
 
   printf("最终的目标字符串: %s\n", dest);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

最终的目标字符串: This is runoob.com

```c

****模拟实现strcpy:****
/1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}

3.  strncpy()
描述:

C 库函数 char *strncpy(char *dest, const char *src, size_t n) 把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。
声明

下面是 strncpy() 函数的声明。

char *strncpy(char *dest, const char *src, size_t n)

参数:

dest -- 指向用于存储复制内容的目标数组。
src -- 要复制的字符串。
n -- 要从源中复制的字符数。

返回值:

该函数返回最终复制的字符串。
实例:

下面的实例演示了 strncpy() 函数的用法。在这里,我们使用函数 memset() 来清除内存位置。
实例:

#include <stdio.h>
#include <string.h>
 
int main()
{
   char src[40];
   char dest[12];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strncpy(dest, src, 10);
 
   printf("最终的目标字符串: %s\n", dest);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

最终的目标字符串: This is ru

模拟实现strncpy

char* Strncpy(char* destination, const char* source, size_t num)
{
  assert(destination != NULL);
  assert(source != NULL);
  size_t i = 0;
  while(i < num && source[i] != '\0')
  {
    destination[i] = source[i];
    i++;
  }
  if(i == num)
  {
    return destination;
  }
  if(source[i] == '\0')
  {
    for(; i < num; i++)
    {
      destination[i] = '\0';
    }
    return destination;
  }
}

4. strcat()

描述:

C 库函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
声明

下面是 strcat() 函数的声明。

char *strcat(char *dest, const char *src)

参数:

dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
src -- 指向要追加的字符串,该字符串不会覆盖目标字符串。

返回值

该函数返回一个指向最终的目标字符串 dest 的指针。
实例:

下面的实例演示了 strcat() 函数的用法。
实例

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char src[50], dest[50];
 
   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");
 
   strcat(dest, src);
 
   printf("最终的目标字符串: |%s|", dest);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

最终的目标字符串: |This is destinationThis is source|

模拟实现strcat

char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++;
}
while((*dest++ = *src++))
{
;
}
return ret;
}

5.  strncat(
描述:

C 库函数 char *strncat(char *dest, const char *src, size_t n) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。
声明:

下面是 strncat() 函数的声明。

char *strncat(char *dest, const char *src, size_t n)

参数:

dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串,包括额外的空字符。
src -- 要追加的字符串。
n -- 要追加的最大字符数。

返回值:

该函数返回一个指向最终的目标字符串 dest 的指针。
实例:

下面的实例演示了 strncat() 函数的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char src[50], dest[50];

   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");

   strncat(dest, src, 15);

   printf("最终的目标字符串: |%s|", dest);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

最终的目标字符串: |This is destinationThis is source|

模拟实现strncat

char* Strncat(char* destination, const char* source, size_t num)
{
  assert(destination != NULL);
  assert(source != NULL);
  size_t i = 0;
  while(destination[i] != '\0')
  {
    i++;
  }
  size_t j = 0;
  while(j < num && source[j] != '\0')
  {
    destination[i] = source[j];
    j++;
    i++;
  }
  destination[i] = '\0';
  return destination;
}

6.  strcmp()
描述:

C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。
声明

下面是 strcmp() 函数的声明。

int strcmp(const char *str1, const char *str2)

参数:

str1 -- 要进行比较的第一个字符串。
str2 -- 要进行比较的第二个字符串。

返回值:

该函数返回值如下:

如果返回值小于 0,则表示 str1 小于 str2。
如果返回值大于 0,则表示 str1 大于 str2。
如果返回值等于 0,则表示 str1 等于 str2。

实例:

下面的实例演示了 strcmp() 函数的用法。
实例

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[15];
   char str2[15];
   int ret;
 
 
   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");
 
   ret = strcmp(str1, str2);
 
   if(ret < 0)
   {
      printf("str1 小于 str2");
   }
   else if(ret > 0) 
   {
      printf("str1 大于 str2");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

str1 大于 str2

模拟实现strcmp

int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(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 );
}

7.  strncmp()
描述:

C 库函数 int strncmp(const char *str1, const char *str2, size_t n) 把 str1 和 str2 进行比较,最多比较前 n 个字节。
声明

下面是 strncmp() 函数的声明。

int strncmp(const char *str1, const char *str2, size_t n)

参数:

str1 -- 要进行比较的第一个字符串。
str2 -- 要进行比较的第二个字符串。
n -- 要比较的最大字符数。

返回值:

该函数返回值如下:

如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。

实例:

下面的实例演示了 strncmp() 函数的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[15];
   char str2[15];
   int ret;


   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");

   ret = strncmp(str1, str2, 4);

   if(ret < 0)
   {
      printf("str1 小于 str2");
   }
   else if(ret > 0) 
   {
      printf("str2 小于 str1");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

str2 小于 str1

模拟实现strncmp

int Strncmp(const char* str1, const char* str2, size_t num)
{
  assert(str1 != NULL);
  assert(str2 != NULL);
  size_t i = 0;
  while(str1[i] == str2[i] && i < num && str1[i] != '\0' && str2[i] != '\0')
  {
    i++;
  }
  if(i == num)
  {
    return 0;
  }
  if(str1[i] == '\0' && str2[i] == '\0')
  {
    return 0;
  }
  if(str1[i] > str2[i])
  {
    return 1;
  }
  if(str1[i] < str2[i])
  {
    return -1;
  }
}

8. strsr
描述:

C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。
声明

下面是 strstr() 函数的声明。

char *strstr(const char *haystack, const char *needle)

参数:

haystack -- 要被检索的 C 字符串。
needle -- 在 haystack 字符串内要搜索的小字符串。

返回值:

该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。
实例:

下面的实例演示了 strstr() 函数的用法。
实例

#include <stdio.h>
#include <string.h>
 
 
int main()
{
   const char haystack[20] = "RUNOOB";
   const char needle[10] = "NOOB";
   char *ret;
 
   ret = strstr(haystack, needle);
 
   printf("子字符串是: %s\n", ret);
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

子字符串是: NOOB

模拟实现strstr

char *my_strstr(const char* str1, const char* str2 )
{
assert(str1);
assert(str2);
char *cp = (char*)str1;
char *substr = (char *)str2;
char *s1 = NULL;
if(*str2 == '\0')
return NULL;
while(*cp)
{
s1 = cp;
substr = str2;
while(*s1 && *substr && (*s1 == *substr))
{
s1++;
substr++;
}
if(*substr == '\0')
   return cp;
 cp++;
}
}

9. strtok
描述:

C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。
声明

下面是 strtok() 函数的声明。

char *strtok(char *str, const char *delim)

参数:

str -- 要被分解成一组小字符串的字符串。
delim -- 包含分隔符的 C 字符串。

返回值:

该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
实例:

下面的实例演示了 strtok() 函数的用法。
实例

#include <string.h>
#include <stdio.h>
 
int main () {
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   
   /* 获取第一个子字符串 */
   token = strtok(str, s);
   
   /* 继续获取其他的子字符串 */
   while( token != NULL ) {
      printf( "%s\n", token );
    
      token = strtok(NULL, s);
   }
   
   return(0);
}

让我们编译并运行上面的程序,这将产生以下结果:

This is 
 www.runoob.com 
 website
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值