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