当前位置:C++技术网 > 资讯 > string系列:8 std::string的字符串拼接操作使用分析

string系列:8 std::string的字符串拼接操作使用分析

更新时间:2016-12-07 18:11:08浏览次数:1+次

    C++中我们处理字符串,很多时候会用std::string。string是std命名空间下定义的字符串处理模板类。string相对于cahr*,用起来还是很方便的。此前做MFC项目,最喜欢的就是CString,用起来太方便了,用的最多的就是CString::Format函数。在非MFC环境,就用回了std::string,然后发现了一些坑,所以在这里总结分享一下。

    如果string用起来溜的话,也是很方便的。基本的string用法就不介绍了。下面来分析经常遇见的string的字符串拼接问题。问题是什么呢?看看下面的代码先:


#include <iostream>
using namespace std;
void main()
{
    string str1 = "www";
    string str2 = "cjjjs";
    string str3 = "com";
    string site = str1 + str2 + str3;//+操作符提示错误
    cout<<site<<endl;//cout不支持string打印
}
    在VS2010环境下,已经直接提示了代码注释中的错误。但是明显的是,string确实可以使用的,比如赋值字符串。下面是VS2010的代码提示图:


没有与这些操作符匹配的+运算符

没有与这些操作符匹配的<<运算符

   如果你基础不错,或许会一眼看出来,要加上这样一句代码:


#include <string>
    是的。加上这个引用头文件,确实解决了问题。但是,这只是简单解决问题的方法。为什么不加这个头文件string一样可以用呢?加了头文件又多了什么呢?如果不加头文件string,我们能不能使用string来拼接字符串呢?如果不加头文件string,能不能使用cout来打印string呢?


    或许你觉得添加string头文件似乎是天经地义的事情,似乎不必浪费时间研究和讨论。如果是这样,你能回答上面几个问题吗?如果回答得了,就不必往下看了。

    当然,本文不是秀技术,这里也没有什么技术含量。只是我之前有时候没有加string头文件,一样用的很顺利,有时候用到了字符串拼接,就出现上述的错误提示。我就纳闷了,所以才觉得简单研究下原因,也就有了这篇文章。对自己用到的东西保持一份兴趣,我想编程才会有更多的乐趣吧。难道我不懂加一个头文件吗?

    要知道加不加头文件有什么区别,我们直接右击这个string,然后转到定义,就可以看到定义的string是什么样的了。如果没有string头文件,我们会跳转到xstring头文件中,string被定义为:


typedef basic_string<char, char_traits<char>, allocator<char> > string;
    string是一个模板类,用char来具体化了。所以string出错时就是各种模板错误提示,看都看不懂。比如:


1>c:\users\wdx\desktop\tmp_c\tmp_c\tmp_c.cpp(9): error C2784: “std::_String_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_iterator<_Elem,_Traits,_Alloc>)”: 未能从“std::string”为“std::_String_iterator<_Elem,_Traits,_Alloc>”推导 模板 参数
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\xstring(434) : 参见“std::operator +”的声明
   看到这样的错误提示,内心是拒绝的,也是痛苦的。不过,硬着头皮看看,其实看到最后的提示,还是能看出来错误是+操作符引起的。你可以直接略过前面的错误提示,因为不略过也看不懂,嘿嘿。

    string被basic_string 重定义typedef了。那么再右击basic_string跳转到定义,可以看到basic_string就是一个模板类。对于操作符的重载,只有=和+=,如下图所示:

basic_string对于操作符的重载,只有=和+=

   所以,basic_string即没有包含string头文件的std::string类可以执行赋值操作,可以执行+=操作,但是不能直接使用+操作符拼接字符串。这也是上面提示错误的原因。同时,也没有对<<操作符的重载,所以cout无法支持直接打印。

    那么如果你只用到=和+=操作符,可以不用包含string头文件。那么这种情况下如何拼接字符串和打印输出呢?当然就是利用+=和char*类型。下面是示例代码:

#include <iostream>
using namespace std;
void main()
{
    string str1 = "www";
    string str2 = "cjjjs";
    string str3 = "com";
    string site;
    site+=str1;
    site+=".";
    site+=str2;
    site+=".";
    site+=str3;
    cout<<site.c_str()<<endl;
}
    效果图:


string效果图

   一样可以拼接字符串,一样可以打印。当然,虽然这样麻烦了,但是确实是可行的哦。

    那么我们可以推测到string头文件一定是重载了+和<<操作符。然后我们打开string头文件,看到string头文件,看到了这个头文件补充了对basic_string类的声明定义,增加了+、<<、>>、<、>、!=、==等各种操作符的重载。所以,添加了string头文件是对string进行扩充。基本版本就是在iostream头文件内部包含了xstring头文件进行了基本的定义。

    所以在包含了string头文件后,我们就可以正常使用一开始的代码了。相信本文不是简单的告诉你添加一个头文件那么简单了事,希望你也能有这个习惯,对于小疑问可以深入研究,说不定可以发现更广阔的世界。