转载至:http://chzhou.blog.sohu.com/97459512.html

以前一直没有注意到STL中的string的length函数,但一直用它。天真的以为它会返回字符串的长度。这是因为我们在C中经常会用strlen去求一个字符串的长度,转到C++,看到std::string中有length,乖乖,万事大吉了。

    我一直这样想当然的用这个函数没有出过问题。是我的运气呢,还是stl防备了这些可能出现的问题呢。

    而我最近发现,std::string的能力比我想像的要更强大。

    这两天对google刚刚开源的protocol buffer(简称PB)产生了兴趣。这个工具是用来将结构化的数据封装成二进制流。并提供反方向的工作。也就是说,它是一个能够完成序列化/反序列化工作的工具。当然,它的功能不限于此。

    PB完成了对整数,实数,字符串的封装,完成了对结构体的封装,一切都完美无缺。它还完成了对Bytes的封装,太好了,这正是我想要的。我是想用它来封装一个地理数据(图层),里面有纯二进制数据。

    等等,等我定义好我的协议文件。是的,我定义好了,帮我翻译成C++吧。

    好的,翻译好了。

    嗯,让我看看。一切都很好。但是,等一下,为什么把我的Bytes翻译成了std::string?

    该死的google,难道不知道string是用来存字符串的吗,二进制中有零的话,不就被截断了,那我的数据还能有救?

    嗯,是的,仔细看了std::string::assign和length的实现,是的。很好,std::string的能力超出了我的想像。二进制数据没有被截断,一切的所有都被完整地保留下来了。

    这很让人兴奋,让我来试一试。编几行代码来测试一下std::string::assign和std::string::length.

    编好了,贴在这里。

// TestStringLength.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"  //这个需要解释,但是算了。呵呵。
#include <string>
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    int pIntBuf[] = {1, 2, 3, 0, 0, 0, 5, 2, 3, 20, 50};
    char pStrBuf[1000];
    pStrBuf[500] = '\0';//在随机的缓冲区中加入一个结束符
    std::string strBuf = "I Love you.";
    char s = ' ';//是的,只是一个空格

    //强制性的硬拷贝可能会越界,但是仍要试试,这当然是不会截断数据了。
    std::string str1, str2, str3;
    str1.resize(sizeof(pIntBuf)+1, '\0');
    str2.resize(sizeof(pStrBuf)+1, '\0');
    str3.resize(strlen(strBuf.c_str()) +1, '\0');
    memcpy((void*)str1.c_str(), pIntBuf, sizeof(pIntBuf)+1);
    memcpy((void*)str2.c_str(), pStrBuf, sizeof(pStrBuf)+1);
    memcpy((void*)str3.c_str(), strBuf.c_str(), strlen(strBuf.c_str()) +1);
    std::cout<<str1.length()<<s<<str2.length()<<s<<str3.length()<<endl;
    std::cout<<strlen(str1.c_str())<<s<<strlen(str2.c_str())<<s<<strlen(str3.c_str())<<endl;
    std::cout<<endl;

    //试试string::assigh(string&), 发现也没有丢失数据。
    std::string str4, str5, str6;
    str4.assign(str1);
    str5.assign(str2);
    str6.assign(str3);
    std::cout<<str4.length()<<s<<str5.length()<<s<<str6.length()<<endl;
    std::cout<<strlen(str4.c_str())<<s<<strlen(str5.c_str())<<s<<strlen(str6.c_str())<<endl;
    std::cout<<endl;

    //用string::assign(char*), 数据丢失了。 当然, 因为char*根本不知道真实的长度,只能找到第一个'\0'
    std::string str7, str8, str9;
    str7.assign(str1.c_str());
    str8.assign(str2.c_str());
    str9.assign(str3.c_str());
    std::cout<<str7.length()<<s<<str8.length()<<s<<str9.length()<<endl;
    std::cout<<strlen(str7.c_str())<<s<<strlen(str8.c_str())<<s<<strlen(str9.c_str())<<endl;
    std::cout<<endl;

    return 0;
}

结果有了,也贴出来:

--------------------------------
45 1001 12
1 500 11

45 1001 12
1 500 11

1 500 11
1 500 11
--------------------------------

略作分析:

分三组,每组两行结果,第一行是真实的长度,第二行是结束符'\0'之前的长度。

第一组,前两行是硬拷贝的结果,很好,没有截断我的数据。

第二组,string::assigh(string& S),也是完全拷贝,没有丢掉S中结束符之后的部分。
由此可见,string并不是专为字符串而设计的,而是缓冲区,把它当成字符串使用的话,反而要多一份小心。

第三组,由于char*类型丢失了缓冲区的长度性息,理所当然的要丢失数据了。

好吧。这个std::string的认识又深了一层。

结论是,string不仅是charString,更是byteString。

继续研究这个google::protocolbuffer。

stl, string不仅是charString, 更是byteString的更多相关文章

  1. 浅谈C++ STL string容器

    浅谈C++ STL string容器 本篇随笔简单讲解一下\(C++STL\)中\(string\)容器的使用方法及技巧. string容器的概念 其实\(string\)并不是\(STL\)的一种容 ...

  2. 深入剖析 linux GCC 4.4 的 STL string

    转自: 深入剖析 linux GCC 4.4 的 STL string 本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Wri ...

  3. 格式字符串分配stl::string

    代码非常easy,不解释,直接在代码: #include <cstdio> #include <cstdarg> #include <iostream> using ...

  4. C++标准模板库Stand Template Library(STL)简介与STL string类

    参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进 ...

  5. 转C++之stl::string写时拷贝导致的问题

    前几天在开发某些数据结构到文件的 Dump 和 Load 功能的时候, 遇到的一个 bug . [问题复现] 问题主要出在 Load 过程中,从文件读取数据的时候, 直接使用 fread 的去操作 s ...

  6. [转载] C++ STL string的Copy-On-Write技术

    原文: http://coolshell.cn/articles/12199.html stl的string是经过严格优化的, 深入理解对以后编程过程中应用string非常有益处, 感谢左耳朵耗子的精 ...

  7. STL——string

    C++之string类型详解 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够.字符串长度等等,而且作为一个泛型类出现,他集成的操作函 ...

  8. C++ STL string对象操作汇总

    string对象 C语言只提供了一个char类型用来处理字符,而对于字符串,只能通过字符串数组来处理,显得十分不便.C++STL提供了string基本字符系列容器来处理字符串,可以把string理解为 ...

  9. C++ STL——string和vector

    目录 一 STL基本概念 二 string容器 三 vector容器 3.1 vector动态增长原理 3.2 vector构造函数 3.3 vector常用赋值操作 3.4 vector大小操作 3 ...

随机推荐

  1. 基于mindwave脑电波进行疲劳检测算法的设计(4)

    上一次的实验做到可以从pc端读取到MindWave传输过来的脑电波原始数据了. 我是先定义一个结构体,该结构体对应保存所有能从硬件中取到的原始数据. struct FD_DATA { int batt ...

  2. 推荐几个Windows工具软件: Stickies - 桌面贴

    主页: http://www.zhornsoftware.co.uk/stickies/index.html Stickies work like Post-it notes for your PC. ...

  3. Python爬虫学习——使用selenium和phantomjs爬取js动态加载的网页

    1.安装selenium pip install selenium Collecting selenium Downloading selenium-3.4.1-py2.py3-none-any.wh ...

  4. Angular4学习笔记(二)-在WebStorm中启动项目

    点击配置 创建 选择命令 package.json 运行 查看运行结果

  5. DOS、Mac 和 Unix 文件格式+ UltraEdit使用

    文件格式 区分DOS.Mac 和 Unix分别对应三种系统 从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种 文件模式 区分ASCII模式和Binary模式  通常由系统决定,大多数 ...

  6. Turning off “Language Service Disabled” error message in VS2017

    We are getting the following "Error" message in our MVC web application in Visual studio 2 ...

  7. Python 字符串转JSON; 先装字典在转JSON; json.dumps(d)

    #-*- coding:UTF-8 -*- import os; import json class MysqlUtil(): def __init__(self): pass if __name__ ...

  8. [Converge] Gradient Descent - Several solvers

    solver : {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}, default: ‘liblinear’ Algorithm to use in the op ...

  9. trace-cmd使用方法

    使用trace-cmd有的时候没有来得及使用ctrl+c, 导致出现多个trace.dat.cpu*, 可以使用下面的办法来手动合并trace.dat If a crash happened on a ...

  10. Git工作流程最佳实践总结

    Git作为一个目前非常流行的版本管理工具,深受开发者的喜爱.那么怎样才能将Git的作用发挥的更好呢?我根据实际的项目经验,归纳总结了以下Git工作流的最佳实践.这里所谓的最佳,是经过多次项目经验后,根 ...