打卡cs106x(Autumn 2017)-lecture3
1、streamErrors
Suppose an input file named streamErrors-data.txt
contains the following text:
Donald Knuth
M
76
Stanford U.
The code below attempts to read the data from the file, but each section has a bug. Correct the code and submit a version that reads the code and prints the values expected as indicated in the comments.
ifstream input;
input.open("streamErrors-data.txt");string name;
name = input.getline(); // #1 "Donald Knuth"
cout << name << endl;char gender;
gender = input.get(); // #2 'M'
cout << gender << endl;int age;
getline(input, age);
stringToInteger(age); // #3 76
cout << age << endl;string jobtitle;
input >> jobtitle; // #4 "Stanford U."
cout << jobtitle << endl;
解答:
#include <iostream>
#include <fstream>
#include <string>
#include "console.h"
#include "strlib.h"using namespace std;int main() {ifstream input;input.open("streamErrors-data.txt");string name;// getline的使用方法应为getline(f&, s&)getline(input, name); // #1 "Donald Knuth"cout << name << endl;char gender;// get()读取的是单个chargender = input.get(); // #2 'M'cout << gender << endl;input.get();string age; // 使用getline(f&, s&)的s是string类型getline(input, age);// cout << age << endl; 根据输出额外的空行得知,#2还有换行符未读取stringToInteger(age); // #3 76cout << age << endl;string jobtitle;// >> 读取以空格为间隔while(input >> jobtitle) { // #4 "Stanford U."cout << jobtitle << " ";}cout << endl;return 0;
}
2、inputStats
Write a function named inputStats
that accepts a string parameter representing a file name, then opens/reads that file's contents and prints information to the console about the file's lines. Report the length of each line, the number of lines in the file, the length of the longest line, and the average characters per line, in exactly the format shown below. You may assume that the input file contains at least one line of input. For example, if the input file carroll.txt
contains the following data:
Beware the Jabberwock, my son,
the jaws that bite, the claws that catch,Beware the JubJub bird and shun
the frumious bandersnatch.
Then the call of inputStats("carroll.txt");
should produce the following console output:
Line 1 has 30 chars
Line 2 has 41 chars
Line 3 has 0 chars
Line 4 has 31 chars
Line 5 has 26 chars
5 lines; longest = 41, average = 25.6
If the input file does not exist or is not readable, your function should print no output. If the file does exist, you may assume that the file contains at least 1 line of input.
Constraints: Your solution should read the file only once, not make multiple passes over the file data.
解答:
#include <iostream>
#include <fstream>
#include <string>
#include "console.h"
using namespace std;void inputStats(string filename);int main() {string filename = "carroll.txt";inputStats(filename);return 0;
}void inputStats(string filename) {ifstream input;input.open(filename);if (input.is_open()) {int totalLength = 0;int numLine = 0;int len;int longest = 0;string line = "";while (getline(input, line)) {numLine++;len = line.length();if (len > longest) {longest = len;}cout << "Line " << numLine << " has " << len << " chars" << endl;totalLength += len;}double avg = totalLength / double(numLine);cout << numLine << " lines; longest = " << longest << ", average = " << avg;}input.close();
}
3、hoursWorked
Write a function named hoursWorked
that accepts as a parameter a string representing an input file name of section leader data and computes and prints a report of how many hours each section leader worked. Each line of the file is in the following format, where each line begins with an employee ID, followed by an employee first name, and then a sequence of tokens representing hours worked each day. Suppose the input file named hours.txt
and contains the following lines:
123 Alex 3 2 4 1
46 Jessica 8.5 1.5 5 5 10 6
7289 Erik 3 6 4 4.68 4
For the above input file, the call of hoursWorked("hours.txt");
would produce the following output.
Alex (ID# 123) worked 10.0 hours (2.50/day)
Jessica (ID# 46) worked 36.0 hours (6.00/day)
Erik (ID# 7289) worked 21.7 hours (4.34/day)
Match the format exactly, including spacing. The names are in a left-aligned 9-space-wide field; the IDs are in a right-aligned 4-space-wide field; the total hours worked should show exactly 1 digit after the decimal; and the hours/day should have exactly 2 digits after the decimal. Consider using functions of the iomanip
library to help you.
解答:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iomanip>
#include "console.h"
#include "strlib.h"using namespace std;void hoursWorked(string filename);int main() {string filename = "hours.txt";hoursWorked(filename);return 0;
}void hoursWorked(string filename) {ifstream input;input.open(filename);// 是否能打开文件if (input.is_open()) {string line;// 循环按行获取数据while (getline(input, line)) {istringstream input2(line);string id;string name;int day = 0;double dayWorked;double totalWorked = 0;// 每行的数据获取input2 >> id;input2 >> name;while (input2 >> dayWorked) {totalWorked += dayWorked;day++;}// 按行格式化输出cout << name;cout << setfill(' ') << setw(9 - name.length() + 5) << "(ID# ";cout << setfill(' ') << setw(4) << id;cout << ") worked " << fixed << setprecision(1) << totalWorked;cout << " hours (" << fixed << setprecision(2) << totalWorked / day;cout << "/day)" << endl;}}input.close();
}
4、gridMystery
What is the grid state after the following code?
Grid<int> g(4, 3);
for (int r = 0; r < g.numRows(); r++) { // {{1, 2, 3},for (int c = 0; c < g.numCols(); c++) { // {1, 2, 3},g[r][c] = c + 1; // {1, 2, 3},} // {1, 2, 3}}
}for (int c = 0; c < g.numCols(); c++) {for (int r = 1; r < g.numRows(); r++) {g[r][c] += g[r - 1][c];}
}
解答:
{{1, 2, 3}, {2, 4, 6}, {3, 6, 9}, {4, 8, 12}}
5、knightCanMove
Write a function named knightCanMove
that accepts a reference to a Grid
of strings and two row/column pairs (r1, c1), (r2, c2) as parameters, and returns true
if there is a knight at chess board square (r1, c1) and he can legally move to empty square (r2, c2). For your function to return true
, there must be a knight at square (r1, c1), and the square at (r2, c2) must store an empty string, and both locations must be within the bounds of the grid.
Recall that a knight makes an "L" shaped move, going 2 squares in one dimension and 1 square in the other. For example, if the board looks as shown below and the board square at (1, 2) stores "knight"
, then the call of knightCanMove(board, 1, 2, 2, 4)
returns true
.
r\c | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
0 | "" | "" | "" | "" | "king" | "" | "" | "" |
1 | "" | "" | "knight" | "" | "" | "" | "" | "" |
2 | "" | "" | "" | "" | "" | "" | "" | "" |
3 | "" | "rook" | "" | "" | "" | "" | "" | "" |
4 | "" | "" | "" | "" | "" | "" | "" | "" |
5 | "" | "" | "" | "" | "" | "" | "" | "" |
6 | "" | "" | "" | "" | "" | "" | "" | "" |
7 | "" | "" | "" | "" | "" | "" | "" | "" |
解答:
bool knightCanMove(Grid<string> g, int r1, int c1, int r2, int c2) {if (g.inBounds(r1, c1) && g.inBounds(r2, c2)) { // 是否在有效范围内if (g[r1][c1] == "knight" && g[r2][c2] =="") { // 值是否正确// 移动方式是否正确bool canMove1 = (abs(r1 - r2) == 2 && abs(c1 - c2) == 1);bool canMove2 = (abs(r1 - r2) == 1 && abs(c1 - c2) == 2);if (canMove1 || canMove2) {return true;}}}return false;
}