Compare commits

...

8 Commits

Author SHA1 Message Date
JamesFlare1212
0dd22a2682 add solution of hw1 2025-01-20 19:48:59 -05:00
Jidong Xiao
f40714a01e add member init list 2025-01-20 19:48:59 -05:00
Jidong Xiao
944a2129a6 notes above destructor order 2025-01-20 19:48:59 -05:00
Jidong Xiao
237db36f55 copy constructor syntax 2025-01-20 19:48:59 -05:00
Jidong Xiao
1aace1130f revising notes 2025-01-20 19:48:59 -05:00
Jidong Xiao
9ba953f648 assignment operator and destructor 2025-01-20 19:48:59 -05:00
Jidong Xiao
5bdf6b8b7e renaming 2025-01-20 19:48:59 -05:00
Jidong Xiao
c393ba86a6 revising rubric 2025-01-20 19:48:59 -05:00
18 changed files with 577 additions and 25 deletions

22
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "nyplaylists",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}", // 指向你的可执行文件
"args": [
"playlist_tiny2.txt",
"actions2.txt",
"output.txt",
"debug"
],
"cwd": "${fileDirname}",
"environment": [],
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"preLaunchTask": "C/C++: g++ build active file"
}
]
}

55
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,55 @@
{
"files.associations": {
"fstream": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
}
}

5
.vscode/tasks.json vendored
View File

@@ -6,8 +6,11 @@
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-std=c++17",
"-Wall",
"-Wextra",
"-g",
"${file}",
"*.cpp",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],

View File

@@ -342,15 +342,15 @@ A: Same as Uber. One decimal place. Just trim it. For example, if the distance i
## Program Requirements & Submission Details
In this assignment, you are required to use a vector to store all drivers, and use a vector to store all riders. You are NOT allowed to use any data structures we have not learned so far, especially std::list.
In this assignment, you are required to use a vector to store all drivers, and use a vector to store all riders. You are NOT allowed to use any data structures we have not learned so far, especially std::list. Your program should involve the definition of at least two classes that have their own .h and .cpp files, named appropriately.
Use good coding style when you design and implement your program. Organize your program into functions:
dont put all the code in main! Be sure to read the [Homework Policies](https://www.cs.rpi.edu/academics/courses/spring24/csci1200/homework_policies.php) as you put the finishing touches on your solution. Be sure to make up new test cases to fully debug your program and dont forget
dont put all the code in main! Be sure to read the [Homework Policies](https://www.cs.rpi.edu/academics/courses/spring25/csci1200/homework_policies.php) as you put the finishing touches on your solution. Be sure to make up new test cases to fully debug your program and dont forget
to comment your code! Use the provided template [README.txt](./README.txt) file for notes you want the grader to read.
You must do this assignment on your own, as described in the [Collaboration Policy & Academic Integrity](https://www.cs.rpi.edu/academics/courses/spring24/csci1200/academic_integrity.php) page. If you did discuss the problem or error messages, etc. with anyone, please list their names in your
You must do this assignment on your own, as described in the [Collaboration Policy & Academic Integrity](https://www.cs.rpi.edu/academics/courses/spring25/csci1200/academic_integrity.php) page. If you did discuss the problem or error messages, etc. with anyone, please list their names in your
README.txt file.
**Due Date**: 01/25/2024, Thursday, 10pm.
**Due Date**: 01/23/2025, Thursday, 10pm.
## Rubric
@@ -362,6 +362,8 @@ README.txt file.
- No reflection. (-1)
- OVERALL CLASS DECLARATION & IMPLEMENTATION AND CODING STYLE (Good class design, split into a .h and .cpp file. Functions > 1 line are in .cpp file. Organized class implementation and reasonable comments throughout. Correct use of const/const& and of class method const. ) (6 pts)
- No credit (significantly incomplete implementation) (-6)
- Does not successfully declare & use any new classes. (-6)
- Only declares/uses a single class. (-5)
- Putting almost everything in the main function. It's better to create separate functions for different tasks. (-2)
- Improper uses or omissions of const and reference. (-1)
- Function bodies containing more than one statement are placed in the .h file. (okay for templated classes) (-2)
@@ -370,7 +372,7 @@ README.txt file.
- Poor file organization: Puts more than one class in a file (okay for very small helper classes) (-1)
- Poor choice of variable names: non-descriptive names (e.g. 'vec', 'str', 'var'), single-letter variable names (except single loop counter), etc. (-2)
- Uses global variables. (-1)
- Contains useless comments like commented-out code, terminal commands, or silly notes. (-1)
<!-- - Contains useless comments like commented-out code, terminal commands, or silly notes. (-1)-->
- DATA REPRESENTATION (Must use vectors for the implementation.) (5 pts)
- No credit (significantly incomplete implementation). (-5)
- Does not use std::vector to store drivers or riders. (-5)

View File

@@ -10,14 +10,14 @@ List the names of everyone you talked to about this assignment
LMS, etc.), and all of the resources (books, online reference
material, etc.) you consulted in completing this assignment.
< insert collaborators / resources >
Qijun Lu, Google, Stack Overflow, W3School
Remember: Your implementation for this assignment must be done on your
own, as described in "Academic Integrity for Homework" handout.
ESTIMATE OF # OF HOURS SPENT ON THIS ASSIGNMENT: 2 hr
ESTIMATE OF # OF HOURS SPENT ON THIS ASSIGNMENT: 16 hr
@@ -27,6 +27,7 @@ ESTIMATE OF # OF HOURS SPENT ON THIS ASSIGNMENT: 2 hr
MISC. COMMENTS TO GRADER:
Optional, please be concise!
Ignore the debug codes. To enable it, take `debug` as the fourth argument.
## Reflection and Self Assessment
@@ -38,4 +39,8 @@ What parts of the assignment did you find challenging? Is there anything that
finally "clicked" for you in the process of working on this assignment? How well
did the development and testing process go for you?
< insert reflection >
During this homework, I used the experience from CS1, which create debugging
output frequently. The hardest part is handle strings. Merge, split, remove,
add. I referenced many examples from internet. The language server in VSCode
also help, it shows a short tip about why it's an error. Anyhow, I believe I
can do better next time.

Binary file not shown.

View File

@@ -1,9 +1,246 @@
//import some basic library
//An implement of CSCI-1200 HW1 Spotify Playlists
//Author: Jinshan ZHou
//Date: 2025/1/16
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <fstream>
//#include <algorithm>
//#include <sstream>
//#include <cmath>
//#include <cstdlib>
int main() {
std::cout << "Hello, World!" << std::endl;
std::string get_text(const std::string &fname) {
//load a text file into a string
std::ifstream inFile(fname);
//check if file exists
if (!inFile) {
std::cout << "Error: File not found" << std::endl;
return "";
}
std::string text;
std::string line;
while (std::getline(inFile, line)) {
text += line;
text += "\n";
}
inFile.close();
return text;
}
std::vector<std::string> load_list(const std::string &fname) {
//load a text file into a vector of strings
std::string text = get_text(fname);
std::vector<std::string> lines;
std::size_t start = 0;
std::size_t end = 0;
while ((end = text.find('\n', start)) != std::string::npos) {
lines.push_back(text.substr(start, end - start));
start = end + 1;
}
if (start < text.size()) {
lines.push_back(text.substr(start));
}
return lines;
}
void debug_print(const std::string &msg) {
std::cout << "DEBUG: " << msg << std::endl;
}
bool is_all_digits(const std::string& s) {
//check if string is int
for (char c : s) {
if (!std::isdigit(static_cast<unsigned char>(c))) {
return false;
}
}
return !s.empty();
}
std::vector<std::string> tokenizer(const std::string &s) {
//split string into tokens
std::vector<std::string> tokens;
std::string token;
for (char c : s) {
if (c == ' ') {
tokens.push_back(token);
token = "";
} else {
token += c;
}
}
tokens.push_back(token);
return tokens;
}
bool check_in_list (const std::string &s, const std::vector<std::string> &list) {
//check if string is in list
for (std::string item : list) {
if (s == item) {
return true;
}
}
return false;
}
void remove_in_list (const std::string &s, std::vector<std::string> &list) {
//remove string from list
if (!check_in_list(s, list)) {return;}
for (int i = 0; i < list.size(); i++) {
if (list[i] == s) {
list.erase(list.begin() + i);
return;
}
}
}
int get_current (std::vector<std::string> &playlist) {
//return the index of the string has word current at the end
for (int i = 0; i < playlist.size(); i++) {
if (playlist[i].find("current") != std::string::npos) {
return i;
}
}
return -1;
}
std::string build_song (const std::vector<std::string> &tokens, const int &start, const int &end) {
//build string from tokens w/ start and end positions
std::string song;
for (int i = start; i < end; i++) {
song += tokens[i];
if (i != end - 1) {
song += " ";
}
}
return song;
}
void write_list(const std::string &fname, const std::vector<std::string> &list) {
//write list to file
std::ofstream outFile(fname);
for (std::string line : list) {
outFile << line << std::endl;
}
outFile.close();
}
int main(int argc, char *argv[]) {
//take 3 arguments
if (argc < 3) {
std::cout << "Error: Not enough arguments" << std::endl;
return 1;
}
//load arguments
std::string playlist_fname = argv[1];
std::string action_list_fname = argv[2];
std::string output_fname = argv[3];
//turn on debug mode is last argument is debug
bool debug_mode = false;
if (std::string(argv[argc - 1]) == "debug") {
debug_mode = true;
}
if (debug_mode) {
debug_print("playlist_fname =" + playlist_fname);
debug_print("action_list_fname =" + action_list_fname);
debug_print("output_fname =" + output_fname);
}
//load working files
std::vector<std::string> playlist = load_list(playlist_fname);
std::vector<std::string> action_list = load_list(action_list_fname);
//get current playing song id
int current_song_id = get_current(playlist);
if (debug_mode) {
debug_print("current_song_id = " + std::to_string(current_song_id));
}
//execute actions
for (std::string command : action_list) {
if (debug_mode) {
debug_print("Command = " + command);
}
//split command into tokens
std::vector<std::string> tokens = tokenizer(command);
if (tokens[0] == "next") {
current_song_id = get_current(playlist);
//remove "current" tag
playlist[current_song_id].erase(playlist[current_song_id].length() - 8);
if (current_song_id == playlist.size() - 1) {
current_song_id = 0;
} else {
current_song_id++;
}
//update current song
playlist[current_song_id] += " current";
}
if (tokens[0] == "previous") {
current_song_id = get_current(playlist);
//remove "current" tag
playlist[current_song_id].erase(playlist[current_song_id].length() - 8);
if (current_song_id == 0) {
current_song_id = playlist.size() - 1;
} else {
current_song_id--;
}
//update current song
playlist[current_song_id] += " current";
}
if (tokens[0] == "add") {
std::string song;
song = build_song(tokens, 1, tokens.size());
playlist.push_back(song);
if (debug_mode) {
debug_print("Added = " + song);
}
}
if (tokens[0] == "remove") {
std::string song;
song = build_song(tokens, 1, tokens.size());
remove_in_list(song, playlist);
if (debug_mode) {
debug_print("Removed = " + song);
}
}
if (tokens[0] == "move") {
if (is_all_digits(tokens.back())){
//set target position
int dest = std::stoi(tokens.back());
//build song from tokens
std::string song;
song = build_song(tokens, 1, tokens.size() - 1);
//fix song name if it has current tag
if (!check_in_list(song, playlist) &&
!check_in_list(song + " current", playlist)) {continue;}
else if (check_in_list(song + " current", playlist)) {
song += " current";
}
remove_in_list(song, playlist);
playlist.insert(playlist.begin() + dest - 1, song);
if (debug_mode) {
debug_print("Moved " + song + " to " + std::to_string(dest));
}
} else {
std::cout << "ERROR: Missing move destination" << std::endl;
continue;
}
}
}
//write back file
write_list(output_fname, playlist);
if (debug_mode) {
debug_print("Playlist Content:");
for (std::string line : playlist) {
std::cout << line << std::endl;
}
}
return 0;
}

View File

@@ -0,0 +1,18 @@
"Someone Like You" Adele
"Shallow" Lady Gaga, Bradley Cooper
"Happier" Marshmello
"Blinding Lights" The Weeknd
"Levitating" Dua Lipa
"Uptown Funk" Mark Ronson, Bruno Mars
"Imagine" John Lennon
"Bad Romance" Lady Gaga current
"Hotel California" Eagles
"Bohemian Rhapsody" Queen
"Stairway to Heaven" Led Zeppelin
"Smells Like Teen Spirit" Nirvana
"Like a Rolling Stone" Bob Dylan
"Hey Jude" The Beatles
"Perfect" Ed Sheeran
"Rolling in the Deep" Adele
"Bad Guy" Billie Eilish
"Dance Monkey" Tones and I

View File

@@ -28,9 +28,9 @@ word processors -> save as/export to PDF, or Google Docs -> Download -> PDF s
Computers, cell-phones, smart watches, calculators, music players, etc. are not permitted. Please do not bring your laptop, books, backpack, etc. to the exam room leave everything in your dorm room. Unless you are coming directly from another class or sports/club meeting.
Do not bring your own scratch paper. We will provide scratch paper. -->
# Lecture 4 --- Classes II: Sort, Non-member Operators
# Lecture 4 --- Classes II: Copy Constructor, Assignment Operator, Destructor, and Non-member Operators
- Classes in C++;
<!--- Classes in C++;
- Non-member operators
## 4.1 C++ Classes
@@ -72,28 +72,238 @@ will sort Date objects into chronological order.
- Can you solve leetcode problem 905 with an overloaded operator &lt;, and make this overloaded operator &lt; a non-member function?
- Can you solve leetcode problem 905 with an overloaded operator &lt;, and make this overloaded operator &lt; a member function?
- Can you solve leetcode problem 905 with an overloaded operator &lt;, and make this overloaded operator &lt; a member function, plus make the definition of this member function outside of the class definition?
-->
## 4.1 Member Initializer List in C++
## 4.4 Copy Constructor
A **member initializer list** is a special syntax in C++ that allows class members to be initialized directly before the constructor body executes. It is used in the constructor definition, right after the parameter list and before the body of the constructor.
### Syntax
```cpp
ClassName(parameter_list) : member1(value1), member2(value2), ... {
// Constructor body (optional, can be empty)
}
```
### Example
```cpp
#include <iostream>
#include <string>
class MyClass {
private:
std::string name;
public:
// Constructor with member initializer list
MyClass(const std::string& initName) : name(initName) {}
void display() const {
std::cout << "Name: " << name << std::endl;
}
};
int main() {
MyClass obj("Alice");
obj.display(); // Output: Name: Alice
return 0;
}
```
## 4.2 Copy Constructor
- A copy constructor is a constructor which is used to create a new object as a copy of an existing object of the same class.
- Copy constructors are automatically generated by the compiler if you do not provide one explicitly. However, if your class uses dynamic memory (which will be covered in next lecture), and you want a copy constructor, then you must write your own copy constructor.
<!-- - Copy constructors are automatically generated by the compiler if you do not provide one explicitly. However, if your class uses dynamic memory (which will be covered in next lecture), and you want a copy constructor, then you must write your own copy constructor.-->
- Copy constructors get called when you create a new object by copying an existing object using the assignment operator (=), or when you pass an object by value to a function.
- Still use the *Date* class as an example, if you have defined your own copy constructor whose prototype is like:
### Copy Constructor Syntax
```cpp
Date(const Date &other);
ClassName(const ClassName& other);
```
and when you have the following lines of code:
### Copy Constructor Example
```cpp
Date a;
Date b = a;
#include <iostream>
class MyClass {
private:
int value;
public:
// Constructor
MyClass(int val) : value(val) {}
// Copy Constructor
MyClass(const MyClass& other) {
value = other.value;
std::cout << "Copy Constructor Called!" << std::endl;
}
void display() const {
std::cout << "Value: " << value << std::endl;
}
};
int main() {
MyClass obj1(10);
MyClass obj2 = obj1; // Copy constructor is called here
obj2.display(); // Output: Value: 10
return 0;
}
```
The first statement will call the default constructor, while the second statement will call the copy constructor.
## 4.3 Assignment Operator
## 4.5 Exercises
- The assignment operator (=) is used to copy the values from one object to another after both objects have been created.
### Assignment Operator Syntax:
```cpp
ClassName& operator=(const ClassName& other);
```
### Assignment Operator Example:
```cpp
#include <iostream>
#include <string>
using namespace std;
class MyClass {
private:
string name; // Using a standard string (no pointers)
public:
MyClass(const string& initName) : name(initName) {}
MyClass& operator=(const MyClass& other) {
name = other.name; // Copy data
return *this;
}
void print() const { cout << "Name: " << name << endl; }
};
int main() {
MyClass obj1("Object1");
MyClass obj2("Object2");
obj1 = obj2; // Assignment operator invoked
obj1.print(); // Output: Name: Object2
return 0;
}
```
All C++ class objects have a special pointer defined called **this** which simply points to the current class object, and the expression **this* is a reference to the class object.
Assignment operators of the form:
```cpp
obj1 = obj2;
```
are translated by the compiler as:
```cpp
obj1.operator=(obj2);
```
- Cascaded assignment operators of the form:
```cpp
obj1 = obj2 = obj3;
```
are translated by the compiler as:
```cpp
obj1.operator=(obj2.operator=(obj3));
```
- Therefore, the value of the assignment operator (obj2 = obj3) must be suitable for input to a second assignment operator. This in turn means the result of an assignment operator ought to be a reference to an object.
**Note**: In C++, the assignment operator is used for assignment after an object has already been created. And because of that, the following two code snippets behave differently.
```cpp
myClass A = B;
```
This one line will invoke the copy constructor, rather than the assignment operator. And this behavior is called copy initialization.
```cpp
myClass A;
A = B;
```
These two lines will: the first line creates the object A, and the second line invokes the assignment operator.
## 4.4 Destructor (the “constructor with a tilde/twiddle”)
A **destructor** is a special member function automatically called when an object goes out of scope or is explicitly deleted.
<!-- - The destructor is responsible for deleting the dynamic memory “owned” by the class.
- The syntax of the function definition is a bit weird. The ~ has been used as a bit-wise inverse or logic negation in other contexts.-->
### Destructor Syntax
```cpp
~ClassName();
```
### Destructor Example
```cpp
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "Constructor called" << std::endl; }
~MyClass() { std::cout << "Destructor called" << std::endl; }
};
int main() {
MyClass obj1; // Constructor called
MyClass obj2; // Constructor called
// Destructor will be called automatically at the end of scope
return 0;
}
```
**Question**: in the above example, obj1's destructor or obj2's destructor, which one gets called first?
## 4.5 Overloading `operator<<` in C++
### Purpose
The `operator<<` is commonly overloaded to enable custom objects to be output using streams such as `std::cout`.
### Example
```cpp
#include <iostream>
#include <string>
class Person {
private:
std::string name;
int age;
public:
// Constructor
Person(const std::string& name, int age) : name(name), age(age) {}
// Public getters
std::string getName() const { return name; }
int getAge() const { return age; }
};
// Non-member function
std::ostream& operator<<(std::ostream& os, const Person& person) {
os << "Name: " << person.getName() << ", Age: " << person.getAge();
return os;
}
int main() {
Person p("Alice", 30);
std::cout << p << std::endl; // Output: Name: Alice, Age: 30
return 0;
}
```
**Question:** Can we overload this operator as a member function?
## 4.6 Exercises
- [Leetcode problem 56: Merge Intervals](https://leetcode.com/problems/merge-intervals/). Solution: [p56_mergeintervals.cpp](../../leetcode/p56_mergeintervals.cpp)
- [Leetcode problem 905: Sort Array By Parity](https://leetcode.com/problems/sort-array-by-parity/). Solution: [p905_sortarraybyparity.cpp](../../leetcode/p905_sortarraybyparity.cpp)