add solution of HW4

This commit is contained in:
JamesFlare1212
2025-02-13 14:25:13 -05:00
parent 84902bd0dc
commit 38c1a8e0d9
6 changed files with 300 additions and 5 deletions

View File

@@ -0,0 +1,127 @@
#include <string>
#include <cctype>
#include <cstdlib>
#include "Business.h"
//extracts a string value for the given field
std::string extractJsonString(const std::string &line, const std::string &field) {
std::string pattern = "\"" + field + "\":";
size_t pos = line.find(pattern);
if (pos == std::string::npos) {return "";} //in case pattern not found
pos += pattern.length();
//skip any whitespace
while (pos < line.size() && isspace(line[pos])) {pos++;}
if (pos >= line.size() || line[pos] != '\"') {return "";} //in case the opening quote is not found
pos++;
//skip the opening quote
size_t endPos = line.find("\"", pos);
if (endPos == std::string::npos) {return "";} //in case the closing quote is not found
return line.substr(pos, endPos - pos);
}
//extracts an integer value for the given field
int extractJsonInt(const std::string &line, const std::string &field) {
std::string pattern = "\"" + field + "\":";
size_t pos = line.find(pattern);
if (pos == std::string::npos) {return -1;} //in case the pattern is not found
pos += pattern.length();
//skip any whitespace
while (pos < line.size() && isspace(line[pos])) {pos++;}
size_t endPos = pos;
//skip the negative sign
if (line[endPos] == '-') {endPos++;}
//skip the digits
while (endPos < line.size() && isdigit(line[endPos])) {endPos++;}
std::string numStr = line.substr(pos, endPos - pos);
int value = std::stoi(numStr);
if (value == 0) {return -1;} //in case the number is not found
return value;
}
//extracts a double value for the given field
double extractJsonDouble(const std::string &line, const std::string &field) {
std::string pattern = "\"" + field + "\":";
size_t pos = line.find(pattern);
if (pos == std::string::npos) {return 0.0;} // in case the pattern is not found
pos += pattern.length();
//skip any whitespace
while (pos < line.size() && isspace(line[pos])) {pos++;}
if (line[pos] == '\"') {
//in case the data is quoted
pos++;
size_t endPos = line.find("\"", pos);
if (endPos == std::string::npos) {return 0.0;}
std::string numStr = line.substr(pos, endPos - pos);
double value = std::stod(numStr);
if (value == 0.0) {return 0.0;} //in case the number is not found
return value;
} else {
//in case the data is not quoted
size_t endPos = pos;
while (endPos < line.size() && (isdigit(line[endPos]) || line[endPos] == '.' || line[endPos]=='-')) {
endPos++;
}
std::string numStr = line.substr(pos, endPos - pos);
double value = std::stod(numStr);
if (value == 0.0) {return 0.0;} //in case the number is not found
return value;
}
}
//extracts a price value for the given field
int extractJsonPrice(const std::string &line, const std::string &field) {
std::string pattern = "\"" + field + "\":";
size_t pos = line.find(pattern);
if (pos == std::string::npos) {return -1;} //in case the pattern is not found
pos += pattern.length();
//skip any whitespace
while (pos < line.size() && isspace(line[pos])) {pos++;}
if (line[pos] == '\"') {
pos++;
size_t endPos = line.find("\"", pos);
if (endPos == std::string::npos) {return -1;}
std::string numStr = line.substr(pos, endPos - pos);
if (numStr == "None") {return -1;} //in case the number is not found
return std::stoi(numStr);
} else {
size_t endPos = pos;
while (endPos < line.size() && (isdigit(line[endPos]) || line[endPos]=='-')) {
endPos++;
}
std::string numStr = line.substr(pos, endPos - pos);
if (numStr == "None") {return -1;} //in case the number is not found
return std::stoi(numStr);
}
}
//load the business data from a JSON line
Business::Business(const std::string &jsonLine) {
name = extractJsonString(jsonLine, "name");
categories = extractJsonString(jsonLine, "categories");
rating = extractJsonDouble(jsonLine, "stars");
price = extractJsonPrice(jsonLine, "RestaurantsPriceRange2");
review_count = extractJsonInt(jsonLine, "review_count");
city = extractJsonString(jsonLine, "city");
postal_code = extractJsonString(jsonLine, "postal_code");
}
std::string Business::getName() const {return name;}
std::string Business::getCategories() const {return categories;}
double Business::getRating() const {return rating;}
int Business::getPrice() const {return price;}
int Business::getReviewCount() const {return review_count;}
std::string Business::getCity() const {return city;}
std::string Business::getPostalCode() const {return postal_code;}
//returns a string representing the star rating.
std::string Business::getStarString() const {
int fullStars = static_cast<int>(rating);
double fraction = rating - fullStars;
std::string stars;
for (int i = 0; i < fullStars; ++i)
stars += "\u2605";
if (fraction >= 0.5)
stars += "\u00BD";
return stars;
}

View File

@@ -0,0 +1,31 @@
#ifndef BUSINESS_H
#define BUSINESS_H
#include <string>
class Business {
public:
//constructs a Business by parsing a JSON-formatted line
Business(const std::string &jsonLine);
//Accessors
std::string getName() const;
std::string getCategories() const;
double getRating() const;
int getPrice() const;
int getReviewCount() const;
std::string getCity() const;
std::string getPostalCode() const;
//returns a string representation of the star rating
std::string getStarString() const;
private:
std::string name;
std::string categories;
double rating;
int price;
int review_count;
std::string city;
std::string postal_code;
};
#endif // BUSINESS_H

View File

@@ -1,7 +1,7 @@
HOMEWORK 4: Yelp Businesses
NAME: < insert name >
NAME: Jinshan Zhou
COLLABORATORS AND OTHER RESOURCES:
@@ -10,13 +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 >
Not really, but when I handle the list, I check many lab examples. Also, I check the
sstream example from alb and my previous homework as well.
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: < insert # hours >
ESTIMATE OF # OF HOURS SPENT ON THIS ASSIGNMENT: 13
MISC. COMMENTS TO GRADER:
@@ -33,4 +34,9 @@ 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 >
I just start writing the code and implementation directly. Then, I found there are
a few given codes on the end instruction. But, it's too late for me. I didn't fully
read through the instruction at the beginning. Which brings me some extra work.
When I realize that, other parts of my code already depends on my extract JSON functions.
So, I have to keep writing on top of that. If, I can do this again, I will check the
instruction in detail and find if there are useful cases.

View File

@@ -0,0 +1,93 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <vector>
#include "Business.h"
int main(int argc, char* argv[]) {
if (argc < 5) {
std::cerr << "Usage: " << argv[0]
<< " input.json output.txt zipcode [categories...]"
<< std::endl;
return 1;
}
//load the arguments
std::string inputFile = argv[1];
std::string outputFile = argv[2];
std::string zipcode = argv[3];
//read all categories from arguments
std::vector<std::string> searchCategories;
for (int i = 4; i < argc; ++i) {
searchCategories.push_back(argv[i]);
}
//open the input file
std::ifstream inFile(inputFile.c_str());
if (!inFile) {
std::cerr << "Error: Could not open input file: "
<< inputFile << std::endl;
return 1;
}
//open the output file
std::ofstream outFile(outputFile.c_str());
if (!outFile) {
std::cerr << "Error: Could not open output file: "
<< outputFile << std::endl;
return 1;
}
//read each line and create a Business object if it matches the zipcode and at least one search category
std::list<Business> matchingBusinesses;
std::string line;
while (std::getline(inFile, line)) {
Business biz(line);
//check zipcode
if (biz.getPostalCode() != zipcode)
continue;
//check categories: at least one category must be found
bool categoryMatch = false;
std::string bizCategories = biz.getCategories();
for (std::vector<std::string>::const_iterator catIt = searchCategories.begin();
catIt != searchCategories.end(); ++catIt) {
if (bizCategories.find(*catIt) != std::string::npos) {
categoryMatch = true;
break;
}
}
if (categoryMatch) {
matchingBusinesses.push_back(biz);
}
}
//sort the list by rating in descending order
matchingBusinesses.sort([](const Business &a, const Business &b) {
return a.getRating() > b.getRating();
});
//output the results in a format similar to Yelp.
if (matchingBusinesses.empty()) {
outFile << "Sorry, we couldn't find any results" << std::endl;
} else {
int index = 1;
for (std::list<Business>::const_iterator it = matchingBusinesses.begin();
it != matchingBusinesses.end(); ++it) {
outFile << "=====================" << std::endl;
//add line 1: Index and Business Name
outFile << index << ". " << it->getName() << std::endl;
//add line 2: Star rating, numeric rating, and review count
outFile << it->getStarString() << " " << it->getRating()
<< " (" << it->getReviewCount() << " reviews)" << std::endl;
//add line 3: City and then the price range (if available)
outFile << it->getCity() << " ";
if (it->getPrice() != -1) {
for (int i = 0; i < it->getPrice(); ++i)
outFile << "$";
}
outFile << std::endl;
//add line 4: Categories
outFile << it->getCategories() << std::endl;
index++;
}
outFile << "=====================" << std::endl;
}
return 0;
}