你会计算C字符串长度吗?


原文 不见得你会计算C字符串长度,CSDN同步发布。

转载请注明出处,谢谢!


无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以跳转到教程。

在这里插入图片描述

C 字符串

在 C 语言中,字符串实际上是使用字符 '\0' 终止的一维字符数组。

以下几种方式表示的都是 C 字符串的正确表达方式。

// 要以 '\0' 结尾
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

// 要以 '\0' 结尾
char greeting[] = {'H', 'e', 'l', 'l', 'o', '\0'};

// 默认会在末尾增加'\0'
char greeting[] = {"Hello"};

// 上面的简写形式
char greeting[] = "Hello";

// 默认会在末尾增加'\0'
char *greeting = "Hello";

看下面另外一种声明方式:

char greeting[] = {'h', 'e', 'l', 'l', 'o'};

printf("greeting: %s\n", greeting);

输出结果:

greeting: hello\376

这个结果在不同编译器下面可能还会不一样,总之输出都不是我们想要的结果。这种方式创建的字符串没有 '\0',不算是真正的 C 字符串,所以建议大家在声明 C 字符串的时候使用字符指针(char *)的方式。

string.h 里面声明了很多关于操作 C 字符串的库函数。

字符串长度

这里在说计算字符串长度的前提是字符编码都是按照UTF-8(中文占用3个字节,英文占用1个字节)的编码形式为前提的。我们先来看下面这个例子,如下:

char *greeting1 = "hello";
char greeting2[] = {'h', 'e', 'l', 'l', 'o'};
char greeting3[] = {'h', 'e', 'l', 'l', 'o', '\0'};
char greeting4[] = "hello";
    
printf("greeting1 sizeOf: %ld, strlen: %ld\n", sizeof(greeting1), strlen(greeting1));

printf("greeting2 sizeOf: %ld, strlen: %ld\n", sizeof(greeting2), strlen(greeting2));

printf("greeting3 sizeOf: %ld, strlen: %ld\n", sizeof(greeting3), strlen(greeting3));

printf("greeting4 sizeOf: %ld, strlen: %ld\n", sizeof(greeting4), strlen(greeting4));

如果你能说出上面 printf 的结果,基本上关于计算字符串长度的问题就迎刃而解了。

按照 UTF-8 编码,上面例子的输出结果如下所示:

greeting1 sizeOf: 8, strlen: 5
greeting2 sizeOf: 5, strlen: 7
greeting3 sizeOf: 6, strlen: 5
greeting4 sizeOf: 6, strlen: 5

如果输出结果令你无法相信,可以选择继续往下看或者你自己写代码试试。

sizeof、strlen

linux.die 可以查到 strlen 的说明,如下:

Synopsis:
#include <string.h>
size_t strlen(const char *s);

Description:
The strlen() function calculates the length of the string s, excluding the terminating null byte (aq\0aq).

Return Value:
The strlen() function returns the number of bytes in the string s.

函数 strlen 返回字符串里的字符数,不包括终止字符 '\0',这里注意 strlen 是一个 C 的函数,而 sizeof 只是一个操作符。

我们知道,sizeof 操作符的参数可以是数组、指针、类型、对象、函数等,函数 strlen 的参数只能是字符串。

对于 sizeof, 其参数不同时,其返回的值也不一样,如下:

1、数组:编译时分配的数组空间大小;
2、指针:存储该指针所用的空间大小(32位机器上是4,64位机器上是8);
3、类型:该类型所占的空间大小;
4、对象:对象的实际占用空间大小(这个指的是在 C++ 中);
5、函数:函数的返回类型所占的空间大小。函数的返回类型不能是 void 类型;

那我们再回头看看上面的例子,我把要说明的写在注释上面了。

// 注意这里是指针
char *greeting1 = "hello";

// 没有结束符 '\0',其 strlen 结果不确定
char greeting2[] = {'h', 'e', 'l', 'l', 'o'};

char greeting3[] = {'h', 'e', 'l', 'l', 'o', '\0'};
char greeting4[] = "hello";
    
/* 结果是 8、5 */
/* greeting1是指针,sizeOf计算的是其存储该指针所用的空间大小,因为我使用的是64位 macOS,所以输出是8 */
/*strlen 计算的是字符个数但是不包括结束符 '\0'*/
printf("greeting1 sizeOf: %ld, strlen: %ld\n", sizeof(greeting1), strlen(greeting1));

/* 结果是 5、7 */
/* sizeof 计算的是编译时分配的数组空间大小,这里是5 */
/* greeting2没有结束符,strlen 的计算结果不确定 */
printf("greeting2 sizeOf: %ld, strlen: %ld\n", sizeof(greeting2), strlen(greeting2));

/* 结果是 6、5 */
/* sizeof 计算的是编译时分配的数组空间大小,这里是6,因为多了结束符 */
/*strlen 计算的是字符个数但是不包括结束符 '\0'*/
printf("greeting3 sizeOf: %ld, strlen: %ld\n", sizeof(greeting3), strlen(greeting3));

/* 结果是 6、5,这里类似上面的情况,不再赘述 */
printf("greeting4 sizeOf: %ld, strlen: %ld\n", sizeof(greeting4), strlen(greeting4));

小结

1、sizeof 是一个操作符,而 strlen 是 C 语言的库函数。

2、sizeof 的参数可以是任意数据类型或者表达式,而 strlen 只能以结尾为 '\0' 的字符串作参数。

3、sizeof 的结果在编译时就计算出了,而 strlen 必须在运行时才能计算出来。

4、sizeof 计算数据类型占内存的大小,strlen 计算字符串实际长度,要记住 strlen 计算出来的结果不包括结束符 '\0'

5、sizeof 反应的并非真实字符串长度而是所占空间大小,所以memset 初始化字符串的时候用 sizeof 较好。

6、系统函数返回值是 char * (字符指针)类型的会在末尾加上结束符 '\0'

7、无论是 sizeof 还是 strlen 计算结果的单位都是字节。

我们还需要注意一点,strlen 函数,当数组名作为参数传入时,实际上数组就退化成指针了。举个例子,如下图所示:

可以看出传入进来的参数会被退化为指针。

探索无止境

在文章的开始,我给出了几种 C 字符串的正确表达方式,那我们再来看另外一种。

char greeting[4] = "blog";

这种方式看起来好像很完美的样子,其实是不对的,写个例子给大家,如下:

int main(int argc, const char *argv[])
{
	char greeting[4] = "blog";
	size_t len = strlen(greeting);
	printf("greeting len: %ld\n", len);
	printf("greeting: %s\n", greeting);
	
	return 0;
}

编译运行,结果如下:

greeting len: 10
greeting: blog\330\365\277\357\376

苍天呀,这结果让人无语。。。

对于 char greeting[4] = "blog" 其实是定义一个长度为 4 的字符数组,但是字符串 "blog" 实际是要包括结束符 \0 的,也就是说下面的代码

char greeting[4] = "blog";

本质和下面代码是一样的,如下:

char greeting[] = {'b', 'l', 'o', 'g'};

显然是不正确的,那我们修改一下代码,如下:

int main(int argc, const char *argv[])
{
	// 注意这里是 5
	char greeting[5] = "blog";
	size_t len = strlen(greeting);
	printf("greeting len: %ld\n", len);
	printf("greeting: %s\n", greeting);
    
	return 0;
}

或者这样写:

int main(int argc, const char *argv[])
{
	// 这里干脆不要写数字
	char greeting[] = "blog";
  	size_t len = strlen(greeting);
	printf("greeting len: %ld\n", len);
	printf("greeting: %s\n", greeting);
    
    return 0;
}

这样修改后,再编译运行结果就对了,如下:

greeting len: 4
greeting: blog

我们知道的东西是有限的,我们不知道的东西则是无穷的。
在这里插入图片描述

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值