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調用運算符():

    我希望自己能建立一種觀念,一切皆函數,一切皆運算。就像調用運算符,輸出輸入運算符這種,雖然表面看不出來,但是實際上當成函數理解纔是正確的。一開始我的理解實在是太狹隘了,以致我遲遲不能接受正確的觀念。

總結:

  相關術語摘錄:

   assignment :

  抹去一個對象的當前值,用一個新值取代。這個地方就可以很好的解釋了賦值和初始化。賦值一定是在有一個值的基礎上進行的。

   buffer :

  緩衝區,分爲輸入輸出緩衝區。IO設施通常將輸入輸出的數據保存在一個緩衝區中。讀寫緩衝區的操作與程序是無關的,我們可以顯式的刷新緩衝區,以便強制的將緩衝區的內容刷新到設備中。默認情況下,cin會刷新cout,程序的非正常終止也會刷新cout.關於緩衝區的詳細知識可以看看計算機組成原理。

   condition:

  求值結果爲真假的表達式。

   end_of_file :

  文件結束符。系統特定的標識符,指出文件中無更多的數據了。

   expression :

最小的計算單元。一個表達式包含一個或者多個運算對象,通常還包含一個或者多個運算符。表達式的求值會產生一個結果。

 習題解答:

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循環中的,也就是說對象裏面存儲的是不包含第一個輸入的。試想一下,給你一串數字,讓你統計出現的次數,怎麼辦?假設相同的數字是聚攏在一起的。我的第一反映是數組啊,多組數字,肯定是數組了。但是這個案例提供了一個更好的解決辦法。多揣摩經典代碼,多學習。










發佈了53 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章