I have an error in line 58 of the code : Robot robot = robot(seglist[0]...) I have tried different things but nothing works. I need to put the numbers that I have in the txt file into a vector and then assigned the values of robotNum, RobotTeam, robotPosX and robotPosY.
Hope someone can help me.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <vector>
struct Robot {
std::string robotNum;
std::string robotTeam;
std::string robotPosX;
std::string robotPosY;
public:
Robot(string robotNum = "empty", string robotTeam = "empty", string robotPosX = "empty", string robotPosY = "empty") {
this->robotNum = robotNum;
this->robotTeam = robotTeam;
this->robotPosX = robotPosX;
this->robotPosY = robotPosY;
}
};
using namespace std;
string* sortArray(string* myArray) {
//cout << "pingas";
//cout << myArray[6];
return myArray;
}
int main()
{
ifstream myfile;
myfile.open("start.txt");
string line;
std::vector<Robot> myArray;
while (getline(myfile, line))
{
std::istringstream iss(line);
string line;
std::string segment;
std::vector<std::string> seglist;
while (std::getline(iss, segment, ','))
{
seglist.push_back(segment);
}
Robot robot = Robot(seglist[0], seglist[1], seglist[2], seglist[3]);
myArray.push_back(robot);
cout << "\n";
}
if (myfile.is_open()) {
string myArray[2];
for (int i = 0; i < 1; i++)
{
myfile >> myArray[i];
}
//string* arraySorted = sortArray(myArray);
sort(myArray->begin(), myArray->end(), greater<int>());
//for (auto& elem : myArray)
// cout << elem << " - " << endl;
}
//cout << myArray[];
myfile.close();
return 0;
}
in struct definition there should be
std:: namespace
for string in Robot constructor:
public:
Robot(std::string robotNum = "empty", std::string robotTeam = "empty", std::string robotPosX = "empty", std::string robotPosY = "empty") {
after that code works for me.
Related
I have a txt file which contains two txt file references ei. main.txt contains eg1.txt and eg2.txt and i have to access the content in them and find the occurences of every word and return a string with the word and the documents it was preasent in(0 being eg1.txt and 1 being eg2.txt). My program compiles but I can't get past the first word I encounter. It gives the right result (word: 0 1) since the word is preasent in both the files and in the first position but it doesn't return the other words. Could someone please help me find the error? Thank you
string func(string filename) {
map<string, set<int> > invInd;
string line, word;
int fileNum = 0;
ifstream list (filename, ifstream::in);
while (!list.eof()) {
string fileName;
getline(list, fileName);
ifstream input_file(fileName, ifstream::in); //function to iterate through file
if (input_file.is_open()) {
while (getline(input_file, line)) {
stringstream ss(line);
while (ss >> word) {
if (invInd.find(word) != invInd.end()) {
set<int>&s_ref = invInd[word];
s_ref.insert(fileNum);
}
else {
set<int> s;
s.insert(fileNum);
invInd.insert(make_pair<string, set<int> >(string(word) , s));
}
}
}
input_file.close();
}
fileNum++;
}
Basically your function works. It is a little bit complicated, but i works.
After removing some syntax errors, the main problem is, that you do return nothing from you function. There is also no output statement.
Let me show you you the corrected function which shows some output.
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <set>
#include <sstream>
#include <utility>
using namespace std;
void func(string filename) {
map<string, set<int> > invInd;
string line, word;
int fileNum = 0;
ifstream list(filename, ifstream::in);
while (!list.eof()) {
string fileName;
getline(list, fileName);
ifstream input_file(fileName, ifstream::in); //function to iterate through file
if (input_file.is_open()) {
while (getline(input_file, line)) {
stringstream ss(line);
while (ss >> word) {
if (invInd.find(word) != invInd.end()) {
set<int>& s_ref = invInd[word];
s_ref.insert(fileNum);
}
else {
set<int> s;
s.insert(fileNum);
invInd.insert(make_pair(string(word), s));
}
}
}
input_file.close();
}
fileNum++;
}
// Show the output
for (const auto& [word, fileNumbers] : invInd) {
std::cout << word << " : ";
for (const int fileNumber : fileNumbers) std::cout << fileNumber << ' ';
std::cout << '\n';
}
return;
}
int main() {
func("files.txt");
}
This works, I tested it. But maybe you want to return the findings to your main function. Then you should write:
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <set>
#include <sstream>
#include <utility>
using namespace std;
map<string, set<int> > func(string filename) {
map<string, set<int> > invInd;
string line, word;
int fileNum = 0;
ifstream list(filename, ifstream::in);
while (!list.eof()) {
string fileName;
getline(list, fileName);
ifstream input_file(fileName, ifstream::in); //function to iterate through file
if (input_file.is_open()) {
while (getline(input_file, line)) {
stringstream ss(line);
while (ss >> word) {
if (invInd.find(word) != invInd.end()) {
set<int>& s_ref = invInd[word];
s_ref.insert(fileNum);
}
else {
set<int> s;
s.insert(fileNum);
invInd.insert(make_pair(string(word), s));
}
}
}
input_file.close();
}
fileNum++;
}
return invInd;
}
int main() {
map<string, set<int>> data = func("files.txt");
// Show the output
for (const auto& [word, fileNumbers] : data) {
std::cout << word << " : ";
for (const int fileNumber : fileNumbers) std::cout << fileNumber << ' ';
std::cout << '\n';
}
}
Please enable C++17 in your compiler.
And please see below a brushed up solution. A little bit cleaner and compacter, with comments and better variable names.
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <set>
#include <sstream>
#include <utility>
using WordFileIndicator = std::map<std::string, std::set<int>>;
WordFileIndicator getWordsWithFiles(const std::string& fileNameForFileLists) {
// Here will stor the resulting output
WordFileIndicator wordFileIndicator{};
// Open the file and check, if it could be opened
if (std::ifstream istreamForFileList{ fileNameForFileLists }; istreamForFileList) {
// File number Reference
int fileNumber{};
// Read all filenames from the list of filenames
for (std::string fileName{}; std::getline(istreamForFileList, fileName) and not fileName.empty();) {
// Open the files to read their content. Check, if the file could be opened
if (std::ifstream ifs{ fileName }; ifs) {
// Add word and associated file number to set
for (std::string word{}; ifs >> word; )
wordFileIndicator[word].insert(fileNumber);
}
else std::cerr << "\n*** Error: Could not open '" << fileName << "'\n\n";
// Continue with next file
++fileNumber;
}
}
else std::cerr << "\n*** Error: Could not open '" << fileNameForFileLists << "'\n\n";
return wordFileIndicator;
}
// Some test code
int main() {
// Get result. All words and in which file they exists
WordFileIndicator data = getWordsWithFiles("files.txt");
// Show the output
for (const auto& [word, fileNumbers] : data) {
std::cout << word << " : ";
for (const int fileNumber : fileNumbers) std::cout << fileNumber << ' ';
std::cout << '\n';
}
}
There would be a much faster solution by using std::unordered_map and std::unordered_set
Please make sure your code is composed from many small functions. This improves readability, it easier to reason what code does, in such form parts of code can be reused in alternative context.
Here is demo how it can looks like and why it is better to have small functions:
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>
#include <vector>
struct FileData
{
std::filesystem::path path;
int index;
};
bool operator==(const FileData& a, const FileData& b)
{
return a.index == b.index && a.path == b.path;
}
bool operator!=(const FileData& a, const FileData& b)
{
return !(a == b);
}
using WordLocations = std::unordered_map<std::string, std::vector<FileData>>;
template<typename T>
void mergeWordsFrom(WordLocations& loc, const FileData& fileData, T b, T e)
{
for (; b != e; ++b)
{
auto& v = loc[*b];
if (v.empty() || v.back() != fileData)
v.push_back(fileData);
}
}
void mergeWordsFrom(WordLocations& loc, const FileData& fileData, std::istream& in)
{
return mergeWordsFrom(loc, fileData, std::istream_iterator<std::string>{in}, {});
}
void mergeWordsFrom(WordLocations& loc, const FileData& fileData)
{
std::ifstream f{fileData.path};
return mergeWordsFrom(loc, fileData, f);
}
template<typename T>
WordLocations wordLocationsFromFileList(T b, T e)
{
WordLocations loc;
FileData fileData{{}, 0};
for (; b != e; ++b)
{
++fileData.index;
fileData.path = *b;
mergeWordsFrom(loc, fileData);
}
return loc;
}
WordLocations wordLocationsFromFileList(std::istream& in)
{
return wordLocationsFromFileList(std::istream_iterator<std::filesystem::path>{in}, {});
}
WordLocations wordLocationsFromFileList(const std::filesystem::path& p)
{
std::ifstream f{p};
f.exceptions(std::ifstream::badbit);
return wordLocationsFromFileList(f);
}
void printLocations(std::ostream& out, const WordLocations& locations)
{
for (auto& [word, filesData] : locations)
{
out << std::setw(10) << word << ": ";
for (auto& file : filesData)
{
out << std::setw(3) << file.index << ':' << file.path << ", ";
}
out << '\n';
}
}
int main()
{
auto locations = wordLocationsFromFileList("files.txt");
printLocations(std::cout, locations);
}
https://wandbox.org/permlink/nBbqYV986EsqvN3t
I need to create a sort algorithm that takes an array called myArray where there is information from a txt file called start.txt. The problem is that I have inside the txt file many vectors like this: 2 2 30 30, where the first number is the robot number, the second the team, and the last two are the x and y position. I only need to order them in ascending order taking the robot number, but the output has to be the whole vector. Any ideas on how to do it?
#include "robot.h"
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <vector>
//class Robot {
// std::string robotNum;
// std::string robotTeam;
// std::string robotPosX;
// std::string robotPosY;
// public:
// Robot(std::string robotNum, std::string robotTeam, std::string robotPosX, std::string robotPosY) {
// this->robotNum = robotNum;
// this->robotTeam = robotTeam;
// this->robotPosX = robotPosX;
// this->robotPosY = robotPosY;
// }
// std::string getRobotNum() {
// return this->robotNum;
// }
// void setRobotNum(std::string robotNum) {
// this->robotNum;
// }
//};
//void bubbleSort(std::vector<Robot> myArray, int n) {
//int i, j;
//for (i= 0; i<n-1; i++)
//}
using namespace std;
string line;
std::vector<robot> myArray;
//string* sortArray(string* myArray) {
//bool sortByNum(const robot& lhs, const robot& rhs) { return lhs.robotNum < rhs.robotNum; }
//return myArray;
//}
void show() {
ifstream myfile;
myfile.open("start.txt");
//string line;
//std::vector<robot> myArray;
while (getline(myfile, line))
{
std::istringstream iss(line);
string line;
std::string segment;
std::vector<std::string> seglist;
while (std::getline(iss, segment, ' '))
{
seglist.push_back(segment);
}
//std::vector<robot> myArray;
robot robot(seglist[0], seglist[1], seglist[2], seglist[3]);
myArray.push_back(robot);
cout << seglist[0] << " " << seglist[1] << " " << seglist[2] << " " << seglist[3] << "\n";
//myArray[0].getRobotNum();
//for (robot &r : myArray)
// std::cout << r.getRobotNum() << " _ " << std::endl;
//for (unsigned int i = 0; i <= unsigned(myArray.size()); i++) {
//}
cout << "\n";
}
//cout << myArray[];
myfile.close();
}
int main()
{
show();
return 0;
}
Use std::sort with a custom comparator that only looks at the robot number
#include <algorithm>
std::vector<robot> myArray;
...
sort(myArray.begin(), myArray.end(),
[](const robot& x, const robot& y) { return x.getRobotNum() < y.getRobotNum(); }
);
The piece starting with [] is a lambda function that compares two robots using the robot number. This function is passed to std::sort which uses it to sort your vector.
When I was trying to run the program Visual Studio threw the error like this: " Error: Unable to open file C:\Users...\test1\Debug\investment.obj. Error code = 0x80070002.
I have tried many ways mentioned online but still not working. So, I was thinking if there was any problem in the code.
What's going on? Please help.
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <numeric>
using namespace std;
struct Investment
{
string Name;
string BankAccount;
string SortCode;
float Investment;
float Contribution;
};
string Trim(string str)
{
str.erase(0, str.find_first_not_of(" \t\r\n"));
str.erase(str.find_last_not_of(" \t\r\n") + 1);
return str;
}
void Get_Data(const string& filename, vector<Investment>& data)
{
ifstream fin(filename);
if (!fin.is_open())
return;
string line;
if (!getline(fin, line))
return;
while (getline(fin, line))
{
istringstream sin(line);
vector<string> fields;
string field;
while (getline(sin, field, ','))
{
fields.push_back(field);
}
Investment inv;
inv.Name = Trim(fields[0]);
inv.BankAccount = Trim(fields[1]);
inv.SortCode = Trim(fields[2]);
inv.Investment = atof(Trim(fields[3]).c_str());
inv.Contribution = 0.0f;
data.push_back(inv);
}
}
void Save_Data(const string& filename, const vector<Investment>& data)
{
ofstream fout(filename);
if (!fout.is_open())
return;
fout << "NAME, BANK ACCOUNT, SORT CODE, INVESTMENT, Contribution\n";
for (auto& inv : data)
{
fout << inv.Name << " "
<< inv.BankAccount << " "
<< inv.SortCode << " "
<< inv.Investment << " "
<< inv.Contribution << "\n";
}
}
int main()
{
vector<Investment> Data_investment;
Get_Data("aaa.csv", Data_investment);
float total = accumulate(Data_investment.begin(), Data_investment.end(), 0.0f,[](float sum, const Investment& inv) { return sum + inv.Investment; }
);
for (auto& inv : Data_investment)
{
float percentage = (inv.Investment * 100.0f) / total;
inv.Contribution = percentage;
}
Save_Data("aaa_new.csv", Data_investment);
return 0;
}
I have successfully compiled your source code into Visual Studio 2017 with very slight modification. Please have a look.
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <numeric>
using namespace std;
struct Investment
{
std::string Name;
std::string BankAccount;
std::string SortCode;
float Invest; // Changed due the variable name goes same as struct name if use Investment
float Contribution;
};
string Trim(string &str)
{
str.erase(0, str.find_first_not_of(" \t\r\n"));
str.erase(str.find_last_not_of(" \t\r\n") + 1);
return str;
}
void Get_Data(const string& filename, vector<Investment>& data)
{
ifstream fin(filename);
if (!fin.is_open())
return;
string line;
if (!getline(fin, line))
return;
while (getline(fin, line))
{
istringstream sin(line);
vector<string> fields;
string field;
while (getline(sin, field, ','))
{
fields.push_back(field);
}
Investment inv;
inv.Name = Trim(fields[0]);
inv.BankAccount = Trim(fields[1]);
inv.SortCode = Trim(fields[2]);
inv.Invest = atof(Trim(fields[3]).c_str());
inv.Contribution = 0.0f;
data.push_back(inv);
}
}
void Save_Data(const string& filename, const vector<Investment>& data)
{
ofstream fout(filename);
if (!fout.is_open())
return;
fout << "NAME, BANK ACCOUNT, SORT CODE, INVESTMENT, Contribution\n";
for (auto& inv : data)
{
fout << inv.Name << " "
<< inv.BankAccount << " "
<< inv.SortCode << " "
<< inv.Invest << " "
<< inv.Contribution << "\n";
}
}
int main()
{
vector<Investment> Data_investment;
Get_Data("aaa.csv", Data_investment);
float total = accumulate(Data_investment.begin(), Data_investment.end(), 0.0f, [](float sum, const Investment& inv) { return sum + inv.Invest; }
);
for (auto& inv : Data_investment)
{
float percentage = (inv.Invest * 100.0f) / total;
inv.Contribution = percentage;
}
Save_Data("aaa_new.csv", Data_investment);
return 0;
}
Below is the modified part
std::string Name;
std::string BankAccount;
std::string SortCode;
float Invest; // Changed due the variable name goes same as struct name if use Investment
Here is the codeshare link of the exact input file: https://codeshare.io/5DBkgY
Ok, as you can see, there are 2 blank lines, (or tabs) between 8 and ROD. How would I skip that and continue with the program? I am trying to put each line into 3 vectors (so keys, lamp, and rod into one vector etc). Here is my code (but it does not skip the blank line).:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <fstream>
using namespace std;
int main() {
ifstream objFile;
string inputName;
string outputName;
string header;
cout << "Enter image file name: ";
cin >> inputName;
objFile.open(inputName);
string name;
vector<string> name2;
string description;
vector<string> description2;
string initialLocation;
vector<string> initialLocation2;
string line;
if(objFile) {
while(!objFile.eof()){
getline(objFile, line);
name = line;
name2.push_back(name);
getline(objFile, line);
description = line;
description2.push_back(description);
getline(objFile, line);
initialLocation = line;
initialLocation2.push_back(initialLocation);
} else {
cout << "not working" << endl;
}
for (std::vector<string>::const_iterator i = name2.begin(); i != name2.end(); ++i)
std::cout << *i << ' ';
for (std::vector<string>::const_iterator i = description2.begin(); i != description2.end(); ++i)
std::cout << *i << ' ';
for (std::vector<string>::const_iterator i = initialLocation2.begin(); i != initialLocation2.end(); ++i)
std::cout << *i << ' ';
#include <cstddef> // std::size_t
#include <cctype> // std::isspace()
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
bool is_empty(std::string const &str)
{
for (auto const &ch : str)
if (!std::isspace(static_cast<char unsigned>(ch)))
return false;
return true;
}
int main()
{
std::cout << "Enter image file name: ";
std::string filename;
std::getline(std::cin, filename); // at least on Windows paths containing whitespace
// are valid.
std::ifstream obj_file{ filename }; // define variables as close to where they're used
// as possible and use the ctors for initialization.
if (!obj_file.is_open()) { // *)
std::cerr << "Couldn't open \"" << filename << "\" for reading :(\n\n";
return EXIT_FAILURE;
}
std::vector<std::string> name;
std::vector<std::string> description;
std::vector<std::string> initial_location;
std::string line;
std::vector<std::string> *destinations[] = { &name, &description, &initial_location };
for (std::size_t i{}; std::getline(obj_file, line); ++i) {
if (is_empty(line)) { // if line only consists of whitespace
--i;
continue; // skip it.
}
destinations[i % std::size(destinations)]->push_back(line);
}
for (auto const &s : name)
std::cout << s << '\n';
for (auto const &s : description)
std::cout << s << '\n';
for (auto const &s : initial_location)
std::cout << s << '\n';
}
... initial_locations look like integers, though.
*) Better early exit if something bad happens. Instead of
if (obj_file) {
// do stuff
}
else {
// exit
}
-->
if(!obj_file)
// exit
// do stuff
makes your code easier to read and takes away one level of indentation for the most parts.
I am completely lost and have been trying for hours to read from a file named "movies.txt" and storing the info from it into arrays, because it has semicolons. Any help? Thanks.
movies.txt:
The Avengers ; 2012 ; 89 ; 623357910.79
Guardians of the Galaxy ; 2014 ; 96 ; 333130696.46
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
int main()
{
const int MAX_SIZE = 100;
Movie movieList[MAX_SIZE];
std::string line;
int i = 0;
std::ifstream movieFile;
movieFile.open("movies.txt");
while (getline(movieFile, line, ';'))
{
movieFile >> movieList[i].name >> movieList[i].year >> movieList[i].rating >> movieList[i].earnings;
i++;
}
movieFile.close();
std::cout << movieList[0].name << " " << movieList[0].year << " " << movieList[0].rating << " " << movieList[0].earnings << std::endl;
std::cout << movieList[1].name << " " << movieList[1].year << " " << movieList[1].rating << " " << movieList[1].earnings << std::endl;
return 0;
}
What I want is to have:
movieList[0].name = "The Avengers";
movieList[0].year = 2012;
movieList[0].rating = 89;
movieList[0].earnings = 623357910.79;
movieList[1].name = "Guardians of the Galaxy";
movieList[1].year = 2014;
movieList[1].rating = 96;
movieList[1].earnings = 333130696.46;
I amended your code.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
std::vector<std::string>
split(const std::string &s, char delim = ',')
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
int main()
{
std::vector<Movie> movieList;
std::string line;
std::ifstream movieFile;
movieFile.open("movies.txt");
while (getline(movieFile, line))
{
std::vector<std::string> columns = split(line,';');
Movie movie;
movie.name = columns[0];
movie.year = std::stoi(columns[1]);
movie.rating = std::stoi(columns[2]);
movie.earnings = std::stof(columns[3]);
movieList.push_back(movie);
}
movieFile.close();
for (const Movie & m: movieList)
{
std::cout << m.name << " " << m.year << " " << m.rating << " " << m.earnings << std::endl;
}
return 0;
}
Basicly, I added a split function that splits the lines using ';'. Also I use vector to store the movies rather than hard coded array of movies. Much better this way.
P.S. Second version without vectors
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
void split(const std::string &s, char delim, std::string elems[])
{
std::stringstream ss(s);
std::string item;
int i = 0;
while (std::getline(ss, item, delim))
{
elems[i++] = item;
}
}
int main()
{
//std::vector<Movie> movieList;
const int MAX_SIZE = 100;
Movie movieList[MAX_SIZE];
int movieNo = 0;
std::string line;
std::ifstream movieFile;
movieFile.open("/home/marcin/testing/movies.txt");
std::string columns[4];
while (getline(movieFile, line))
{
split(line,';', columns);
movieList[movieNo].name = columns[0];
movieList[movieNo].year = std::stoi(columns[1]);
movieList[movieNo].rating = std::stoi(columns[2]);
movieList[movieNo].earnings = std::stof(columns[3]);
++movieNo;
}
movieFile.close();
for (int i =0; i < movieNo; ++i) {
std::cout << movieList[i].name
<< " "
<< movieList[i].year
<< " "
<< movieList[i].rating
<< " "
<< movieList[i].earnings
<< std::endl;
}
return 0;
}
Use getline(my_movieFile, movie_name, ';') to get the name of the movie up to the ;.
You'll need to figure out how to remove the trailing whitespace from the name if necessary.. you can search for examples.
Read the rest of the line using getline(movieFile, line)
Use std::replace to replace all ; with a space in line
Put line into a std::stringstream.
Then extract the remaining fields from the stringstream using the >> operators.
Put this in loop do { ... } while (movieFile);
Also, don't hardcode an arbitrary number of movies. Use a std::vector<Movie> and push_back to add new ones.
I think you want to break your line into tokens using something like std::strtok. Check out the reference here. The example given on that page uses a blank as a separator, you would use a semicolon.