I am having trouble reading a file to my class object's members. It says it cannot read the file.
This is my class:
const int SIZE_OF = 5;
class Student
{
public:
Student();
Student(const Student &);
Student(string, int, int, int, int, int);
friend std::istream& operator >> (std::istream& in, Student& S);
void display();
private:
string lastName;
int grades[SIZE_OF];
};
The cpp file associated with my class object to define the functions:
#include "Student.h"
Student::Student()
{
int i;
string lastName = "default";
for (i = 0; i < 5; i++)
{
grades[i] = 0;
}
}
Student::Student(const Student & S)
{
int i;
lastName = S.lastName;
for (i = 0; i < 5; i++)
{
grades[i] = S.grades[i];
}
}
Student::Student(string S, int a, int b, int c, int d, int e)
{
lastName = S;
grades[0] = a;
grades[1] = b;
grades[2] = c;
grades[3] = d;
grades[4] = e;
}
std::istream& operator >> (std::istream& in, Student& S)
{
char dummy;
in >> S.lastName >> S.grades[0]
>> dummy >> S.grades[1]
>> dummy >> S.grades[2]
>> dummy >> S.grades[3]
>> dummy >> S.grades[4];
return in;
}
void Student::display()
{
int i;
int sum = 0;
double average;
cout << "Last Name: " << lastName << endl;
cout << "Grades: " << endl;
for (i = 0; i < 5; i++)
{
cout << grades[i] << endl;
}
for (i = 0; i < 5; i++)
{
sum = sum + grades[i];
}
average = sum / 5;
cout << "Average: " << average;
}
And finally, the main function that I have so far to test the file opening and reading it to the various variables inside the class.
void main()
{
fstream File;
string FileName = "ProgramSixData.txt";
bool FoundFile;
string Line;
Student testStudent;
do {
File.open(FileName, ios_base::in | ios_base::out);
FoundFile = File.is_open();
if (!FoundFile)
{
cout << "Could not open file named " << FileName << endl;
File.open(FileName, ios_base::out); // try to create it
FoundFile = File.is_open();
if (!FoundFile)
{
cout << "Could not create file named " << FileName << endl;
exit(0);
}
else;
}
else;
} while (!FoundFile);
do {
File >> testStudent;
if (File.fail())
{
cout << "Read Failed" << endl;
cout << "Bye" << endl;
exit(0);
}
else;
testStudent.display();
} while (!File.eof());
cout << "Bye" << endl;
File.close();
}
The text document that I am reading from is the following:
George
75,85,95,100,44
Peter
100,100,100,100,100
Frank
44,55,66,77,88
Alfred
99,88,77,66,55
How do I save each of the names and the associated 5 grades to a particular object of the student class?
You are digging too deep. I made an example solution for you, focusing on the parsing. Things could be way shorter and we could instantly make the students instead of doing it the map way, but I want you to understand how to parse the file, because that is obviously what you are struggling with. Ask me anything about the code if you don't understand it.
void main()
{
string FileName = "ProgramSixData.txt";
bool FoundFile;
string Line;
vector<Student> Students;
ifstream file(FileName); //an ifstream is an INPUTstream (same as a fstream with ::in flag. Passing the FileName as argument opens that file
if (file.fail()) //check if the file opened correctly
{
cout << "Failed to open inputfile\n";
return;
}
map <string, vector<int>> studentAndGrades; //map is a container that uses keys and values, every key has a value, we will use the name of the student as the key to access his marks (a vector of int)
vector<string> allLines;
string line;
while (file >> line) //these 2 linessimply reads ALL the lines to the allLines vector
allLines.push_back(line);
for (size_t i = 0; i < allLines.size(); i += 2) //loop over all lines, by 2 at a time (1 for the students name and 1 for his marks)
{
vector<int> numbers;
size_t lastCommaIdx = 0;
size_t currentCount = 0;
string scores(allLines[i + 1]); //make a copy of allLines[i + 1] for convenient use
bool firstLine = true;
for (size_t i = 0; i < scores.size(); ++i) //following code is just to split the numbers from the comma's and put them in a vector of int
{
if (scores[i] == ',')
{
if (firstLine)
{
numbers.push_back(stoi(scores.substr(lastCommaIdx, currentCount)));
firstLine = false;
}
else
{
numbers.push_back(stoi(scores.substr(lastCommaIdx + 1, currentCount)));
}
lastCommaIdx = i;
currentCount = 0;
}
else
{
++currentCount;
}
}
numbers.push_back(stoi(scores.substr(lastCommaIdx + 1))); //last number
studentAndGrades.insert(make_pair(allLines[i], numbers)); //finally, insert them in the map
}
for (const auto& student : studentAndGrades)
Students.push_back(Student(student.first, student.second[0], student.second[1], student.second[2], student.second[3], student.second[4])); //make students from the information that we read into the map
for (auto& student : Students) //display all students with a range based for loop
student.display();
file.close();
}
Related
I have a class Employees. I'm trying to make the user insert and delete an employee but it's not working. The size of the vectors should be 500.
class Employees{
public:
int maxx = 500;
vector<string> Surname;
vector<string> FirstName;
vector<string> birthdate;
int vacation[500];
public:
Employees() : Surname(500) {}
};
This is the function that inserts, but printing elements of the vectors is not working at all:
void Process(Employees ZZ){
string dateyear;
string datemonth;
string dateday;
int dateyear1;
int datemonth1;
int dateday1;
int Realage;
int Vacationi = 0;
for(int i = 0; i < 500; i++) {
string s;
cin >> s;
string d;
cin >> d;
string c;
cin >> c;
ZZ.Surname.push_back(s);
ZZ.FirstName.push_back(d);
ZZ.birthdate.push_back(c);
cout << endl << ZZ.Surname[1] << endl;
}
Now the delete function, if I input a string then search for it in the vector then get his index then delete, but the vector doesn't update any values.
void DeleteEmployee(Employees ZZ){
cout<< endl << ZZ.Surname[1] << endl ;
for (int i = 0; i < ZZ.Surname.size(); i++){
cout << ZZ.Surname[i] ;
}
cout << " delete employee";
string delete1;
cin >> delete1;
auto it = std::find(ZZ.Surname.begin(), ZZ.Surname.end(), delete1);
if (it == ZZ.Surname.end())
{
cout<< " name not in vector " << endl;
}
else
{
//auto index = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_)));
//ZZ.Surname.erase(ZZ.Surname.begin()+index) ;
}
}
This is the main function, also the values of the vector are not printing:
int main()
{
Employees ZZ;
Process(ZZ);
DeleteEmployee(ZZ);
cout << "fyccck";
for (int i = 0; i < ZZ.Surname.size(); i++){
cout << ZZ.Surname[i] ;
}
}
There are a lot of things wrong with this code. But the particular issue you are asking about is caused by your functions passing the Employees object by value, so a copy is made, and any changes you make to the copy are not reflected in the original object in main().
You need to change the parameters to pass the Employees object by reference instead:
void Process(Employees &ZZ)
void DeleteEmployee(Employees &ZZ)
That being said, the whole design of the code is not good in general. The vectors are not being kept in sync properly, and for that matter you are using more vectors then you actually need, 1 single vector will suffice. And Process() and DeleteEmployee() should be members of the Employees class, not separate functions. And they are both accessing out-of-bounds of the Surname vector.
I would suggest completely rewriting the code from scratch, for instance something more like this:
struct Employee{
string Surname;
string FirstName;
string BirthDate;
int Vacation;
string DisplayName() const { return Surname + ", " + FirstName; }
};
class Employees{
public:
static const int maxx = 500;
vector<Employee> employees;
Employees() { employees.reserve(maxx); }
bool Add(const Employee &e);
bool Delete(string Surname, string FirstName);
};
bool Employees::Add(const Employee &e) {
if (employees.size() < maxx) {
employees.push_back(e);
return true;
}
return false;
}
bool Employees::Delete(string Surname, string FirstName) {
auto it = std::find_if(employees.begin(), employees.end(),
[&](const Employee &e){
return e.Surname == Surname && e.FirstName == FirstName;
}
);
if (it != employees.end()) {
employees.erase(it);
return true;
}
return false;
}
int main()
{
Employees ZZ;
for(int i = 0; i < Employees::maxx; ++i) {
Employee e;
cin >> e.Surname;
cin >> e.FirstName;
cin >> e.BirthDate;
e.Vacation = 0;//cin >> e.Vacation;
ZZ.Add(e);
cout << endl << e.DisplayName() << endl;
}
cout << " delete employee";
string Surname, FirstName;
if (cin >> Surname >> FirstName) {
if (ZZ.Delete(Surname, FirstName)) {
cout << " name deleted from vector " << endl;
} else {
cout << " name not in vector " << endl;
}
}
cout << "fyccck";
for (auto &e : ZZ.employees) {
cout << e.DisplayName() << endl;
}
return 0;
}
So I am doing a school project that requires me to execute my program with arguments and display the contents of a file based on a particular action.
This is done by simply requesting the action after the file name is specified.
It is:
./executable_name 'filename' 'action'
actions include list or find. List will list all the book contents of the specific file in that order and find will find a book by it's ISBN number specified.
Now my error lies with the find function, more specifically how i compare the Strings. I cannot compare the strings within the "find" function for the life of me. Ive tried "strcmp()" with the ".c_str()", I've tried "==", I've tried "string.copmare(string2)", and nothing. I have developed some interesting clues though.
If I try to print the string from my array of arguments concatenated with a few letters it properly does some expected printing, BUT if I perform the same action from the struct instance of any particular book array it seems to be overwritten like a return carriage type.
EX:
argv[4] = 0-201-60464-7 near here
books[0].isbn = near here-60464-7
Driver File
##include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = argv[1];
int filesRead = read (filename, books);
if(string(argv[2])== "list")
{
for(int index =0;index < filesRead; index++ )
{
cout << books[index].title << endl;
cout << books[index].authorCount<< endl;
for(int j =0; j < books[index].authorCount; j++)
{
cout << books[index].authors[j] << endl;
}
cout << books[index].publisher <<endl;
cout << books[index].yearPublish <<endl;
cout << books[index].hardcover << endl;
cout << books[index].price << endl;
cout << books[index].isbn << endl;
cout << books[index].copies << endl;
}
}
if(argc > 3)
{
if(string(argv[2]) == "find")
{
int book_index = find(argv[3], books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
}
}
Function file
#include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
Header File
// #file book.h
#ifndef BOOK_H
#define BOOK_H
#include <string>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
/**
* #param filename name of the input data file
* #param books[] an array of textbook records read from the file
*
* #return the number of textbook records read
*/
int read (string filename, Book books[]);
/**
* #param id the ISBN number to search for
* #param books[] the list of textbook records
* #param length the number of textbook records in the array
*
* #return the array index of the matching record, otherwise it returns -1
*/
int find (string id, Book books[], int length);
#endif /* BOOK_H */
condensed Code
e
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
int filesRead = read (filename, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
test file in txt or dat whichever extension preferred
#file.txt
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
refactored to one compilation unit and zero test files.
Fixed logic errors
added some (hopefully explanatory) comments
added handling of windows-style line endings for increased portability
Note: Avoid the use of using namespace at global scope. A reasonable exception to this rule is using namespace std::literals;
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
#include <sstream>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
void strip(std::string& str)
{
if (str.size() && str.back() == '\r')
{
str.pop_back();
}
}
std::istream& get_line_and_strip(std::istream& is, std::string& result)
{
std::getline(is, result);
strip(result);
return is;
}
// be specific about the bounds of the output variable.
int read (std::istream& inputFile, Book books[35])
{
//validation for the file itself
if(!inputFile)
{
std::cout << "File does not exist!" << std::endl;
// avoid UB by returning a value as per the function signature
return 0;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
std::string consume_line;
while(counter < 35)
{
get_line_and_strip(inputFile, books[counter].title);
inputFile >> books[counter].authorCount;
std::getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
get_line_and_strip(inputFile, books[counter].authors[j]);
}
get_line_and_strip(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
std::getline(inputFile, consume_line);
inputFile >> books[counter].hardcover;
std::getline(inputFile, consume_line);
inputFile >> books[counter].price;
std::getline(inputFile, consume_line);
get_line_and_strip(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
std::getline(inputFile, consume_line);
if(!inputFile) // tests for EOF or error during input
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[35], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
auto test_data = ""
"C++ Network Programming – Volume 1\r\n"
"2\r\n"
"Douglas C. Schmidt\r\n"
"Stephen D. Huston\r\n"
"Addison-Wesley\r\n"
"2002\r\n"
"0\r\n"
"35.99\r\n"
"0-201-60464-7\r\n"
"236\r\n"
""s;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
auto test_file = std::istringstream(test_data);
int filesRead = read (test_file, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
// would be invalid to continue if book not found
return 0;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j] <<endl;
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
Expected output:
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
https://coliru.stacked-crooked.com/a/9b08598ffcd0edc2
So I have a .txt file looking like this:
1:Meat Dish:Steak:11.5
2:Fish Dish:Fish and chips:12
The first number is the itemNo, 'Meat Dish' is my category, 'Steak' is my description and finally '11.5' is my price.
So basically I want to search for the itemNo and I want it to display the price from that line. This is what I have until now:
#include <iostream>
#include <fstream>
#include <string>
#include <vector> // We will use this to store Players
using std::string;
using std::ofstream;
using std::ifstream;
using std::cout;
using std::cin;
struct MenuList // Define a "Player" data structure
{
string itemNo;
string category;
string descript;
double price;
};
std::istream& operator>>(std::istream& infile, MenuList& menu)
{
// In this function we will define how information is inputted into the player struct
// std::cin is derived from the istream class
getline(infile, menu.itemNo, ':');
getline(infile, menu.category, ':');
getline(infile, menu.descript, ':');
infile >> menu.price;
// When we have extracted all of our information, return the stream
return infile;
}
std::ostream& operator<<(std::ostream& os, MenuList& menu)
{
// Just like the istream, we define how a player struct is displayed when using std::cout
os << "" << menu.itemNo << " " << menu.category << " - " << menu.descript;
// When we have extracted all of our information, return the stream
return os;
}
void Load(std::vector<MenuList>& r, string filename)
{
std::ifstream ifs(filename.c_str()); // Open the file name
if(ifs)
{
while(ifs.good()) // While contents are left to be extracted
{
MenuList temp;
ifs >> temp; // Extract record into a temp object
r.push_back(temp); // Copy it to the record database
}
cout << "Read " << r.size() << " records.\n\n";
}
else
{
cout << "Could not open file.\n\n";
}
}
void Read(std::vector<MenuList>& r) // Read record contents
{
for(unsigned int i = 0; i < r.size(); i++)
cout << r[i] << "\n";
}
void Search(std::vector<MenuList>& r) // Search records for name
{
string n;
cout << "Search for: ";
cin >> n;
for(int i = 0; i < r.size(); i++)
{
if(r[i].itemNo.find(n) != string::npos)
cout << r[i];
}
}
int main()
{
std::vector<MenuList> records;
Load(records, "delete.txt");
Read(records);
Search(records);
return 0;
}
I don't really know how to make it so it shows just the price without showing the whole line.
I have written my own code that reads in your text file and stores the information in a struct. Once you have a vector of MenuList, it is dead simple to only print what you want.
include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
struct MenuList // Define a "Player" data structure
{
string itemNo;
string category;
string descript;
double price;
};
void addToList(vector<MenuList*>& vector_menu_list, string& itemNo, string& category, string& descript, string& price)
{
MenuList* p_menu_list = new MenuList;
p_menu_list->itemNo = itemNo;
p_menu_list->category = category;
p_menu_list->descript = descript;
p_menu_list->price = std::stod(price);
vector_menu_list.push_back(p_menu_list);
}
vector<MenuList*> readFile(string filename, bool& error_encountered)
{
vector<MenuList*> vector_menu_list;
ifstream file;
file.open(filename);
if (file.is_open())
{
string itemNo;
string category;
string descript;
string price;
short number_of_colons_encountered = 0;
char c;
while (file.get(c))
{
if ('\n' != c && EOF != c)
{
if (':' == c)
{
number_of_colons_encountered++;
continue;
}
switch (number_of_colons_encountered)
{
case 0:
itemNo += c;
break;
case 1:
category += c;
break;
case 2:
descript += c;
break;
case 3:
price += c;
break;
default:
error_encountered = true;
file.close();
return vector_menu_list;
}
}
else
{
addToList(vector_menu_list, itemNo, category, descript, price);
itemNo.clear();
category.clear();
descript.clear();
price.clear();
number_of_colons_encountered = 0;
}
}
addToList(vector_menu_list, itemNo, category, descript, price);
error_encountered = false;
}
else
{
error_encountered = true;
}
file.close();
return vector_menu_list;
}
int main()
{
bool error_encountered;
vector<MenuList*> p_menu_list = readFile("menu list.txt", error_encountered);
if (true == error_encountered)
{
return -1;
}
cout << "List menu items:" << endl;
for (unsigned long long i = 0; i < p_menu_list.size(); i++)
{
cout << p_menu_list.at(i)->itemNo << " ";
cout << p_menu_list.at(i)->category << " ";
cout << p_menu_list.at(i)->descript << " ";
cout << p_menu_list.at(i)->price << endl;
}
cout << "\n\nHere are only the prices: " << endl;
for (unsigned long long i = 0; i < p_menu_list.size(); i++)
{
cout << p_menu_list.at(i)->price << endl;
}
for (unsigned long long i = 0; i < p_menu_list.size(); i++)
{
delete p_menu_list.at(i);
}
return 0;
}
struct LLGM{
float Lat;
float Long;
};
int main ()
{
string Filename;
int count = 0;
string value;
string temp;
ifstream infile2;
Filename = "LLMGReadingsv2.csv";
infile2.open(Filename);
if(infile2.fail())
{
cout << "Error opening file" << endl;
exit(1);
}
while(!infile2.eof())
{
getline(infile2, temp, ',');
count++;
}
cout << count << endl;
cout << endl;
infile2.close();
ifstream infile;
infile.open(Filename);
LLGM *points;
points = new LLGM [count];
for (int i = 0; i < count; i++)
{
infile >> points[i].Lat;
infile >> points[i].Long;
cout << points[i].Lat;
cout << points[i].Long;
}
cout << endl;
return 0;
}
My question is, how can I assign the values being read in from the CSV file to individual variables?
For Example:
35.123445,-85.888762 (values in one row from the file)
I would like the first number before the comma to be Latitude, and the second value to be Longitude.
Any help would be greatly appreciated!
You can create your own std::ctype facet that will interpret the comma character as the delimiter. Then you can imbue it on your file stream and insert the contents of that stream into the array.
#include <iostream>
#include <locale>
#include <sstream>
struct my_facet : std::ctype<wchar_t>
{
bool do_is(mask m, char_type c) const
{
if ((m & space) && c == L' ') {
return false;
}
if ((m & space) && c == L',')
{
return true;
}
return ctype::do_is(m, c);
}
};
int main()
{
std::wifstream infile(Filename);
infile.imbue(std::locale(infile.getloc(), new my_facet));
for (int i = 0; i < count; ++i)
{
if ((infile >> points[i].Lat) && (infile >> points[i].Long))
{
std::wcout << points[i].Lat;
std::wcout << points[i].Long;
}
}
}
Here is a demo that uses a stringstream instead of a file (for demonstrating purposes only).
I need to merge two text files and have them sort by "lastName" on a third outputted file. My code is below, it is outputting gibberish, all on one line. I understand my overload may be stupid, any help is appreciated.
//header
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
struct mergedList {
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator << (ostream& os, mergedList A) {
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >> (istream& is, mergedList& A) {
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
void swap(mergedList D1[], int i, int j);
void sort(mergedList D1[], int size);
int main() {
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merge1.txt");
indata2.open("merge2.txt");
outdata.open("merged.txt");
//begin sentinel controlled loop for both lists
mergedList D1[100];
int index = 0;
indata >> D1[index];
while (!indata.eof()) {
index++;
indata >> D1[index];
}
sort(D1, index);
mergedList D2[100];
int index2 = 0;
indata2 >> D2[index2];
while (!indata2.eof()) {
index2++;
indata2 >> D2[index2];
}
sort(D2, index); {
int i = 0, j = 0;
while ((i < index) && (j < index2)) if (D1[i].lastName < D2[j].lastName) {
outdata << D1[i];
i++;
indata >> D1[i];
} else {
outdata << D2[j];
j++;
indata2 >> D2[j];
}
}
indata.close();
indata2.close();
outdata.close();
return 0;
}
void swap(mergedList D1[], int i, int j) {
mergedList temp;
temp = D1[i];
D1[i] = D1[j];
D1[j] = temp;
return;
}
void sort(mergedList D1[], int size) {
for (int p = 1; p < size; p++) {
for (int c = 0; c < size - p; c++) {
if (D1[c].lastName > D1[c + 1].lastName) swap(D1, c, c + 1);
}
}
return;
}
Here is some code. I have tried to explain as much as I can. If you are using C++ you should try to take advantage of the containers and algorithms that are already available for you.
struct mergedList
{
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator <<(ostream& os, mergedList A)
{
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >>(istream& is, mergedList& A)
{
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
// We use this to compare two MergedList structs. i.e. by first name
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
struct my_sorter {
bool operator() (mergedList one, mergedList two) { return one.firstName < two.firstName ; }
};
int main()
{
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merged.txt");
indata2.open("merged2.txt");
outdata.open("merged.txt");
// This can be a vector. No need for array here.
vector<mergedList> D1;
int index=0, index2 = 0;
mergedList tmp;
// You can read from streams like this if the data is formatted.
while (indata >> tmp)
{
D1.push_back(tmp);
index++; // Maybe you need this??
}
// Read the second file in to the same vector.
// You don't need another one.
while (indata2 >> tmp)
{
D1.push_back(tmp);
index2++;
}
cout << "Before sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Sort the vector using the std::sort algorithm.
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
sort(D1.begin(), D1.end(), my_sorter());
cout << "After sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Write the sorted list to the output file
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(outdata, "\n"));
indata.close();
indata2.close();
outdata.close();
return 0;
}
If optimization is an issue for you, I suggest you use STL containers as the proper sort methods are implemented. Do not use static arrays if your code should work on every given input file. I might also add that you can first merge the two files and then sort the third one.