Study Guide 2 s25
Study Guide 2 s25
Tong Yi
In this project, we display questions and answer them. If the answer is correct, we display true,
otherwise, we display false. This project can serve as a study guide for our courses or Civics (History
and Government) Questions for the Naturalization Test, as in https://www.uscis.gov/sites/default/
files/document/questions-and-answers/100q.pdf.
Warning:
3. Use solutions from ChatGPT or online tutoring websites like, but not limited to, chegg.com, violates
academic integrity and is not allowed.
2. Define function
void read_file(string fileName, Question ques[], int capacity, int& size);
Note that the return type is void, but the size of the array may be increased after reading a file, so
size needs to be passed by reference. See the & near type int for parameter size?
1
(b) Read a file whose name is saved in fileName.
(c) Read each question in the file, if the current size Question array ques does not equal to the
capacity of the array, add to the end of the array. Increase the current size by 1.
6. Define void display(Question ques[], int size) function, which displays the fields of each
question in array ques. You need to fill in the ... parts.
void display(Question ques[], int size) {
for (int i = ...; i < ...; ...) {
cout << i + 1 << endl; //start labeling from 1
int size = 0;
2
//TODO: call display function on array ques.
//Do not forget to pass the size of array ques,
//that is, the number of elements in ques,
//as the second parameter.
return 0;
}
Here is a sample output (the number of empty lines between fields might be a little different).
1
question: Given char arr[] = {’A’, ’B’, ’C’}, what is arr[1]?
answer: ’B’
explanation: arr[1] is the second element of array arr, which is ’B’ in this
example.
type: array
version: f24 v1
label: 1.1
2
question: Declare function increase, given an integer array arr with size many
elements, increase each element of the array by 1. Return type is void. Define
the function header (no implementation is needed).
answer: void increase(int arr[], int size);
explanation: (1) the first parameter is int arr[], the name of array arr, which
also implies the address of the first element of array.
(2) the second parameter represents the number of elements of the array.
3
question: Assume that n is properly declared and initialized. Write a statement to
declare lastDigit as an integer and initialize it to be the least significant
digit of integer n. Suppose n is 123, after the statement, lastDigit is 3.
answer: int lastDigit = n % 10;
explanation: (1) operator % is called remainder or modular operator.
(2) For example, 12 % 10 means the remainder when dividing 12 pens among 10
students, each student gets 1 pen, and there are 2 pens left.
(3) In general, n % 10 returns the last digit, or the rightmost digit (least
significant digit), of n.
(4) int lastDigit = n % 10; is a statement to declare lastDigit as an int and
initialize it by the last digit of n.
3
version: f24 v1
label: 1.3
29
question: What is the output for the following code?
#include <iostream>
using namespace std;
int main() {
int i = 1;
int j = 3;
foo(i, j);
cout << "i = " << i
<< ", j = " << j << endl;
return 0;
}
answer: i = 2, j = 3
explanation:
type: function; pass by value; pass by reference
version: s24 v1
label: 1.9
30
question: Write a condition to represent that char variable ch is none of the
following: ’a’, ’b’, or ’c’.
answer: (ch != ’a’ && ch != ’b’ && ch != ’c’)
explanation: another solution is (! (ch == ’a’ || ch == ’b’ || ch == ’c’))
type: condition
version: s24 v1
label: 1.10
4
2 Task B: more functions
The goal is to organize the tasks into functions, each concentrate on a task. In this way, we can unit test
a function before moving to the next.
Here is an outline.
2. Extract types from type field of Question, which is separated by semicolons (symbol ;).
3. The type field of a question may involve more than one type. As a result, we need to use an array
to hold each type.
(a) If a type is
integer division; arithmetic
Then the returned array has two elements: integer division and arithmetic.
(b) If a type is
integer division; arithmetic; remainder
Then the returned array has three elements: integer division, arithmetic and remainder.
4. Then add the types to an array of strings. Make sure that the array is sorted.
In this task, we define functions, let each function concentrate on a task, then main function calls the
key functions.
1. Why do we need the function? When we extract possible types from type field of a question, the
extracted result might contain spaces before the first non-space character and the after the last non-
space character, to avoid adding " array " and "array" to the array at the same time, we only add
a type without those extra spaces.
(a) Find out the index of first non-space character of a string using find_first_not_of method.
Or, search the string from the first character to the last character until there is no more character
in the string or the first non-space character is encountered. Save that index.
5
(b) Find the index of the last non-space character of a string using find_last_not_of method.
Or, search the string backwards from the last character to the first one until there is no more
character or a non-space character is found. Save the index.
(c) Use substr method to find out the substring between those two indices (inclusive). Note that
the first parameter of substr method in C++ is the index of the first character of the resulting
substring in the original string, and the second parameter is the number of characters in the
substring.
1. Refer to Lab 7A for help. This function belongs a category called counting. Given an array, find out
the number of elements of a feature (equal to something, longer than or larger than something, and
so on).
2. A string can be thought as an array of characters (type char) with methods to find out number of
elements using its length or size method.
Warning: an array of C++ is not a class, so dot operator does not apply. Specifically, the size of an
array needs to be given explicitly in a function.
In general, codes for array can be modified to work on similar problems for strings.
3. Call the above function to find out the number of semicolons of the type field of a question to find
out the number of elements in a dynamically allocated array in function extract_type.
If the number of semicolons is n, then the number of types in this type field is n+1. For example, if
there are two semicolons like the type field integer division; arithmetic; remainder, then the
number of individual types is 3.
We need this number as the size to apply for a dynamically allocated array of strings to hold the
types in that type field.
1. Need a parameter to hold the number of elements in this array. Since a function in C++ can return
at most one value, we need to work around this limit by pass a parameter by reference as shown in
int& num_types_curr_item, where & after int means the following parameter pass by reference.
Pass by reference means the formal parameter is the original actual parameter (aka argument).
Whatever change made on the formal parameter in the function is carried back to its caller.
6
By contrast, pass by value – no & after the type in formal parameters in function header – means
to a formal parameter is the duplicated copy of the actual parameter. Whatever changes made on
the duplicated copy, it will not affect the actual parameter in the caller function, unless the value is
returned.
Note that if a formal parameter is an array, which implies the address of the first element of the
array, then the contents of the array can be modified. Reason: each element has a unique address.
Once the address is know, we can access and may change the elements.
(a) Call count_occurrences to find out number of semicolon symbol (;) in type, add 1 to this
value (why?) and save it to num_types_curr_item.
(b) Apply a dynamically allocated array of strings with size num_types_curr_item.
(c) Extract the corresponding types in type separated by semicolon (;).
(d) Trim those obtained types and save them to the dynamically allocated array.
(e) Return the dynamically allocated array. No need to sort the array.
i. For example, if the argument for type is integer division; array; remainder, apply
a dynamically allocated array of size 3. Initialize with elements "integer division",
"array", and "remainder". Return the dynamically allocated array.
3. Students may wonder what the difference of statically allocated memory and dynamically allocated
memory are.
(a) Statically allocated array memory, whose size is a const int, is allocated in the stack or a separate
data segment (also known as the static memory region).
(b) Dynamically allocated array memory, whose size can be an int variable, is allocated from heap.
(c) Statically allocated memory is released once a function finishes and returns to its caller. So a
statically allocated array declared and initialized in a callee function cannot return to its caller.
(d) Dynamically allocated array applied in a callee function can be carried back to its caller. That
is, dynamically allocated memory allocated in a callee function can be kept even after the callee
function finishes.
(e) Related example: you may rent a textbook for 120 days. After the expiration date, the book
is returned to the publisher, whether you like it or not. The publisher removes the book from
your bookshelf.
This is like statically allocated memory is released back to the operating system automatically
when the function ends.
On the other hand, my textbook came from a different branch (memory) of the publisher
(system). My book is like dynamically allocated memory. I can keep it until I no longer need
the book and then return it to the publisher. The return is initialized from me.
It is like I use new (fill an application) to apply for an instructor book from the publisher. When
I no longer need the book (memory), I use delete (remove the book from my bookshelf) to
return it.
7
2.4 Define function insert order unique
void insert_order_unique(string types[], int type_capacity, int& type_count, string
toAdd);
These are parameters.
2. type_capacity: capacity of array types, that is, the maximum number of elements array types can
hold.
5. Goal: insert toAdd to types if there the string does not appear in the array and the array is not full.
The array is sorted before insertion and need to be sorted after insertion. Here are some hints.
(a) If the array is full, that is, type_count is larger than or equal to type_capacity, do nothing
and return.
(b) Traverse through the array until the end is reached or the elements are smaller than toAdd.
String a is smaller than string b means a appears in a dictionary before b. For example,
"success" is smaller than "work" since "success" appears before "work" in dictionary.
(c) If the end is reached, that means all current elements are smaller than toAdd, add toAdd to the
end.
(d) Otherwise, there is an element in the array is larger than or equal to toAdd.
i. If they are equal, no need to add a type already saved in the array, do nothing and return
to the caller.
ii. Otherwise, move the element in the array and all its right side neighbor one spot to the
right to make room for toAdd.
iii. Put toAdd to the correct position.
iv. After toAdd is inserted, increase type_count by 1.
(a) Learn bubble sort on 3/6/25. Key idea: swap out-of-order adjacent pairs from beginning to the
end, doing so would put the largest element to the rightmost position.
i. Repeat the above process to put the second largest element to the second-to-rightmost
position. Keep the process until n − 1 out of n elements are in their correct position after
sorting, where n is the number of element of the array.
ii. In Problem 1.9 of midterm of Spring 25, we test bubble sort in descending order.
(b) On 3/10/25, we share ideas of homework E5.14 and E5.15, to put four elements a, b, c, and
d in order.
i. First, if a is larger than b, we swap a and b. Now a is the smaller of a and b.
8
ii. Second, if a is larger than c, swap a and c. Now a is the smallest of a, b, and c.
iii. Third, if a is larger than d, swap a and d. Now a is the smallest of a, b, c, and d.
iv. Repeat the above process to work with b, c, and d.
v. In general, select the smallest element of an array and put it in the first position of the
array. Select the second smallest element of the array and put it in the second position of
the array, and so on. This is the key idea of selection sort.
(c) In this project, we learn insertion sort, insert an element to a sorted array and keep it sorted
after insertion.
(d) Bubble sort, selection sort, and insert sort are not efficient. The most efficient sorting algorithm
is quick sort.
2.5 Define function insert order unique for types of each question
void insert_order_unique(string types[], int type_capacity, int& type_count, Question
ques[], int ques_size);
1. You may notice the function has exact the same name as the above function but the parameter list
is different. This is called function overload. That is, two or more functions have
9
(a) Call the following function to extract each type from type field of a question.
string* extract_type(string type, int& num_types_curr_item);
(b) Call the following version to insert each type to array types.
void insert_order_unique(string types[], int type_capacity, int& type_count,
string
toAdd);
(c) Do not forget to release dynamically allocated memory returned from extract_type function.
Afterwards, types save all types, once and exactly once, from the type field of all questions in
sorted order.
2. Print items from sorted array types, where the label of the first type starts from label 1. The label
of the last type is type_count.
3. Ensure to choose an integer in [0, type_count], where both ends are included. If the number is
out of range, prompt the user to select again.
4. If a user chooses 0, then return an empty string reprsenting all types, otherwise, return the corre-
sponding item in array types. Note that the label starts from 1, but the index starts from 0, so
there is an offset by 1.
2. Choose a random integer in [0, numToRandomize). That is, a random integer that is at least 0 but
is smaller than numToRandomize. That is a valid index of the sub-array of the first numToRandomize
elements.
10
3. The above step is like to choose the element indexed at that generated random number. To avoid
that element to be chosen again, swap the element with the element indexed at numToRandomize -1,
the last element in the sub-array with the first numToRandomize elements.
4. Reduce numToRandomize by 1.
5. Repeat the above process by going back to Step 2 until numToRandomize is reduced to 1.
1. Print out the number of correctly answered questions, saved in parameter numCorrect in a line.
2. Calculate and and print the percentage based on numCorrect and numQuestions. The latter is the
total number of questions worked.
3. If percentage is at least 90%, print "excellent", otherwise, if percentage is at least 80%, print
"good", otherwise, if percentage is at least 70%, print "pass", otherwise, print "please ask help ASAP".
#include <iostream>
11
#include <string>
using namespace std;
int main() {
cout << "Enter your age: ";
int age;
cin >> age;
1. To finish input, need to enter return key, which is \n new line character.
3. If statement getline(cin, stringVariable); follows, then getline statement takes everything be-
fore and at \n. So it is like to stringVariable is set to be an empty string. This might not be what
we want.
#include <iostream>
#include <string>
using namespace std;
int main() {
cout << "Enter your age: ";
int age;
cin >> age;
12
cout << "Enter your major: ";
string major;
getline(cin, major); //major might contain spaces
cout << "Your age is " << age << endl;
cout << "Your major is " << major << endl;
return 0;
}
3. Both files have main functions. However, each C++ project can have only one main function.
4. To use the main function from unit_test.cpp, change the name of function main of checkAnswer_function_
to be main2 when we run unit test for functions in the above source code.
In terminal, run the following command with return key.
13
//4. Both files have main functions. However, each C++ project can have only one main
function.
//5. To run the main function in unit_test.cpp, change the name of function main of
checkAnswer_function_rand.cpp to be main2.
//6. g++ -std=c++20 unit_test.cpp -o test
//7. If there is no error in unit_test.cpp, a runnable file called test is generated,
run the following commands with return key to test each function.
//./test 1
//or
//./test 2
//./test 3
//...
//./test c
//test answer_by_type
Question q1;
q1.text = "Given char arr[] = {’A’, ’B’, ’C’}, what is arr[1]?";
q1.answer = "’B’";
q1.explanation = "arr[1] is the second element of array arr, which is ’B’
in this example.";
q1.version = "f24 v1";
q1.label = "1.1";
q1.type = "array";
Question q2;
q2.text = "Declare function increase, given an integer array arr with size
many elements, increase each element of the array by 1. Return type is void. Define
the function header (no implementation is needed).";
q2.answer = "void increase(int arr[], int size);";
q2.explanation = "(1) the first parameter is int arr[], the name of array
arr, which also implies the address of the first element of array.\n(2) the second
parameter represents the number of elements of the array.";
q2.version = "f24 v1";
q2.label = "1.2";
q2.type = "function; array";
14
Question q3;
q3.text = "Assume that n is properly declared and initialized. Write a
statement to declare lastDigit as an integer and initialize it to be the least
significant digit of integer n. Suppose n is 123, after the statement, lastDigit is
3.";
q3.answer = "int lastDigit = n % 10;";
q3.explanation = "(1) operator % is called remainder or modular operator.\n
(2) For example, 12 % 10 means the remainder when dividing 12 pens among 10 students
, each student gets 1 pen, and there are 2 pens left.\n(3) In general, n % 10
returns the last digit, or the rightmost digit (least significant digit), of n.\n(4)
int lastDigit = n % 10; is a statement to declare lastDigit as an int and
initialize it by the last digit of n.";
q3.version = "f24 v1";
q3.label = "1.3";
q3.type = "arithmetic; modular; remainder";
Question q4;
q4.text = "What is the output?\n\nstring tens_name(int n);\n\nint main() {\
n cout << tens_name(82) << endl;\n return 0;\n}\nstring tens_name(int n) {\n
if (n < 20 || n > 99)\n return \"\";\n\n string names[] = {\"\", \"\",
\"twenty\", \"thirty\", \"forty\", \"fifty\", \"sixty\", \"seventy\", \"eighty\", \"
ninety\"};\n return names[n / 10];\n}";
q4.answer = "eighty";
q4.explanation = "(1) When calling tens_name(82), n in tens_name is
initialized to be 82.\n(2) Since 82 is not less than 20 or 82 is not larger than 99,
no return \"\";\n(3) 82 / 10 is integer division. It is like to divide 82 pens
among 10 students, each student get 8 pens. So 82 / 10 returns 8.\n(4) names[n / 10]
is names[82 / 10], which is names[8].\n\nindex 0 1 2 3 4
5 6 7 8\n\nelement
+--+--+--------+--------+-------+-------+-------+---------+--------+...\n
|\"\"|\"\"|\"twenty\"|\"thirty\"|\"forty\"|\"fifty\"|\"sixty\"|\"seventy\"|\"eighty
\"|...\n +--+--+--------+--------+-------+-------+-------+---------+--------+...\n\n
(5) The return of tens_name(82) is \"eighty\".\n(6) In main function, print
tens_name(82), so the print out is \"eighty\" (without quotes).";
q4.version = "f24 v1";
q4.label = "1.4";
q4.type = "integer division; array";
switch (*argv[1]) {
case ’1’: {
const int CAPACITY = 1000;
15
Question ques[CAPACITY]; //question array
read_file_into_array(ques, CAPACITY);
break;
}
case ’2’: {
//test when capacity is reached
const int CAPACITY = 25;
Question ques[CAPACITY]; //question array
read_file_into_array(ques, CAPACITY);
break;
}
case ’3’: {
//test trim
//the string is given randomly in gradescript
cout << "Enter a string: ";
string inputStr;
getline(cin, inputStr);
//cout << "input String: " << inputStr << endl;
//Run ./test 3
//sample input / output
//Enter a string: Hello, World
//"Hello, World"
}
case ’4’: {
//test string* extract_type(string type, int& num_types_curr_item)
string types[] = {"function; array",
"arithmetic; modular; remainder", "integer division; array
" };
for (string type : types) {
int num_types_curr_item = 0;
string* pStr = extract_type(type, num_types_curr_item);
for (int i = 0; i < num_types_curr_item; i++)
cout << pStr[i] << endl;
16
pStr = nullptr;
}
break;
//run
//./test 4
//Sample input/output:
//function
//array
//arithmetic
//modular
//remainder
//integer division
//array
}
case ’5’: {
//test int count_occurrences(string str, char ch)
string strs[] = {"integer division; array", "arithmetic; modular; remainder
"};
int size = sizeof(strs) / sizeof(strs[0]);
for (int i = 0; i < size; i++) {
cout << count_occurrences(strs[i], ’;’) << endl;
cout << count_occurrences(strs[i], ’a’) << endl;
}
break;
//Run ./test 5 in terminal
//Here is the sample input / output:
//1
//2
//2
//3
}
case ’6’: {
//insert_order_unique(string types[], int type_capacity, int& type_count,
string toAdd)
const int TYPE_CAPACITY = 30;
string types[TYPE_CAPACITY];
int type_count = 0;
17
"array"
};
18
ques[8].type = "function";
ques[9].type = "condition";
break;
case ’8’: {
const int SIZE = 10;
Question ques[SIZE];
for (int i = 0; i < SIZE; i++) {
string str = "1.";
ques[i].label = str + to_string(i+1);
}
randomize(ques, SIZE);
break;
//output in Mac when no srand setting up
//Run ./test 8 with return key in terminal
//1.4
19
//1.9
//1.6
//1.1
//1.3
//1.5
//1.7
//1.2
//1.10
//1.8
}
case ’9’: {
answer_by_type(ques, size, "array");
break;
20
//number of tries: 1
//true
//
//number of correct problems: 3
//percentage of correct: 100%
//excellent
}
case ’a’: {
answer_by_type(ques, size, "");
break;
21
// cout << tens_name(82) << endl;
// return 0;
//}
//string tens_name(int n) {
// if (n < 20 || n > 99)
// return "";
//
// string names[] = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy
", "eighty", "ninety"};
// return names[n / 10];
//}
//Enter you answer: eighty
//number of tries: 1
//true
//
//number of correct problems: 4
//percentage of correct: 100%
//excellent
}
case ’b’: {
string types[] = {
"arithmetic",
"array",
"condition",
"function",
"integer division",
"modular",
};
int size = sizeof(types) / sizeof(types[0]);
22
//3. condition
//4. function
//5. integer division
//6. modular
//Enter a type: 1
//chosen type: "arithmetic"
//
//
//Test when users choose 0. ALL TYPES
//
//0. ALL TYPES
//1. arithmetic
//2. array
//3. condition
//4. function
//5. integer division
//6. modular
//Enter a type: 0
//chosen type: ""
}
case ’c’: {
//void feedback(int numCorrect, int numQuestions)
int numQuestions = 7;
for (int numCorrect = 4;
numCorrect <= numQuestions;
numCorrect++)
feedback(numCorrect, numQuestions);
break;
//sample input/output
//number of correct problems: 4
//percentage of correct: 57.1429%
//please ask help ASAP
//number of correct problems: 5
//percentage of correct: 71.4286%
//pass
//number of correct problems: 6
//percentage of correct: 85.7143%
//good
//number of correct problems: 7
//percentage of correct: 100%
23
//excellent
}
}
return 0;
}
24
#include <string> //starts_with, c++20
#include <climits> //INT_MAX
#include <string.h> //c-string, strlen(...)
#include <cctype> //isspace
struct Question {
string text; //question text
string answer;
string explanation;
string version;
string type;
string label;
};
25
int main() {
//Declare CAPACITY as a const int with value 1000.
const int CAPACITY = 1000;
//Declare ques as an array of Questions
//that hold CAPACITY many Questions.
Question ques[CAPACITY]; //question array
//Declare size to be 0.
int size = 0;
read_file("cs135_midterm_f24_v1.txt", ques, CAPACITY, size);
read_file("cs135_midterm_f24_v2.txt", ques, CAPACITY, size);
read_file("cs135_midterm_s24_v1.txt", ques, CAPACITY, size);
//optional
//display(ques, size);
//TODO: call answer_by_type with the return from the above statement.
return 0;
}
if (fin.fail()) {
cerr << fileName << " cannot be opened" << endl;
exit(1);
}
string text;
string answer;
string explanation;
string version;
26
string type; //type of the code
string label;
string line;
line = "";
while (getline(fin, line) && !line.starts_with("answer: ") )
text += ’\n’ + line;
if ( line.starts_with("answer: ") ) {
answer = line.substr(strlen("answer: "));
line = "";
while (getline(fin, line) && !(line.starts_with("question: ") || line.
starts_with("version: ") || line.starts_with("label: ") || line.starts_with("type: "
) || line.starts_with("explanation: ") ) )
answer += line + ’\n’;
//use do-while statement, otherwise, the entry following answer: is not read
do {
if (line.starts_with("version: "))
version = line.substr(strlen("version: "));
else if (line.starts_with("type: "))
type = line.substr(strlen("type: "));
else if (line.starts_with("label: "))
label = line.substr(strlen("label: "));
27
line = "";
} while (getline(fin, line) && !(line.starts_with("question: ")));
//TODO: if size is larger or equal to capacity, close the file and return.
text = "";
answer = "";
version = "";
type = "";
label = "";
explanation = "";
}
}
fin.close();
}
28
}
}
29