0
点赞
收藏
分享

微信扫一扫

13 C语言进阶字符串函数内存函数

西风白羽 2022-01-17 阅读 93

字符函数和字符串函数

函数部分的解析来源于( C++资源网络)

  • 求字符串长度
    strlen
  • 长度不受限制的字符串函数
    strcpy
    strcat
    strcmp
  • 长度受限制的字符串函数介绍
    strncpy
    strncat
    strncmp
  • 字符串查找
    strstr
    strtok
  • 错误信息报告
    strerror
  • 字符操作
  • 内存函数操作
    memcpy
    memmove
    memset
    memcmp

C语言中的字符串问题

写代码时对字符和字符串的处理很频繁,但是C语言中本身没有字符串类型,字符串通常存储在常量字符串中或者字符数组中。常量字符串适用于那些对它不做修改的字符串函数。

函数介绍

1. strlen

1.1 功能:

Get string length获取字符串长度

返回C语言中字符串的长度。

1.2 库函数形式
size_t strlen ( const char * str );
1.3 注意事项:

字符串的长度由终止字符确定。字符串‎‎的长度与字符串开头和终止空字符之间的字符数一样长(不包括终止空字符本身)。

1.4 实例
int main ()
{
  char szInput[256];
  printf ("Enter a sentence: ");
  gets (szInput);
  printf ("The sentence entered is %u characters long.\n",(unsigned)strlen(szInput));
  return 0;
}

2. strcpy

2.1 功能:

Copy block of memory复制字符串

所指向的 C 字符串复制到**目标**所指向的数组中,包括终止空字符(并在该点停止)。

2.2 库函数形式
char * strcpy ( char * destination, const char * source );
2.3 注意事项:

为避免溢出,目标所指向的数组的大小应足够长,以包含与源相同的 C 字符串(包括终止空字符),并且不应在内存中与 source 重叠。

2.4 实例
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;
}

3. strcat

3.1 功能:

Concatenate strings连接字符串

将‎‎‎‎字符串的副本追加到‎‎目标‎‎字符串。‎‎目标‎‎中的终止空字符被‎‎源‎‎的第一个字符覆盖,并且在‎‎目标‎‎中由两者串联形成的新字符串的末尾包含一个空字符。‎

3.2 库函数形式
char * strcat ( char * destination, const char * source );
3.3 注意事项:

‎目的地‎‎和‎‎来源‎‎不得重叠。

3.4 实例
int main ()
{
  char str[80];
  strcpy (str,"these ");
  strcat (str,"strings ");
  strcat (str,"are ");
  strcat (str,"concatenated.");
  puts (str);
  return 0;
}

4. strcmp

4.1 功能:

Compare two strings比较两个字符串

将 C 字符串‎str1‎‎与 C 字符串‎‎str2进行比较‎‎。

返回值表明
<0第一个不匹配的字符在ptr1中的值低于ptr2中的值
0两个字符中的内容相等
>0第一个不匹配的字符在ptr1中的值低于ptr2中的值
4.2 库函数形式
int strcmp ( const char * str1, const char * str2 );
4.3 注意事项:

此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或达到终止空字符。

4.4 实例
int main ()
{
  char key[] = "apple";
  char buffer[80];
  do {
     printf ("Guess my favorite fruit? ");
     fflush (stdout);
     scanf ("%79s",buffer);
  } while (strcmp (key,buffer) != 0);
  puts ("Correct answer!");
  return 0;
}

5. strncpy

5.1 功能:

Copy characters from string从字符串中复制字符

的前num字符复制到目标。如果在复制num个字符之前找到C 字符串(由空字符指示)的末尾,则目标将填充零,直到向其写入总共num个字符。

5.2 库函数形式
char * strncpy ( char * destination, const char * source, size_t num );
5.3 注意事项:

‎如果源的长度超过 num,则不会在目标末尾隐式追加空字符。
因此,在这种情况下,目标不应被视为以空值结尾的 C 字符串(这样读取它会溢出)。
目的地和来源不得重叠(重叠时,请参阅 memmove 以了解更安全的替代方案)。

5.4 实例
int main ()
{
  char str1[]= "To be or not to be";
  char str2[40];
  char str3[40];

  /* copy to sized buffer (overflow safe): */
  strncpy ( str2, str1, sizeof(str2) );

  /* partial copy (only 5 chars): */
  strncpy ( str3, str2, 5 );
  str3[5] = '\0';   /* null character manually added */

  puts (str1);
  puts (str2);
  puts (str3);

  return 0;
}

6. strncat

6.1 功能:

Append characters from string

的前num个字符追加到目标,加上一个终止空字符。

6.2 库函数形式
char * strncat ( char * destination, const char * source, size_t num );
6.3 注意事项:

如果源中 C 字符串的长度小于num,则仅复制直到终止空字符的内容。

6.4 实例
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;
}

7. strncmp

7.1 功能:

Compare characters of two strings 比较两个字符串的字符

将 C 字符串str1最多 num个字符与 C 字符串str2的字符数进行比较。

7.2 库函数形式
int strncmp ( const char * str1, const char * str2, size_t num );
7.3 注意事项:

此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续向后比较,直到字符不同,直到达到终止空字符,或者直到两个字符串中的num字符匹配,以先发生的情况为准。

7.4 实例
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;
}

8. strstr

8.1 功能:

**Locate substring ** 定位子字符串

返回一个指向str1中第一次出现的str2的指针,如果str2 不是 str1的一部分,则返回空指针。

8.2 库函数形式
const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );
8.3 注意事项:

匹配过程不包括终止空字符,但碰到它就此停止。

8.4 实例
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;
}

9. strtok

9.1 功能:

Split string into tokens 将字符串拆分为标记

对该函数的一系列调用将str拆分为标记,这些标记是由分隔符中的任何字符分隔的连续字符序列。

9.1 库函数形式
char * strtok ( char * str, const char * delimiters );
9.3 注意事项:

在第一次调用时,函数需要一个C字符串作为str的参数,str的第一个字符用作扫描标记的起始位置。在随后的调用中,函数需要一个空指针,并使用最后一个标记结束后的位置作为扫描的新起始位置。

要确定标记的开头和结尾,函数首先从起始位置扫描分隔符中未包含的第一个字符(即标记的开头)。然后从标记的这个开头开始扫描分隔符中包含的第一个字符,它将成为标记的结尾。如果找到终止的空字符,扫描也会停止。

令牌的这一端将自动替换为空字符,函数将返回令牌的开头。

在对strtok的调用中找到str的终止null字符后,所有后续对该函数的调用(以null指针作为第一个参数)都会返回null指针。

找到最后一个令牌的点由函数在内部保留,以便在下次调用时使用(不需要特定的库实现来避免数据争用)。

9.4 实例
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;
}

10. strerror

10.1 功能:

Get pointer to error message string获取指向错误消息字符串的指针

解释errnum的值,生成一个字符串,其中包含一条描述错误条件的消息,就好像被库的函数设置为errno一样。

10.2 库函数形式
char * strerror ( int errnum );
10.3 注意事项:

字符串。对此函数的进一步调用可能会覆盖其内容(不需要特定的库实现来避免数据争用)。strerror 生成的错误字符串可能特定于每个系统和库实现。

10.4 实例
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main ()
{
  FILE * pFile;
  pFile = fopen ("unexist.ent","r");
  if (pFile == NULL)
    printf ("Error opening file unexist.ent: %s\n",strerror(errno));
  return 0;
}

11. memcpy

10.1 功能:

Copy block of memory 复制内存块

num字节的值从指向的位置直接复制到目标所指向的内存块。源指针和目标指针所指向的对象的基础类型与此函数无关。

10.2 库函数形式
void * memcpy ( void * destination, const void * source, size_t num );
10.3 注意事项:

结果是数据的二进制副本。该函数不检查中是否有任何终止空字符 - 它始终精确地复制数字字节。

为避免溢出,目标参数和源参数所指向的数组的大小应至少为 num 字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。

11.4 实例
struct {
  char name[40];
  int age;
} person, person_copy;

int main ()
{
  char myname[] = "Pierre de Fermat";

  /* using memcpy to copy string: */
  memcpy ( person.name, myname, strlen(myname)+1 );
  person.age = 46;

  /* using memcpy to copy structure: */
  memcpy ( &person_copy, &person, sizeof(person) );

  printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );

  return 0;
}

12. memmove

10.1 功能:

Move block of memory 移动内存块

num字节的值从所指向的位置复制到目标所指向的内存块。

10.2 库函数形式
void * memmove ( void * destination, const void * source, size_t num );
10.3 注意事项:

复制就像使用中间缓冲区一样进行,允许目标重叠。
源指针和目标指针所指向的对象的基础类型与此函数无关;结果是数据的二进制副本。该函数不检查中是否有任何终止空字符 - 它始终精确地复制数字字节。

为避免溢出,目标参数和源参数所指向的数组的大小应至少为 num 字节。

12.4 实例
int main ()
{
  char str[] = "memmove can be very useful......";
  memmove (str+20,str+15,11);
  puts (str);
  return 0;
}

13. memcmp

13.1 功能:

比较两个字符串

ptr1指向的内存块的第一个字节数与ptr2指向的第一个数字字节进行比较

返回值表明
<0在两个内存块中不匹配的第一个字节在ptr1中的值低于ptr2中的值(如果计算为无符号字符值)
0两个内存块的内容相等
>0两个内存块中不匹配的第一个字节在ptr1中的值大于ptr2中的值(如果计算为无符号 char值)
13.2 库函数形式
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
13.3 注意事项:

ptr1指向的内存块的第一个字节数与ptr2指向的第一个数字字节进行比较,如果它们都匹配,则返回零,或者一个值不同于零,表示如果它们不匹配,则表示哪个值更大。请注意,与strcmp不同,该函数在找到空字符后不会停止比较。

13.4 实例
int main ()
{
  char buffer1[] = "DWgaOtP12df0";
  char buffer2[] = "DWGAOTP12DF0";

  int n;

  n=memcmp ( buffer1, buffer2, sizeof(buffer1) );

  if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
  else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
  else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);

  return 0;
}

函数的模拟实现

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;
}

strcpy的模拟实现

//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
char *my_strcpy(char *dest, const char *src) {
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL);

    while ((*dest++ = *src++)) { ;
    }
    return ret;
}

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;
}

strstr的模拟实现

char *strstr(const char *str1, const char *str2) {
    char *cp = (char *) str1;
    char *s1, *s2;
    if (!*str2)
        return ((char *) str1);
    while (*cp) {
        s1 = cp;
        s2 = (char *) str2;
        while (*s1 && *s2 && !(*s1 - *s2))
            s1++, s2++;
        if (!*s2)
            return (cp);
        cp++;
    }
    return (NULL);
}

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);
}

memcpy的模拟实现

void *memcpy(void *dst, const void *src, size_t count) {
    void *ret = dst;
    assert(dst);
    assert(src);
   /*
   * copy from lower addresses to higher addresses
   */
    while (count--) {
        *(char *) dst = *(char *) src;
        dst = (char *) dst + 1;
        src = (char *) src + 1;
    }
    return (ret);
}

memmove的模拟实现

void *memmove(void *dst, const void *src, size_t count) {
    void *ret = dst;
    if (dst <= src || (char *) dst >= ((char *) src + count)) {
        /*
        * Non-Overlapping Buffers
        * copy from lower addresses to higher addresses
        */
        while (count--) {
            *(char *) dst = *(char *) src;
            dst = (char *) dst + 1;
            src = (char *) src + 1;
        }
    } else {
        /*
        * Overlapping Buffers
        * copy from higher addresses to lower addresses
        */
        dst = (char *) dst + count - 1;
        src = (char *) src + count - 1;
        while (count--) {
            *(char *) dst = *(char *) src;
            dst = (char *) dst - 1;
            src = (char *) src - 1;
        }
    }
    return (ret);
}
举报

相关推荐

0 条评论