转载至: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. .NET+MVC+ORACLE存储分页查询一后端实现

    MemberController:public ActionResult UserList() { UserBll userBll = new UserBll(); string keyWords = ...

  2. C++11模版元编程

    1.概述 模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序.模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程 ...

  3. 海量数据中找top K专题

    1. 10亿个数中找出最大的1000个数 这种题目就是分治+堆排序. 为啥分治?因为数太多了,全部加载进内存不够用,所以分配到多台机器中,或者多个文件中,但具体分成多少份,视情况而定,只要保证满足内存 ...

  4. 跨浏览器的placeholder-jQuery版(jQuery插件EnPlaceholder)

    案例:整搜索框,需要默认占位符为"请输入关键词",获取焦点时,占位符消失或不可用(不影响正常输入),丢失焦点后,若用户无内容输入,占位符继续出现,继续占位.这种代码我想前端们已经很 ...

  5. PHP最全笔记(二)(值得收藏,不时翻看一下)

    /* [goto]5.3+ 版本 */用来跳转到程序中的某一指定位置该目标位置可以用目标名称 加上冒号来标记.PHP中的goto有一定限制,只能在同一个文件和作用域中跳转,    也就是说你无法跳出一 ...

  6. ABBYY FineReader Pro for Mac有哪些特性(上)

    使用ABBYY FineReader Pro for Mac轻松转换纸质文档.PDF文件和数字文本照片为可编辑和可搜索的文件,再也不需要手动重新输入或格式化了,相反,可以编辑.搜索.共享.归档和复制文 ...

  7. iOS开发之--宏定义与const的区别及使用方法

    宏定义的常见用法: 定义一段代码,或指定字符串抽成宏. const(常量): 当有字符串常量的时候,苹果推荐我们使用const,苹果经常把常用的字符串定义成const 宏定义与const的区别: 编译 ...

  8. [转]ubuntu bits/predefs.h:没有那个文件或目录

    [转]ubuntu bits/predefs.h:没有那个文件或目录 (2012-04-28 10:09:38) 转载▼ 标签: it 分类: Linux In file included from ...

  9. 【Important】数据库索引原理

    为什么要给表加上主键? 为什么加索引后会使查询变快? 为什么加索引后会使写入.修改.删除变慢? 什么情况下要同时在两个字段上建索引? 想理解索引原理必须清楚一种数据结构(平衡树非二叉)也就是b tre ...

  10. css布局 - 垂直居中布局的一百种实现方式(更新中...)

    首先将垂直居中的现象和实现方式两大方向细分类如下: 接下来逐条累加不同情况下的垂直居中实现. 目录: 一.父元素高度固定时,单行文本 | 图片的垂直居中 1. line-height行高简单粗暴实现法 ...