C++ Primer 札记+习题解答(一)

C++ Primer 笔记+习题解答(一)

今天是第一次笔记,说实话拖了很久,因为刚刚到家,没有稳定的学习环境,各种事情分心,就连C++Primer 的第一章都看了那么长时间,直到今天才有时间来写笔记。每次看书都能有点收获,蛮欣慰的。

若存在错误 请指针 万分感谢

1.1 简介:

 1.每个C++程序包含一个或多个functions,其中一定有main函数,此函数是操作系统执行程序的入口。

 2.函数定义几个要素:return type; function name; parameter list; function body.

 3.main function‘s return type must be int and void is banned.

 4.函数体以左花括号(curly brace)开始,以右花括号的语句块结束(block of statements)

 5.main 函数的返回值来指示函数的执行状态,一般0表示执行成功,非0值的具体含义由系统定义,通常用了表示错误的类型。

 6.类型概念:类型是程序设计的最基本概念,类型既定义了数据元素内容,也定义了其上可以进行的操作。比如定义一个int 型的变量,那么同时也定义了其上可以进行的操作,比如加法等。其实和类的概念很相像。程序所处理的数据都保存在变量中,每个变量都有自己的类型。若一个名为v的变量类型为T,等价于v具有类型T,也等价于v是T类型变量。

1.2 相关:

 1.Integrated Development Environment IDE。

 2.程序源文件名约定:通常是 .cpp;.c;.cxx;.cc;.cp

 3.从命令行运行编译器:$ CC prog1.cc其中CC是编译器的名字 ,prog1.cc 是源文件。

    执行后生成一个可执行文件:如prog1.exe

    获取返回值:$ echo %ERRORLEVEL%

1.3初始化输入输出:

  1.C++为定义IO语句,而且 用标准库提供IO机智。

   2.流的理解:一个流就是一个字符序列,是从IO设备读取或写入IO设备的。术语流想表达的是随着时间的推移,字符是顺序生成或消耗的。

   3.四个对象:cin,cout,cerr,clog.四个对象。标准输入,标准输出,标准错误。

   4.这四个对象通常和程序所运行的窗口关联起来,因为当我们读取cin时,将从程序运行的窗口读入当我们向cout/cerr/clog写数据的时候,也会写到同一窗口。

   5.向流写入数据:C++中一个表达式产生一个计算结果,它是 由一个或者对歌运算对象和一个或者多个运算符构成的,比如使用了<<运算符,:

std::cout<<"Enter two numbers"<<std::endl;
    这个地方的输出运算符<<需要两个运算对象,左边的运算对象是一个ostream 对象,右边是一个常量字符串。此运算符将给定的值写到cout对象中,此表达式的计算结果是ostream对象。

    为什么可以连续使用<<运算符呢?因为一个输出运算符的结果是ostream对象,所以可以连用,那么上面的语句等价于:

(std::cout<<"Enter two numbers")<<std::endl;
//也等价于:
std::cout<<"Enter two numbers";
std::cout<<std::endl;
     因为cout对象是关联到屏幕这个文件的,所以string literal被打印到屏幕上。

   std::endl是操纵符(manipulator)功能:结束当前行,并且将与它关联的设备的缓冲区刷新到设备中。缓冲刷新操作可以确保目前程序所产生的输出都真正的写入到流中,而不是仅仅停在内存中等待写入。

  6.程序调试经常添加打印语句,应该保持刷新流,否则程序崩溃,输出还停留在buffer中,可能会错误推断程序出错的位置。

  7.使用标准库中名字,需要使用std+作用域运算符(::)

  8.向流写入数据:需要使用>>运算符。>>运算符类似输出运算符,左运算对象是一个istream对象,右边运算对象是需要操作的变量。>>运算符的连用操作类似<<输出运算符。

  9.解释一个语句:std::cout<<"The sum of "<<v1<<" and "<<v2<<" is "

                                          <<v1+v2<<std::endl;

这个地方的运算对象并不是同类型,但是为何可以进行运算呢?你看上面既有整型,字符串,还要两个整型数据的运算结果。但是仍然可以进行运算,原因就是重载了运算符,更多的内容后面会介绍。

1.3 注释简介:

  1.单行注释//

  2.界定符注释,注意不能嵌套。注意多行注释的好风格:如

/*
*
*
*/

1.4 控制流语句:

   程序一般是顺序执行的,通过流程控制语句可以写出各种跳转语句。

1.5 while 语句:

     while(condition) {statements} 执行流程:检测条件,执行语句(快),再次检测。如果条件为假,跳出循环, 否则继续执行。

1.6 for 语句:

    上面那种在循环中检测变量,在循环体中改变执行条件。C++中重新定义了一种循环语句,简化上述模式。for语句的构造,循环头,循环体。其中循环头由三部分构成,initialization statement,condition,expression 执行的流程:执行初始化语句,条件检测执行,执行循环体,执行循环头的表达式,再次进行条件检测。若条件不成立,跳出循环,顺序执行循环后的语句。    

1.7 读取不定量的数据:

    这个例子我感觉十分有意思,用一个变量却做了多个变量的事情。

示例:

#include <iostream>
int main(){
	int sum = 0, var = 0;
	while (std::cin>>var){
		sum += var;
	}
	std::cout << "The sum is " << sum << std::endl;
	system("pause");
	return 0;
}
这个例子和我一开始想的完全不一样,这个程序一开始输入所有要进行计算的数字,而不是我认为的是输入一次判读一次。这个程序是一次性把所有的输入都保存在缓冲区中,然后程序在检测的时候进行读取就可以了,而不是直接的要求用户输入。这个例子可以很好的加深对while语句的理解。在上述的例子中,检测的到底是什么呢?是var变量嘛?实际上根据<<运算符函数的运算结果可以知道返回的计算结果是一个对象。所以这个地方检测的是对象,对象是个复杂的东西,至于一个cin对象里面到底是啥,等我有机会翻开源码一探究竟吧。对流的检测实际上是检测流的状态,如果流是有效的,那么程序可以继续执行,如果流是无效的或者遇到文件结束符(eof),那么条件为假,退出循环。windows 中的文件结束符是 Ctrl + Z 键。UNIX系统中,是Ctrl D。

1.8 错误类型检测:

    编译器无法检测逻辑上的错误,只能检测到一个错误的原则进行,然后进行编译。不要根据编译器的提示一下改正所以错误,因为编译器的报错具有连带性形式上的错误。一般分为三类:

语法错误,类型错误,声明错误。改错的时候一般按照先改第,所以有的可能是连坏反应。

1.9 if 语句:

#include <iostream>
int main(){
	int var = 0;
	int CurVal = 0;//正在统计的数.
	int cnt = 0;//计数器.
	if (std::cin >> CurVal  )//如果有需要处理的数字。
		++cnt;
	while (std::cin >> var){
		if (var == CurVal)
			++cnt;
		else{
			std::cout << CurVal << " occurs " << cnt << " times " << std::endl;
			cnt = 1;
			CurVal = var;
		}
	}
	std::cout << CurVal << " occurs " << cnt << " times " << std::endl;
	system("pause");
	return 0;
}
真是一个很巧妙的例子,要多多揣摩这个模式以及涉及的思想。

1.10 类简介:

    类的是C++的特性,类定义了一个类型,以及其上可以进行的操作。C++最初的设计焦点就是自然地使用上像内置型一样的类类型。在1.5节的例子中,我们进行类对象的加减,我们可以发现这个同内置类型的数据运算非常相似,只不过我们把运算对象由内置对象替换成类类型。而且这个例子中重新定义了和的概念。比如这个地方的ISBN相加就是无意义的。学习的过程就是推翻自己最初认知的过程。一开始建立的认知对学习有帮助,但是一方面也会阻碍自己对新事物的学习啊。

1.11调用运算符():

    我希望自己能建立一种观念,一切皆函数,一切皆运算。就像调用运算符,输出输入运算符这种,虽然表面看不出来,但是实际上当成函数理解才是正确的。一开始我的理解实在是太狭隘了,以致我迟迟不能接受正确的观念。

总结:

  1.相关术语摘录:

   assignment :抹去一个对象的当前值,用一个新值取代。这个地方就可以很好的解释了赋值和初始化。赋值一定是在有一个值的基础上进行的。

   buffer :缓冲区,分为输入输出缓冲区。IO设施通常将输入输出的数据保存在一个缓冲区中。读写缓冲区的操作与程序是无关的,我们可以显式的刷新缓冲区,以便强制的将缓冲区的内容刷新到设备中。默认情况下,cin会刷新cout,程序的非正常终止也会刷新cout.关于缓冲区的详细知识可以看看计算机组成原理。

   condition: 求值结果为真假的表达式。

   end_of_file 文件结束符。系统特定的标识符,指出文件中无更多的数据了。

   expression 最小的计算单元。一个表达式包含一个或者多个运算对象,通常还包含一个或者多个运算符。表达式的求值会产生一个结果。

  2.习题解答:

1.1

//命名约定 :.cpp 
#include <iostream>
int main(){
	return 0;
}

1.2

#include <iostream>
int main(){
	return -1;//无提示。
}

1.3

#include <iostream>
int main(){
	std::cout << "Hello," << " World." << std::endl;
	return 0;
}

1.4

#include <iostream>
using namespace std;
int main(){
	int var1 = 0, var2 = 0;
	cout << "Enter two numbers ";
	cin >> var1 >> var2;
	cout << "The value of var1 multiply var2 is " << var1*var2 << endl;
	system("pause");
	return 0;
}

1.5

#include <iostream>
using namespace std;
int main(){
	int var1 = 0, var2 = 0;
	cout << "Enter two numbers ";
	cin >> var1 
		  >> var2;
	cout << "The value of var1 multiply var2 is "
		<< var1*var2
		<< endl;
	system("pause");
	return 0;
}

1.6

//不合法
修改方案:std::cout<<"The sum of "<<v1
                   <<" and "<<v2
                   <<" is "<<v1+v2<<std::endl;
1.7

#include <iostream>
using namespace std;
int main(){
	/*
	 *int var1 = 0,/* */ var2 = 0;
	 *cout << "Enter two numbers ";
	 *cin >> var1 
		  >> var2;
	 */
	cout << "The value of var1 multiply var2 is "
		<< var1*var2
		<< endl;
	system("pause");
	return 0;
}
//错误信息:
 error C2065: “var2”: 未声明的标识符
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(6): error C2100: 非法的间接寻址
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(6): error C2088: “<<”: 对于 class 非法
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(7): error C2100: 非法的间接寻址
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(8): error C2065: “var1”: 未声明的标识符
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(8): error C2065: “var2”: 未声明的标识符
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(9): warning C4138: 在注释外找到“*/”
1>d:\visual studio 2013 代码\consoleapplication18\consoleapplication18\源.cpp(9): error C2059: 语法错误:“/” 
1.8

#include <iostream>
int main(){
	std::cout << "/*";  //正确
	std::cout << "*/";  //正确
	//std::cout <</* "*/" */;  //错误
	std::cout <</* "*/" /* "/*" */;  //正确。
	system("pause");
	return 0;
}
1.9

#include <iostream>
int main(){
	int sum = 0;
	int var = 50;
	while (var <= 100){
		sum += var;
		++var;
	}
	std::cout << "The sum from 50 to 100 is " << sum << std::endl;
	system("pause");
	return 0;
}
1.10

#include <iostream>
int main(){
	int var =10;
	while (var >=0){
		std::cout << var << " ";
		--var;
	}
	system("pause");
	return 0;
}
1.11

#include <iostream>
int main(){
	int begin_var = 0;
	int end_var = 0;
	std::cout << "Enter two numbers ";
	std::cin >> begin_var >> end_var;
	if (begin_var >end_var){
		int temp = end_var;
		end_var = begin_var;
		begin_var=temp;
	}
	std::cout << "Print number from " << begin_var << " to " << end_var << std::endl;
	while (end_var>=begin_var){
		std::cout << begin_var++<< " ";
	}
	system("pause");
	return 0;
}
1.12
//求 -100 到 100 的和.
//结果是 0.
1.13

#include <iostream>
int main(){
	int sum = 0;
	for (int i = 50; i < 101; ++i){
		sum += i;
	}
	std::cout << "The sum from 50 to 100 is " << sum << std::endl;
	system("pause");
	return 0;
}
#include <iostream>
int main(){
	for (int i = 10; i >-1; --i){
		std::cout << i << " ";
	}
	system("pause");
	return 0;
}
#include <iostream>
int main(){
	int begin_var = 0, end_var = 0;
	std::cout << "Enter two numbers ";
	std::cin >> begin_var >> end_var;
	if (begin_var > end_var){
		int temp = end_var;
		end_var = begin_var;
		begin_var = temp;
	}
	std::cout << "Print numbers from " << begin_var << " to " << end_var << std::endl;
	for (int i =begin_var; i <=end_var; ++i){
		std::cout << i << " ";
	}
	system("pause");
	return 0;
}
1.14

for循环的有点在我看来就是简洁吧。while循环感觉比较随意,有点拖沓。
1.15

//略
1.16

#include <iostream>
int main(){
	int var = 0;
	int sum = 0;
	std::cout << "Enter numbers or (Ctrl z to stop ) ";
	while (std::cin >> var)//重点关注程序的执行流程,其次就是对对象的检测是如何的。
		sum += var;
	std::cout << "The sum is " << sum << std::endl;
	system("pause");
	return 0;
}
一个cin>>var里面究竟可以容纳多少东西呢?正常情况下我们只可以读取出一个一个出来,但是通过循环却能缓冲中内容全部读取出来,真的是颠覆了对输入输出的理解。

#include <iostream>
int main(){
	int var = 0;
	int sum = 0;
	std::cout << "Enter numbers or (Ctrl z to stop ) ";
	while (std::cin >> var)//重点关注程序的执行流程,其次就是对对象的检测是如何的。
		//sum += var;
		std::cout << var << " ";
	//std::cout << "The sum is " << sum << std::endl;
	system("pause");
	return 0;
}
这个简单的例子却是给我一个很好的启示:是否可以抽象出一个模型出来?一个变量却完成了多个变量的任务。

1.17

#include <iostream>
int main(){
	int CurVal = 0, var = 0;
	int cnt = 0;
	std::cout << "Enter numbers or Ctrl to stop ";
	if (std::cin >> CurVal){  //确保有数字可以处理。
		++cnt;
		while (std::cin >> var){
			if (var == CurVal)
				++cnt;
			else{
				std::cout << "The " << CurVal << " occurs "
					<< cnt << " times " << std::endl;
				cnt = 1;
				CurVal = var;
			}
		}
	}
	std::cout << "The " << CurVal << " occurs "
		  << cnt << " times " << std::endl;
}
//程序可以处理全部重复的输入,也可以处理全部不同的输入。

1.18 略

1.19 参看1.10。

1.20

#include "Sales_item.h"
int main(){
	Sales_item book;
	std::cin >> book;
	std::cout << book;
	system("pause");
	return 0;
}
1.21

#include "Sales_item.h"
int main(){
	Sales_item book1,book2;
	std::cin >> book1 >> book2;
	std::cout << book1 + book2;
	system("pause");
	return 0;
}
1.22

#include "Sales_item.h"
int main(){
	Sales_item book, sum;
	std::cout << "Enter Sales_items or Press CTRL Z to stop ";
	while (std::cin >> book)
		sum += book;
	std::cout << "The sum is " << sum << std::endl;
	system("pause");
	return 0;
}
//这个代码是不是感觉很熟悉啊,我们真的可以像对待内置类型数据那样处理类类型数据(自定义类型数据).

1.23

#include "Sales_item.h"
int main(){
	Sales_item book, CurBook;
	int cnt = 0;
	if (std::cin >> CurBook){//有数据可以处理
		++cnt;
		while (std::cin >> book){
			if (book.isbn()== CurBook.isbn())
				++cnt;
			else{
				std::cout << "The " << CurBook.isbn()<< " occurs "
					          << cnt << " times " << std::endl;
				cnt = 1;
				CurBook = book;
			}
		}
	}
	std::cout << "The " << CurBook.isbn()<< " occurs "
		<< cnt << " times " << std::endl;
	system("pause");
	return 0;
}
1.24 参看1.23

1.25

#include "Sales_item.h"
int main(){
	Sales_item total, Book;
	if (std::cin >> total){//有数据可以处理
		while (std::cin >> Book){
			if (total.isbn() == Book.isbn())
				total += Book;
			else{
				std::cout << "The " << total << std::endl;
				total = Book;
			}
		}
	}
	std::cout << "The " << total<< std::endl;
	system("pause");
	return 0;
}
    和上面的一样,都是一些比较经典代码,确实值得反复揣摩。其中的设计思想姑且一次是无法把握的。

就拿while之前的那个if语句设计,的确是精巧至极。因为if不是循环,所以你后面的输入是算在while循环中的,也就是说对象里面存储的是不包含第一个输入的。试想一下,给你一串数字,让你统计出现的次数,怎么办?假设相同的数字是聚拢在一起的。我的第一反映是数组啊,多组数字,肯定是数组了。但是这个案例提供了一个更好的解决办法。多揣摩经典代码,多学习。