c++ 自带string类 的对象 字符串结尾带不带‘’?

浏览:39日期:2023-05-05

问题描述

c++ 自带string类 的对象 字符串结尾带不带‘0’?

问题解答

回答1:

c++ 自带string类 的对象 字符串结尾带不带‘’?先上图

string 类型把’ 0’当做普通字符处理,长度加一,可见’ 0’不是结束字符,不含有特殊功能,string末尾不需加’ 0’

C语言中没有string类型,而是用字符数组代替,一般字符数组可以不确定长度char * string = ' ABCD' ,编译器靠什么知道字符串结束,一般在后面加 ’ 0’

回答2:

C++ 中的std::string和 C-style string 是两种不同的字符串,前者是标准库中定义的一个类,后者是字符数组的别名。

C-style string:通常都以0作为结尾。

std::string:标准中未规定需要0作为字符串结尾。编译器在实现时既可以在结尾加0,也可以不加。但是,当通过c_str()或data()(二者在 C++11 及以后是等价的)来把std::string转换为const char *时,会发现最后一个字符是0(原因见文末附录)。

C-style string 中一般不能包含0字符(因为这个字符被当作表示字符串结束的特殊字符处理了),如果包含这个字符,那么其后的字符将会被忽略。即:

char s[] = 'ab0c';cout << s << endl; // 输出 ab

而std::string没有这个限制。即:

std::string s{’a’, ’b’, ’0’, ’c’};//std::string s = 'ab0c'; // 这里由于是从 C-style string 构造 std::string,所以仍然会忽略 0 之后的字符cout << s << endl; // 输出 ab c附录

通过c_str()或data()(二者在 C++11 及以后是等价的)来把std::string转换为const char *时,会发现最后一个字符是0。想理解这个问题需要一点背景知识:

一,std::string 是 std::basic_string<CharT, Traits, Allocator>这个模板的特例std::basic_string<char>。即模板:

template< class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>> class basic_string;

中的参数CharT为char时的特例。

二,s.size()会返回std::string中字符的个数,即:

string s{’a’, ’b’, ’0’, ’c’};cout << s.size() << endl; // 输出 4s += ’0’;s += ’d’;cout << s.size() << endl; // 输出 6

三,使用[]运算符(即std::basic_string::reference std::basic_string::operator[](size_type pos);)获取std::string中的字符时,其字符的范围pos是从0到size()。其中0到size()-1是所存储的字符,而对于pos == size()有如下规定:

If pos == size(), a reference to the character with value CharT() (the null character) is returned. For the first (non-const) version, the behavior is undefined if this character is modified.

意思是当访问s[s.size()]时,会返回CharT()的返回值的引用,而CharT对于std::string是char,且char()返回的是000,所以s[s.size()]会返回0。

四,通过c_str()或data()(const CharT* c_str() const;)返回的指针访问字符串时,其效果为:

Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].

即p[s.size()]等价于p + s.size()等价于&s.operator[](s.size())等价于s[s.size()],所以会发现返回值是0。

回答3:

0是C语言中的的字符数组作为结束标记用的,C++字符串没有这个需要

回答4:

何不创建一个string对象,打印看看他的size?

回答5:

c语言用char*指针作为字符串时,在读取字符串时需要一个特殊字符0来标记指针的结束位置,也就是通常认为的字符串结束标记。而c++语言则是面向对象的,长度信息直接被存储在了对象的成员中,读取字符串可以直接根据这个长度来读取,所以就没必要需要结束标记了。而且结束标记也不利于读取字符串中夹杂0字符的字符串。

参照std::string的实现 bits/basic_string.h回答6:

String本身是封装过的,会把’0’在调用的时候给去掉,但实际上存储的时候还是有’0’的不管是用data()还是c_str()获取到的字符串都是一样的

#include <iostream>#include <stdio.h>#include <string>using std::string;using namespace std;void test1(){ string s1 = 'Hello'; const char * v1 = s1.data(); printf('0x%.2xn', v1[s1.size()]); string *s2 = new string('Hello'); const char * v2 = s2->data(); printf('0x%.2xn', v2[s2->size()]);}void test2(){ string s1 = 'Hello'; const char * v1 = s1.c_str(); printf('0x%.2xn', v1[s1.size()]); string *s2 = new string('Hello'); const char * v2 = s2->c_str(); printf('0x%.2xn', v2[s2->size()]);;}int main(){ test1(); test2(); return 0;}

输出都是0x00

相关文章: