簡體   English   中英

加速 C++ 練習 4-0

[英]Accelerated C++ Exercise 4-0

我正在研究 Andrew Koenig 和 Barbara Moo (2000) 的 Accelerated C++,並堅持使用第 4 章的代碼。我認為這段代碼讀取包含多個學生的考試、期末和家庭作業成績的外部數據文件,並返回每個學生的課程成績學生。

我已經從 GitHub 的 Andrew Koenig 那里下載了練習的解決方案:

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

我可以運行第 4 章 ( main1.cc ) 中的第一個示例,當從鍵盤輸入期中、期末和家庭作業成績時,它會返回單個學生的課程成績。 下面是一個例子:

data: harriet 85 95 88 87 93 45 76 99
student name = harriet
midterm grade = 85
final grade = 95
median of six homework grades (88, 87, 93, 45, 76, 99) = 87.5
final grade = 90
0.2 * 85 + 0.4 * 95 + 0.4 * 87.5 = 90

但我無法運行第二個示例 ( main2.cc ),其中從外部文件為多個學生讀取數據。 創建或運行main2.exe文件時不會出現錯誤消息。 當我嘗試運行main2.exe時,Windows 10 命令窗口中的光標只是移動到下一行,但沒有顯示任何內容,甚至沒有顯示目錄。 以下是我制作可執行文件時返回的行:

c:\Users\mark_\myCppprograms\mychapter04>make
g++     main1.cc   -o main1
g++     main2.cc   -o main2
g++    -c -o main3.o main3.cc
g++    -c -o grade.o grade.cc
g++    -c -o median.o median.cc
g++    -c -o Student_info.o Student_info.cc
g++   main3.o grade.o median.o Student_info.o   -o main3

main2.cc的代碼很長。 第 4 章中的第三個示例 ( main3.cc ) 將此代碼分解為多個C++header文件,但我也無法讓main3.exe文件返回任何內容。

這是main2.cc的代碼。 我改#include "../minmax.h"#include "minmax.h" ,把一個文件"minmax.h"在同一文件夾中main2.cc 文件"minmax.h"並非來自上述 GitHub 站點,我將其內容粘貼在下面。

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

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

using std::cin;
using std::cout;
using std::domain_error;
using std::endl;
using std::istream;
using std::ostream;
using std::setprecision;
using std::setw;
using std::sort;
using std::streamsize;
using std::string;
using std::vector;

struct Student_info {
  string name;
  double midterm, final;
  vector<double> homework;
};  // 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 grade(s.midterm, s.final, s.homework);
}

// 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) {
  // read and store the student's name and midterm and final exam grades
  is >> s.name >> s.midterm >> s.final;

  read_hw(is, s.homework);  // read and store all the student's homework grades

  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;

  // 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);
  }

  // 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
     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;
       }

main1.ccmain2.ccmain3.cc的代碼都使用單個makefilemake語句make編譯。 下面是makefile的內容。 我不相信main2.cc使用了這個makefile提到的任何header文件,但我沒有對makefile進行任何更改。 我沒有在這里粘貼任何這些header文件的內容。 如果它們與main2.cc相關,我可以應要求提供它們,或者它們都可以在上面的 GitHub 站點上找到。

CXX = g++
CC = g++

all:        main1 main2 main3

Student_info.o: Student_info.cc Student_info.h

grade.o:    grade.cc grade.h median.h Student_info.h

main3.o:    main3.cc grade.h median.h Student_info.h

median.o:   median.cc median.h

main3:      main3.o grade.o median.o Student_info.o

test:       all
    ./main1 <../data/single_grade
    ./main2 <../data/single_grade
    ./main2 <../data/grades
    ./main3 <../data/grades

clobber:
    rm -f *.o *.exe core main1 main2 main3

我創建了一個名為datasubfolder並在其中放置了兩個數據文件: gradessingle_grade 以下是grades的內容:

Moo 100 100 100 100 100 100 100 100
Moore 75 85 77 59 0 85 75 89
Norman 57 78 73 66 78 70 88 89
Olson 89 86 70 90 55 73 80 84
Peerson 47 70 82 73 50 87 73 71

Russel 72 87 88 54 55 82 69 87
Thomas 90 96 99 99 100 81 97 97
Vaughn 81 97 99 67 40 90 70 96
Westerly 43 98 96 79 100 82 97 96


Baker 67 72 73 40 0 78 55 70
Davis 77 70 82 65 70 77 83 81
Edwards 77 72 73 80 90 93 75 90
Franklin 47 70 82 73 50 87 73 71

Jones 77 82 83 50 10 88 65 80
Harris 97 90 92 95 100 87 93 91
Smith 87 92 93 60 0 98 75 90
Carpenter 47 90 92 73 100 87 93 91

Fail1 45 55 65 80 90 70 65 60
Fail2 55 55 65 50 55 60 65 60

以下是single_grade的內容:

harriet 85 95 88 87 93 45 76 99

我發現上述任何代碼中提到的這兩個數據文件的唯一地方是在makefile ,這讓我感到困惑,但我猜這個makefile main2.cc和兩個數據文件關聯main2.cc

以下是"minmax.h"的內容:

/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the mingw-w64 runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */
#ifndef _INC_MINMAX
#define _INC_MINMAX

#ifndef __cplusplus
#ifndef NOMINMAX
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif
#endif

#endif

這是我的Windows 10筆記本電腦上的c++ -v返回的內容:

c:\Users\mark_\myCppprograms>c++ -v
Using built-in specs.
COLLECT_GCC=c++
COLLECT_LTO_WRAPPER=c:/rtools/MINGW_64/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.3/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-4.9.3/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/home/Jeroen/mingw-gcc-4.9.3/x86_64-493-posix-seh-rt_v3-s/mingw64 --with-gxx-include-dir=/mingw64/x86_64-w64-mingw32/include/c++ --enable-static --disable-shared --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-isl-version-check --disable-cloog-version-check --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static --with-mpc=/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static --with-isl=/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static --with-cloog=/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static --enable-cloog-backend=isl --with-pkgversion='x86_64-posix-seh, Built by MinGW-W64 project' --with-bugurl=http://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -I/home/Jeroen/mingw-gcc-4.9.3/x86_64-493-posix-seh-rt_v3-s/mingw64/opt/include -I/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-zlib-static/include -I/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -I/home/Jeroen/mingw-gcc-4.9.3/x86_64-493-posix-seh-rt_v3-s/mingw64/opt/include -I/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-zlib-static/include -I/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS= LDFLAGS='-pipe -L/home/Jeroen/mingw-gcc-4.9.3/x86_64-493-posix-seh-rt_v3-s/mingw64/opt/lib -L/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-zlib-static/lib -L/home/Jeroen/mingw-gcc-4.9.3/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 4.9.3 (x86_64-posix-seh, Built by MinGW-W64 project)

c:\Users\mark_\myCppprograms>

我知道其他人已經上傳了 Accelerated C++ 練習的解決方案。 我看了好幾個。 但是我無法讓它們中的任何一個與main2.ccmain3.cc一起運行並返回預期的結果。

我不確定你是如何實際運行它的,但在我的情況下它工作得很好。 如果你采取仔細看看mainmain2.cc ,你會發現,有一個阻塞read調用,這導致程序等待用戶輸入。 從 makefile 中查看test目標:

test:           all
        ./main1 <../data/single_grade
        ./main2 <../data/single_grade
        ./main2 <../data/grades
        ./main3 <../data/grades

<表示我們將把single_grade中的內容重定向到正在運行的進程。 隱含地假設在可執行二進制文件的上述文件夾中將是一個包含single_grade數據文件的data目錄。 因此,當您運行$ make test ,您會注意到一切都按預期工作(假設目錄結構未更改)。 如果您只是運行$ ./main2 ,則程序等待輸入時不會發生任何事情。 或者,假設您的數據文件在main2二進制文件旁邊,您可以運行$ main2 < single_grade 或者,您也可以完全省略這些文件:

$ ./main2
$ Moo 100 100 100 100 100 100 100 100
$ Moore 75 85 77 59 0 85 75 89
$ EOF (in bash shell it's CTRL + D, on windows cmd: CTRL + Z)

其中產生:

Moo   100
Moore 79.4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM