I have 2 files: main.cpp and parser.hpp
I am returning vector<vector> from a member function in class in parser.hpp. However it seems I am not getting anything in my main.cpp from the return value because when I print its size I get 0.
This is my main.cpp:
#include <vector>
#include <cstring>
#include <fstream>
#include <iostream>
#include "parser.hpp"
using namespace std;
int main()
{
ifstream file;
file.open("test.csv");
csv obj;
obj.parse(file);
obj.print_parsed_csv(file);
vector<vector<string>> parsed_csv_data = obj.parse(file);
cout << parsed_csv_data.();
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
This is my parser.hpp
using namespace std;
class csv
{
public:
vector<vector<string>> parse(ifstream &file)
{
string str;
vector<vector<string>> parsed_data;
while (getline(file, str))
{
vector<string> parsed_line;
while (!str.empty())
{
int delimiter_pos = str.find(',');
string word = str.substr(0, delimiter_pos);
// cout << word << " ";
if (delimiter_pos == -1)
{
parsed_line.push_back(word);
break;
}
else
{
str = str.substr(delimiter_pos + 1);
// cout << str << endl;
parsed_line.push_back(word);
}
}
parsed_data.push_back(parsed_line);
}
return parsed_data;
}
void print_parsed_csv(ifstream &file)
{
vector<vector<string>> parsed_csv_data = parse(file);
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
};
I am getting correct cout output in parse() only. print_parsed_csv() in parser.hpp and the cout in main.cpp both are giving 0 as the variable's size.
How do I resolve this?
The first time you call obj.parse the stream object is read from until you get to the end of the file. You need to either reopen the file or reset file to point back to the beginning of the file after reading from it.
You pass the same file variable to each of the three functions below but only the first one works. The first call to obj.parse moves where file is pointing in the input file. When obj.parse exits the first time, file is pointing to the end of the file so when it's used in the subsequent 2 calls, there's nothing to read.
obj.parse(file); // <-- this works fine
obj.print_parsed_csv(file); // <-- this fails
vector<vector<string>> parsed_csv_data = obj.parse(file);fails
// ^^^^^^^^^- this fails
See this question for answers on how to reset the ifstream to the beginning of the file.
i have been provided middleearth.h/cpp and was asked to make a makefile, doxyfile (which i did correctly) and a topological.cpp that works but has a small mistake in the output and i need help with that please.ill provide all three files and the text we use to test and the error.
cs2110 cs2150
cs2102 cs2150
cs1110 cs2110
cs3330 cs4414
cs2150 cs4414
cs2110 cs3330
cs1110 cs2102
0 0
middleearth.h
#ifndef MIDDLEEARTH_H
#define MIDDLEEARTH_H
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <random>
using namespace std;
// see the comments in the lab11 write-up, or in middleearth.cpp
class MiddleEarth {
public:
MiddleEarth(int xsize, int ysize, int num_cities, int seed);
void print();
void printTable();
float getDistance(const string& city1, const string& city2);
vector<string> getItinerary(unsigned int length);
private:
int num_city_names, xsize, ysize;
unordered_map<string, float> xpos, ypos;
vector<string> cities;
unordered_map<string, unordered_map<string, float>> distances;
mt19937 gen; // Mersenne-Twister random number engine
};
#endif
middleearth.cpp
#include "middleearth.h"
#include <algorithm>
#include <array>
#include <cstdlib>
#include <cmath>
// New shuffle method that uses the Mersenne Twister engine
void shuffle (vector<string>::iterator first, vector<string>::iterator last, mt19937& g) {
for (auto i=(last-first)-1; i>0; --i) {
unsigned int n = (g() / (double) g.max())*distance(first,last);
swap (first[i], first[n]);
}
}
// The list of all the place names that we'll be using
const array<string, 40> all_city_names{
// human towns, cities and strongholds
"Bree", // a human and hobbit town between the Shire and Rivendell
"Isengard", // the tower fortress where Saruman resided; Gandalf was imprisoned there.
"Minas Tirith", // capital of Gondor, the "white city"; home to Boromir, Denethor, and later, Aragorn
"Osgiliath", // city on the river Anduin; is at the other end of Pelennor Fields from M. Tirith
"Edoras", // the capital city of Rohan, where King Theoden resides
"Helm's Deep", // fortress of Rohan, it is where the people of Edoras fled to from the orc invasion
"Dunharrow", // a refuge of Rohan, it is where Elrond presents the sword to Aragorn in the movie
// dwarf cities
"Moria", // the enormous dwarven underground complex that the Fellowship traveled through
// elvish cities
"Lothlorien", // the elvish tree-city, home of Lady Galadriel and Lord Celeborn
"Rivendell", // the elvish city that is home to Lord Elrond
"The Grey Havens", // the port city on the western coast from which the elves travel westward
// hobbit villages
"Bucklebury", // a Shire village, it has a ferry across the Brandywine River that the Hobbits use
"Bywater", // a Shire village, it is the site of the Battle of Bywater (removed from the movie)
"Hobbiton", // a Shire village, it is home to Bilbo and, later, Frodo
"Michel Delving", // a Shire village, it is the chief town of the Shire
// Mordor places
"Orodruin", // Mount Doom in Mordor, it is where the Ring was made, and later, unmade
"Barad-Dur", // Sauron's fortress that was part castle, part mountain
"Minas Morgul", // formerly the Gondorian city of Minas Ithil; renamed when Sauron took it over
"Cirith Ungol", // the mountianous pass that Sam & Frodo went through; home of Shelob
"Gorgoroth", // the plains in Mordor that Frodo & Sam had to cross to reach Mount Doom
// places that are not cities
"Emyn Muil", // the rocky region that Sam & Frodo climb through after leaving the Fellowship
"Fangorn Forest", // the forest where Treebeard (and the other Ents) live
"Dagorlad", // great plain/swamp between Emyn Muil & Mordor where a great battle was fought long ago
"Weathertop", // the tower between Bree and Rivendell where Aragorn and the Hobbits take refuge
"Gladden Fields", // this is where the Ring is lost in the River Anduin, after Isildur is ambushed and killed by Orcs
"Entwash River", // a river through Rohan, which flows through Fangorn Forest
"River Isen", // river through the Gap of Rohan; Theoden's son was slain in a battle here.
"The Black Gate", // huge gate to Mordor that Aragorn and company attack as the ring is destroyed
"The Old Forest", // a forest to the west of the Shire (adventures there were removed from the movie)
"Trollshaws", // area to the west of Rivendell that was home to the trolls that Bilbo met
"Pelennor Fields", // great plain between M. Tirith and Osgiliath; site of the Battle of M. Tirith
"Hollin", // the empty plains that the Fellowship crosses between Rivendell and Moria
"Mirkwood", // Legolas' forest home; Bilbo travels there in 'The Hobbit'.
"Misty Mountains", // the north-south moutain range that runs through Middle-earth
"Prancing Pony", // an inn in Bree where the hobbits tried to meet Gandalf, but meet Aragorn instead
// places from the Hobbit book and movies
"Laketown", // also called Esgaorth, it is the town of men on the Long Lake near Erebor
"Dale", // the town of men outside Erebor, destroyed by Smaug long before the Hobbit story
"Erebor", // the Elvish name for the Lonely Mountain, where the dwarves had their fortress
"Beorn's House", // Beorn is the shape-shifter who shelters the dwarf party
"Dol Guldur", // fortress in Mirkwood where Sauron, as the Necromancer, hid during most of the Hobbit
};
// Iluvatar, the creator of Middle-Earth
MiddleEarth::MiddleEarth(int xsize, int ysize, int num_cities, int seed) {
this->xsize = xsize;
this->ysize = ysize;
// set up the random number generator
gen.seed(seed == -1 ? random_device{}() : seed);
// count the number of cities in the array
this->num_city_names = all_city_names.size();
if (num_cities > num_city_names) {
cout << "There are only " << num_city_names << " city names, so "
<< num_cities << " cities cannot be created." << endl;
cout << "Exiting." << endl;
exit(0);
}
if (num_cities < 5) {
num_cities = 5;
}
// copy all the cities into a mutable vector
this->cities = vector<string>(all_city_names.begin(), all_city_names.end());
shuffle(cities.begin(), cities.end(), gen); // shuffle all the cities
cities.erase(cities.begin() + num_cities, cities.end()); // then remove the ones we won't be using
// compute random city positions
for (auto city : cities) {
xpos.emplace(city, (gen() / (double) gen.max()) * xsize);
ypos.emplace(city, (gen() / (double) gen.max()) * ysize);
}
// compute the 2-d distance array
// we assume that num_cities < xsize * ysize
for (auto city1 : cities) {
for (auto city2 : cities) {
distances[city1].emplace(city2, sqrt((xpos[city2] - xpos[city1]) * (xpos[city2] - xpos[city1]) +
(ypos[city2] - ypos[city1]) * (ypos[city2] - ypos[city1])));
}
}
}
// The Mouth of Sauron!
// Prints out info on the created 'world'
void MiddleEarth::print() {
cout << "there are " << num_city_names
<< " locations to choose from; we are using " << cities.size() << endl;
cout << "they are: " << endl;
for (auto city : cities) {
cout << "\t" << city << " # (" << xpos[city] << ", " << ypos[city]
<< ")" << endl;
}
}
// Prints a tab-separated table of the distances,
// which can be loaded into Excel or similar
void MiddleEarth::printTable() {
cout << "Table: " << endl << endl << "Location\txpos\typos\t";
for (auto city : cities) {
cout << city << "\t";
}
cout << endl;
for (auto city1 : cities) {
cout << city1 << "\t" << xpos[city1] << "\t" << ypos[city1] << "\t";
for (auto city2 : cities) {
cout << distances[city1][city2] << "\t";
}
cout << endl;
}
}
// This method returns the distance between the two passed cities.
// If we assume that the hash table (i.e. the map) is O(1),
// then this method call is also O(1)
float MiddleEarth::getDistance(const string& city1, const string& city2) {
return distances[city1][city2];
}
// Returns the list of cities to travel to.
// The first city is the original start point as well as the end point.
// The number of cities passed in does not include this start/end point
// (so there will be length+1 entries in the returned vector).
vector<string> MiddleEarth::getItinerary(unsigned int length) {
// check parameter
if (length >= cities.size()) {
cout << "You have requested an itinerary of " << length
<< " cities; you cannot ask for an itinerary of more than length "
<< cities.size() - 1 << endl;
exit(0);
}
length++; // to account for the start point
// we need to make a deep copy of the cities vector
vector<string> itinerary(cities.begin(), cities.end());
// shuffle, erase unneeded ones, and return the itinerary
shuffle(itinerary.begin(), itinerary.end(), gen);
itinerary.erase(itinerary.begin() + length, itinerary.end());
return itinerary;
}
topological.cpp
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <list>
#include <stack>
#include <string>
#include <map>
using namespace std;
/**
#date 11/16/2020
*/
/** #brief
*/
class Graph
{
public:
Graph(int vert);
/** #brief adds an edge to the list
* #param string v
* #param string w
* #param map<string, int> m
*
*/
void addEdge(string v, string w, map<string, int> m);
void printSort();
private:
int vertices;
list<int> *myList;
void sort(int v, stack<int> &myStack, bool visited[]);
map<int, string> myMap;
};
Graph::Graph(int vert) {
vertices = vert;
myList = new list<int>[vertices];
}
void Graph::addEdge(string v, string w, map<string, int> m) {
int loc1 = m[v];
int loc2 = m[w];
myMap[loc1] = v;
myMap[loc2] = w;
myList[loc1].push_back(loc2);
}
void Graph::sort(int v, stack<int> &myStack, bool visited[]) {
visited[v] = true;
list<int>::iterator i;
for(i = myList[v].begin(); i != myList[v].end(); ++i) {
if(!visited[*i]) {
sort(*i, myStack, visited);
}
}
myStack.push(v);
}
void Graph::printSort() {
stack<int> myStack;
bool *visited = new bool[vertices];
for(int i = 0; i < vertices; i++) {
visited[i] = false;
}
for(int i = 0; i < vertices; i++) {
if(visited[i] == false)
sort(i, myStack, visited);
}
while(myStack.empty() == false) {
int x = myStack.top();
string output = myMap[x];
cout << output << " ";
myStack.pop();
}
}
int main (int argc, char **argv) {
if ( argc != 2 ) {
cout << "Must supply the input file name as the one and only parameter" << endl;
return 1;
}
ifstream file(argv[1], ifstream::binary);
ifstream file1(argv[1], ifstream::binary);
if ( !file.is_open() ) {
cout << "Unable to open file '" << argv[1] << "'." << endl;
return 1;
}
string s1, s2;
int count = 0;
list <string> edges;
while(!file.eof()) {
file >> s1;
file >> s2;
if(s1 == "0" && s2 == "0") {
break;
}
edges.push_back(s1);
edges.push_back(s2);
}
file.close();
edges.sort();
edges.unique();
int size = edges.size();
map<string, int> myMap;
Graph myGraph(size);
list<string>::iterator i;
for(i = edges.begin(); i != edges.end(); i++) {
string s = *i;
myMap[s] = count;
count++;
}
while(!file1.eof()) {
file1 >> s1;
file1 >> s2;
if(s1 == "0" && s2 == "0") {
break;
}
myGraph.addEdge(s1, s2, myMap);
}
myGraph.printSort();
cout<<endl;
file1.close();
return 0;
}
You are confusing yourself. You have your solution in edges. There isn't a reason to read the data a second time. For example, you can simply output sorted/unique elements of edges, e.g. the modifications to your code are:
int main (int argc, char **argv) {
if ( argc != 2 ) {
cout << "Must supply the input file name as the one and only parameter" << endl;
return 1;
}
ifstream file(argv[1], ifstream::binary);
// ifstream file1(argv[1], ifstream::binary);
if ( !file.is_open() ) {
cout << "Unable to open file '" << argv[1] << "'." << endl;
return 1;
}
string s1, s2;
// int count = 0;
list <string> edges;
while(file >> s1 && file >> s2) {
if(s1 == "0" && s2 == "0") {
break;
}
edges.push_back(s1);
edges.push_back(s2);
}
file.close();
edges.sort();
edges.unique();
// int size = edges.size();
// map<string, int> myMap;
bool first = true;
for (const auto& n : edges) {
if (!first)
cout.put(' ');
cout << n;
first = false;
}
cout.put('\n');
// Graph myGraph(size);
// list<string>::iterator i;
// for(i = edges.begin(); i != edges.end(); i++) {
// string s = *i;
// myMap[s] = count;
// count++;
// }
//
// while(file1 >> s1 && file1 >> s2) {
// if(s1 == "0" && s2 == "0") {
// break;
// }
// myGraph.addEdge(s1, s2, myMap);
// }
//
// myGraph.printSort();
// cout<<endl;
// file1.close();
return 0;
}
(note: how while (!file.eof())) was replaced with while(file >> s1 && file >> s2))
Example Use/Output
With your sample data in dat/topological.txt, you would receive:
$ ./bin/topological dat/topological.txt
cs1110 cs2102 cs2110 cs2150 cs3330 cs4414
If you are having problems editing your code, then you can do things much easier with a std::set, e.g.
#include <iostream>
#include <fstream>
#include <string>
#include <set>
int main (int argc, char **argv) {
if ( argc != 2 ) {
std::cerr << "Must supply the input file name as the one and only parameter\n";
return 1;
}
std::set<std::string> strset {};
std::string s {};
std::ifstream f (argv[1]);
if (!f.good()) {
std::cerr << "file open failed.\n";
return 1;
}
while (f >> s && s != "0")
strset.insert(s);
bool first = true;
for (const auto& unique : strset) {
if (!first)
std::cout.put(' ');
std::cout << unique;
first = false;
}
std::cout.put('\n');
}
(same answer)
This is when i used the main you gave me:
enter image description here
This is when i added (Yes. after edges.unique(); you can simply do. bool first = true; for (const auto& n : edges) { if (!first) cout.put(' '); cout << n; first = false; } cout.put('\n');):
enter image description here
the first line on output is correct, i dont want the line under it
Hi I am new to c++ and am having trouble understanding on how I would push and pop elements read from a text file to an array and displaying those elements in reverse order for example if i have a text file called hero.txt with elements Goku Luffy Naruto I would like the output to be Naruto Luffy Goku
this is what I have so far
string hero[100]; // array to store elements
int count=0;
int main()
{
fstream myfile;
string nameOffile;
string text;
string mytext;
cout << "Enter name of file" << endl;
cin >> nameOffile
myfile.open(nameOffile.c_str());
if (!myfile)
{
cerr << "error abort" << endl;
exit(1);
}
while (myfile >> text )
{
Push(mytext); //Note I know this is wrong I just don't know how to write it in a manner that will push the first element of the textfile to the top
}
myfile.close();
while(hero[count]=="")
{
//Again I know these two lines are incorrect just don't know how to implement in correct manner
cout <<hero[0] << " " <<endl;
Pop(mytext);
}
}
// Function for push
void Push(string mytext)
{
count = count + 1;
hero[count] = mytext;
}
void Pop(string mytext)
{
if(count=0)
{
mytext = " ";
}
else
{
mytext = hero[count];
count = count - 1;
}
}
Normally, a stack will begin with index = -1 to indicate that the stack is empty. So you need to replace
int count = 0
with
int count = -1
After you do all the pushing, your stack will look like this:
hero[0] = "Goku"
hero[1] = "Luffy"
hero[2] = "Naruto"
Now, to print it out in reverse order, you can just loop from the last index to the first. After pushing all the heroes string, count is now equal to 2. The last heroes will be at index = 0. So you can rewrite the loop as
while(count >= 0)
{
cout << hero[count] << " " <<endl;
Pop();
}
Your Pop function is also incorrect. In the if statement, you will replace the value of count to 0. What you need to do in Pop is just to decrement the value of count.
So you can rewrite it as
void Pop()
{
count = count - 1;
}
The vector class defined in the standard library acts like a stack.
For example:
// include the library headers
#include <vector>
#include <string>
#include <iostream>
// use the namespace to make the code less verbose
using namespace std;
int main()
{
// declare the stack
vector<string> heroStack;
// insert the elements
heroStack.push_back("Goku");
heroStack.push_back("Luffy");
heroStack.push_back("Naruto");
// print elements in reverse order
while(!heroStack.empty())
{
// get the top of the stack
string hero = heroStack.back();
// remove the top of the stack
heroStack.pop_back();
cout << hero << endl;
}
}
ok let's tart by improving your functions
push function works good but just change the order of it to be like this
void Push(string mytext)
{
hero[count] = mytext; //now you will start at index 0
count = count + 1;
}
pop function should be like this
you need to return a string value and you don't need to pass a parameter
string Pop()
{
if(count == 0)
{
return "";
}
else
{
count = count - 1;
mytext = hero[count];
return mytext;
}
}
now you are functions are ready let's use them
you are using the push function correctly in your main
we need to change the while which displays the output
it should be like this
while(true)
{
tempText = pop(); // this function will get you the last element and then remove it
if ( tempText == "" ) // now we are on top of the stack
break;
cout <<tempText << " " <<endl;
}
#include "stdafx.h"
#include <fstream>
#include <stack>
#include <string>
#include <iostream>
class ReadAndReversePrint
{
std::stack<std::string> st;
std::ifstream file;
public:
ReadAndReversePrint(std::string path)
{
file.open(path);
if (file.fail())
{
std::cout << "File Open Failed" << std::endl;
return;
}
std::string line;
while (!file.eof())
{
file >> line;
st.push(line);
}
file.close();
std::cout << "Reverse printing : " << std::endl;
while (!st.empty())
{
std::cout << st.top().c_str() << "\t";
st.pop();
}
std::cout << std::endl;
}
};
int main()
{
ReadAndReversePrint rrp("C:\\awesomeWorks\\input\\reverseprint.txt");
return 0;
}
I created a vector of vector (10*10000) and try to access this vector through member function. but I got a segmentation fault. I don't know what's wrong here...
Here is Simple.h
class Simple
{
private:
std::vector<double> data_row;
std::vector<std::vector<double> > data;
public:
Simple():data_row(10000), data(10, data_row){};
/*initialize data vector*/
int getSampleCounts(std::istream &File);
/*return number of packet samples in this file*/
Result getModel(std::istream &File);
/*return average and variance of simple delta time*/
void splitData (std::istream &File, const int & sample_in_fold);
};
#endif /* SIMPLE_H */
here is Simple.cpp
void Simple::splitData(std::istream& File, const int & sample_in_fold) {
double value = 0.0;
bool isFailed = true;
int label = 0;
while (File >> value) {
// for each value, generate a label
srand(time(NULL));
label = rand() % 10; // generate label between 0 to 9
while (isFailed) {
// segmentation fault in the next line!
std::cout << "current data size is: " << this->data.size() <<endl;
std::vector<double>::size_type sz = this->data[label].size();
if (sz <= sample_in_fold) {
std::cout << "current size is " << sz << "< samples in fold: " << sample_in_fold << endl;
this->data[label].push_back(value);
std::cout << "push_back succeed!" << endl;
isFailed = false;
} else {
std::cout << "label " << label << "if full. Next label. \n";
srand(time(NULL));
label = rand() % 10;
sz = this->data[label].size();
}
}
}
}
and I'm attaching the main file here.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for system())
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <limits.h> // for PATH_MAX
#include "Complex.h"
#include "Result.h"
#include "Simple.h"
#include <math.h>
using namespace std;
int main(int argc, char ** argv) {
struct dirent *pDirent;
DIR *pDir;
std::string line;
// check for args
if (argc == 1) {
printf("Usage: ./main + folder name. \n");
return 1;
}
pDir = opendir(argv[1]);
if (pDir == NULL) {
printf("Cannot open directory '%s' \n", argv[1]);
return 1;
}
// readdir returns a pointer to the next direcctory entry dirent structure
while ((pDirent = readdir(pDir)) != NULL) {
// get file name and absolute path
char *name = pDirent->d_name;
char buf[PATH_MAX + 1];
realpath(name, buf);
// std::cout << "Current file is: " << (pDirent->d_name) << endl;
if (has_suffix(pDirent->d_name, ".txt")) {
printf("[%s]\n", pDirent->d_name);
//printf("absolute path is %s. \n", buf);
ifstream infile;
// open file with absolute path
infile.open(buf, ios::in);
if (!infile) {
cerr << "Can't open input file " << buf << endl;
exit(1);
}
//processing for simple pattern
if (has_suffix(name, "testfile.txt")) {
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
Result simplerst = simple_obj->getModel(infile);
std::cout << "Number of delta time is " << number << endl;
infile.clear();
infile.seekg(0);
write_to_file(pDirent->d_name, simplerst);
// divide data into k = 10 folds, get number of data in each fold
int sample_in_fold = floor(number / 10);
std::cout << sample_in_fold << std::endl;
simple_obj->splitData(infile, sample_in_fold);
}
} else {
// printf("This is not a txt file. Continue\n");
}
}
closedir(pDir);
return 0;
}
And here is a sample testfile.txt. I only copied part of the original file, for illustration.
10.145906000
10.151063000
10.131083000
10.143461000
10.131745000
10.151285000
10.147493000
10.123198000
10.144975000
10.144484000
10.138129000
10.131634000
10.144311000
10.157710000
10.138047000
10.122754000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
10.154170000
10.139574000
10.140207000
10.149151000
10.164629000
10.106818000
10.142431000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
Here is Result.h
#ifndef RESULT_H
#define RESULT_H
typedef struct Result {
double average;
double sigma;
}Result;
and getModel function in Simple.cpp:
Result Simple::getModel(std::istream &File) {
double value = 0.0;
double average = 0.0;
double sum = 0.0;
double counter = 0.0;
double sumsqr = 0.0;
double var = 0.0;
double sigma = 0.0;
while (File >> value) {
++counter;
sum += value;
sumsqr += value * value;
}
average = sum / counter;
var = sumsqr / counter - average * average; //E(x^2) - (E(x))^2
sigma = sqrt(var);
std::cout << "average is " << average << std::endl;
std::cout << "std deviation is " << sigma << std::endl;
File.clear();
File.seekg(0);
Result result = {average, sigma};
return result;
}
One issue right away:
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
simple_obj is an uninitialized pointer, thus your program exhibits undefined behavior at this point.
Why use a pointer anyway? You could have simply done this to avoid the issue:
Simple simple_obj;
simple_obj.getSampleCounts(infile);
Also, this line may not be an issue, but I'll mention it anyway:
Result simplerst = simple_obj->getModel(infile);
We already know that in your original code, simple_obj is bogus, but that's not the issue here. If Result is an object, and that object does not have correct copy semantics, then that assignment will also cause undefined behavior.
You've got a couple of uses of endl without specifying std::endl (they're not the same thing - you always have to type the std:: ). Is endl silently referring to another variable somewhere else?
I am almost done with my project, but I still have one small thing that needs to be done...I need to run the entire program for each file in the directory. There are about 200 files in total. Below is the main class of the program that needs to run. I'm thinking I will put the entire thing in a do-while loop and run it until there are no more .dat files in the directory, but I'm not sure if that will work. Obviously, I'd like to replace the hard-coded file names with variables...I'm just not sure how to do that, either. Please let me know if you need clarification. I've been working on this project for a while and I'm getting kind of brain-numb. Thanks in advance for your help!
Edit My test directory is on a Windows machine, but it will be uploaded to a linux machine at school.
int main() {
NearestNeighbor face;
//string path = "C:\Users\Documents\NetBeansProjects\CSCE350";
//string searchPattern = "*dat";
// string fullSearchPath = path + searchPattern;
/*TEMPLATE DATA*/
/***********************************************************************************/
fstream templateData;
double data = 0.0;
templateData.open("003_template.dat", std::ios::in);
//check that the file is opened
if (!templateData.is_open()) {
std::cerr << "Template: Nooooooo!\n";
exit(0);
}
/*************************************************************************************/
//fill the templateVector with the values from templateData
std::vector<std::vector<double> > templateVector;
std::string line;
while (getline(templateData, line, '\n'))
templateVector.push_back(face.splitData(line));
//testing the contents of the templateVector
// cout << "TemplateVector: ";
// for (unsigned i = 0u; i != templateVector.size(); ++i) {
//
// std::cout << "Index[" << i << "] ";
// for(double value : templateVector[i])
// std::cout << value << " ";
// std::cout << "\n";
// }
/*QUERY DATA*/
/************************************************************************************/
std::ifstream inFile("003_AU01_query.dat", std::ios::in);
std::vector<double> queryVector;
double pixel = 0.0;
// Check that the file opened
if (!inFile.is_open()) {
std::cerr << "Query: Nooooooo!\n";
exit(1);
}
// fill the queryVector with the query data
while (inFile >> pixel) {
queryVector.push_back(pixel);
}
inFile.close();
// testing the content of the query vector
// for (unsigned i =0u; i < pixels.size(); i++){
// std::cout << "Index["<< i << "] " << pixels[i];
// }
// std::cout << "\n";
/*OUTPUT SCALAR PRODUCT*/
/****************************************************************************************/
vector<double> theList;
/*break out each of the vectors from the templateVector and compute the scalar product*/
for (auto& vec : templateVector) {
int i;
cout << "\nscalar_product: Index[" << i << "] " << face.scalar_product(vec, queryVector);
theList.push_back(face.scalar_product(vec, queryVector));//fill theList vector with the computations
i++;
std::cout << "\n";
}
//make sure that the sorted products are output with their original index numbers
vector<pair<int, double> > sorted;
sorted.reserve(theList.size());
for(size_t i = 0.00; i != theList.size(); i++){
sorted.push_back(make_pair(theList[i], i));
}
//sort the scalar products and print out the 10 closest neighbors
face.quickSort(sorted);
cout << "\nVector after sort:\n";
for(size_t i = 0; i < 10; i++){
cout << "idx: " << sorted[i].second << " " << "val: " << sorted[i].first << endl;
}
}
A solution in bash:
#!/bin/bash
for file in `ls`
do
./program $file
done
Of course you'd have to modify your main function to take an argument to pass to the fstream constructor:
int main(int argc, char **argv)
{
if (argc != 2)
{
// some error handling code
}
ifstream templateData(argv[1]);
if (!templateData)
{
// more error handling
}
// process the file
}
From your code it is windows.
This code will print all the *.dat file names in your folder:
Instead of printing do whatever you like.
first You'll need to include:
#include <windows.h>
Now to the code:
const wstring dir = L"C:\\Users\\Documents\\NetBeansProjects\\CSCE350";
const wstring ext = L"dat";
wstring findstr = dir;
findstr += L"\\*.";
findstr += ext;
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(findstr.c_str(),&ffd);
do{
if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
wstring path = dir;
path += L"\\";
path += ffd.cFileName;
wcout<< path<<endl;
}
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
EDIT:
On linux you can give your program a parameter path/to/dir/*.dat and you'll get the parameters trough argv, maybe its the better solution.
But if you insist to do it with code it is like this:
includes:
#include <sys/types.h>
#include <dirent.h>
Now the code:
const string dirname = "path/to/dir";
const string ext = ".dat";
DIR *dir;
struct dirent *de;
if((dir = opendir(dirname.c_str())) == NULL) {
//error... check errno and so on
cerr<<"Error..."<<endl;
}else{
while ((de = readdir(dir)) != NULL) {
//you can use stat to check if is is file or dir...
string filename(de->d_name);
if(ext = filename.substr(filename.size()-ext.size())){
cout<<dirname<<"/"<<filename<<endl;
}
}
closedir(dp);
}
Good luck