c++ primer(第五版)学习笔记及习题答案代码版(第三章)字符串、向量和数组


笔记较为零散,都是自己不熟悉的知识点。
习题答案至于一个.cc 中,需要演示某一题直接修改 #define NUM**, 如运行3.23题为#define NUM323;

chapter 3

1、

string a4(n, 'c');   //把s4初始化为由连续n个字符c组成的串。

string s5 =string(10,'c');   //拷贝初始化

  while(getline(cin, line))    //每次读入一整行,知道达到文件末尾

      cout<< line <<endl;

触发getline函数返回的按个换行符实际上被丢弃了,得到的string对象不包含换行符。

string.empty();   //函数返回一个对应的布尔值

string.size();    //返回一个string::size_type类型的值,这是一个unsigned int型

                  //所以,一条表达式中已经有size()函数就不要再使用int了,避免混用带来问题。

 

string s3 = s1 + s2;   //两个string对象相加

string s4  = "hello" + ",";   //包含字面值相加的情况,必须保证+两侧中有一个是string型

2、

为兼容C语言的标准库,C++将这些文件命名为cname。在名为cname的头文件中定义的名字从属于命名空间std,而定义在.h中的头文件则不然。

decltype(s.size()) punct_cnt =0;  //punct_cnt的类型和s.size的返回值类型一样。

ispunct(c);                        //判断标点符号的个数

for(auto &c : s)                  //对于s中的每个字符(c是引用)

    c = toupper(c);               //c是一个引用,因此赋值语句将改变c中字符的值。

cout<< s <<endl;


3、

vector是模板而非类型,由vector生成的类型必须包括vector中元素的类型,例如vector<int>

vector<vector<int>>vector对象的又尖括号和其他元素类型之间要添加一个空格。

vector<int>v1{"a", "an", "the"};   //列表初始化

vector<int> vi =10;               //错误,必须使用直接初始化的形式执行想来那个大小。

vector<string> v7{10};vector<string> v8{10, "hi"}; //都不是列表初始化,有10个元素的初始化

vector对象(包括string对象)的下标可用于访问已存在的元素,而不能用于添加元素。

string s("string");

if(s.begin() != s.end()){

  auto it = s.begin();

  *it = toupper(*it);       //通过解引用迭代器来获取它所指示的元素。

}

将指向同一容器中元素的两个迭代器相减,结果是两个迭代器的距离。其类型是difference_type,可正可负,是带符号类型的。

 4、

char a3[] = "c++";

const char s4[6] ="Daniel";    //错误,没有空间可存放空字符

指针和数组

string nums ={"one","two","three"};

string *p = &nums[0];               //p指向nums的第一个元素

string *p2 = nums;                   //等价于p2 = &nums[0];

int arr[] ={0,1,2,3,4,5,6,7,8,9};

int *e = &arr[10];               //指向尾元素的下一个元素

for(int *b = arr; b != e; ++b)

  cou<<*b <<endl;               //输出arr的元素

 5、

两个指针相减的结果类型是一种名为ptrdiff_t的标准库类型,和size_t一样,其也是定义在cstddef头文件中的机器相关的类型。ptrdiff_t是带符号的类型。

int ia[] = {0,2,4,5,8};

int *p = &ia[2];

int k = p[-2];                  //p[-2]是is[0]表示的那个元素

内置的下标运算符所用索引值不是无符号类型,这与string和vector不同。

6、

char ca[] = {'c', '*', '1'};

cout << strlen(ca)<<endl;      //严重错误,C语言风格的字符串函数,ca没有以空字符结尾

string s("hello");

char *str = s;                //错误,不能用string对象初始化char*

const char *str =s.c_str();   //正确。如果想一直使用c_str()返回的数组,最好将其拷贝一份

多维数组

int ia[3][4];

int (*p)[4] = ia;

int *ip[4];                   //整形指针的数组

int (*ip)[4];                 //指向含有4个整数的数组

 

#include <iostream>
#include <vector>
#include <cstring>
#define NUM343

using namespace std;
string sa[10];
int ia[10];

int main(){
/*3.1*/
#ifdef NUM31
	cout<<"参见:http://blog.csdn.net/refuil/article/details/51226530 "
		"http://blog.csdn.net/refuil/article/details/51236735"<<endl;
#endif
/*3.2*/
#ifdef NUM32
	string line;
	string word;
	while(getline(cin, line)//一次读入一行,直至遇见文件结束符
		cout << line <<endl;
	while(cin >> word)		//一次读入一个单词,直至遇见文件结束符
		cout << word <<endl;
#endif
/*3.3*/
#ifdef NUM33
	cout<<"string类型读取并忽略有效字符之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止(空白字符仍留在输入流中)"
		"getline()函数不忽略开头的空白字符,读取字符直至遇到换行符,读取终止并丢弃换行符。"<<endl;
#endif
/*3.4*/
#ifdef NUM34
	string str1, str2;
	cout << "Enter two strings: " <<endl;
	cin >> str1 >> str2;
	if(str1 == str2)
		cout << "They are the same."<<endl;
	else if(str1 > str2)
		cout << "The bigger one is: " << str1 <<endl;
	else 
		cout << "The bigger one is: " << str2 <<endl;
/* 比较size */	
	string::size_type len1, len2;
	len1 = str1.size();
	len2 = str2.size();
	if(len1 == len2)
		cout << "They are the same length."<<endl;
	else if(len1 > len2)
		cout << "The longer one is: "<<str1<<endl;
	else 
		cout << "The longer one is: "<<str2<<endl;
#endif
/*3.5*/
#ifdef NUM35
	string str, sum;
	cout << "Enter two strings: " <<endl;
	while(cin >> str)
		sum += str;
	cout<< "The concatenation of string is: "<< sum <<endl;
/* Add the blank*/
	cout << "Enter two strings: " <<endl;
	while(cin >> str)
		sum += " " + str;
	cout<< "The concatenation of string is: "<< sum <<endl;	
#endif
/*3.6*/
#ifdef NUM36
	string str("abcddefg");
	for(auto  &c :  str){
		if(!isspace(c))
			c = 'X';
	}
	cout<< str << endl;
#endif
/*3.7*/
#ifdef NUM37
	string str("abcddefg");
	for(char &c : str){
		if(!isspace(c))
			c = 'X';
	}
	cout << str << endl;
#endif
/*3.8*/
#ifdef NUM38
	string str("abcddefg");	
	int index = 0;
	while(index !=str.size()){
		if(!isspace(str[index]))
		str[index] = 'X';
		++index;
	}
	cout<< "while语句: "<< str<<endl;
/* for语句*/
	for(decltype(str.size()) index =0; index != str.size();++index){
		if(!isspace(str[index]))
			str[index] = 'X';
	}
	cout<< "for语句: " <<str <<endl;
#endif
/*3.9*/
#ifdef NUM39
	string s;
	cout << s[0] << endl;
	cout<<"输出s字符的第一个字符,不合法,因为s没有初始化是空字符串,是s[0]是无效的."<<endl;
#endif
/*3.10*/
#ifdef NUM310
	string str, result;
	bool has_punct;
	cout<<"Enter the string with punctuation: "<<endl;
	getline(cin,  str);
	for(auto &c : str){
		if(ispunct(c))
			has_punct = true;
		else
			result += c;
	}
	if(has_punct)
		cout<<"After the remove: "<< result <<endl;
	else{
	cout<<"No punctuation character in the string" <<endl;
	return -1;
	}
#endif
/*3.11*/
#ifdef NUM311
	cout<<"当且仅当不去改变 c 值时才是合法的,c的类型是const char&; 如果试图改变就是不合法的。"<<endl;
#endif
/*3.12*/
#ifdef NUM312
	cout<<"(b)不合法,赋值左右类型不同,svec是string对象的vector对象,ivec是保存vector<int>对象的vector对象. "<<endl;
#endif
/*3.13*/
#ifdef NUM313
	cout<<"(a)0个int元素;(b)10个int元素,值都是0;(c)10个int元素,值都是42;(d)1个int型元素,值是10;(e)两个int元素,10和42;(f)10个string元素,值为0;(g)10个hi元素。"<<endl;
#endif
/*3.14*/
#ifdef NUM314
	vector<int> vec;
	int i;
	cout<<"Enter number: "<<endl;
	while(cin >> i){
		vec.push_back(i);
	}
	for(auto &c : vec)
		cout<< c;
	cout<<endl;
#endif
/*3.15*/
#ifdef NUM315
	vector<string> vec;
	string i;
	cout<<"Enter string : "<<endl;
	while(cin >> i){
		vec.push_back(i);
	}
	for(auto &c : vec)
		cout<< c;
	cout<<endl;
#endif
/*3.16*/
#ifdef NUM316
	vector<int> v1;         // size:0,  no values. 
	cout<<"v1: size is "<<v1.size()<<" ";
	for(auto &c : v1)
		cout<< c;
	cout<<endl;
	vector<int> v2(10);     // size:10, value:0
	cout<<"v2: size is "<<v2.size()<<" ";
	for(auto &c : v2)
		cout<< c <<" ";
	cout<<endl;
	vector<int> v3(10, 42); // size:10, value:42 
	cout<<"v3: size is "<<v3.size()<<" ";
	for(auto &c : v3)
		cout<< c <<" ";
	cout<<endl;
	vector<int> v4{10};     // size:1,  value:10 
	cout<<"v4: size is "<<v4.size()<<" ";
	for(auto &c : v4)
		cout<< c <<" ";
	cout<<endl;
	vector<int> v5{10, 42}; // size:2,  value:10, 42 
	cout<<"v5: size is "<<v5.size()<<" ";
	for(auto &c : v5)
		cout<< c <<" ";
	cout<<endl;
	vector<string> v6{10};  // size:10, value:""  
	cout<<"v6: size is "<<v6.size()<<" ";
	for(auto &c : v6)
		cout<< c <<" ";
	cout<<endl;
	vector<string> v7{10, "hi"};  // size:10, value:"hi"
	cout<<"v7: size is "<<v7.size()<<" ";
	for(auto &c : v7)
		cout<< c <<" ";
	cout<<endl;
#endif
/*3.17*/
#ifdef NUM317
	string str;
	vector<string> vec;
	while(cin >> str)
		vec.push_back(str);
	for(decltype(vec.size()) index = 0; index != vec.size(); ++index){
		for(auto &c : vec[index]){
			toupper(c);
		}
		cout<< vec[index] <<endl;
	}
#endif
/*3.18*/
#ifdef NUM318
	vector<int> ivec;
	ivec[0] = 42;
	cout<<"不合法,ivec是空的vector,不允许通过下标形式访问任何元素,只能用push_back添加元素."<<endl;
#endif
/*3.19*/
#ifdef NUM319
	vector<int> vec1(10,42);
	vector<int> vec2{42,42,....};
	vector<int> vec3(10);
	for(vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter)
		*iter  = 42;
#endif
/*3.20*/
#ifdef NUM320
	int val;
	vector<int> vec;
	cout<< "Enter numbers: " <<endl;
	while(cin >> val)
		vec.push_back(val);
	if(!vec.size()){
		cout<<"No elements! " <<endl;
		return -1;
	}
	cout<<"The result has been sumed: "<<endl;
	for(vector<int>::size_type index =0; index < vec.size()-1; index = index +2)//这里不能用index != vec.size();因为index是逢2加,可能直接略过size()大小
		cout << vec[index] + vec[index+1] <<" ";
	cout<< endl;
//program changed
	cout<<"头尾元素相加: "<<endl;
	vector<int>::size_type first, last;
	for(first = 0, last = vec.size()-1; first < last; ++first, --last)
		cout<< vec[first] + vec[last] << " ";
	cout<<endl;
#endif
/*3.21*/
#ifdef NUM321
	/*原理都在3.20中体现*/
	int val;
	vector<int> vec;
	cout<< "Enter the numbers: "<<endl;
	while(cin >> val)
		vec.push_back(val);
	if(!vec.size()){
		cout<<"No element! "<<endl;
		return -1;
	}
	cout <<"相邻两个元素相加: "<<endl;
	for(vector<int>::iterator iter = vec.begin(); iter < vec.end()-1; ++iter)
		cout<< *iter + *(iter+1) <<" ";
	cout<<endl;
//program changed 
	cout<<"头尾元素相加: "<<endl;
	vector<int>::iterator first, last;
	for(first = vec.begin(), last = vec.end()-1; first < last; ++first, --last)
		cout<< *first + *last << " ";
	cout<<endl;
	if(first == last)
		cout<<"The mid element isn't been sumed: "<< *first<<endl;
#endif
/*3.22*/
#ifdef NUM322
	string word;
	vector<string> text;
	while(cin >> word)
		text.push_back(word);
	vector<string>::iterator it = text.begin();
	for(string::iterator iter = (*it).begin(); iter != (*it).end(); ++iter)
		*iter = toupper(*iter);
	for(;it != text.end(); ++it)
		cout<< *it <<endl;
#endif
/*3.23*/
#ifdef NUM323
	vector<int> vec(10,1);
	for(vector<int>::iterator iter = vec.begin(); iter !=vec.end(); ++iter){
		*iter = (*iter) * 2;
		cout<< *iter <<" ";
		if(iter == vec.end()-1) cout<<endl;
	}
#endif
/*3.24*/
#ifdef NUM324
	cout<<"见3.21"<<endl;
#endif
/*3.25*/
#ifdef NUM325
	vector<unsigned> scores(11,0);
	vector<unsigned>::iterator iter = scores.begin();
	unsigned grade;
	while(cin >> grade){
		if(grade <= 100){
			iter = iter + (grade/10);
			(*iter)++;
			iter = scores.begin();   //The iterator must be returned
		}
	}
	for(iter = scores.begin(); iter != scores.end(); ++iter)
		cout<< *iter <<" ";
	cout<<endl;
#endif
/*3.26*/
#ifdef NUM326
	cout<<"begin + end是非法的,因为vector的迭代器并没有定义+运算符,编译器会报错."<<endl;
#endif
/*3.27*/
#ifdef NUM327
	cout<<"(a)非法,buf_size是一个变量,不能用于下标取值。"
		"(c)非法,txt_size()是函数调用,不是常量表达式。"
		"(d)非法,存放这个字符串的数组必须要有12个元素. "<<endl;
#endif
/*3.28*/
#ifdef NUM328
	string sa2[10];
	int ia2[10];
	cout<< sa[0]<<" "<<sa2[0]<< " "<<ia[0]<<" "<<ia2[0]<<endl;
	cout<<"sa, sa2默认构造函数将各元素初始化为空字符串;"
		"ia在函数体外初始化,默认初始化0; ia2在函数体内初始化,默认初始化不确定."<<endl;
#endif
/*3.29*/
#ifdef NUM329
	cout<<"数组长度固定,要扩大容量,只能重新定义更大的数组再讲之前的拷贝进去;"
		"数组也没有vector的size/push_back操作,程序相对较复杂。"<<endl;
#endif
/*3.30*/
#ifdef NUM330
	cout<<"ix = array_size时数组越界了."<<endl;
#endif
/*3.31*/
#ifdef NUM331
	constexpr size_t array_size = 10;
	int ia[array_size];
	for(size_t ix =0; ix < array_size; ++ix){
		ia[ix] = ix;
		cout<< ia[ix]<<" ";
	}
#endif
/*3.32*/
#ifdef NUM332
	constexpr size_t array_size = 10;
	int ia1[array_size];
	int ia2[array_size];
	cout<<"ia1: ";
	for(size_t ix =0; ix < array_size; ++ix){
		ia1[ix] = ix;
		cout<< ia1[ix]<<" ";
	}
	cout<<endl;
	cout<<"ia2: ";
	for(size_t ix =0; ix < array_size; ++ix){
		ia2[ix] = ia1[ix];
		cout<< ia2[ix]<<" ";
	}
	cout<<endl;
	vector<int> vec1(10);
	vector<int> vec2(10);
	int i = 0;
	cout<<"vec1: ";
	for(auto &c : vec1){
		c = i;
		++i;
		cout<< c<<" ";
	}
	cout<<endl;
	i = 0;
	cout<<"vec2: ";
	for(auto &c : vec2){
		c = vec1[i];
		++i;
		cout<<c<<" ";
	}
	cout<<endl;
#endif
/*3.33*/
#ifdef NUM333
	cout<<"如果不初始化,scores就是未定义的,它的元素取值是不确定的."<<endl;
#endif
/*3.34*/
#ifdef NUM334
	p1 += p2 - p1;
	cout<<"该语句使得p1也指向p2原来所指向的元素,只要p1和p2都是指向同一个数组的元素,该语句总是合法的。"<<endl;
#endif
/*3.35*/
#ifdef NUM335
	int arr[] = {1,2,3,4,5};
	int *p = arr;
	for(int i= 0; i <= 4; ++i){
		*(p + i) = 0;
		cout<< *p << " ";
	}
	cout << endl;
#endif
/*3.36*/
#ifdef NUM336
	/*For arrays*/
	int arr_size = 5;
	int arr1[arr_size], arr2[arr_size];
	cout << "Enter 5 numbers for array1: " <<endl;
	for(size_t i = 0; i < 5; i++)
		cin >> arr1[i];
	cout << "Enter 5 numbers for array2: " <<endl;
	for(size_t i = 0; i < 5; i++)
		cin >> arr2[i];
	for(size_t i = 0; i !=arr_size; ++i)
		if(arr1[i] != arr2[i]){
			cout<< "array1 is not same with array2."<<endl;
			return 0;//只要存在一个元素不相同直接退出
		}
	cout<< "array1 is same with array2."<<endl;
	/*For vectors*/
	vector<int> vec1(5), vec2(5);
	cout<< "Enter 5 numbers for vector1: "<<endl;
	for(auto &c : vec1)
		cin >> c;
	cout<< "Enter 5 numbers for vector2: "<<endl;
	for(auto &c : vec2)
		cin >> c;
	for(vector<int>::size_type ivec =0; ivec != vec1.size(); ++ivec)
		if(vec1[ivec] != vec2[ivec]){
			cout<< "vector1 is not same with vector2."<<endl;
			return 0;
		}
	cout<< "vector1 is same with vector2."<<endl;
#endif
/*3.37*/
#ifdef NUM337
	const char ca[] = {'h','e', 'l', 'l', 'o'};
	const char *cp = ca;
	while(*cp){
		cout << *cp <<endl;
		++cp;
	}
	cout<<"混合C风格的字符串类型,在数组末尾往汪有'/0'结束,所以输出的一般会多于5个字符."<<endl;
#endif
/*3.38*/
#ifdef NUM338
	cout<<"当两个指针指向头一个数组,相减表示两者之间的距离;相加却很难解释,也是没有定义的,所以没有意义."
#endif
/*3.39*/
#ifdef NUM339
	/*For string*/
	string str1 = "linuxc++a"; 
	string str2 = "linuxc++b";
	if(str1 > str2)
		cout<< str1 <<endl;
	else 
		cout<< str2 << endl;
	/*For C style char**/
	const char* s1 = "linuxc++c";
	const char* s2 = "linuxc++d";
	if(strcmp(s1, s2) > 0)
		cout<< s1 <<endl;
	else 
		cout<< s2 << endl;
#endif
/*3.40*/
#ifdef NUM340
	const char* str1 = "linux";
	const char* str2 = "c++";
	size_t len = strlen(str1) + strlen(str2);
	char* str3 = new char[len+1];;
	strcpy(str3, str1);
	strcat(str3, str2);
	cout << "str3: " <<str3<<endl;
#endif
/*3.41*/
#ifdef NUM341
	const size_t arr_size  = 5;
	int arr[arr_size];
	cout<< "Enter 5 numbers for array. "<<endl;
	for(size_t i =0; i!= arr_size; ++i)
		cin >> arr[i];
	vector<int> vec(begin(arr), end(arr));//另一种写法vector<int> vec(arr, arr+arr_size)
	for(auto &c : arr)
		cout << c << " ";
#endif
/*3.42*/
#ifdef NUM342
	int val;
	vector<int> vec;
	cout<< "Enter numbers for vector: " <<endl;
	while(cin >> val)
		vec.push_back(val);
	if(!vec.size()){
		cout<<"No elements! " <<endl;
		return -1;
	}
	size_t ix = 0;       //C风格数组的类型与vector的元素不一样,ix需要初始化
	int *pstr = new int[vec.size()];
	for(vector<int>::iterator i = vec.begin(); i != vec.end(); ++i, ++ix)
		pstr[ix] =  *i;
	for(ix =0; ix < vec.size(); ++ix)
		cout<< *(pstr+ix) <<" ";
	delete []pstr;
#endif
/*3.43*/
#ifdef NUM343
	int arr[3][4] ={0,1,2,3,4,5,6,7,8,9,10,11};
	/*版本一*/
	for(auto *p = begin(arr); p != end(arr); ++p)
		for(auto q = begin(*p); q != end(*p); ++q)
			cout<< *q <<" ";
	cout<<endl;
	/*版本一*/
	for(int i =0; i < 3; ++i)
		for(int j =0; j < 4; ++j)
			cout<< arr[i][j]<<" ";
	cout<<endl;
	/*版本三*/
	using int_array = int[4];
	for(int_array *p = arr; p != arr+3; ++p)
		for(int *q = *p; q != *p+4; ++q)
			cout<< *q <<" ";
	cout<<endl;
#endif
/*3.44*/
#ifdef NUM344
	int arr[3][4] ={0,1,2,3,4,5,6,7,8,9,10,11};
	typedef int int_array[4];
	for(int_array *p = arr; p != arr+3; ++p)
		for(int *q = *p; q != *p+4; ++q)
			cout<< *q <<" ";
	cout<<endl;	
#endif
/*3.45*/
#ifdef NUM345
	int arr[3][4] ={0,1,2,3,4,5,6,7,8,9,10,11};
	for(auto (&row)[4] : arr)
		for(auto (&col) : row)
			cout<< col <<" ";
	cout<<endl;
#endif
	return 0;
}

参考资料:
c++ primer中文版第五版,电子工业出版社。
c++ primer第四版习题解答,人民邮电出版社。


你可能感兴趣的:(字符串,数组,向量,C++Primer,C++语法)