I am a university student and recently started programming on C++, I am currently having an issue reading in a string using a stringstream.
I am reading information from a .csv file and storing the information in a class, what is puzzling me the most is that my code works perfectly for the first line of my .csv file but not for the second.
This is my class:
class Player {
public:
string name;
int points = 0;
int gamesPlayed = 0;
int todaysPoints = 0;
int timesPresident = 0;
int timesScum = 0;
char playing = 'n';
};
This is how my .csv file is formatted:
Name;Points;Games Played;Times President;Times Scum
Grace;0;0;0;0
Gabriel;0;0;0;0
And this is how I am reading it:
int readInPlayersList(Player playersList[], string filename) {
listIn.open(filename);
string line;
istringstream fixedLine;
int i = 0;
int j;
getline(listIn, line); //first line doesn't matter
while (getline(listIn, line)) {
if (listIn.eof()) { break; }
j = 0;
while (line[j]) {
if (line[j] == ';') { //swapping ; by space to read in easily
line[j] = ' ';
}
++j;
}
fixedLine.str(line);
cout << "Before reading, line = " << line << endl;
fixedLine >> playersList[i].name >> playersList[i].points >> playersList[i].gamesPlayed >> playersList[i].timesPresident >> playersList[i].timesScum;
cout << "After readng -> " << playersList[i].name << " " << playersList[i].points << " " << playersList[i].gamesPlayed << " " << playersList[i].timesPresident << " " << playersList[i].timesScum << endl; //testing output
++i;
}
return i;
listIn.close();
}
As you can see, in order to find out what's wrong, I output what's in the line before reading into the class, and then I output the class members, for the first line, it reads it perfectly but not for the second and any other thereafter... See output below:
I really want to know what I am doing wrong here, appreciate any help, cheers!
Gabriel Groff
Related
I try this code using a method, array, and struct, but it doesn't produce output at all.
I also use most types of include, but it still doesn't produce any output.
#include<conio.h>
#include<iostream>
#include<stream>
#include<string>
#include<stream>
using namespace std;
struct PetLabel {
string petname;
string pettype;
int petprice;
string petowner;
string phoneno;
};
PetLabel pet [10];
stringstream ss;
void DataPet();
void petPrice();
void findOwner();
int main(){
DataPet();
findOwner();
petPrice();
return 0;
}
void DataPet(){
ifstream infile;
infile.open("petSold.txt");
string cnvt[10];
for(int i = 0; i < 10; i++){
getline(infile, pet[i].petname, ',');
getline(infile, pet[i].pettype, ',');
getline(infile, cnvt[i], ',');
ss << cnvt[i];
ss >> pet[i].petprice;
getline(infile, pet[i].petowner, ',');
getline(infile, pet[i].phoneno);
ss.clear();
}
infile.close();
}
void findOwner(){
int chosen;
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
i = chosen;
}
}
cout << "Owner name : " << pet[chosen].petowner << " Phone no : " << pet[chosen].phoneno << endl;
}
void petPrice(){
ofstream outfile("catSold.txt");
outfile << "The cat sold with price greater than RM1000" << endl;
for (int i = 0; i < 10; i++){
if (pet[i].petprice > 1000){
cout << pet[i].petname << "," << pet[i].pettype << "," << pet[i].petprice << "," << pet[i].petowner << "," << pet[i].phoneno << endl;
}
}
outfile.close();
}
the output that I get is:
Owner name : Phone no :
but I can't understand, because there is no syntax error at all.
Is there anything I can add, so I can get the right output?
This method is weird:
void findOwner(){
int chosen;
for (int i=0;i<10;i++){
if (pet[i].petname == "Uyasolu"){
i = chosen;
}
}
cout<<"Owner name : "<<pet[chosen].petowner<<" Phone no : "<<pet[chosen].phoneno<<endl;
}
I think you mean chosen = i instead.
findOwner() is coded wrong.
int chosen; is uninitialized before the loop is entered. Inside the loop, chosen is never updated (i is updated instead, which affects the looping). After the loop is done, chosen has an indeterminate value, so accessing pet[chosen] is undefined behavior.
It should look more like this instead:
void findOwner(){
int chosen = -1;
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
chosen = i;
break;
}
}
if (chosen != -1)
cout << "Owner name : " << pet[chosen].petowner << " Phone no : " << pet[chosen].phoneno << endl;
else
cout << "Pet not found" << endl;
}
Alternatively:
void findOwner(){
for (int i = 0; i < 10; i++){
if (pet[i].petname == "Uyasolu"){
cout << "Owner name : " << pet[i].petowner << " Phone no : " << pet[i].phoneno << endl;
return;
}
}
cout << "Pet not found" << endl;
}
There are some other issues in your code, too:
don't use <conio.h>, its old, and you are not using anything from it anyway.
you have #include<stream> twice, and also <stream> should be <sstream>
string cnvt[10]; should be string cnvt; and then cnvt[i] should be cnvt. You don't need a whole array when you are converting only 1 string at a time.
ss.clear(); does not do what you think it does. You need to use ss.str("") instead. Or, simply move the declaration of ss inside the loop as a local variable so it is destroyed and recreated on each loop iteration.
petPrice() is creating an output catSold.txt file, but is not writing anything to it.
I'm trying to get all the data from a .txt file that have a similar last value, as in the image.
for example, I go through and create a vector where I save in a file only the lines that have the same last value "1565514F" then when I find a different final value "1678721F" I create another file and so on infinitely, the first file would have the name "1565514F.txt" and would save in the same, or in another vector, data like
1001;2021-03-01;False;0;0;1565514F
1001;2021-03-02;False;0;0;1565514F
1002;2021-03-03;False;0;0;1565514F
1002;2021-03-04;False;0;0;1565514F
1003;2021-03-05;False;0;0;1565514F
1003;2021-03-06;False;0;0;1565514F
1004;2021-03-07;False;0;0;1565514F
another file would be called "1678721F.txt" and would have data like this
1006;2021-03-03;False;0;0;1678721F
1006;2021-03-04;False;0;0;1678721F
1001;2021-03-05;False;0;0;1678721F
1001;2021-03-06;False;0;0;1678721F
1004;2021-03-07;False;0;0;1678721F
1004;2021-03-08;False;0;0;1678721F
1003;2021-03-09;False;0;0;1678721F
the code that I have done is the following
// read file
ifstream archivoPlanificacion;
archivoPlanificacion.open("entrada/Planificacion.txt");
string linea;
vector<string> planificacionVector;
while(getline(archivoPlanificacion, linea))
{
planificacionVector.push_back(linea);
}
archivoPlanificacion.close();
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (planificacionRut == planificacionSplitted[5]){
vector<string> soloRutMismoUser;
soloRutMismoUser.push_back(planificacionSplitted[5]);
//imprimir vector soloRutMismoUser
for (int i = 0; i < soloRutMismoUser.size(); i++) {
cout << "soloRutMismoUser: " << soloRutMismoUser[i] << endl;
}
} else {
cout << "nuevo rut" << endl;
string aux = planificacionRut;
//crear archivo de salida
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I don't know if there is a better way, but I asked because I was nesting many for, I would appreciate any help, I still can't separate the data with the "if", thanks
Modifying your loop
string currentCol5; // current 'rut'
vector<string> sameCol5; // collection of same 'rut' col5
for (int i = 0; i < planificacionVector.size(); i++) {
vector<string> planificacionSplitted = splits(planificacionVector[i], ';');
string planificacionFecha = planificacionSplitted[1];
string planificacionRut = planificacionSplitted[5];
cout << "Planificacion Rut: " << planificacionRut << endl;
if (currentCol5 == planificacionSplitted[5] || currentCol5.length() == 0){
sameCol5.push_back(planificacionSplitted[5]);
} else {
// write file here
for (int i = 0; i < sameCol5.size(); i++) {
cout << "soloRutMismoUser: " << sameCol5[i] << endl;
}
// start next set
currentCol5 = planificacionSplitted[5];
sameCol5.clear();
}
cout << "Planificacion Fechas: " << planificacionFecha << endl;
}
I have not tested any of this because I don't have the data structures or the file.
Here is my code
enum Status {IN, OUT };
const int TITLE_SIZE = 50, ISBN_SIZE = 13, AUTHOR_SIZE = 25;
struct Info
{
char title[TITLE_SIZE];
char isbn[ISBN_SIZE];
char author[AUTHOR_SIZE];
Status inOrOut;
};
int main()
{
fstream dataFile;
string filename;
int numOfBooks = 0;
Info *test = 0;
int enumHolder = 0;
cout << "How many books does the file contain? ";
cin >> numOfBooks;
test = new Info[numOfBooks];
cout << "Enter a file (with path) for input and output: ";
cin >> filename;
dataFile.open(filename.c_str(), ios::in );
if (dataFile.fail())
{
cout << "Could not open file; closing program" << "\n";
return 0;
}
for (int i=0; i < (numOfBooks-1); i++)
{
dataFile >> test[i].title;
dataFile >> test[i].isbn;
dataFile >> test[i].author;
dataFile >> enumHolder;
test[i].inOrOut = static_cast<Status>(enumHolder);
}
for (int j=0; j < (numOfBooks-1); j++)
{
cout << test[j].title << " ";
cout << test[j].isbn << " ";
cout << test[j].author << " ";
cout << test[j].inOrOut << " ";
cout << "\n";
}
Here is the .txt file
The Book
012345678901
Guy Duder
1
THAT Article
210987654321
Mr. Dr. Professor
0
Here is the output
How many books does the file contain? 2
Enter a file (with path) for input and output: D:/Documents/input.txt
The Book 012345678901 0
Question
What does the dataFile stop reading in a the first test[i].author? Is using static_cast causing this?
In order to convert an enum to printable text and text to an enum, you need to use a lookup table or an associative array. You could use a switch statement, but that is not as easy to maintain.
See also: std::map.
Search Stackoverflow for "c++ lookup table".
The following code is supposed to get a text file and read all its lines and print them put on console but although it properly saves the fname, it won't do anything after that. I appreciate if you could let me know what the problem is.
EDIT: To be more accurate, I will eventually want to call a few functions inside the else block but I first need to figure out why my program doesn't get to that point.
int main()
{
string fname = "", line, content;
ifstream ifs; // input file stream
string command = "";
int k;
cout << "---- Enter your command and the file name : ";
while (getline(cin, line)){
int i = 0;
for (i = 0; i<line.length(); i++) {
command += line[i];
if (line[i] == ' ')
{
break;
}
}
for (int j = i + 1; j<line.length(); j++)
{
fname += line[j];
}
cout << command;
}
if (command == "exit ")
{
exit(EXIT_SUCCESS);
}
// tries to open the file whose name is in string fname
ifs.open(fname.c_str());
if (ifs.fail()) {
cerr << "ERROR: Failed to open file " << fname << endl;
ifs.clear();
}
else { //do getline here to read content
while (getline(ifs, content))
{
cout << "Content " << k++ << " : " << content << endl;
//Call functions here later
}
}
ifs.close(); // always remember to close it
cout << "---- Enter another file and command name : ";
}
Got it sorted out myself. I was closing the while loop too early. It has to be closed after ifs.close(); instead.
my text file was like
123456123456
Jason
uk
012456788
1000
456789456789
david
uk
012456788
1000
i'm trying to get the data from a text file and save it into arrays
however when i want to store the data from the text file into array it loop non-stop.
what should i do ?
the problem exiting in looping or the method i get the data from text file ?
code:
#include <iostream>
#include <fstream>
using namespace std;
typedef struct {
char acc_no[12];
char name[30];
char address[50];
char phone_no[12];
double balance;
} ACCOUNT;
//function prototype
void menu();
void read_data(ACCOUNT record[]);
int main() {
ACCOUNT record[31]; //Define array 'record' which have maximum size of 30
read_data(record);
}
//--------------------------------------------------------------------
void read_data(ACCOUNT record[]) {
ifstream openfile("list.txt"); //open text file
if (!openfile) {
cout << "Error opening input file\n";
return 0;
} else {
int loop = -1; //size of array
cout << "--------------Data From File--------------"<<endl;
while (!openfile.eof()) {
if (openfile.peek() == '\n')
openfile.ignore(256, '\n');
openfile.getline(record[++loop].acc_no, 12);
openfile.getline(record[loop].name, 30);
openfile.getline(record[loop].address, 50);
openfile.getline(record[loop].phone_no, 12);
openfile >> record[loop].balance;
}
openfile.close(); //close text file
for (int i = 0; i <= loop + 1; i++) {
cout << "Account " << endl;
cout << "Account No. : " << record[i].acc_no << endl;
cout << "Name : " << record[i].name << endl;
cout << "Address : " << record[i].address << endl;
cout << "Phone Number : " << record[i].phone_no << endl;
cout << "Balance : " << record[i].balance << endl;
}
}
}
UPDATE:
The OP didn't properly cite the correct format in his data file. This answer is only valid up until the last iteration.
Don't use .eof() - that's more applicable to when you want to open the file and read it by characters.
A better way would be to use the insertion operator >> as follows:
#define ARR_SIZE 31
ACCOUNT temp;
ACCOUNT record[ARR_SIZE];
int i=0;
while(i < ARR_SIZE) {
openfile >> temp.acc_no >> temp.name >> temp.address >> temp.phone_no >> temp.balance;
record[i] = temp;
i++;
}
Of course, even better is to use std::string to hold the values from the input file, in addition to using std::vectors instead of arrays.