add solution of HW4
This commit is contained in:
127
hws/yelp_businesses/Business.cpp
Normal file
127
hws/yelp_businesses/Business.cpp
Normal 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;
|
||||
}
|
||||
31
hws/yelp_businesses/Business.h
Normal file
31
hws/yelp_businesses/Business.h
Normal 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
|
||||
@@ -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.
|
||||
|
||||
93
hws/yelp_businesses/nybusninesses.cpp
Normal file
93
hws/yelp_businesses/nybusninesses.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user