C语言常见字符串函数、字符分类函数与内存函数的使用

前言

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。下面介绍C语言中的一些常用的字符串函数和内存函数的功能以及实现原理。

字符串函数(包含在头文件string.h)

strlen

函数声明
size_t strlen ( const char * str );

注:size_t类型其实就是unsigned long long类型

函数的功能

返回str指向的字符串长度,从str指向的字符算起,一直到字符串末尾的\0结束,如果没有\0,函数将继续增加str长度知道遇到\0为止。

使用案例
/* strlen example */
#include 
#include 

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

输出结果为:
Enter sentence: just testing
The sentence entered is 12 characters long.

strcpy

函数声明
char* strcpy(char * destination, const char * source );
函数功能

把字符串source拷贝到字符串destination中,从source指向的位置开始拷贝直到遇到\0,并把\0拷贝到destination字符串中。使用此函数要注意为字符串destination分配的空间要大于为source字符串分配的空间,否则会越界访问报错。

注意事项

源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。

使用案例
/* strcpy example */
#include 
#include 

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

输出结果为:
str1: Sample string
str2: Sample string
str3: copy successful

strcat

函数声明
char * strcat ( char * destination, const char * source );
函数功能

把source字符串接到destination字符串后,destination字符串末尾的\0会被覆盖,source字符串包括其末尾的\0都会被拷贝到destination字符串末尾。

注意事项

源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

使用案例
/* strcat example */
#include 
#include 

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

输出结果为:
these strings are concatenated.

strcmp

函数声明
int strcmp ( const char * str1, const char * str2 );
函数功能

函数从两字符串开头开始,按照每个字符的ASCII码大小向后一一比较每个字符,直到遇到不相等的字符或是遇到\0结束。如果遇到不相等的字符时str1中的字符ASCII码大于str2中的,函数返回一个正整数,如果小于,函数返回一个负整数。如果两字符串中的每个字符都相同,函数返回0。

使用案例
//猜水果游戏
#include 
#include 

int main ()
{
  char key[] = "apple";
  char buffer[80];
  do {
     printf ("Guess my favorite fruit? ");
     scanf ("%79s",buffer);
  } while (strcmp (key,buffer) != 0);//猜错了就继续猜,猜对了才退出循环
  puts ("Correct answer!");
  return 0;
}

strncpy

函数声明
char * strncpy ( char * destination, const char * source, size_t num );
函数功能

把source指向的字符串的前num个字节复制给destination指向的num个字节,如果source字符串本身并没有num那么长,那么复制的时候会把不够的地方用0补上,0是\0的ASCII码值,也就是说不够的地方复制的是\0。destination和source参数所指向的数组的大小至少应该是num字节,并且不应该重叠(对于重叠的内存块,memmove是一个更安全的方法)。

使用案例
/* strncpy example */
#include 
#include 

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

Output:

To be or not to be
To be or not to be
To be

strncat

函数声明
char * strncat ( char * destination, const char * source, size_t num );
函数功能

把source字符串的前num个字节接到destination字符串后,destination字符串末尾的\0会被覆盖,source字符串接好后在最末尾加上\0,如果source中的C字符串长度小于num,则只复制到空字符结束之前的内容。

使用案例
/* strncat example */
#include 
#include 

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

Output:

To be or not

strncmp

函数声明
int strncmp ( const char * str1, const char * str2, size_t num );
函数功能

比较C字符串stri和C字符串str2的num字符。这个函数开始比较每个字符串的第一个字符。如果它们相等,则继续执行下面的一对字符,直到字符不同,直到达到一个结束的空字符,或直到两个字符串中的num字符匹配,以先发生的为准。如果比较过程中str1的字符大于对应的str2的字符则返回大于0的整数,如果全部相同返回0,如果比较过程中str1的字符小于于对应的str2的字符则返回小于0的整数,这里比较原则是根据字符的ASCII码大小比较的。

使用案例
/* strncmp example */
#include 
#include 

int main ()
{
  char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
  int n;
  puts ("Looking for R2 astromech droids...");
  for (n=0 ; n<3 ; n++)
  //str[n]是二维数组第n+1行的地址或是理解为第n+1行字符串名或者地址
    if (strncmp (str[n],"R2xx",2) == 0)
    {
      printf ("found %s\n",str[n]);
    }
  return 0;
}

Output:

Looking for R2 astromech droids…
found R2D2
found R2A6

strstr

函数声明
char * strstr ( const char *str1, const char * str2);
函数功能

在str1字符串中匹配查找字符串str2,如果str2是str1的子串则函数返回str2第一次出现在str1中的地址,如果str2不是str1的子串则返回NULL。在匹配过程中不包括字符串的结束标志\0。

使用案例
/* strstr example */
#include 
#include 

int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  //pch指向str中simple的s
  if (pch != NULL)
    strncpy (pch,"sample",6);
  puts (str);
  return 0;
}

Output:

This is a sample string

strtok

注:此函数比较难用,要想掌握此函数,必须多次使用而且掌握函数的实现原理。

函数声明
char * strtok ( char * str, const char * sep );
函数功能

扫描一个字符串str,若在str中遇到字符串sep的任意子串,则把str中对应的子串
的第一位替换为\0,并返回扫描开始位置的地址。

函数实现原理

这个函数中有一个静态全局变量(假设为p),p是保存扫描的开始地址,如果str为字符串首地址,那么p就会被赋值为str,如果str为空,p的值为上次调用完成后p保存的值。从p位置开始向后扫描,如果遇到sep的子串,函数会把str中对应的子串的第一位置为\0,p保存这个str中这个子串的后一位地址,并返回扫描开始的地址,如果一直扫描到|\0也没遇到sep的子串,那返回值为NULL。stroke函数会改变str字符串的内容,若不想改变,则需新建立一个内容相同的字符串。

使用案例
/* strtok example */
#include 
#include 

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

Output:

Splitting string “- This, a sample string.” into tokens:
This
a
sample
string

字符分类函数(包含在头文件ctype.h)

C语言常见字符串函数、字符分类函数与内存函数的使用_第1张图片

这些函数的声明的格式都是:int 函数名(int c)
参数c可以是要判断的字符c,也可以是c的ASCII码。

内存函数(包含在头文件string.h)

memcpy

函数声明
void * memcpy ( void * destination, const void * source, size_t num );
函数功能

将num字节的值从source指向的位置直接复制到destination指向的内存块。source指针和destination指针所指向的对象的基础类型与此函数无关;结果是数据的二进制拷贝。该函数不检查源文件中是否有任何终止空字符——它总是精确地复制num字节。为了避免溢出,destination和source参数所指向的数组的大小至少应该是num字节,并且不应该重叠(对于重叠的内存块,memmove是一个更安全的方法)。函数返回的是void*类型的destination保存的值,若需要使用此函数的返回值则需要进行相应的类型转换。

使用案例
/* memcpy example */
#include 
#include 

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

Output:

person_copy: Pierre de Fermat, 46

memmove

函数声明
void * memmove ( void * destination, const void * source, size_t num );
函数功能

移动内存块将num字节的值从source所指向的位置复制到destination所指向的内存块。复制就像使用了中间缓冲区一样,允许destination和source重叠。source指针和destination指针所指向的对象的基础类型与此函数无关;结果是数据的二进制拷贝。该函数不检查源文件中是否有任何终止空字符——它总是精确地复制num字节。为了避免溢出,目标参数和源参数所指向的数组的大小应至少为num字节。

使用案例
/* memmove example */
#include 
#include 

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

Output:

memmove can be very very useful.

注:到这里认真的你应该会发现,memmove、strncpy和memcpy三个函数在对字符串的使用中具有差不多的作用

memcmp

函数声明
int memcmp ( const void * ptr1,  const void * ptr2,  size_t num );
函数功能

比较两个内存块将ptri指向的内存块的第一个num个字节与ptr2指向的第一个num个字节进行比较;如果在两个内存块中不匹配的第一个字节在ptr1中的值比在ptr2中的值低(如果计算为unsigned char值)返回一个负整数,如果两个内存块的内容是相等的返回0,如果在两个内存块中不匹配的第一个字节在ptr1中的值大于ptr2中的值(如果计算为unsigned char值)返回一个正整数。注意,与strcmp不同,该函数在找到空字符后不会停止比较。

使用案例
/* memcmp example */
#include 
#include 

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

Output:

‘DWgaOtP12df0’ is greater than ‘DWGAOTP12DF0’.

你可能感兴趣的:(C语言语法,c语言)