【C】strcpy strcat strlen strcmp等字符串函数的使用与说明

strlen

  • size_t strlen ( const char * str );
  • 作用:获取字符串长度
  • 参数说明:传入一个字符数组或者指向一个字符串的字符指针
  • 返回值:字符串长度

官方说明:C字符串的长度由终止的空字符决定:C字符串的长度等于字符串开头和终止的空字符之间的字符数(不包括终止的空字符本身)。

测试程序

	char *test = "abcdef";
	int length = strlen(test);
	printf("字符串长度为:%d\n",length);

output:字符串长度为:6

模拟实现strlen方法

size_t mystrlen(const char * str){
    unsigned int count = 0;
    while (*str != '\0'){
        str++;
        count++;
    }
    return count;
}

特别说明:字符串末尾都是有一个终止字符的(’\0’),而strlen函数并不讲终止字符计入字符串长度。

strcpy

  • char* strcpy ( char* destination, const char* source );
  • 作用:将source字符串复制进destination字符串中
  • 参数说明:
    • source:指向待复制内容的目标数组的字符指针
    • destination:指向将内容复制进入的数组的字符指针
  • 返回值:destination

官方说明:将源指向的C字符串复制到目标指向的数组中,包括终止的空字符(并在该点停止)。为避免溢出,目标指向的数组大小应足够长,以包含与源相同的C字符串(包括终止的空字符),并且不应在内存中与源重叠。

测试程序

	const char *source = "abcd";
	char destination[50] = "123456";
	strcpy(destination,source);
	puts(destination);

output:abcd

特别说明:上述程序的destination数组经过复制之后保存的数据为:a b c d \0 6 \0,由于输出时遇见终止字符’\0’便停止输出,所以后面的6并不会输出

模拟实现strcpy方法

char * mystrcpy(char * destination, const char * source){
	char *dst = destination;
    while (*source != '\0'){
        *destination = *source;
        destination++;
        source++;
    }
    *destination = '\0';
    return dst;
}

strcat

  • char* strcat ( char* destination, const char* source );
  • 作用:将源字符串接到目标字符串之后,形成新字符串
  • 参数说明:
    • source:源字符串
    • destination:目标字符串
  • 返回值:destination

官方说明:将源字符串的副本附加到目标字符串。目标中的终止空字符将被源的第一个字符覆盖,并且在由目标中的两个字符串联而成的新字符串的末尾包含一个空字符。目的地和来源地不得重叠。

测试程序

	const char *source = "abcd";
	char destination[50] = "1234";
	strcat(destination,source);
	puts(destination);

output:1234abcd

特别说明:源字符串和目标字符串的地址不可相同

模拟实现strcat方法

char * mystrcat(char * destination, const char * source){
    char *dst = detination;
    while (*destination != '\0'){
        destination++;
    }
    while (*source != '\0'){
        *destination = *source;
        destination++;
        source++;
    }
    *destination = '\0';
    return dst;
}

strcmp

  • int strcmp ( const char* str1, const char* str2 );
  • 作用:比较两个字符串的大小
  • 参数说明:str1和str2是待比较的两个字符数组
  • 返回值:
    • 0:两个字符串完全相同
    • 负数:str1中的ASCII值低于str2
    • 正数:str1中的ASCII值高于str2

官方说明:此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续比对,直到字符不同或达到终止的空字符为止。

测试程序

	char* str1 = "abcd";
	char* str2 = "abcd";
	char* str3 = "efgh";
	printf("%d\n",strcmp(str1,str2));
	printf("%d\n",strcmp(str1,str3));
	printf("%d\n",strcmp(str3,str1));

output:
0
-1
1

模拟实现strcmp方法

int mystrcmp(const char * str1, const char * str2){
    while (*str1 != '\0'){
        if (*str1 > *str2){
            return 1;
        }
        else if (*str1 < *str2){
            return -1;
        }
        else{
            str1++;
            str2++;
            continue;
        }
    }
    return 0;
}

strncpy

  • char* strncpy ( char* destination, const char* source, size_t num );
  • 作用:选择源字符串前num个字符复制到目标字符串中去
  • 参数说明:
    • source:源字符串
    • destination:目标字符串
    • num: 数量
  • 返回值:destination

官方说明:将源的前几个字符复制到目标。如果在复制num个字符之前找到源C字符串的结尾,则用零填充目标,直到总共写入num个字符为止。
如果源的长度超过num,则在目标的末尾不会隐式追加空字符。因此,在这种情况下,目标不应被视为以空结尾的C字符串(这样读取会溢出)。
目的地和来源地不得重叠(重叠时,参见memmove以获得更安全的替代方案)。

测试程序

	char *source = "abcd";
	char destination[50] = "1234";
	strncpy(destination,source,3);
	puts(destination);

output:
abc4

	char *source = "abcd";
	char destination[50] = "1234";
	strncpy(destination,source,10);
	puts(destination);

output:
abcd

strncat

  • char* strncat ( char* destination, const char* source, size_t num );
  • 作用:将源字符串的num个字符接到目标字符串后面
  • 参数说明:
    • source:源字符串
    • destination:目标字符串
    • num: 数量
  • 返回值:destination

官方说明:将源的前几个字符附加到目标,再加上一个终止的空字符。如果源中C字符串的长度小于num,则只复制不超过终止空字符的内容。

测试程序

	char *source = "abcd";
	char des[50] = "1234";
	strncat(des,source,2);
	puts(des);

output:
1234ab

	char *source = "abcd";
	char des[50] = "1234";
	strncat(des,source,6);
	puts(des);

output:
1234abcd

strncmp

  • int strncmp ( const char* str1, const char* str2, size_t num );
  • 作用:比较源字符串和目标字符串中前num个字符的大小
  • 参数说明:
    • str1和str2是待比较的两个字符数组
    • num: 比较字符的数量
  • 返回值:
    • 0:两个子字符串完全相同
    • 负数:子字符串中的ASCII值低于str2
    • 正数:子字符串中的ASCII值高于str2

官方说明:将C字符串str1的至多个字符与C字符串str2的最多个字符进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的num个字符匹配,以先发生的为准。

测试程序

	char *s1 = "abcdABCD";
	char *s2 = "abcd1234";
	printf("%d\n",strncmp(s1,s2,4));
	printf("%d\n",strncmp(s1,s2,5));

output:
0
1

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

output:
Looking for R2 astromech droids…
found R2D2
found R2A6

strstr

  • char* strstr ( const char* str1, const char* str2);
  • 作用:寻找str2第一次在str1中出现的位置
  • 参数说明:
    • str1:包含待匹配字符串序列的字符串
    • str2:需寻找的字符串序列
  • 返回值:返回一个指针,指向str2整个字符串第一次在str1中出现的位置,如果str1不包含str2则返回空指针

官方说明:返回指向str1中第一个str2的指针,如果str2不是str1的一部分,则返回空指针。匹配过程不包括终止的空字符,但它在此停止。

测试程序

	char *s1 = "abcd1234";
	char *s2 = "12";
	char *s = strstr(s1,s2);
	puts(s);

output:
1234

模拟实现strstr

const char * strstr(const char * str1, const char * str2){
    while (*str1 != '\0'){
        if (*str1 == *str2){
            const char* pstr1 = str1;
            const char* pstr2 = str2;
            while (*pstr2 != '\0'){
                if (*pstr1 == *pstr2){
                    pstr1++, pstr2++;
                }
                else{
                    break;
                }
            }
            if (*pstr2 == '\0'){
                return str1;
            }
        }
        str1++;
    }
    return NULL;
}

strtok

  • char* strtok ( char* str, const char* delimiters );
  • 作用:按照某些分隔符将字符串分割成一个个子字符串
  • 参数说明:
    • str:待分割字符串
    • delimiters: 分隔符集合
  • 返回值:如果找到标记,则指向标记开头的指针。否则,为空指针。当扫描的字符串到达字符串的末尾(即空字符)时,总是返回空指针。

官方说明:
对此函数的一系列调用将str拆分为标记,这些标记是由作为分隔符一部分的任何字符分隔的连续字符序列。
在第一次调用时,函数需要一个C字符串作为str的参数,str的第一个字符用作扫描标记的起始位置。在随后的调用中,函数需要一个空指针,并使用最后一个标记结束后的位置作为新的扫描起始位置。
要确定标记的开始和结束,函数首先从开始位置扫描分隔符中未包含的第一个字符(它将成为标记的开始)。然后从标记的开头开始扫描分隔符中包含的第一个字符,该字符将成为标记的结尾。如果找到终止的空字符,扫描也会停止。
标记的这一端自动替换为空字符,并且该函数返回标记的开头。
一旦在对strtok的调用中找到str的终止空字符,对该函数的所有后续调用(以空指针作为第一个参数)都将返回空指针。
找到最后一个标记的点由下一次调用时使用的函数内部保存(不需要特定的库实现来避免数据竞争)。

测试程序
程序说明:将str字符串按照3个分隔符(,.-)分成子字符串

	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, " ,.-");
	}

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

程序解释:
在这里插入图片描述中间指针pch分别指向’T’、‘a’、‘s’、‘s’

strerror

  • char* strerror ( int errnum );
  • 作用:显示errnum对应的错误信息
  • 参数说明:
    • errnum:错误编号
  • 返回值:根据错误编号返回相应的错误信息

解释errnum的值,生成一个字符串,其中包含一条消息,该消息描述错误条件,就像库的函数设置为errno一样。
返回的指针指向静态分配的字符串,程序不应修改该字符串。进一步调用此函数可能会覆盖其内容(不需要特定的库实现来避免数据竞争)。
strerror生成的错误字符串可能特定于每个系统和库实现。

测试程序
程序解释:显示Windows系统下所有错误编号对应的错误信息

	for (int i = 0; i < 44; i++)
	{
		printf("%d:%s\n", i, strerror(i));
	}

output:
0:No error
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted function call
5:Input/output error
6:No such device or address
7:Arg list too long
8:Exec format error
9:Bad file descriptor
10:No child processes
11:Resource temporarily unavailable
12:Not enough space
13:Permission denied
14:Bad address
15:Unknown error
16:Resource device
17:File exists
18:Improper link
19:No such device
20:Not a directory
21:Is a directory
22:Invalid argument
23:Too many open files in system
24:Too many open files
25:Inappropriate I/O control operation
26:Unknown error
27:File too large
28:No space left on device
29:Invalid seek
30:Read-only file system
31:Too many links
32:Broken pipe
33:Domain error
34:Result too large
35:Unknown error
36:Resource deadlock avoided
37:Unknown error
38:Filename too long
39:No locks available
40:Function not implemented
41:Directory not empty
42:Illegal byte sequence
43:Unknown error

由此可知Windows系统下一共有42个错误信息+1个无错误信息

猜你喜欢

转载自blog.csdn.net/weixin_45437022/article/details/106676245