[c++菜鳥]《Accelerate C++》習題解答


第0章

0-0 編譯並運行Hello, world! 程序。

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello, world!" << endl;
    return 0;
}

0-1 下面的表達式是做什么的?

 3+4

計算3+4,結果為7

0-2 編寫一個程序,使它在運行時輸出:

This (*) is a quote , and this (\) is a backlash.
#include <iostream>
using namespace std;
int main()
{
    cout << "This (\*) is a quote , and this (\\) is a backlash" << endl;
    return 0;
}

0-3 字符串直接量"\t"代表一個水平制表符;不同的C++實現以不同的形式顯示制表符。在你的實現中實驗一下,看它是怎樣處理制表符的。

\t處理為4個空格

0-4 編寫一個程序,運行時以Hello, world!程序作為這個程序輸出。

#include <iostream>
using namespace std;
int main()
{
    cout << "#include <iostream>\n"
         << "using namespace std;\n"
         << "int main()\n"
         << "{\n"
         << "\tcout << \"Hello, world!\" << endl;\n"
         << "\treturn 0;\n"
         << "}\";\n"
         << "return 0;\n";
    return 0;
}

0-5 下面的程序是一個有效的程序嗎?說出理由。

#include <iostream>
int main()  std::cout << "Hello, world!" << std::endl;
這是一個無效程序,因為函數的函數體必須用花括號括起來,就算函數的函數體只有一條語句,也必須用花括號括住它。

0-6 下面的程序是一個有效的程序嗎?說出理由。

#include <iostream>
int main()  {{{{{{ std::cout << "Hello, world!" << std::endl; }}}}}}
這是一個有效程序,一般來說,函數必須包含至少一條的return語句,而且函數的最后一定要有return語句,但main比較特殊,它可以沒有返回語句,若果這樣,編譯器就會假設它返回0。

0-7 那下面的這個程序呢?

#include <iostream>
int main()  
{
    /*這是一個注釋,因為我們使用了/*和*/來作為它的定界符,
    所以它占據了幾行的范圍*/
    std::cout << "Does this work?" << std::endl;
    return 0;
}
無效程序,注釋有誤,注釋在前一個結束符*/就結束了,所以后面的內容都未能注釋。

0-8 ······這個呢?

#include <iostream>
int main()  
{
    //這是一個注釋,它占據了幾行的范圍
    //在這里,我們使用了//而不是/*
    //和*/來為注釋定界
    std::cout << "Does this work?" << std::endl;
    return 0;
}
有效程序,單行注釋使用后,后面的多行注釋符號不在起作用。

0-9 最短的有效程序是什么?

int main() {}

0-10 重寫Hello, workd! 程序,讓程序中每一個允許出現空白符的地方都換行。

#include<iostream>
#include<conio.h>
 
int
main()
{
std::cout
<< 
"hello, world!"
<<
std::endl;
return 0;
}

第1章

1-0 編譯、允許並測試本章中的程序。

#include "stdafx.h"
#include<iostream>
#include<string>

int main()
{
    std::cout <<"Pleause enter your first name: ";
    std::string name;
    std::cin >> name; 
    std::cout << "Hello, " << name << "!" << std::endl;   
    return 0;
}
#include "stdafx.h"
#include<iostream>
#include<string>

int main()
{
    std::cout << "Please enter your first name: ";
    std::string name;
    std::cin >> name;
 
    const std::string greeting = "Hello," + name + "!";
 
    const std::string spaces(greeting.size(),' ');
    const std::string second = "*" + spaces + "*";
 
    const std::string first(second.size(),'*');
 
    std::cout << std::endl;
    std::cout <<first << std::endl;
    std::cout <<second << std::endl;
    std::cout << "*" << greeting << "*" << std::endl;
    std::cout << second << std::endl;
    std::cout << first << std::endl;
 
    return 0;
}

 1-1 以下的定義有效嗎?理由是什么?

const std::string hello = "Hello";
const std::string message = hello + ", world" + "!";
a) 定義有效,可以將一個字符串直接量直接賦給一個字符串變量
b) 定義有效,可以用 + 將一個字符串和一個字符串直接量連接起來

1-2 以下的定義有效嗎?理由是什么?

const std::string exclam = "!";
const std::string message = "Hello" + ", world" + exclam;
a) 定義有效
b) 定義無效,”Hello” 和 “world”都是字符串直接量,用+操作符是不合法的,因為其中一個必須std::string對象才是合法的。

1-3 以下的定義有效嗎?如果有效的話,它是做什么的?如果無效,為什么呢?

#include<iostream>
#include<string>

int main()
{
    {const std::string s = "a string";
    std::cout << s << std::endl;}

    {const std::string s = "another string";
    std::cout << s << std::endl;}

    return 0;
}
有效,s分別為每對花括號內的局部變量。程序輸出了兩個字符串

1-4 下面的這個程序又怎樣呢?如果我們把倒數第三行的 }} 改成 };} 的話,會出現什么情況呢?

#include "stdafx.h"
#include<iostream>
#include<string>

int main()
{
    {const std::string s = "a string";
    std::cout << s << std::endl;

    {const std::string s = "another string";
    //std::cout << s << std::endl;}}
    std::cout << s << std::endl;} ;}

    return 0;
}
有效。內部作用域嵌套在外部作用域,內部作用域的s隱藏了外部作用域的s,所以程序是有效的,改變之后仍然有效。

1-5 下面這個程序呢?如果有效,它是做什么的?如果無效,說出理由,然后把它改寫成有效的程序。

#include "stdafx.h"
#include<iostream>
#include<string>

int main()
{
    {std::string s = "a string";
    {std::string x = s+ ", really";
    std::cout << s << std::endl;}
    std::cout << x << std::endl; // x is out of its scope here
    }

    return 0;
}
無效,x是在內部作用域定義的,出了內部作用域后,x便是不可用的。去掉內部的花括號,程序就變為有效程序。

1-6 在下面的程序向你發出輸入請求的時候,如果你輸入了兩個名字(例如,Samuel Beckett),它會怎么樣處理呢?在運行程序之前先預測一下結果,然后上機測一下。

#include "stdafx.h"
#include<iostream>
#include<string>

int main()
{
    std::cout << "What is your name? ";
    std::string name;
    std::cin >> name;
    std::cout << "Hello, " << name
              << std::endl << "And what is yours? ";
    std::cin >> name;
    std::cout << "Hello, " << name
              << ";nice to meet you roo!" << std::endl;
    return 0;
}

第2章

2-0 編譯並運行我們在本章中介紹的程序。

#include "stdafx.h"
#include<iostream>
#include<string>

using std::cin;
using std::cout;
using std::endl;
using std::string;
 
int main()
{
    cout <<"please enter your first name:";
    string name;
    cin >> name;
 
    const string greeting ="hello," + name +"!";
    const int pad = 1;
 
    const int rows = pad*2 + 3;
    const string::size_type cols = greeting.size() + pad*2 + 2;
 
    cout << endl;
  
    for (int r = 0; r !=rows; r++) {
        string::size_type c = 0;
        while (c != cols) {
        if (r == pad+1 && c == pad+1) {
            cout << greeting;
            c += greeting.size();
        }else {
            if (r == 0 || r == rows-1 || c == 0 || c == cols-1)
                cout<< "*";
            else
                cout<< " ";
            ++c;
        }
      }
      cout << endl;
   }
   return 0;
}

 2-1 改寫框架程序,輸出跟框架沒有間隔的問候語。

2-0中 const int pad = 1; 改為 const int pad = 0;

2-2 在我們的框架程序中,我們使用了一定數目的空格來把問候語和頂部以及底部邊界分隔開來。現在,重新編寫這個程序,在重寫的程序中使用數量跟源程序不同的空格來把各邊界和問候語分隔開。

把pad的值變成由用戶輸入即可:
const int pad = 1;
替換成    
cout <<"please enter the pad:";
int pad;
cin >> pad;

2-3 重寫框架程序,讓用戶自己提供在框架和問候語之間的空格個數。

同上

2-4 在框架程序中的空白行是用來把邊界和問候語分隔開的,程序每次一個字符地輸出了大部分的空白行。改寫這個程序,讓它在單獨的一條輸出表達式中輸出所有的空白行。

#include "stdafx.h"
#include<iostream>
#include<string>

using std::cin;
using std::cout;
using std::endl;
using std::string;
 
int main()
{
    cout <<"please enter your first name:";
    string name;
    cin >> name;
 
    const string greeting ="hello," + name +"!";
    const int pad = 1;
 
    const int rows = pad*2 + 3;
    const string::size_type cols = greeting.size() + pad*2 + 2;

    const string spaces = string(greeting.size() + pad * 2, ' ');
    
    cout << endl;
  
    for (int r = 0; r !=rows; r++) {
        string::size_type c = 0;
        while (c != cols) {
        if (r == pad+1 && c == pad+1) {
            cout << greeting;
            c += greeting.size();
        }else {
            if (r == 0 || r == rows-1 || c == 0 || c == cols-1)
            {
                cout<< "*";
                ++c;
            }
            else if (r == pad + 1) {
                  cout<< " ";
                 ++c;
               }else {
                  cout<< spaces;
                  c +=spaces.size();
               }
            }        
        }
      
        cout << endl;
    }
    return 0;
}

2-5 編寫一個程序,讓它輸出一系列的“*”字符,程序輸出的這些字符將構成一個正方形,一個長方形和一個三角形。

#include "stdafx.h"
#include<iostream>
#include<string>

using std::cin;
using std::cout;
using std::endl;
using std::string;
 
int main()
{
   // this constant is the height of each figure
   const int height = 5;
 
   // these variables are used to track the row and
   // column count while drawing each figure
   int row;
   int col;
 
   // draw square
   row = 0;
   col = 0;
 
   // draw top line
   while (col < height) {
      cout <<'*';
      ++col;
   }
 
   cout << endl;
   ++row;
 
   // draw middle lines
   while (row < height - 1) {
      col = 0;
      while (col < height) {
         ++col;
         if (col == 1)
            cout <<'*';
         else {
            if (col == height)
               cout<<'*';
            else
               cout<<' ';
         }
      }
      cout <<endl;
      ++row;
   }
 
   // draw bottom line
   col = 0;
 
   while (col < height) {
      cout <<'*';
      ++col;
   }
 
   // new line after figure
   cout << endl;
 
   // blank line between figures
   cout << endl;
 
   // draw rectangle
   row = 0;
   col = 0;
 
   // draw top line
   while (col < height * 2) {
      cout <<'*';
      ++col;
   }
 
   cout << endl;
   ++row;
 
   // draw middle lines
   while (row < height - 1) {
      col = 0;
      while (col <= height * 2) {
         ++col;
         if (col == 1)
            cout<<'*';
         else {
            if (col == height * 2)
               cout<<'*';
            else
               cout<<' ';
         }
      }
      cout <<endl;
      ++row;
   }
 
   // draw bottom line
   col = 0;
 
   while (col < height * 2) {
      cout <<'*';
      ++col;
   }
 
   // new line after figure
   cout << endl;
 
   // blank line between figures
   cout << endl;
 
   // draw triangle
   row = 0;
 
   // draw rows above base
   while (row < height - 1)
   {
      col = 0;
      while (col < height + row) {
         ++col;
         if (col == height - row)
            cout<<'*';
         else {
 
            if (col == height + row)
               cout<<'*';
            else
               cout<<' ';
         }
      }
      cout <<endl;
      ++row;
   }
 
   // draw the base
   col = 0;
 
   while (col < height * 2 - 1) {
      cout <<'*';
      ++col;
   }
 
   // new line after figure
   cout << endl;
   
   return 0;
}

2-6 下面的代碼是做什么的?

    int i=0;
    while(i<10)
    {
        i+=1;
        std::cout << i << std::endl;
    }
代碼運行輸出1—10的數字,且每個數字占一行。

2-7 編寫一個程序來一次輸出從10~-5的整數

    int i=10;
    while(i>-5)
    {    
        std::cout << i << std::endl;
        i-=1;
    }

2-8 編寫一個程序來計算區間[1,10)中的所有數值的乘積。

  int result = 1;
   for (int i = 1; i< 10; i++) {
      result *= i;
   }
   cout << result<< endl;

2-9 編寫一個程序,讓用戶輸入兩個數值並告知用戶在這兩個數值中哪一個較大。

#include "stdafx.h"
#include<iostream>
 
using std::cin;
using std::cout;
using std::endl;
 
int main()
{
   int m, n;
   cout <<"please enter two numbers:";
   cin >> m;
   cin >> n;
   if (m == n) {
      cout << m<<" equals " << n;
   }else if (m > n) {
      cout << m<<" > " << n;
   }else {
      cout << m<<" < " << n;
   }
   return 0;
}

2-10 在下面的程序中,對std::的每一次使用進行解釋。

int main()
{
    int k =0;
    while (k!=n){
        using std::cout;
        cout << "*";
    }
   std::cout << std::endl;
   return 0;
}
第1個std::是一個using聲明,只適用於最里面的{}內
第2個std::必須明確指出,表示cout的名稱空間
第3個std::也要明確指出,表示輸出一個新行

 

第3章

3-0 編譯、運行並測試本章中的程序

// test3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<ios>
#include<iostream>
#include<string>
#include<iomanip>

using std::cin;
using std::cout;
using std::endl;

using std::setprecision;
using std::string;
using std::streamsize;

int main()
{
    //請求輸入並讀入學生的姓名
    cout << "please enter your first name: ";
    string name;
    cin >> name;
    cout << "Hello, " << name << "!" << endl;
 
    //請求輸入並讀入期中和期末成績
    cout << "please enter your midterm and final exam grades: ";
    double midterm, final;
    cin >> midterm >> final;
 
    cout <<"enter all your homework grades, followed by end-of-file: ";
    
    //到目前為止,讀到的家庭作業成績的個數及總和
    int count =0;
    double sum =0;

    //把家庭作業成績讀到變量x中
    double x;

    //不變式
    //到目前為止,我們已經讀到了count個家庭作業成績,而且sum等於頭count個成績的總和
    while (cin >> x)
    {
        ++count;
        sum += x;
    }
    
    //輸出結果
    streamsize prec = cout.precision();
    cout << "Your final grade is " << setprecision(3)
         << 0.2 * midterm + 0.4 * final + 0.4 * sum / count
         << setprecision(prec) << endl;
   
    return 0;
}
View Code

此處不加using namespace std;會報錯error C2653: 'vector<double,class std::allocator<double> >' : is not a class

#include "stdafx.h"
#include<iomanip>
#include<ios>
#include<iostream>
#include<string>

#include<vector>
#include<algorithm>

using namespace std;

int main()
{
    //請求輸入並讀入學生的姓名
    cout << "please enter your first name: ";
    string name;
    cin >> name;
    cout << "Hello, " << name << "!" << endl;
 
    //請求輸入並讀入期中和期末成績
    cout << "please enter your midterm and final exam grades: ";
    double midterm, final;
    cin >> midterm >> final;
 
    cout <<"enter all your homework grades, followed by end-of-file: ";
    
    vector<double> homework;
    double x;

    //不變式 home包含了所有的家庭作業成績
    while (cin >> x)
    {
        homework.push_back(x);
    }
    
    //檢查homework是否為空
    typedef vector<double>::size_type vec_sz;
    vec_sz size =homework.size();
    if (size == 0) {
        cout << endl<< "you must enter your grades."
                      "please try again." << endl;
        return 1;
    }
    //對成績進行排序
    sort(homework.begin(), homework.end());
 
    //計算家庭作業成績的中值
    vec_sz mid = size/2;
    double median;
    median = (size % 2 ==0) ? (homework[mid] + homework[mid-1]/2) : homework[mid];
 
    //計算並輸出總成績
    streamsize prec = cout.precision();

    cout << "Your final grade is " << setprecision(3)
         << 0.2 * midterm + 0.4 * final + 0.4 * median
         << setprecision(prec) << endl;
   
    return 0;
}

3-1 假設我們希望找出一個數值集合的中值;同時假定到目前為止,我們已經讀進一些數值了,而且不清楚還要再讀進多少個值。證明:我們不能丟掉已經讀到的任何值。提示:一個可行的證明策略是,先假定我們可以丟掉一個值,然后找出我們的集合中未讀的(也就是未知的)那部分數值,要求這些數值將會使中值恰好就是我們丟掉的那個值。

中值是一個可將數值集合划分為相等的上下兩部分的數值。對於有限的數集,通過把所有的值高低排序后找出正中間的一個作為中位數。中間點取決於所有的數值。

由此可知,如果任何一個我們已經讀到的值被丟棄,則會改變原先中間點的位置,這樣就得不出准確的中值。

3-2 把一個整數集合分為個數相等的四部分,而且第一部分含有的整數值比其他各部分的都大,第二部分的值比第一部分的小比其他兩部分的大,剩下的兩部分則以此類推。按照上面的要求,編寫一個程序來計算並且打印這四部分。

#include "stdafx.h"
#include<algorithm>
#include<iostream>
#include<vector>
#include<conio.h>
 
using namespace std;

int main() {
  vector<int> integers;
 
  cout << "Integers: ";
  int x;
 
  while (cin >> x)
   integers.push_back(x);
 
  if (integers.size() == 0) {
    cout << endl<<"No integers!" <<endl;
    return 1;
  }
  
  sort(integers.rbegin(), integers.rend());
  typedef vector<int>::size_type vec_sz;
 
  cout << "1st quartile" << endl;
  for (vec_sz i = 0; i < integers.size() / 4; ++i)
   cout <<integers[i] << endl;
 
  cout << "2nd quartile" << endl;
  for (vec_sz j = integers.size() / 4; j <integers.size() / 2; ++j)
    cout <<integers[j] << endl;
 
  cout << "3rd quartile" << endl;
  //注意這里確定第3部分范圍的時候的技巧
  for (vec_sz k = integers.size() / 2; k <integers.size() * 3 / 4; ++k)
    cout <<integers[k] << endl;
 
  cout << "4th quartile" << endl;
  for (vec_sz l = integers.size() * 3 / 4; l <integers.size(); ++l)
    cout <<integers[i] << endl;
 
  return 0;
}

 3-3  編寫一個程序來計算在它的輸入中的每個不同的單次所出現的次數。

#include "stdafx.h"
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
 
using namespace std;

int main() {
  vector<string> words;
  vector<int> counts;
  typedef vector<string>::size_type vec_sz;

  cout << "enter the words: ";
  string str;
 
  while (cin >> str)
  {
      bool found = false;
 
      for (vec_sz i = 0; i < words.size(); ++i) {
        if (str == words[i]) {
           ++counts[i];
           found = true;
        }
      }
      //新字符串才加入向量
      if (!found) {
        words.push_back(str);
        counts.push_back(1);
      }

  }
   for (vec_sz i = 0; i < words.size(); ++i) {
      cout <<words[i] <<" appears "<< counts[i] <<" times"<< endl;    
   }

  return 0;
}

3-4 編寫一個程序來報告它的輸入中最長的以及最短的字符串的長度。

#include "stdafx.h"
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
 
using namespace std;

int main() {
    typedef string::size_type str_sz;
    string longest;
    str_sz longest_size =0;
    string shortest;
    str_sz shortest_size= 0;

    cout << "enter words: ";
    string s;

    while (cin >> s)
    {
        if (longest_size == 0 || s.size() > longest_size) {
            longest = s;
            longest_size = s.size();
        }
       if (shortest_size == 0 || s.size() < shortest_size) {
            shortest = s;
            shortest_size = s.size();
        }        
    }
    
    cout <<" 最長的:"<< longest << " (" << longest_size << ")" << endl;
    cout <<" 最短的:"<< shortest << " (" << shortest_size<< ")" << endl;
  

  return 0;
}

3-5 編寫一個程序來跟蹤n個學生的成績。要求程序能夠保持兩個向量的同步:第一個應保存學生的姓名;第二個保存總成績,而這個總成績能根據讀到的輸入來計算。讀者應假定家庭作業成績的個數是固定的。

#include "stdafx.h"
#include "iostream"
#include "string"
#include "vector"

using namespace std;
 
int main()
{
    int n;  //學生總數n
    string name;
    vector<string> vNames;
    vector<double> vGrade;
    //請求輸入並讀入學生的姓名
    cout << "Please enter number of students: ";

    cin >> n;
    
    for(int i=1; i <= n; i++)
    {
        cout << "Please enter name of student " << i << ": ";
        
        cin >> name;
                
        vNames.push_back(name); //把輸入的name加入向量
        cout << "Hello, " << name << "!" << endl;

        int num = 3;
            
        cout << "Please enter "<< num << " grades: ";  //提示輸入3個成績
        double grade;
        double gradeCount = 0;
        while(num-->0)
        {            
            cin >> grade;
            gradeCount += grade;            
        }
        //計算的總成績,加入向量
        vGrade.push_back (gradeCount);
    }

    for(vector<string>::size_type j=0; j < vNames.size(); j++)
    {    
        cout << "name: " << vNames[j] << "  ,total grade: " << vGrade[j] << endl;    
    }

    return 0;
}

 第4章

4-0

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>

using namespace std;

//1 4.1.1 median函數
double median (vector<double>vec) //查找中值
{
   typedef vector<double>::size_type vec_sz;
   vec_sz size =vec.size();
   if (size == 0)
      throw domain_error ("median of an empty vector");
 
   sort(vec.begin(), vec.end());
   vec_sz mid = size/2;
   return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 :vec[mid];
}
//2 4.1   grade函數
double grade(double midterm, double final, double homework)
{
    return 0.2 * midterm + 0.4 * final +0.4 * homework;
}
//3 4.1.2 grade函數
double grade(double midterm, double final, const vector<double>& hw)
{
    if (hw.size() == 0)
      throw domain_error ("student has done no homework");
 
    return grade(midterm, final, median(hw));
}
//4 4.1.3 read_hw函數
istream read_hw(istream& in, vector<double>& hw)
{
    if(in){
        hw.clear(); //清除原先的內容
        double x;   //讀家庭作業成績
        while (in >>x)
            hw.push_back(x);

        in.clear(); //清除流以使輸入動作對下一個學生有效
    }
    return in;
}

int main()
{
    //請求並讀入學生姓名
    cout << "Please enter your first name: ";
    string name;
    cin >> name;
    cout << "Hello, " << name << "!" << endl;

    //請求並讀入期中和期末考試的成績
    cout << "Please enter your midterm and final exam grades: ";
    double midterm, final;
    cin >> midterm >> final;

    //請求用戶輸入家庭作業成績
    cout << "Enter all your homework grades, folloowed by end-of-file: ";
    vector<double> homework;

    //讀入家庭作業成績
    read_hw(cin, homework);
    //如果可以的話,計算成總成績
    try    {
        double final_grade = grade(midterm, final, homework);
        //streamsize prec = cout.setprecision();
        streamsize prec = cout.precision();
        cout << "Your final grade is " << setprecision(3) 
            << final_grade << setprecision(prec) << endl;
    }catch (domain_error) {
        cout <<endl << "You must enter your grades. "
            << "Please try again." <<endl;
        return 1;
    }
    return 0;
}

2

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>

using namespace std;

//1 4.1.1 median函數
double median (vector<double>vec) //查找中值
{
   typedef vector<double>::size_type vec_sz;
   vec_sz size = vec.size();
   if (size == 0)
      throw domain_error ("median of an empty vector");
 
   sort(vec.begin(), vec.end());
   vec_sz mid = size/2;
   return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 :vec[mid];
}
//2 4.1   grade函數
double grade(double midterm, double final, double homework)
{
    return 0.2 * midterm + 0.4 * final +0.4 * homework;
}
//3 4.1.2 grade函數
double grade(double midterm, double final, const vector<double>& hw)
{
    if (hw.size() == 0)
      throw domain_error ("student has done no homework");
 
    return grade(midterm, final, median(hw));
}

//4 4.1.3 read_hw函數
istream read_hw(istream& in, vector<double>& hw)
{
    if(in){
        hw.clear(); //清除原先的內容
        double x;   //讀家庭作業成績
        while (in >>x)
            hw.push_back(x);

        in.clear(); //清除流以使輸入動作對下一個學生有效
    }
    return in;
}

struct Student_info{
    string name;
    double midterm, final;
    vector<double> homework;
};

double grade(const Student_info& s)
{
    return grade(s.midterm, s.final, s.homework);
}

istream& read(istream& is, Student_info& s)
{
    //讀入並存儲學生的姓名以及期中、期末考試成績
    is >> s.name >> s.midterm >> s.final;
    read_hw(is, s.homework);  //讀入並存儲學生的所有家庭作業成績
    return is;
}

bool compare(const Student_info& x, const Student_info& y)
{
    return x.name < y.name;  
}


int main()
{
    vector<Student_info> students;
    Student_info record;
    string::size_type maxlen = 0;
    
    //讀並存儲所有的記錄,然后找出最長的姓名的長度
    while(read(cin, record)){
        //maxlen = max(maxlen, record.name.size());
        maxlen=_MAX(maxlen, record.name.size());    //vc6用_MAX替代max函數
        students.push_back(record);
    }
    
    //按字母順序排列記錄
    sort(students.begin(), students.end(), compare);

    for(vector<Student_info>::size_type i = 0; i != students.size(); ++i){
    //輸出姓名,填充姓名以達到maxlen +1的長度
        cout << setw(maxlen+1) << students[i].name;
        //計算並輸出成績
        try{
            double final_grade = grade(students[i]);
            streamsize prec = cout.precision();
            cout << setprecision(3) << final_grade
                << setprecision(prec);
        }catch(domain_error e){
            cout << e.what();
        }
        cout << endl;
    }
    
    return 0;
}
View Code

3

#ifndef GUARD_median_h
#define GUARD_median_h
 
#include<vector>
double median(std::vector<double>);
#endif
median.h
#include<algorithm>
#include<stdexcept>
#include<vector>
 
//using std::domain_error;
//using std::sort;
//using std::vector;
using namespace std;
double median (vector<double>vec)
{
   typedef vector<double>::size_type vec_sz;
   vec_sz size =vec.size();
   if (size == 0)
      domain_error ("median of an empty vector");
 
   sort (vec.begin(),vec.end());
   vec_sz mid = size/2;
   return size % 2 == 0 ? (vec[mid] + vec[mid-1]) :vec[mid];
}
median.cpp
#ifndef GUARD_Student_info
#define GUARD_Student_info
 
#include<iostream>
#include<string>
#include<vector>
 
struct Student_info {
   std::string name;
   double midterm, final;
   std::vector<double> homework;
};
 
bool compare(const Student_info&,const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif
Student_info.h
#include"Student_info.h"
 
using std::istream;
using std::vector;
 
bool compare (const Student_info& x,const Student_info& y){
   return x.name < y.name;
}
 
istream& read (istream& is, Student_info& s) {
   is >> s.name>> s.midterm >> s.final;
 
   read_hw (is,s.homework);
   return is;
}
 
istream& read_hw (istream& in, vector<double>& hw) {
   if (in) {
      hw.clear();
 
      double x;
      while (in >> x)
        hw.push_back(x);
      in.clear();
   }
   return in;
}
Student_info.cpp
#ifndef GUARD_grade_h
#define GUARD_grade_h
 
#include<vector>
#include"Student_info.h"
 
double grade(double,double,double);
double grade(double,double,const std::vector<double>&);
double grade(const Student_info&);
#endif
grade.h
#include<stdexcept>
#include<vector>
#include"grade.h"
#include"median.h"
#include"Student_info.h"
 
using std::domain_error;
using std::vector;
 
double grade (double midterm,double final,double homework) {
   return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
 
double grade (double midterm,double final,const vector<double>& hw) {
   if (hw.size() == 0) {
      throw domain_error("studenthas done no homework");
   }
   return grade (midterm, final, median(hw));
}
 
double grade (const Student_info& s) {
   return grade (s.midterm, s.final, s.homework);
}
grade.cpp
#include<algorithm>
#include<iomanip>
#include<ios>
#include<iostream>
#include<stdexcept>
#include<string>
#include<vector>
#include<conio.h>
#include"grade.h"
#include"Student_info.h"

using namespace std;

int main()
{
   vector<Student_info> students;
   Student_info record;
   string::size_type maxlen = 0;
 
   while (read(cin, record)) {
       maxlen =_MAX(maxlen, record.name.size());
      students.push_back(record);
   }
 
   sort(students.begin(),students.end(), compare);
 
   for (vector<Student_info>::size_type i = 0; i!= students.size(); ++i) {
      cout <<students[i].name << string(maxlen+1-students[i].name.size(),' ');
 
      try {
        double final_grade = grade(students[i]);
        streamsize prec= cout.precision();
        cout <<setprecision(3) << final_grade << setprecision(prec);
      } catch (domain_error e) {
        cout <<e.what();
      }
      cout <<endl;
   }
   getch();
   return 0;
}
main.cpp

4-1 我們注意到,在4.2.3中,在調用max的時候,必須讓參數的類型嚴格匹配。下面的代碼正確嗎?如果有問題的話,那你將怎樣改正他呢?

int maxlen;
Student_info s;
max(s.name.size(), maxlen);
將maxlen定義為int類型是不正確的,因為max函數兩個參數必須是同樣的類型,而第一個參數的類型是string::size_type,第二個參數的類型是int,不相同,因此是不正確的。

正確的做法是將maxlen的類型定義為string::size_type類型。

4-2 編寫一個程序來計算從1-100的整數(int)值的平方。程序的輸出分為兩列:第一列是整數值,第二列是整數值的平方。使用控制器來控制輸出,讓數值按列排列起來。

#include<algorithm>
#include<iomanip>
#include<ios>
#include<iostream>
#include<conio.h>

using namespace std;

int main()
{
   for(int i=1;i<=100;i++)
   {
       cout<< setw(3) << i << setw(5) << i*i <<endl;
   }
   return 0;
}

4-3 如果我們重寫了上題中的程序,讓它計算從1到999的整數的平方。但是,我們忘記了更改setw的參數的值。這樣做會有什么問題呢?重寫這個程序,讓它具有更好的適應性。重寫后的程序應實現這樣的目標:當i增長時我們不需要修正setw的參數。

#include<iostream>
#include<iomanip>
#include<math.h>

using namespace std;

int get_width(int n)
{  
   return log10(n*1.0) + 1;  //注意log10()的參數
}

int main()
{
    cout << "enter the range min to max: ";
    int min, max;
    cin >> min >> max;

    for(int i=min;i<=max;i++)
    {
       cout << setw(get_width(max)) << i << setw(get_width(max*max) + 1) <<i * i << endl;
    }
    return 0;
}

4-4 現在,再次修改你的求平方程序,用它來求double類型而不是int類型的值的平方。使用控制器來控制輸入,讓數值按列排列起來。

#include<iostream>
#include<iomanip>
#include<math.h>

using namespace std;

int get_width(double n)
{  
   return log10(n) + 1;
}

int main()
{
    cout << "enter the range min to max: ";
    double min, max;
    cin >> min >> max;
    for(double i=min;i<=max;i++)
    {
       cout << setw(get_width(max)) << i << setw(get_width(max*max)) << i * i << endl;
    }
    return 0;
}

4-5 編寫一個函數來從輸入流讀單詞,把讀到的單詞存儲在一個向量中。利用這個函數編寫一個程序來計算輸入的單詞的數目以及每一個單詞所出現的次數。

#include<iostream>
#include<vector>
#include<string>
#include<conio.h>

using namespace std;

int main()
{
    vector<string> words;
    vector<int> counts;
    int sum = 0;

    typedef vector<string>::size_type vec_sz;

    cout << "Enter words: ";
    string s;

    while(cin >> s)
    {
        bool found = false;
        for(vec_sz i=0; i<words.size(); i++)
        {
            if(words[i] == s)
            {
                counts[i]++;
                found = true;
            }
        }
        if(!found)
        {
            words.push_back(s);
            counts.push_back(1);            
        }
        sum++;
    }

    cout << "The total number of words are "<< sum << endl;

    for(vec_sz i = 0; i <= words.size(); i++)
    {
       cout << words[i] << " appears " << counts[i] << " times" << endl;
    }
    return 0;
}

4-6 重寫Student_info結構並使用重寫后的結構來直接計算成績,要求在程序中僅僅存儲總成績。

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>


#ifdef _MSC_VER
//#include "../minmax.h"
#else
using std::max;
#endif

using namespace std;

struct Student_info {
  string name;
  double grade;
};    // note the semicolon--it's required

// compute the median of a `vector<double>'
// note that calling this function copies the entire argument `vector'
double median(vector<double> vec) {

#ifdef _MSC_VER
  typedef std::vector<double>::size_type vec_sz;
#else
  typedef vector<double>::size_type vec_sz;
#endif

  vec_sz size = vec.size();
  if (size == 0)
    throw domain_error("median of an empty vector");

  sort(vec.begin(), vec.end());

  vec_sz mid = size/2;

  return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid];
}

// compute a student's overall grade from midterm and final exam grades and homework grade
double grade(double midterm, double final, double homework) {
  return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}

// compute a student's overall grade from midterm and final exam grades
// and vector of homework grades.
// this function does not copy its argument, because `median' does so for us.
double grade(double midterm, double final, const vector<double>& hw) {
  if (hw.size() == 0)
    throw domain_error("student has done no homework");

  return grade(midterm, final, median(hw));
}

double grade(const Student_info& s) {
  return s.grade;
}

// read homework grades from an input stream into a `vector<double>'
istream& read_hw(istream& in, vector<double>& hw) {
  if (in) {
    // get rid of previous contents
    hw.clear();

    // read homework grades
    double x;
    while (in >> x)
      hw.push_back(x);

    // clear the stream so that input will work for the next student
    in.clear();
  }

  return in;
}

istream& read(istream& is, Student_info& s) {
  double midterm, final;
  // read and store the student's name and midterm and final exam grades
  is >> s.name >> midterm >> final;

  vector<double> homework;
  read_hw(is, homework);  // read and store all the student's homework grades

  if (cin)
    s.grade = grade(midterm, final, homework);

  return is;
}

bool compare(const Student_info& x, const Student_info& y) {
  return x.name < y.name;
}

int main() {
  vector<Student_info> students;
  Student_info record;
  string::size_type maxlen = 0;

  try {
    // read and store all the records, and find the length of the longest name
    while (read(cin, record)) {
      maxlen = _MAX(maxlen, record.name.size());
      students.push_back(record);
    }
  } catch (domain_error e) {
    cout << e.what() << endl;
  }

  // alphabetize the records
  sort(students.begin(), students.end(), compare);
  
#ifdef _MSC_VER
  for (std::vector<Student_info>::size_type i = 0;
#else
       for (vector<Student_info>::size_type i = 0;
#endif
        i != students.size(); ++i) {

     // write the name, padded on the right to `maxlen' `+' `1' characters
     cout << students[i].name
          << string(maxlen + 1 - students[i].name.size(), ' ');

     // compute and write the grade
     double final_grade = grade(students[i]);
     streamsize prec = cout.precision();
     cout << setprecision(3) << final_grade
          << setprecision(prec);

     cout << endl;
       }

     return 0;
       }
View Code

4-7 編寫一個程序來計算存儲在一個vector<double>類型的向量中的數據的平均值。

#include <iostream>
#include <iomanip>
#include <vector>
#include <numeric>

using namespace std;

int main() {
    cout << "Enter numbers: ";
 
    vector<double> numbers;
 
    double num;
    while (cin >> num) 
    {
        numbers.push_back(num);
    }
 
    cout << "Average: "
        <<accumulate(numbers.begin(),numbers.end(), 0.0)/numbers.size();
 
    return 0;
}
View Code

4-8 如果下面的代碼是合法的,那么對於f的返回類型我們能做出什么推斷呢?

double d = f() [n];
#include<iostream>
#include<conio.h>
 
double *f()
{
    static double value[]= {1.1, 2.2, 3.3, 4.4, 5.5};
    return value;
}
int main ()
{
    int n = 2;
    double d = f() [n];
    std::cout << "d = " << d <<'\n';
    getch();
    return 0;
}

4-9 在C++編程中有一個相當常見的程序錯誤:如果我們像在4.2.3中所做的那樣給setw一個字符串類型的參數,那么setw函數可能會無法正常工作。重寫4.2.3中的程序,讓它不用再依賴setw函數。提示(1.2): string spaces(n,' ')構造了一個含有歐n個空格的字符串。

第5章

5-0

#include "stdafx.h"
#pragma warning(disable : 4786) //屏蔽4876錯誤
#include <vector>
#include <cctype>

#include <iostream>
#include <string>

using namespace std;

vector<string> split(const string & s)
{
    vector<string> ret;
    typedef string::size_type string_size;
    string_size i = 0;

    while(i!=s.size())
    {
        while(i!=s.size() && isspace(s[i]))
            ++i;
        string_size j = i;
        while(j != s.size() && !isspace(s[j])) //書中這里錯誤寫的i
            ++j;

        if(i!=j)
        {
            ret.push_back(s.substr(i,j-i));
            i=j;
        }
    }
    return ret;
}

int main()
{
    string s;
    while(getline(cin,s))
    {
        vector<string> v =split(s);
        for(vector<string>::size_type i=0; i!=v.size(); ++i)
            cout<<v[i]<<endl;
    }

    return 0;
}
5-0

 

參考

[1]https://blog.csdn.net/u013706695/article/details/19493443

[2]https://github.com/bitsai/book-exercises/tree/master/Accelerated%20C%2B%2B

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM