Refactor for robustness and clarity
This commit is contained in:
parent
8c04650caf
commit
6603f96d69
@ -6,6 +6,6 @@ Project 2 for CSCE4600, for Team G4
|
||||
|
||||
Build with `make`
|
||||
|
||||
Run with `make run`
|
||||
Run with `./main.out filename`
|
||||
|
||||
Clean with `make clean`
|
||||
|
@ -11,9 +11,8 @@ public:
|
||||
graph() {}
|
||||
// Initializers:
|
||||
// Read a graph from a file
|
||||
void read(std::string filename);
|
||||
// TODO: generate a random graph
|
||||
void random(int processes, int resources);
|
||||
int read(std::string filename);
|
||||
|
||||
// check functions:
|
||||
// is the graph...
|
||||
bool reducible();// ?
|
||||
@ -23,17 +22,13 @@ public:
|
||||
// print the graph
|
||||
void print ();
|
||||
|
||||
struct m{
|
||||
int x, y;
|
||||
std::vector<std::vector<int>> data;
|
||||
};
|
||||
typedef std::vector<std::vector<int>> matrix;
|
||||
|
||||
private:
|
||||
int num_processes = 0;
|
||||
int num_resources = 0;
|
||||
std::vector<int> resource_counts;
|
||||
struct m matrix; // Tell me, Mr. Anderson, what good is a phone call if you are unable to speak?
|
||||
bool is_blocked(int process_id);
|
||||
matrix m; // Tell me, Mr. Anderson, what good is a phone call if you are unable to speak?
|
||||
};
|
||||
|
||||
#endif
|
@ -6,7 +6,7 @@
|
||||
#include "graph.hpp"
|
||||
|
||||
void graph::print () {
|
||||
printf("np: %d\tnr: %d\n", num_processes, num_resources);
|
||||
printf("resource_counts:\n"); for (auto e: resource_counts) printf("%d\t", e); printf("\n");
|
||||
printf("matrix:\n"); for (auto x: matrix.data) {for (auto y: x) printf("%d\t", y); printf("\n");}
|
||||
printf("num_processes: %d\nnum_resources: %d\n", num_processes, num_resources);
|
||||
printf("resource_counts: ["); for (auto e: resource_counts) printf("%d, ", e); printf("\b\b]\n");
|
||||
printf("matrix:\n| "); for (auto x: m) {for (auto y: x) printf("%d, ", y); printf("\b\b |\n| ");} printf("\b\b \b\b");
|
||||
}
|
||||
|
@ -15,11 +15,14 @@ int main(int argc, char** argv) {
|
||||
graph g;
|
||||
|
||||
//TODO: Implement reading from a file
|
||||
g.read(filename);
|
||||
int err = g.read(filename);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
g.print();
|
||||
|
||||
// TODO: Implement graph reduction and/or knot detection
|
||||
printf("Graph is %s\n", g.reducible()?"not reducible (deadlock!)":"reducible (no deadlock!)");//?
|
||||
printf("Graph is %s\n", g.reducible()?"not reducible! Deadlock!":"reducible! No deadlock!");//?
|
||||
|
||||
// TODO: Destroy the graph created by read_file
|
||||
return 0;
|
||||
|
@ -7,45 +7,51 @@
|
||||
#include <regex>
|
||||
#include "graph.hpp"
|
||||
|
||||
#define MAX_INT_LEN 16
|
||||
|
||||
// Vector of regices, in order of precedence. Earlier entries will be checked before later entries.
|
||||
//* Vector of regex rules, in order of precedence. Earlier entries will be checked before later entries.
|
||||
std::vector<std::regex> patterns = {
|
||||
//* Rule 1: A line starting with a % is a comment, and should not be parsed
|
||||
std::regex("^\\s*(%)"),
|
||||
//* Rule 2: A line starting with `num_processes=` contains the number of processes
|
||||
std::regex("^.*(num_processes)\\s*=\\s*(\\d+).*"),
|
||||
//* Rule 3: A line starting with `num_resources=` contains the number of resources
|
||||
std::regex("^.*(num_resources)\\s*=\\s*(\\d+)"),
|
||||
//* Rule 4: A line containing only comma-separated values should be captured completely
|
||||
std::regex("^([\\-0-9, ]+)") // matches comma-separated space-separated signed decimal integers
|
||||
//* Rule 1: A line containing % is a comment, and should not be parsed
|
||||
std::regex("(%)"),
|
||||
//* Rule 2: A line containing `num_processes` contains the number of processes
|
||||
std::regex("(num_processes)\\D*(\\d+)"),
|
||||
//* Rule 3: A line containing `num_resources` contains the number of resources
|
||||
std::regex("(num_resources)\\D*(\\d+)"),
|
||||
//* Rule 4: A line containing integers should be saved somewhere
|
||||
std::regex("(-?[0-9]+.*-?[0-9]+)") // Magical!
|
||||
};
|
||||
|
||||
// convert comma-separated string s to vector<int>
|
||||
std::vector<int> stovi (const std::string &s);
|
||||
|
||||
// TODO: Implement reading from a file
|
||||
void graph::read(std::string filename) {
|
||||
|
||||
// Open file with name filename as read-only
|
||||
std::fstream f; f.open(filename, f.in);
|
||||
// TODO: Check for file IO errors (I might have a solution for that in another project)
|
||||
|
||||
// Say hi to Stovey, here to bake your cakes.
|
||||
//* convert string s to vector<int> no matter the cost
|
||||
std::vector<int> stovi (const std::string &s) {
|
||||
// Create the number classification rule
|
||||
std::regex rule("-?[0-9]+");
|
||||
// Make a new tokenizing iterator using the rule
|
||||
std::sregex_token_iterator start{s.begin(), s.end(), rule, 0}, end;
|
||||
// Match the numbers
|
||||
std::vector<int> res;
|
||||
for (auto i = start; i != end; ++i) res.push_back(atoi(i->str().c_str()));
|
||||
// give the numbers back
|
||||
return res;
|
||||
}
|
||||
|
||||
//* Read from a file of name `filename`
|
||||
int graph::read(std::string filename) {
|
||||
// Open file with name filename as input fstream
|
||||
std::ifstream f(filename);
|
||||
// Read the entire file
|
||||
while (!f.eof()) {
|
||||
// acquire a line
|
||||
std::string line;
|
||||
std::getline (f, line);
|
||||
|
||||
// Iterate over each pattern, and grab the associated data
|
||||
for (auto pattern: patterns) {
|
||||
for (const auto &pattern: patterns) {
|
||||
std::smatch res;
|
||||
// Capture data with a regex search, using the pattern
|
||||
if (std::regex_search (line, res, pattern)) {
|
||||
// get the pattern type, value
|
||||
std::string type = res.format("$1"), value = res.format("$2");
|
||||
// Handle the pattern
|
||||
// Rule 1: If line is a comment, ignore it and move on
|
||||
if (type == "%"); else
|
||||
if (type == "%") break;
|
||||
|
||||
// Rule 2: If num_processes= matched, assign value to num_processes
|
||||
if (type == "num_processes") { num_processes = std::stoi(value); } else
|
||||
@ -53,32 +59,48 @@ void graph::read(std::string filename) {
|
||||
// Rule 3: If num_resources= matched, assign value to num_resources
|
||||
if (type == "num_resources") { num_resources = std::stoi(value); } else
|
||||
|
||||
// Rule 4: If this line is a comma-separated list of numbers,
|
||||
// and this is the first match, assign it to resource counts
|
||||
// Rule 4: If this line is a comma-separated list of numbers:
|
||||
// If resource_counts is empty, assume this is the resource counts,
|
||||
// else it's part of the matrix being reloaded
|
||||
if (!resource_counts.size()) { resource_counts = stovi(type); } else
|
||||
// and this is a subsequent match, push it onto the matrix
|
||||
{ matrix.data.push_back(stovi(type)); }
|
||||
|
||||
// If a pattern is matched, go to the next line and skip evaluating other patterns
|
||||
{ m.push_back(stovi(type)); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close file
|
||||
f.close();
|
||||
// TODO: Check for file IO errors (Shouldn't be any)
|
||||
//* Test validity of the input file
|
||||
// Check if all sections are properly defined:
|
||||
const char errmsg[] = "%s: Definition failed for %s\n";
|
||||
int ret = 0;
|
||||
if (!num_processes){
|
||||
printf(errmsg, filename.c_str(), "num_processes");
|
||||
ret |= 0b00001;
|
||||
}
|
||||
if (!num_resources){
|
||||
printf(errmsg, filename.c_str(), "num_resources");
|
||||
ret |= 0b00010;
|
||||
}
|
||||
if (resource_counts.size() != num_resources){
|
||||
printf(errmsg, filename.c_str(), "resource counts");
|
||||
ret |= 0b00100;
|
||||
}
|
||||
if (m.size() != num_processes + num_resources){
|
||||
printf(errmsg, filename.c_str(), "adjacency matrix rows");
|
||||
ret |= 0b01000;
|
||||
}
|
||||
for (auto i: m) {
|
||||
if (i.size() != num_processes + num_resources)
|
||||
ret |= 0b10000;
|
||||
}
|
||||
if (ret & 0b10000) {
|
||||
printf(errmsg, filename.c_str(), "adjacency matrix columns");
|
||||
}
|
||||
if (ret) {
|
||||
printf("Check to ensure your input file is correct and follows the Rules.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> stovi (const std::string &s) {
|
||||
// Create the number classifier
|
||||
std::regex pattern("[0-9]+");
|
||||
std::sregex_token_iterator first{s.begin(), s.end(), pattern, 0}, last;
|
||||
// Match the numbers
|
||||
std::vector<int> res;
|
||||
for (auto i = first; i != last; ++i) res.push_back(atoi(i->str().c_str()));
|
||||
// give the numbers back
|
||||
return res;
|
||||
// fstream destructor closes file when going out of scope
|
||||
// in this house we RAII sometimes.
|
||||
return ret;
|
||||
}
|
29
test1.txt
29
test1.txt
@ -1,13 +1,14 @@
|
||||
% This file is a very poorly formatted example file, which contains all sorts of garbage
|
||||
% This was written to ensure the parser is as robust as possible, and won't crash on malformed input
|
||||
% This was written to stress-test the parser
|
||||
|
||||
nv249hvbwer8oysbvdofuvbfdz wsdfabsv num_processes = 4
|
||||
// Gee, this isn't actually a comment is it?
|
||||
# but most of that is there to distract the program!
|
||||
this is horrible to read!
|
||||
nv249hvbwer8oysbvdofuvbfdzwsdfabsvnum_processesbgskjhdfd=lbahfbzjhxbc,4gsv4wf5fewf6, 7, 8
|
||||
^^^^ Believe it or not, this is a num_processes line! ^^^^
|
||||
// Gee, this isn't actually a comment is it? As long as I don't include a number, it won't care.
|
||||
[][][][]\\\\\';./` num_resources= 4ibeoifbavdivbkdhbz
|
||||
% lines beginning with % are comments
|
||||
% for example: num_processes = 128314
|
||||
% The first line containing a list of numbers will be interpreted as resource_counts
|
||||
% lines containing % are comments
|
||||
for example: num_processes = 128314%
|
||||
% The first non-comment line containing a list of numbers will be interpreted as resource_counts
|
||||
12 ,14,16 , 18
|
||||
% this line is missing a comma
|
||||
1,2 3,4,5,6,7,8
|
||||
@ -16,8 +17,12 @@ nv249hvbwer8oysbvdofuvbfdz wsdfabsv num_processes = 4
|
||||
% and this one, before the comma
|
||||
1 ,2 ,3 ,4 ,5 ,6 ,7,8
|
||||
% nevertheless, it keeps on chugging.
|
||||
1,2,3,4,5,6,7,8
|
||||
1,2,3,4,5,6,7,8
|
||||
1,2,3,4,5,6,7,8
|
||||
1,2,3,4,5,6,7,8
|
||||
1,2,3,4,5,6,7,8
|
||||
~~~1~~~2~~~3~~~4~~~5~~~6~~~7~~~8~~~
|
||||
1a 2b 3c, 4d 5e 6f, 7g 8h
|
||||
^^^^ Testing mixed letters and numbers ^^^^
|
||||
@Xx_1_2_3_4_5_6_7_8_()_xX#
|
||||
words, words, words!
|
||||
|
||||
vvvv testing negative numbers vvvv
|
||||
1,-2,3,4,5,6,-7,8
|
||||
-1,2,3,4,5,6,7,-8
|
Loading…
Reference in New Issue
Block a user