C++string与C语言字符串结合使用易错点总结

文章讨论了在C++中使用string对象时,通过data()和c_str()方法赋值的常见错误。data()和c_str()返回的constchar*指针不能直接用于修改string内容,因为它们是只读的。正确的方法是先将数据复制到char数组,然后赋值给string。另外,使用size()或length()时要注意它们不包含结束符,在复制到char*时需额外添加1以包含结束符。
摘要由CSDN通过智能技术生成

易错点1:通过string的data()方法,来给string赋值

说明:

(1)string的data()方法:函数原型为 const char* data() const noexcept; 返回的指针指向string对象当前用于存储其字符值的内部数组,该字符数组包含字符串结束符"\0"。

(2)string的c_str()方法:函数原型为 const char *c_str() const noexcept; 返回一个指向数组的指针。该数组包含组成string对象值的相同字符序列,并在末尾加上一个额外的终止空字符('\0')。

data()方法和 c_str()作用是相同的。

string的size()和length()方法也是相同的。

想使用memcpy和sscanf等方法给string赋值时,必须借助char *或cha[],先将值赋值给char *或char[], 然后再用char *或char[] 给string赋值,而不能直接操作string的data()或c_str()返回的指针,首先data()和c_str()返回的指针为const char*类型,即使通过const_cast等方法强转后,也无法为string赋值,有时甚至会引起crash等异常。

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

int main()
{
    std::string str{};
    std::cout<<"str.length="<<str.length()<<" str.size="<<str.size()<<" str.capacity="<<str.capacity()<<std::endl;
    
    std::string str1{"hello123456789a world"};
    sscanf(str1.c_str(), "%s%*s", const_cast<char *>(str.data()));
    //memcpy(const_cast<char *>(str.data()), str1.c_str(), str.length());
    std::cout<<"str.length="<<str.length()<<" str.size="<< str.size()<<" str.capacity="<<str.capacity()<<" str="<<str<<std::endl;
    std::cout<<"str.data()="<<str.data()<<std::endl;
    return 0;
}

运行结果如下:

如上的代码目的是想把str1的空格前的部分"hello123456789a"赋值给str,但是操作后打印str的值发现为空,并没有赋值成功,size/length也为0。倒是给str.data()这个指针赋值成功了。

定义一个空的string对象,编译器会为其分配一个初始的capacity大小,一般为15。

如果给str赋值的字符串的大小超过capacity的话,那么不但没有给str赋值成功,可能还会引起crash。比如上面的代码,"hello123456789a"长度为15,如果我们再加一个字符,重新编译运行就会crash。

int main()
{
	std::string str{};
	std::cout<<"str.length="<<str.length()<<" str.size="<<str.size()<<" str.capacity="<<str.capacity()<<std::endl;
	
	std::string str1{"hello123456789ab world"};
	sscanf(str1.c_str(), "%s%*s", const_cast<char *>(str.data()));
	//memcpy(const_cast<char *>(str.data()), str1.c_str(), str.length());
	std::cout<<"str.length="<<str.length()<<" str.size="<< str.size()<<" str.capacity="<<str.capacity()<<" str="<<str<<std::endl;
	std::cout<<"str.data()="<<str.data()<<std::endl;
	return 0;
}

 

 正确的做法是通过char[]或char *接过数据之后,在赋值给string。

#include <string>
#include <iostream>

int main()
{
	std::string str{};
	std::cout<<"str.length="<<str.length()<<" str.size="<<str.size()<<" str.capacity="<<str.capacity()<<std::endl;
	
	std::string str1{"hello123456789ab world"};
	char chr[32]{};
	sscanf(str1.c_str(), "%s%*s", chr);
	str = chr;
	std::cout<<"str.length="<<str.length()<<" str.size="<< str.size()<<" str.capacity="<<str.capacity()<<" str="<<str<<std::endl;
	std::cout<<"str.data()="<<str.data()<<std::endl;
	return 0;
}

通俗的将就是:string的data()方法和 c_str()返回的就是const char*类型,其目的就是只能用data()和 c_str()去获得指向string字符串的指针,只能去使用它,而不能反过来通过data()方法和 c_str()去修改string。

易错点2:通过string的data()/c_str()方法,和string的length()/size()方法组合使用给char *赋值

如下的代码中,为chr *分配了str.size()的空间,然后再strncpy()函数中,通过str.c_str()指定src,通过str.size()指定copy的字节数。编译运行输出chr后发现出现乱码,原因是:str.size()/length()计算的大小不包括结束符,而c_str()和data()方法返回的const char*指针指向的字符数组是包含 '\0'结束符的。所以正确的应该在new的时候和copy的时候len为str.size()/length()+1。否则chr 指向的字符串无结束符。

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

int main()
{
	std::string str{"hello"};
	std::cout<<"str.size="<<str.size()<<std::endl;
	char* chr{new char[str.size()]};
	strncpy(chr, str.c_str(), str.length());
	std::cout<<"chr="<<chr<<std::endl;
	return 0;
}

正确代码:

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

int main()
{
	std::string str{"hello"};
	std::cout<<"str.size="<<str.size()<<std::endl;
	char* chr{new char[str.size()+1]};
	strncpy(chr, str.c_str(), str.length()+1);
	//strncpy(chr, str.data(), str.length()+1);  //和c_str()一样
	std::cout<<"chr="<<chr<<std::endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值