打卡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;
}