5.字符串相关函数

size_t strlen(const char *str)

#include<string.h>

·字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
·参数指向的字符串必须要以’\0’结束。
·注意函数的返回值为size_t,是无符号的(易错)
·strlen函数的模拟实现

例子:
/* strlen example1 */
#include <stdio.h>
#include <string.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;
}

/* strlen example2 */
#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);
}

计数器模拟实现:
/* simulation of strlen function with counter */
#include <stdio.h>
//计数器实现
size_t Strlen(const char* str)
{
	size_t count = 0;
	while (*str != '\0')
	{
		++str;
		++count;
	}
	return count;
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

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

用递归模拟实现:
/* simulation of strlen function with recursion */
#include <stdio.h>
//递归实现
size_t Strlen(const char* str)
{
	if (*str != '\0')
	{
		return Strlen(str + 1) + 1;
	}
	else
		return 0;
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

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


用指针地址差法模拟实现:
/* simulation of strlen function with indicator */
#include <stdio.h>
//指针地址差实现
size_t strlen(const char* str)
{
	const char* eos = str;
	while (*eos++);
		return (eos - str - 1);
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

	len = strlen(str);
	printf("|%s| 的长度是 |%u|\n", str, len);
	return 0;
}
库中的实现:
/*strlen in lib*/


size_t __cdecl strlen (
        const char * str
        )
{
        const char *eos = str;

        while( *eos++ ) ;

        return( eos - str - 1 );
}

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

#include<string.h>

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

例子:
/* strcpy example1 */
#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);
}

/* strcpy example2 */
#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;
}

模拟实现:
/* simulation of strcpy1*/
#include <stdio.h>
#include <string.h>
char* Strcpy(char* dest, const char* src)
{
    char * cp = dest;
	while (*src)
	{
		*cp++ = *src++;
	}
	*cp = *src;
	return dest;
}
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);
}


/* simulation of strcpy2*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* Strcpy(char* dest, const char* src)
{
    char * cp = dest;
	assert(src != NULL);
	while (*cp++ = *src++);
	return dest;
}
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);
}

库中的实现:
/*strcpy in lib*/


char * __cdecl strcpy(char * dst, const char * src)
{
	char * cp = dst;
 
	while (*cp++ = *src++)
		;               /* Copy src over dst */
 
	return(dst);

}

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

#include<string.h>

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

例子:
/* strcat example */
#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);
}

模拟实现:
/* simulation of strcat*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* Strcat(char* dest, const char* src)
{
    char * cp = dest;
	/*while (*cp) 
		++cp;*/
	if (*cp)
		while (*(++cp));
	assert(src != NULL);
	while (*cp++ = *src++);
	return dest;
}
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);
}


库中的实现:
/*strcat in lib*/  
char * __cdecl strcat (
        char * dst,
        const char * src
        )
{
        char * cp = dst;

        while( *cp )
                cp++;                   /* find end of dst */

        while( *cp++ = *src++ ) ;       /* Copy src to end of dst */

        return( dst );                  /* return dst */

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

#include<string.h>

str1 – 要进行比较的第一个字符串。
str2 – 要进行比较的第二个字符串。
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。

例子:
/* strcmp example */
#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("str2 小于 str1");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

模拟实现:
/* simulation of strcmp*/
#include <stdio.h>
#include <string.h>

int Strcmp(const char* src, const char* dst)
{
	while ( (*src && *dst) && *src++ == *dst++);  //*src != '\0'&& *dst != '\0'  --> *src && *dst
	if (!*src && !*dst)	return 0;
	else if (!*src) return -1;
	else if (!*dst) return 1;
	else
		return *src - *dst;
}

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("str2 小于 str1");
	}
	else
	{
		printf("str1 等于 str2");
	}

	return(0);
}
库中的实现:
/*strcmp in lib*/
int __cdecl strcmp (
        const char * src,
        const char * dst
        )
{
        int ret = 0 ;

        while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
                ++src, ++dst;

        if ( ret < 0 )
                ret = -1 ;
        else if ( ret > 0 )
                ret = 1 ;

        return( ret );
}
char *strncpy(char *dest, const char *src, size_t n)

#include<string.h>

dest – 指向用于存储复制内容的目标数组。
src – 要复制的字符串。
n – 要从源中复制的字符数。
该函数返回最终复制的字符串。

例子:
/* strncpy example */  //不追加'\0'
#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);
}
模拟实现
/* simulation of strncpy*/  //不追加'\0'
#include <stdio.h>
#include <string.h>

char* Strncpy(char* dest, const char* src, size_t n)
{
	char* cp = dest;
	while (n--)
	{
		*cp++ = *src++;
	}
	return dest;
}

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

库中的实现:
/*Strncpy in lib*/
char * __cdecl strncpy (
        char * dest,
        const char * source,
        size_t count
        )
{
        char *start = dest;

        while (count && (*dest++ = *source++))    /* copy string */
                count--;

        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = '\0';

        return(start);
}
char *strncat(char *dest, const char *src, size_t n)

#include<string.h>

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

例子:
/* strncat example */  //追加'\0'
#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);
}
模拟实现:
/* simulation of strncat*/
#include <stdio.h>
#include <string.h>
char* Strncat(char* dest, const char* src, size_t n)
{
	char* cp = dest;
	if(*cp)
		while (*(++cp));  //如果dest第一个是\0元素,防止从从它后面开始复制
	while (n--)
	{
		if(!(*cp++ = *src++))    //防止越界写
		return dest;
	}
	*cp = '\0';
	return dest;
}

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

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


	Strncat(dest, src, 15);

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

	return(0);
}
库中的实现:
/*Strncat in lib*/  //追加'\0'
char * __cdecl strncat (
        char * front,
        const char * back,
        size_t count
        )
{
        char *start = front;

        while (*front++)
                ;
        front--;

        while (count--)
                if (!(*front++ = *back++))
                        return(start);

        *front = '\0';  //追加'\0'
        return(start);
}
int strncmp(const char *str1, const char *str2, size_t n)

#include<string.h>

str1 – 要进行比较的第一个字符串。
str2 – 要进行比较的第二个字符串。
n – 要比较的最大字符数。
返回值
该函数返回值如下:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。

例子:
/* strncmp example */
#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);
}
模拟实现:
/* simulation of strncmp1*/
#include <stdio.h>
#include <string.h>
int Strncmp(const char* str1, const char* str2, size_t n)
{
	while (n && (*str1 && *str2) && (*str1++ == *str2++)) n--;
	if (!*str1 && !*str2) return 0;
	else if (!*str1) return -1;
	else if (!*str2) return 1;
	else return *str1 - *str2;
}

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);
}
/* simulation of strncmp2*/
#include <stdio.h>
#include <string.h>
int Strncmp(const char* str1, const char* str2, size_t n)
{
	int res = 0;
	while (n && (*str1 && *str2) && !(res = *str1++ - *str2++)) n--;
	if (!n) return 0;
	if (res < 0) return -1;
	else return 1;
}

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


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

	ret = strncmp(str1, str2, 3);

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

	return(0);
}

/* simulation of strncmp3 鲍*/
#include <stdio.h>
#include <string.h>

int Strncmp(
	const char* first,
	const char* last,
	size_t     count)
{
	assert(first != NULL);
	assert(last  != NULL);

	while (count && *first == *last)
	{
		first++,last++;
		count--;
	}
	return (int)(*first - *last);
}

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


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

	ret = strncmp(str1, str2, 3);

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

	return(0);
}

库中的实现:
/*Strncmp in lib*/
int __cdecl strncmp
(
    const char *first,
    const char *last,
    size_t      count
)
{
    size_t x = 0;

    if (!count)
    {
        return 0;
    }

    /*
     * This explicit guard needed to deal correctly with boundary
     * cases: strings shorter than 4 bytes and strings longer than
     * UINT_MAX-4 bytes .
     */
    if( count >= 4 )
    {
        /* unroll by four */
        for (; x < count-4; x+=4)
        {
            first+=4;
            last +=4;

            if (*(first-4) == 0 || *(first-4) != *(last-4))
            {
                return(*(unsigned char *)(first-4) - *(unsigned char *)(last-4));
            }

            if (*(first-3) == 0 || *(first-3) != *(last-3))
            {
                return(*(unsigned char *)(first-3) - *(unsigned char *)(last-3));
            }

            if (*(first-2) == 0 || *(first-2) != *(last-2))
            {
                return(*(unsigned char *)(first-2) - *(unsigned char *)(last-2));
            }

            if (*(first-1) == 0 || *(first-1) != *(last-1))
            {
                return(*(unsigned char *)(first-1) - *(unsigned char *)(last-1));
            }
        }
    }

    /* residual loop */
    for (; x < count; x++)
    {
        if (*first == 0 || *first != *last)
        {
            return(*(unsigned char *)first - *(unsigned char *)last);
        }
        first+=1;
        last+=1;
    }

    return 0;
}

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

#include<string.h>

haystack – 要被检索的 C 字符串。
needle – 在 haystack 字符串内要搜索的小字符串。
返回值:
该函数返回在 haystack 中第一次出现 needle 字符串的位置,如果未找到则返回 null。

例子:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main()
{
	const char haystack[20] = "RUNOOB";
	const char needle[10] = "NOOB";
	const char* ret = NULL;

	ret = strstr(haystack, needle);

	printf("子字符串是: %s\n", ret);

	return(0);
}
函数strstr的原型是char *strstr(char *str1, char *str2); 其功能是在str1中返回指定字符串str2的第一次出现的位置。 模拟实现:
/*simulation of strstr1*/
#include <stdio.h>
#include <string.h>

char* Strstr(const char* str1, const char* str2)
{
	const char* p1 = str1;
	while (*p1++);  //p指向'\0'后面
	int length1 = p1 - str1 - 1;

	const char* p2 = str2;
	while (*p2++);  //p指向'\0'后面
	int length2 = p2 - str2 - 1;

	//while(*p2)  p2++;  //p指向'\0'
	//int length2 = p2 - str2; 

	int nums = length1 - length2 + 1;

	for (int i = 0; i < nums; ++i)
	{
		if (!strncmp(str1 + i, str2, length2))
			return (char*)(str1 + i);
	}
	return nullptr;
}

int main()
{
	char haystack[20] = "RUNOOB";
	char needle[10] = "NOOB";
	char* ret = NULL;

	ret = Strstr(haystack, needle);

	printf("子字符串是:%s\n", ret);

	return(0);
}

/*simulation of strstr2*/
#include <stdio.h>
#include <string.h>

char* Strstr(const char* str1, const char* str2)
{
	const char* p1 = str1;
	while (*p1++);  //p指向'\0'后面
	int length1 = p1 - str1 - 1;

	const char* p2 = str2;
	while (*p2++);  //p指向'\0'后面
	int length2 = p2 - str2 - 1;

	//while(*p2)  p2++;  //p指向'\0'
	//int length2 = p2 - str2; 

	int nums = length1 - length2 + 1;
	for (int i = 0; i < nums; ++i)
	{
		//if (!strncmp(str1 + i, str2, length2))
		int flag = 0;
		for (int j = 0; j < length2; ++j)
		{
			if (*(str1 + i + j) == *(str2 + j))
				flag = 1;
			else
				flag = 0;
		}
		if(flag)
			return (char*)(str1 + i);
	}
	return nullptr;
}

int main()
{
	char haystack[20] = "RUNOOB";
	char needle[10] = "NOOB";
	char* ret = nullptr;

	ret = Strstr(haystack, needle);

	printf("子字符串是:%s\n", ret);

	return(0);
}

char * strtok ( char * str, const char * delimiters );

#include<string.h>

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

例子:
/* strtok example1 */
#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;
}
/* strtok example2 */
#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);
}
库中的实现:
/*strtok in lib  1*/
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <string.h>

char* strtok(char *s, const char *delim)
{
  const char *spanp;
  int c, sc;
  char *tok;
  static char *last;

  if (s == NULL && (s = last) == NULL)
    return (NULL);
  /*
   * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
   * 跳过字符串首部的分隔符
   */
 cont:
  c = *s++;
  for (spanp = delim; (sc = *spanp++) != 0;) {
    if (c == sc)
      goto cont;
  }
  
  /*
   *分割符后面没有字符串了
   */
  if (c == 0) {                 /* no non-delimiter characters */
    last = NULL;
    return (NULL);
  }
  tok = s - 1;    /*分割符后面还有字符串,将tok指向字符串首部(不包括分隔符)*/

  /*
   * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
   * Note that delim must have one NUL; we stop if we see that, too.
   * 循环字符串中的字符,直到找到分隔符或者结束符,并替换成结束符
   */
  for (;;) {
    c = *s++;
    spanp = delim;
    /*
     *判断字符串中的某字符是否是分割符中的字符
     *如果是,将分隔符替换成结束符并返回tok;
     *如果不是,继续判断下一个字符
     */
    do {
      if ((sc = *spanp++) == c) {
        if (c == 0)
          s = NULL;
        else
          s[-1] = 0;
        last = s;
        return (tok);
      }
    } while (sc != 0);
  }
  /* NOTREACHED */
}
/*strtok in lib  2*/
#ifdef _SECURE_VERSION
#define _TOKEN *context
#else  /* _SECURE_VERSION */
#define _TOKEN ptd->_token
#endif  /* _SECURE_VERSION */
 
#ifdef _SECURE_VERSION
char * __cdecl strtok_s (
        char * string,
        const char * control,
        char ** context
        )
#else  /* _SECURE_VERSION */
char * __cdecl strtok (
        char * string,
        const char * control
        )
#endif  /* _SECURE_VERSION */
{
        unsigned char *str;
        const unsigned char *ctrl = control;
 
        unsigned char map[32];
        int count;
 
#ifdef _SECURE_VERSION
 
        /* validation section */
        _VALIDATE_RETURN(context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(string != NULL || *context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(control != NULL, EINVAL, NULL);
 
        /* no static storage is needed for the secure version */
 
#else  /* _SECURE_VERSION */
 
        _ptiddata ptd = _getptd();
 
#endif  /* _SECURE_VERSION */
 
        /* Clear control map */
        for (count = 0; count < 32; count++)
                map[count] = 0;
 
        /* Set bits in delimiter table */
        do {
                map[*ctrl >> 3] |= (1 << (*ctrl & 7));
        } while (*ctrl++);
 
        /* Initialize str */
 
        /* If string is NULL, set str to the saved
         * pointer (i.e., continue breaking tokens out of the string
         * from the last strtok call) */
        if (string)
                str = string;
        else
                str = _TOKEN;
 
        /* Find beginning of token (skip over leading delimiters). Note that
         * there is no token iff this loop sets str to point to the terminal
         * null (*str == '\0') */
        while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
                str++;
 
        string = str;
 
        /* Find the end of the token. If it is not the end of the string,
         * put a null there. */
        for ( ; *str ; str++ )
                if ( map[*str >> 3] & (1 << (*str & 7)) ) {
                        *str++ = '\0';
                        break;
                }
 
        /* Update nextoken (or the corresponding field in the per-thread data
         * structure */
        _TOKEN = str;
 
        /* Determine if a token has been found. */
        if ( string == str )
                return NULL;
        else
                return string;
}
strerror

#include<string.h>

C 库函数 char *strerror(int errnum) 从内部数组中搜索错误号 errnum,并返回一个指向错误消息字符串的指针。strerror 生成的错误字符串取决于开发平台和编译器
声明
下面是 strerror() 函数的声明。
char *strerror(int errnum)
参数
errnum – 错误号,通常是 errno。
返回值
该函数返回一个指向错误字符串的指针,该错误字符串描述了错误 errnum。

例子:
/* strerror example */
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main ()
{
   FILE *fp;

   fp = fopen("file.txt","r");
   if( fp == NULL ) 
   {
      printf("Error: %s\n", strerror(errno));
   }
   
  return(0);
}
发布了188 篇原创文章 · 获赞 65 · 访问量 8388

猜你喜欢

转载自blog.csdn.net/qq_43808700/article/details/104591195