c++ - 加速 C++ 练习 4-0

标签 c++ makefile

我正在学习 Andrew Koenig 和 Barbara Moo 的 Accelerated C++(2000 年),并且卡在第 4 章的代码上。我认为这段代码读取了一个包含多个学生的考试、期末和家庭作业成绩的外部数据文件,并返回了一个类(class)每个学生的成绩。

我已经从 GitHub 下载了 Andrew Koenig 的练习答案:

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

我可以运行第 4 章中的第一个示例 (main1.cc),当从键盘输入期中、期末和家庭作业成绩时,它会返回单个学生的类(class)成绩。这是一个例子:

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 的代码都使用单个 makefile 进行编译> 和 make 语句。以下是 makefile 的内容。我不相信 main2.cc 使用了此 makefile 中提到的任何 header 文件,但我没有对 进行任何更改生成文件。我没有在此处粘贴任何这些 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

我创建了一个名为data子文件夹,并在其中放置了两个数据文件: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 和两个数据文件。

"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

这是 c++ -v 在我的 Windows 10 笔记本电脑上返回的内容:

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调用,这会导致程序等待用户输入。看看test来自 makefile 的目标:

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

<意味着我们将重定向 single_grade 中的内容到正在运行的进程。隐含地假设在上面的文件夹中可执行二进制文件将是 data目录 single_grade数据文件。所以,当你运行 $ 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

关于c++ - 加速 C++ 练习 4-0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63766533/

相关文章:

c++ - GTKmm - 如何将 pixbuf 放入 TreeView 中

c++ - C++ 中的 Shared_ptr 和内存可见性

python-3.x - RHEL 7.6 - 从 Source Broke Network 构建 Python3.6

c - 将库添加到 autotools 文件不起作用(链接器忽略它)

gcc - 如何让链接器和加载器在特定路径选择共享库?

makefile - 我怎样才能 "alias"执行一些不同的命令

c - 没有制定目标的规则

c++ - Mingw libgcc_s_sjlj-1.dll 丢失

c++ - 为什么大型本地数组会使我的程序崩溃,而全局数组却不会?

c++ - 使用 Code::Blocks 在 Windows 上构建 FLTK