C字符串操作strlen/strnlen_s详解

前言

strcat、strcpy、strcmp、strlen是C中针对字符串的库函数,这四个函数不安全,然后C针对这个情况整出strcat_s、strcpy_s、strncmp、strnlen_s(这个并不是替代stelen的)来弥补。

这篇文章主要讲:strlen以及strnlen_s的用法。

 

1 strlen

1.1 函数功能

计算指定字符串的长度,但不包括结束字符。

 

1.2 函数声明、参数及返回值

头文件:

#include<string.h>  (C)  、 #include<cstring>

声明:

size_t strlen(char const *str);

参数:
           str -- 要计算的字符串

返回值:字符串长度,size_t是unsigned int

 

1.3 注意 

(1)strlen计算时,一定要确保字符数组是以空字符结束的,如果没有则可能沿着数组在内存中的位置不断向前寻找,知道遇到空字符才停下来。

(2)当字符串为nullptr时,strlen行为未定义。

 

 

1.4 代码演示

(1)字串串结尾有空字符

#include "stdafx.h"
#include <iostream>
#include <cstring>

int main(){
	char str[] = "Hello,world";
	size_t len = strlen(str);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 11
请按任意键继续. . .

 

(2)字符串结尾无空字符结尾

#include "stdafx.h"
#include <iostream>
#include <cstring>

int main(){
	char str[] = { 'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd' };
	size_t len = strlen(str);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 23
请按任意键继续. . .

很明显,当字符串结尾无空字符时,结果未定义。

 

2 strnlen_s

2.1 函数功能

strnlen这个函数一般用于检测不可信的数据(如网络数据),因为这种数据中可能没有'\0',这时如果用strlen的话会一直扫描无法停止(直到越界触碰到无效内存),而strnlen限制住了扫描范围所以不会出事。

 

2.2 函数声明、参数及返回值

头文件:

#include<string.h>  (C)  、 #include<cstring>

声明:

size_t strnlen(const char *str, size_t numberOfElements);

参数:
           str -- 要计算的字符串

           numberOfElements -- 最大数量的字符进行检查

返回值:字符串长度,size_t是unsigned int

 

2.3 注意 

(1)如果在刚开始的numberOfElements长度里找到不到空字符,则返回numberOfElements。

(2)如果字符串长度小于numberOfElements,且字符串结尾有空字符则返回字符串长度,如果结尾没有空字符,则返回numberOfElements。

(3)字符串为nullptr时,返回为0。

 

1.4 代码演示

(1)如果在刚开始的numberOfElements长度里找到不到空字符,则返回numberOfElements

#include "stdafx.h"
#include <iostream>
#include <cstring>

int main(){
	char str[] = "Hello,world";
	size_t len = strnlen_s(str, 5);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 5
请按任意键继续. . .

 

(2)字符串实际长度小于numberOfElements,结尾有空字符和无空字符的情况

#include "stdafx.h"
#include <iostream>
#include <cstring>

int main(){
	char str[] = {'H', 'e', 'l', 'l', '\0'};
	size_t len = strnlen_s(str, 5);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 4
请按任意键继续. . .



int main(){
	char str[] = {'H', 'e', 'l', 'l'};
	size_t len = strnlen_s(str, 5);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 5
请按任意键继续. . .

 

(3)字符串为nullptr

#include "stdafx.h"
#include <iostream>
#include <cstring>


int main(){
	char *str = nullptr;
	size_t len = strnlen_s(str, 5);
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出:
length is 0
请按任意键继续. . .

 

3 C++ string类

综上所述,strlen函数不安全,虽然引进了strnlen_s函数,但这个函数并不是为了替代strlen。而且两者都有同样的缺陷。

C++中string类中有计算字符串长度的函数size()和length()

注意:char* 转成 string时,如果char*没有空字符,则会造成未定义行为。

#include "stdafx.h"
#include <iostream>
#include <string>

int main(){
	char str[] = "Hello,world";
	size_t len = std::string(str).size();;
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出为:
length is 11
请按任意键继续. . .



// 未定义行为
int main(){
	char str[] = {'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd'};
	size_t len = std::string(str).length();;
	std::cout << "length is " << len << std::endl;
	return 0;
}


结果输出为:
length is 29
请按任意键继续. . .



 

如果用直接初始化string对象会发生什么?

#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <string>


int main(){
	std::string str1 = { 'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd' };
	std::string str2 = "Hello,world";
	std::string str3 = { 'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r', 'l', 'd', '\0'};
	size_t len1 = std::string(str1).size();
	size_t len2 = std::string(str2).size();
	size_t len3 = std::string(str3).size();
	std::cout << "str1's length is " << len1 << std::endl;
	std::cout << "str2's length is " << len2 << std::endl;
	std::cout << "str3's length is " << len3 << std::endl;
	return 0;
}


str1's length is 11
str2's length is 11
str3's length is 12
请按任意键继续. . .

从以上程序可以看出:

(1)对于字符串常量,string.size()返回的时候不包含最后的空字符

(2)对于字符串数组,string.size()把'\0'当作普通字符处理。

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值