【零基础玩转C语言】字符函数和字符串函数

0. 前言

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

1. 函数介绍

1.1 strlen

strlen

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

注:

#include <stdio.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;
}

输出结果为:

srt1>str2

因为strlen返回值的类型是size_t,也就是无符号整型,相减如果本该得到一个负数,反而会得到一个非常大的正数,因此会得到这个输出结果。所以我们在使用size_t类型的数进行运算的时候,需要注意!

使用实例:

/* strlen example */
#include <stdio.h>
#include <string.h>

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.

1.2 strcpy

strcpy

char * strcpy ( char * destination, const char * source );
  • Copies the C string pointed by source into the array pointed by destination, including the
    terminating null character (and stopping at that point).
  • 源字符串必须以'\0'结束。
  • 会将源字符串中的'\0'拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变

注意:

  1. 当我们想要将一个字符串的内容拷贝到另一个字符串中时,不能简单地使用赋值运算符,比如
char str1[] = "hello world";
char str2[20] = { 0 };
str2 = str1;

这样编译器会报错,因为str1,str2数组名是地址,地址是一个常量值,不能被赋值或者修改,拷贝字符串可以使用strcpy函数。

  1. 使用strcpy函数时,所传递的第一个参数,也就是目标空间必须可变,比如:
const char *p = "abcdef";
char arr[] = "bit";
strcpy(p, arr);

此时p指向的是一个常量字符串,目标区域不可修改,因此也会出现拷贝失败

使用实例:

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

输出结果:

str1: Sample string
str2: Sample string
str3: copy successful

1.3 strcat

strcat

char * strcat ( char * destination, const char * source );
  • Appends a copy of the source string to the destination string. The terminating null characterin destination is overwritten by the first character of source, and a null-character is includedat the end of the new string formed by the concatenation of both in destination.
  • 源字符串必须以'\0'结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。

注意:

  • 字符串自己给自己追加会导致错误,比如:
#include <stdio.h>
#include <string.h>
int main()
{
	char str1[20] = "hello ";
	char str2[] = "world!";
	strcat(str1, str1);
	printf("%s\n", str1);
	return 0;
}

这样的程序的输出会出现错误

使用实例:

/* strcat example */
#include <stdio.h>
#include <string.h>

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. 

1.4 strcmp

strcmp

int strcmp ( const char * str1, const char * str2 );
  • This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
  • 标准规定:
    第一个字符串大于第二个字符串,则返回大于0的数字
    第一个字符串等于第二个字符串,则返回0
    第一个字符串小于第二个字符串,则返回小于0的数字

比较两个字符串是否相等不能简单地用==来判断,即使两个字符串的内容一模一样,使用==进行判断也会得到不相等的结果

#include <stdio.h>

int main()
{
	char str1[20] = "abcdef";
	char str2[] = "abcdef";
	if (str1 == str2)
		printf("==\n");
	else
		printf("!=\n");

	return 0;
}

输出结果:

=
//str1是数组名,str2是数组名
//数组名是数组首元素的地址,这两个数组的首元素地址不相等
//因此会输出!=

因此比较两个字符串不能使用==,可以用strcpy函数来进行判断。

那么如何比较两个字符串?

  1. strcmp从两个字符串的第一个字符开始比较,比较它们的ASCII码值的大小。
  2. 如果相等,则比较下一个,直至其中一个字符串所有的字符都比较完,那么还没有比较完的那个字符串较大,返回-1或者1
  3. 如果两个字符串同时比较完,并且比较过程中每个字符都相等,则返回0
  4. 如果比较过程中两个字符不相等,则直接返回-11

使用实例:

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[] = "ABCD";
	char str2[] = "abcd";
	int ret1 = strcmp(str1, str2);
	if (ret1 == 0)
		printf("str1 == str2\n");
	else if (ret1 < 0)
		printf("str1 < str2\n");
	else
		printf("str1 > str2\n");

	char str3[] = "abcdef";
	char str4[] = "abcd";
	int ret2 = strcmp(str3, str4);
	if (ret2 == 0)
		printf("str3 == str4\n");
	else if (ret2 < 0)
		printf("str3 < str4\n");
	else
		printf("str3 > str4\n");

	char str5[] = "abwde";
	char str6[] = "abced";
	int ret3 = strcmp(str5, str6);
	if (ret3 == 0)
		printf("str5 == str6\n");
	else if (ret3 < 0)
		printf("str5 < str6\n");
	else
		printf("str5 > str6\n");

	char str7[] = "abcd";
	char str8[] = "abcd";
	int ret4 = strcmp(str7, str8);
	if (ret4 == 0)
		printf("str7 == str8\n");
	else if (ret4 < 0)
		printf("str7 < str8\n");
	else
		printf("str7 > str8\n");
		
	return 0;
}

输出结果:

str1 < str2
str3 > str4
str5 > str6
str7 == str8

1.5 strncpy

strncpy

char * strncpy ( char * destination, const char * source, size_t num );
  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到总共写入num个字符为止。

使用实例:

/* strncpy example */
#include <stdio.h>
#include <string.h>

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 */

	printf("%s\n", str1);
	printf("%s\n", str2);
	printf("%s\n", str3);

	return 0;
}

输出结果:

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

1.6 strncat

strncat

char * strncat ( char * destination, const char * source, size_t num );
  • 将源字符串的前num个字符追加到目标字符串,再加上一个终止的null字符。
  • 如果源中的C字符串的长度小于num,则只复制终止null字符之前的内容。

使用实例:

/* strncat example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str1[20];
  char str2[20];
  strcpy (str1,"To be ");
  strcpy (str2,"or not to be");
  strncat (str1, str2, 6);
  printf("%s\n", str1);
  return 0;
}

输出结果:

To be or not

1.7 strncmp

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );
  • 比较C字符串str1和C字符串str2的最多num个字符。
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
    在这里插入图片描述
    使用实例:
/* strncmp example */
#include <stdio.h>
#include <string.h>

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

1.8 strstr

strstr

const char * strstr ( const char * str1, const char * str2 );      char * strstr (       char * str1, const char * str2 );
  • 返回一个指向str1中第一个出现的str2的指针,如果str2不是str1的一部分,则返回一个空指针。也就是查找子串的一个函数。
  • 匹配过程不包括终止的null字符,但仅限于此。

使用实例:

/* strstr example */
#include <stdio.h>
#include <string.h>

int main()
{
    char str[] = "This is a simple string";
    char* pch;
    pch = strstr(str, "simple");
    puts(pch);
    return 0;
}

输出结果:

sample string

1.9 strtok

strtok

char * strtok ( char * str, const char * delimiters );
  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回NULL指针。

使用实例1:

/* strtok example */
#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;
}

输出结果:

Splitting string "- This, a sample string." into tokens:
This
a
sample
string

使用实例2:

#include <stdio.h>
#include <string.h>
int main()
{
	char* p = "www.baidu@com.cn";
	const char* sep = ".@";
	char arr[30];
	char* str = NULL;
	strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);
	}
}

输出结果:

www
baidu
com
cn

1.10 strerror

strerror

char * strerror ( int errnum );
  • 返回错误码所对应的错误信息。
  • 使用错误码必须包含errno.h这个头文件

C语言的库函数,在执行失败的时候,都会设置错误码。errno是C语言设置的一个全局的错误码存放的变量。strerror函数解释errnum的值,生成一个字符串,其中包含一条描述错误条件的消息,就像库的函数设置为errno一样。
可以使用下面的程序查看每个错误码所代表的信息

#include <stdio.h>
#include <errno.h>

int main()
{
	for (int i = 0; i < 50; i++)
		printf("errno:%d -> %s\n", i, strerror(i));

	return 0;
}

可以看到,C语言一共有43个错误码,其中0表示程序正常运行,其他错误码分别代表程序出现了不同的错误的信息

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

使用实例:

/* strerror example : error list */
#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));
	//errno: Last error number
	return 0;
}

输出结果:

Error opening file unexist.ent: No such file or directory

1.11 字符分类函数

函数如果他的参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a~z或A~Z
isalnum字母或者数字,a~z,A~Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

字符转换:

int tolower ( int c );//将大写字母转换为小写字母
int toupper ( int c );//将小写字母转换为大写字母

使用实例:

/* isupper example */
#include <stdio.h>
#include <ctype.h>
int main()
{
	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
		c = str[i];
		if (isupper(c))
			c = tolower(c);
		putchar(c);
		i++;
	}
	return 0;
}

输出结果:

test string.

1.12 memcpy

memcpy

void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpysource的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到'\0'的时候并不会停下来。
  • 如果sourcedestination有任何的重叠,复制的结果都是未定义的。
  • memcpy负责拷贝两块独立空间中的数据。
  • strcpy只能拷贝字符串,而memcpy可以拷贝任何类型的数据

使用实例:

/* memcpy example */
#include <stdio.h>
#include <string.h>

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

输出结果:

person_copy: Pierre de Fermat, 46

1.13 memmove

memmove

void * memmove ( void * destination, const void * source, size_t num );
  • memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

使用实例:

/* memmove example */
#include <stdio.h>
#include <string.h>

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

输出结果:

memmove can be very very useful.

1.13 memcmp

memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • ptr1所指向的内存块的前num个字节与ptr2所指向的前num个字节进行比较,如果它们都匹配则返回零,或者如果不匹配则返回与零不同的值,表示哪个值更大。
  • strcmp不同,该函数在找到空字符后不会停止比较。
    返回值如下:
    在这里插入图片描述
    使用实例:
/* memcmp example */
#include <stdio.h>
#include <string.h>

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

输出结果;

'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.

1.14 memset

memset

void * memset ( void * ptr, int value, size_t num );
  • ptr指向的内存块的前num个字节设置为指定值(解释为无符号字符)
  • memset不适用于整型和浮点型数组的初始化,整型和浮点型数组的初始化最好用for循环来完成

使用实例:

/* memset example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "almost every programmer should know memset!";
  memset (str,'-',6);
  puts (str);
  return 0;
}

输出结果:

------ every programmer should know memset!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值