督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正。

问题1:养成一个好习惯,在头文件中只定义确实需要的东西

using namespace std;  //建议需要什么再using声明什么,最好不使用这个偷懒的写法

问题2:C++定义了一个内容丰富的抽象数据类型的标准库,最重要的两个标准库类型是string和vector

因为他们是c++基本内置类型基础上改进而来,故重要!前者支持变长字符串,后者可以保存一组指定类型的对象。

问题3:什么时候会调用默认的构造函数?

默认构造函数,是不带参数的,可以为所有形参提供默认实参。且它是系统默认提供的,在定义类对象的时候,没有提供初始化时会自动调用。

问题4:初始化string对象的三个方式:

默认构造函数初始化

string s;//全局变量,默认初始化为空

int main(void)
{
string s1;//调用string类的默认构造函数,初始化为空
cout << s << "|" << s1 << endl;//打印|return ;
}

string对象初始化和字符串字面值常量初始化

    string s = "adadad";//字符串字面值复制初始化
string s1 = s;//已有的string对象 复制初始化
string s2(s);//已有的string对象直接初始化
string s3("darfxfw");//字符串字面值直接初始化 //string s(n, '单个字符');此种形式的初始化,只能写为直接初始化的形式!
string s4(, 'd');//比较重要的用法!可以初始化s4为10个d组成的字符串
cout << s4 << endl;

问题5:cin读取string的特点

    string s;
//从标准输入读取string类型数据,存储在s
//写法:cin >> s; 注意:
//1、读取的时候忽略开头的所有空白字符(tab,space,enter等)
//2、再次遇到空白字符,自动结束输入,类似c语言里的scanf函数,遇到空白就停止输入!
//cout << s << endl;
//测试输入: 123 456 ,输出123,前面的空白,和后面的空白被自动忽略!
//测试输入: ,输出空,同理 //同时输入多个string对象
//1、可以空格为区分,如
string ss;
cin >> s >> ss;//测试:先输入hello,然后输入空格(可多个),继续输入world,则最后输出helloworld,空格不被读取
//2、既然可以用 不限个数的 空字符区分,自然可以输入回车换行之后继续输入ss,效果一样
cout << s << ss << endl;

注意:程序开头要包含头文件和using声明

#include <iostream>
#include <string>
using std::string;
using std::endl;
using std::cin;
using std::cout;

问题6:如果想读取空白字符,那么不能用输入流,而是需要使用getline()函数

    string line;
//不忽略空白字符,但是换行例外!也就是说,只要getline函数遇到换行,就自动结束读取,其他空白不会!结束输入后返回istream对象
//如果是在开始输入的时候,就输入换行,那么输入就会终止,返回一个空串!
while (getline(cin, line))
{
//实现输入一行文本,打印一行文本
cout << line << endl;
}

注意:因为getline函数以换行为结束,且是忽略换行!那么依然要使用endl换行,之所以遇到换行就结束输入,是因为getline()是用来读取一整行内容的函数。

问题7:比较string的cin输入和getline输入方式

cin适合读取一个单词,getline函数适合读取一行文本,如:

string in;
//cin返回所读的istream对象,但是仅仅适合读入单词,如果开头遇到任何空白字符,则被忽略!即使是换行也是忽略掉!后续遇到空白则终止读取
while (cin >> in)
{
cout << in << endl;
}
//直到遇到文件末尾且是无效输入,或者ctrl+z符号(不同操作系统不一样),则结束循环

小结:当遇到需要每次读入一个单词的要求,则使用cin+循环,如果是每次需要读取一行内容,则使用getline()函数+循环。且还有一个问题,如果使用cin读取string对象,那么我们知道开头或者中间的任何空白都被忽略,且后续遇到空白字符,就终止读取,但是此时,空白字符还是留在了输入流内!而getline恰恰相反,不会忽略开头的空白字符,遇到换行符就结束读取!但是会丢弃换行符,不会保留在输入流内!更不会存到string对象里!

问题8:再论,为何不建议偷懒的直接使用using namespace xxx;俗称using指示,而建议使用using声明?

就怕习惯了,在大型程序里,经常使用不同的多个库,如用using指示,就会包含全部库的名字空间,有可能出现命名冲突。标准库std虽然不会,但是专家建议别怕麻烦。

问题9:字符串字面值常量和string类型不是同一个类型!

目的是兼容c语言而规定,不要混淆两者。注意区分!

问题10:string对象的求长度操作

求长度,指的是string对象中字符的个数

string st("hello world!");
string nullStr;
cout << nullStr.size() << endl;//
cout << nullStr.length() << endl;//
cout << st.length() << endl;//
cout << st.size() << endl;//

注意:basic_string<>有双重身份,一是代替传统的C字符串,所以应该针对C中的strlen给出相应的函数length()。另一个身份是可以用作STL容器,所以要按照STL容器的惯例给出size(),两者功能一样。

问题11:为什么不建议把size()函数的返回值赋值给c/c++基本内置类型int or其他整型?

string类的size()成员函数返回的不是整型,而是string::size_type类型,这样的类型叫库类型的配套类型,目的是实现机器无关性!因为不同机器的int类型或者无符号int的大小不一样!平台换了,则一样的程序可能出现类型的长度溢出错误

注意:size_type功能上和 无符号的 int或者 无符号的 long int一样大小,但是只是功能一样!千万不要随便的赋值给int类型,他们不是一个类型!针对不同平台,不同存储的string对象,返回的大小极有可能和内置类型的范围不一样!引起溢出错误!

且显式的使用返回值时,应该加上string::size_type,来说明这个类型是string类定义的

    string str = "";
int len = str.size();//不是不对,而是不建议这样用,没有超过范围,这样是ok的,但是要禁止类似写法!
cout << len << endl;//4

看下对应的汇编源码:

int len = str.size();
011233E4 lea ecx,[ebp-34h]
011233E7 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::size (11212FDh)
011233EC mov dword ptr [ebp-40h],eax

发现内部实现机制确实是这样调用的:std::basic_string<char,std::char_traits<char>,std::allocator<char> >::size ()

问题12:string对象判空操作

string str = "";
//判空,数据结构中常见啊,empty()函数返回bool值,空就是true,不空就是false
if (str.empty())
{
cout << "NULL" << endl;
}
//打印NULL
//当然也可以使用求长度判断string串空
string str1;
if ( == str1.length())
{
cout << "str1空" << endl;
}
//打印str1空

问题13:string对象的关系操作(串比较),使用运算符重载,实现比较对象的功能!返回bool类型

1、string对象比较操作,区分大小写!比如

    string a = "aaa";
string A = "AAA";
if (a == A)
{
cout << "haha" << endl;//没有执行!说明两个对象不等!
}

2、判等或不等,要比较两点,一是长度,二是内容

    string a = "aaa";
string A = "aaa";
if (a == A)
{
cout << "haha" << endl;//执行
}

而下面就不是相等的

    string a = "aaa";
string A = "aa";
if (a != A)
{
cout << "haha" << endl;//执行
}

问题14:string对象的关系比较比的谁大,谁小的依据是什么?

比较原理是字典排序的原理

1、如果s1和s2长度不一样,且短的整体和长的前面某连续的部分匹配,那么比较长度,判断结果

    string str1 = "";
string str2 = "";
//str1 < str2
if (str1 < str2)
{
cout << "haha" << endl;//执行
}

再看

    string str1 = "hello";
string str2 = "hello world";
//str1 < str2
if (str1 < str2)
{
cout << "haha" << endl;//执行
}

2、如果s1和s2长度不一样,且短的整体和长的前面部分没有匹配,那么只需比较第一个不匹配的字符来做判断

    string str1 = "1";
string str2 = "";
if (str1 < str2)
{
cout << "haha" << endl;//不执行
//因为字符不匹配,那么比较第一个不匹配的0和2,显然0小
}

再看

    string str1 = "hi";
string str2 = "hello world";
if (str1 < str2)
{
//1和2长度不等,且hi和串2前面没有匹配,那么比较第一个不匹配的字符
cout << "haha" << endl;//不执行
//abcdefghijk……e在i前面,说明str2小,就是1>2
}

即使str1长度比str2大,此时此景,比较和长度无关

    string str1 = "";
string str2 = "";
//str1 < str2
if (str1 < str2)
{
cout << "haha" << endl;//执行
//因为短的str2整体和str1前面部分不匹配,那么比较第一个不匹配的0和1,显然0小
}

3、如果s1和s2长度一样,那就直接看s1和s2的字符匹配否,匹配就是相等,不匹配就比较第一个不匹配的字符,来判断大小

    string str1 = "";
string str2 = "";
//str1 < str2
if (str1 < str2)
{
cout << "haha" << endl;//执行
//因为字符不匹配,那么比较第一个不匹配的0和1,显然0小
}

对于有大写,有小写,或者数字的情况,是依据ASCII码,大写字母码值比0-9的数字小,数字又比小写字母小(也就是大写字母在最前面,其次是数字,然后小写最后面),也就是任何大写字母的string对象和小写比较,都是小于关系!

    string str1 = "h1";
string str2 = "hello world";
if (str1 < str2)
{
//ASCII码表编码值,大写 < 数字 < 小写
cout << "haha" << endl;//执行
}

问题15:string对象的赋值操作

把一个string对象赋值给另一个string对象

    string str1;
string str2("hdaf");
str1 = str2;
cout << str1 << endl;//hdaf
cout << str2 << endl;//hdaf

string串对象赋值操作的底层实现机制

1、先把str1占有的内存释放

2、分配给str1满足存放str2副本的内存空间

3、把str2所有字符复制到str1的新内存空间内

这样的繁琐操作,导致大部分的string库类型的赋值操作效率比较低!

问题16:string串对象的连接操作,使用运算符重载的+和+=号

连接string对象

    string str1("");
string str2("");
string str3 = ""; string str4 = str1 + str2 + str3;
cout << str4 << endl;//打印123456789 //string str5 += str4;error C2143: 语法错误 : 缺少“;”(在“+=”的前面),不允许这样初始化string字符串对象,初始化和赋值不一样!
string str5;
str5 += str4;
cout << str5 << endl;//打印123456789

连接string对象和字符串字面值常量

    string str6 = str1 + "," + str2;
cout << str6 << endl;//打印123,456

注意,这样混合连接,必须保证+操作符的两边至少有一个操作数是string对象!

    string str7 = str1 + "/" + "\n";
cout << str7;//已经包含了换行符,

这样没问题,因为前面+之后是string对象类型,后面+\n也是ok的。比如如下就是错误的:

    //string str8 = "123" + "456"; error C2110: “+”: 不能添加两个指针
string str8 = "hello " + "," + str4;//同样的错误,前面+还是都是字面值常量

问题17:string串对象下标操作的陷阱

    //类似数组,通过[]访问string字符串的单个字符,下标也叫索引,从0开始,同样超出下标作用范围的引用会出现溢出问题,且下标返回的值可以作为左值、右值
//注意,下标操作符类型不是int,而是string::size_type类型
string str("This is a dog!");
for (int i = ; i != str.size(); i++)
{
cout << str[i] << endl;
}

上面的写法,严格来说,是错的!即使运行对,因为前面说过,这样失去了c++设计库类型跨平台的初衷!容易溢出错误!改为:

    string str("This is a dog!");
for (string::size_type i = ; i != str.size(); i++)
{
cout << str[i];//打印This is a dog!
}

因为size函数返回类型不是整型!在计算下标值的时候,最好不要用内置整型类型!且不要越界!范围是0~(length-1),类似c和c++的数组下标范围。因为c++标准库对索引的范围不作检测!这就需要程序员手动注意!

问题18:string对象对字符的处理操作

不仅针对string的字符,对其他char类型也适用。这些操作定义在头文件cctype.h中,数量很多:

    string str("123abc。!?");
char c = ' ';

测试是否为数字或者字母

    //如果字符是字母或数字,返回true
if (isalnum(str[]))
{
cout << "haha" << endl;//执行
}

很好理解,is一般是判断函数的前缀名称,num=number代表判断数字0-9,al=alphabet代表判断字母表的字母

测试数字,是就返回ture

    //如果字符是数字,返回true,digital数字的
if (isdigit(str[]))
{
cout << "haha" << endl;//执行
}

测试字母,是就返回true

    if (isalpha(str[]))
{
cout << "haha" << endl;//执行
}

测试小写字母,是就返回true

islower('a');

测试标点符号

ispunct(str[]);//是就返回ture,punctuation标点符号的意思

测试空白字符

    isspace(' ');//是就返回true

测试大写字母

    isupper(str[]);//是就返回true

测试16进制数

    isxdigit(0x1111);//是就返回ture

大写、小写转换

    char cc = 'a';
cout << toupper(cc) << endl;//如果参数cc是小写,则返回大写,否则直接返回cc
//cout默认输出的是字母的ASCII码值
cout << tolower(cc) << endl;//如果参数cc是大写,则返回小写,否则直接返回cc

大写A的ASCII值为65,小写a为97,大写排在小写前面,码值娇小

测试是否是可打印字符

    isprint(c);//如果是可以打印的字符,返回true

可以打印的字符,比如:数字0-9,字母a-z,A-Z,空白字符是空格 ,回车,水平和垂直制表,换行,进纸符,标点符号是除了字母,数字或者可打印空白字符以外的其他可打印字符。

测试是否为空格,如果不是空格但是可以打印,返回ture,否则false

    isgraph(c);

测试是否为控制字符,control缩写cntrl

    iscntrl(c);//是返回true
控制字符(Control Character),出现于特定的信息文本中,表示某一控制功能的字符。
在ASCⅡ码中,第0~31号及第127号(共33个)是控制字符或通讯专用字符,如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)、BEL(振铃)等;通讯专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等。

问题19:c版本的头文件在c++的写法

cctype头文件就是c的type.h头文件,即c++的c版本头文件,不要写.h,而是前面加c。且cname头文件都定义在了命名空间std内部,而.h文件没有这样定义!

建议使用cname形式的头文件,在c++里。即使他们的内容是一样的!这样做的目的是为了和标准库std保持一致!

问题20:计算给定string字符串的标点符号个数

 #include <iostream>
#include <string>
#include <cctype>
using std::string;
using std::endl;
using std::cin;
using std::cout; int main(void)
{
string str("hello world!!!!");
string::size_type count = ; for (string::size_type i = ; i != str.size(); i++)
{
/*
中文字符没有对应的ASCII码,中文字符占两个字节,如果判断中文标点,会报错!
*/
if (ispunct(str[i]))
{
count++;
}
} cout << count << endl;//打印4 system("pause");
return ;
}

汉字不是用ascii表示的,汉字有其单独的编码。GB2312,GBK……一个汉字是有两个字节组成,具体参见:GB2312-80,ASCII码表针对的是西洋文字。

问题21:判断下面程序合法性

    string s;
cout << s[] << endl;

报错,程序发生中断,看似是输出string字符串对象的第一个字符,但是发现,s是一个空字符串,长度=0,故s[0]不管用!在vs2010中编译出错,程序中断。

问题22:从string字符串中去掉标点,要求如果输入字符串包含标点,输出则是去掉标点的字符串

 #include <iostream>
#include <string>
#include <cctype>
using std::string;
using std::endl;
using std::cin;
using std::cout; int main(void)
{
string str;
string str_receive;
//判断输入的字符串是不是带标点,默认不带
bool isPunction = false;
cout << "现在输入字符串" << endl;
//因为cin忽略开头和以后的空白,不能使用cin,用getline函数获取一行完整的文本
getline(cin, str); for (string::size_type i = ; i != str.size(); i++)
{
if (ispunct(str[i]))
{
//字符串含标点,标志变量设为真
isPunction = true;
}
else
{
str_receive += str[i];
}
}
//假如没有标点存在
if (!isPunction)
{
cout << "输入的字符串没有标点!重新输入!" << endl;
}
else
{
cout << "输入的字符串去掉标点之后=" << str_receive << endl;
} system("pause");
return ;
}

如果没有标点

发现,c++在处理字符串问题上,比c要方便。

问题23:读取多个string对象,把他们连接为新串,然后把组成新串的字符串对象用空格隔开

 #include <iostream>
#include <string>
#include <cctype>
using std::string;
using std::endl;
using std::cin;
using std::cout; int main(void)
{
string str;
string str_receive;
cout << "请输入若干字符串,不要太多了!" << endl; while (cin >> str)
{
//连接
//str_receive = str + " ";//这样写不好,最后遗留一个空格
str_receive = str + " " + str_receive;
}
cout << "字符串进行连接:";
cout << "结果为:" << endl << str_receive << endl; system("pause");
return ;
}

欢迎关注

dashuai的博客是终身学习践行者,大厂程序员,且专注于工作经验、学习笔记的分享和日常吐槽,包括但不限于互联网行业,附带分享一些PDF电子书,资料,帮忙内推,欢迎拍砖!

把《c++ primer》读薄(3-1 标准库string类型初探)的更多相关文章

  1. 【C++ Primer每日刷】之三 标准库 string 类型

    标准库 string 类型 string 类型支持长度可变的字符串.C++ 标准库将负责管理与存储字符相关的内存,以及提供各种实用的操作.标准库string 类型的目的就是满足对字符串的一般应用. 与 ...

  2. C++标准库string类型

    string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作.标准库string类型的目的就是满足对字符串的一般应用. 本文地址:http://www.cn ...

  3. 把《c++ primer》读薄(3-3 标准库bitset类型)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. //开头 #include <bitset> using std::bitset; 问题1.标准库bitset类型( ...

  4. C++标准库string类型的使用和操作总结

    string是C++标准库最重要的类型之一,string支持长度可变的字符串,其包含在string头文件中.本文摘自<C++PRIMER 第四版·特别版>和个人的一些总结. 一.声明和初始 ...

  5. 标准库string类型简述

    若想使用标准库的string类需要使用如下声明: #include <string> Using std::string: Using std::wstring: 那么就可以使用这两个类了 ...

  6. 标准库string类型

    一.string 对象的定义和初始化的方式 1. string s1: 2. string s2(s1): 3. string s3("hello"); 4. string s4( ...

  7. 把《c++ primer》读薄(3-2 标准库vector容器+迭代器初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 标准库vector类型初探,同一种类型的对象的集合(类似数组),是一个类模版而不是数据类型,学名容器,负责管理 和 存储的元素 ...

  8. C++ primer读书笔记 chapter3 标准库类型

    除第二章介绍的是C++的基本类型,本章将大致介绍一下C++定义的内容丰富的抽象数据库类型标准库.着重介绍一下sting.vector和bitset. 3.2标准库string类型 1.string类型 ...

  9. C++ Primer学习笔记2--c++标准库中的 vector、string 和 bitset 类型

    一.string    #include <string>  using std::string    初始化函数:    string s1;        默认构造函数 s1 为空串 ...

随机推荐

  1. css中单位px、pt、em和rem的区别

    国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? px :像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的.(引自CSS ...

  2. <!DOCTYPE html>很重要

    噩梦开始的源头:之前写html或者jsp页面,从来不注意doctype的声明,也不太明白doctype的作用.直到最近碰到了一个非常奇葩的 bug:某一个页面在IE7和8,Chrome,ff等下正常, ...

  3. 数据分析之Numpy基础:数组和适量计算

    Numpy(Numerical Python)是高性能科学计算和数据分析的基础包. 1.Numpy的ndarray:一种多维数组对象 对于每个数组而言,都有shape和dtype这两个属性来获取数组的 ...

  4. MaxTemperature程序Mapper ClassNotFoundException

    错误: 执行hadoop权威指南上MaxTemperature程序出现Mapper类ClassNotFoundException异常: 解决: 将书上的 JobConf job = new JobCo ...

  5. 数据库中数据DELETE了怎样恢复

    USE [BBDAS_FP_DATA] GO /****** Object: StoredProcedure [dbo].[Recover_Deleted_Data_Proc] Script Date ...

  6. 整理一自己不怎么熟悉的HTML标签(会陆续更新)

    ---恢复内容开始--- 小白刚开始接触HTML和CSS,在学习过程中发现又遇到很多不认识的标签,于是就想把他们都记录下来,一来可加深记忆,二来也方便以后查阅,当然如果能帮助到你们也是很开心的啦! 1 ...

  7. Microsoft Avro介绍

    Microsoft发布了他们自己对Apache Avro通信协议的实现.Avro被描述为"紧凑的二进制数据序列化格式,类似于Thrift或者Protocol Buffers",同时 ...

  8. ABP框架理论学习之后台工作(Jobs)和后台工作者(Workers)

    返回总目录 本篇目录 介绍 后台工作 后台工作者 让你的应用程序一直运行 介绍 ABP提供了后台工作和后台工作者,它们会在应用程序的后台线程中执行一些任务. 后台工作 后台工作以队列和持续的方式在后台 ...

  9. ABP理论学习之SignalR集成

    返回总目录 本篇目录 介绍 安装 建立连接 内置功能 你自己的SignaR代码 介绍 Abp.Web.SignalR 使得在基于ABP的应用程序中使用 SignalR相当容易.查看SignalR文档获 ...

  10. 探索c#之递归APS和CPS

    接上篇探索c#之尾递归编译器优化 累加器传递模式(APS) CPS函数 CPS变换 CPS尾递归 总结 累加器传递模式(Accumulator passing style) 尾递归优化在于使堆栈可以不 ...