How to fix Error that leads to program Crash - c++

For some reason or another I cannot figure out why the data when opened does not get put into arrays and the program crashes. I have searched around for a answer to no avail. I get the feeling I will be posting a here a few more times before I finish this program!
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string bookTitle [14];
string bookAuthor [14];
int loadData (string pathname);
void showall (int counter);
int main ()
{
int counter;
string pathname;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
cout<<"Press <Enter> to Exit";
cin.ignore();
cin.get();
return 0;
}
int loadData (string pathname) // Loads data from infile into arrays
{
fstream infile;
int counter = 0;
infile.open(pathname.c_str()); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
cout<<"File Opened"; // I get the "File Opened" text and then a crash
infile >> bookTitle [14] ; //takes input and puts into parallel arrays
infile >> bookAuthor [14];
cout<<"Data Put in Arrays";
counter++;
}
infile.close();
}
void showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
}
Edit: The assignment is to take a file with names in a format such as title
author
title
author
Then it must output the arrays to screen in a title(author) format.
After this I must make it a looping program so a search can be chosen of one of the arrays and returns the entry in a title(author) format.
Here is how the code stands now;
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string bookTitle [50];
string bookAuthor [50];
int loadData (string pathname);
int showall (int counter);
int main ()
{
string pathname;
int counter=0;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
cout<<"Press <Enter> to Exit";
cin.ignore();
cin.get();
return 0;
}
int loadData (string pathname) // Loads data from infile into arrays
{
fstream infile;
int counter = 0;
infile.open(pathname.c_str()); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
infile >> bookTitle [counter] ; //takes input and puts into parallel arrays
infile >> bookAuthor [counter];
counter++;
}
infile.close();
}
int showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
return 0;
}

A Quick problem I see is:
infile >> bookTitle [14] ;
infile >> bookAuthor [14];
Is incorrect, What you need is:
infile >> bookTitle[counter];
infile >> bookAuthor [counter];
Also,
The counter variable declared in main() and in loadData() are two different variables. The one declared in main()is never iniitalized at all.

There are many problems with this code.
Main problem
These lines write only into 14th elements of the arrays
infile >> bookTitle [14] ; //takes input and puts into parallel arrays
infile >> bookAuthor [14];
In order to fill the entire array you need to use the counter variable for index:
infile >> bookTitle [counter] ; //takes input and puts into parallel arrays
infile >> bookAuthor [counter];
BTW: if array's size is 14 then the maximum index is 13. So you can't access an element with index 14. And that's probably causes the crash.
Other problems I noticed
counter in main() is not initialized
showall() function takes an argument but does not use it, which is probably the index.
showall() call in main() probably needs to be in a loop, to show all elements.

Related

C++ reading strings,int,floats from a text file into a array/string

My .txt file contains the following
12345
John Smith
45 12.50
54234
Joe Paul
32 10.25
12324
Chris Lee
43 22.50
The first int is the employee ID, then the string name, then hours and rate of pay(float).
My Program:
using namespace std;
const int Size = 10;
typedef int intarray[Size];
typedef float farray[Size];
typedef string starray[Size];
void readdata(intarray,starray,intarray,farray, ifstream &);
void print(intarray,starray,intarray,farray,ifstream &);
int main()
{
ifstream fin("data.txt");
//ofstream fout;
starray EmployeeName;
intarray EmployeeID,EmployeeHoursWorked;
farray EmployeeRate;
readdata(EmployeeID,EmployeeName,EmployeeHoursWorked,EmployeeRate,fin);
print(EmployeeID,EmployeeName,EmployeeHoursWorked,EmployeeRate,fin);
cin.get();
cin.ignore();
}
My functions, my code is not properly reading the file.
void readdata(intarray ID, starray Name, intarray Hours, farray Rate, ifstream & infile)
{
for(int i = 0; i < Size; i++)
{
//this code is not working as intended
infile >> ID[i];
getline(infile, Name[i]);
infile >> Hours[i] >> Rate[i];
infile.ignore();
}
}
Im not getting any results.
void print(intarray ID, starray Name, intarray Hours, farray Rate, ifstream & infile)
{
for(int i = 0; i < Size; i++)
{
cout << ID[i] << endl;
cout<<Name[i]<<endl;
cout << Hours[i] << Rate[i] << endl;
}
}
When you call getline in readdata you are reading the end of line character after the ID. You need to be positioned on the line with the name prior to calling getline. Try this
infile >> ID[i];
infile.ignore(); //Consume the new line char
getline(infile, Name[i]);
infile >> Hours[i] >> Rate[i];

Avoiding the use of eof in this case

I have posted the following code where I am reading from an input file -- storing information in a structure -- and then writing to an output file. I know that the eof function is not safe and hence one must use the getline function to check whether the end of file has been detected or not; however, in this particular code, I have not been able to use the getline function and hence has finally relied on the eof function. Hence, can you please suggest an alternative to the eof function or let me know how I can use the getline function when I am trying to initialize an array of structures . I have used two asterisk symbols to indicate where I want to use the getline function.
#include <iostream>
#include <fstream>
using namespace std;
//student structure
struct student
{
char name[30];
char course[15];
int age;
float GPA;
};
ifstream inFile;
ofstream outFile;
student getData();
void writeData(student writeStudent);
void openFile();
int main (void)
{
const int noOfStudents = 3; // Total no of students
openFile(); // opening input and output files
student students[noOfStudents]; // array of students
// Reading the data from the file and populating the array
for(int i = 0; i < noOfStudents; i++)
{
if (!inFile.eof()) // ** This where I am trying to use a getline function.
students[i] = getData();
else
break ;
}
for(int i = 0; i < noOfStudents; i++)
writeData(students[i]);
// Closing the input and output files
inFile.close ( ) ;
outFile.close ( ) ;
}
void openFile()
{
inFile.open("input.txt", ios::in);
inFile.seekg(0L, ios::beg);
outFile.open("output.txt", ios::out | ios::app);
outFile.seekp(0L, ios::end);
if(!inFile || !outFile)
{
cout << "Error in opening the file" << endl;
exit(1);
}
}
student getData()
{
student tempStudent;
// temp variables for reading the data from file
char tempAge[2];
char tempGPA[5];
// Reading a line from the file and assigning to the variables
inFile.getline(tempStudent.name, '\n');
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
tempStudent.age = atoi(tempAge);
inFile.getline(tempGPA, '\n');
tempStudent.GPA = atof(tempGPA);
// Returning the tempStudent structure
return tempStudent;
}
void writeData(student writeStudent)
{
outFile << writeStudent.name << endl;
outFile << writeStudent.course << endl;
outFile << writeStudent.age << endl;
outFile << writeStudent.GPA << endl;
}
You want to write an operator>> for your student type. Something like:
std::istream& operator>>(std::istream& in, student& s) {
in >> s.age; // etc.
return in;
}
Which then allows you to write:
int studentNo = 0;
students[maxStudents];
while (studentNo < maxStudents && (in >> students[studentNo]))
++studentNo;
Why not write this way?
instead of
inFile.getline(tempStudent.name, '\n');
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
You may
while(inFile.getline(tempStudent.name, '\n'))
{
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
//do stuffs
}

Infile incomplete type error

I am building a program that takes an input file in this format:
title author
title author
etc
and outputs to screen
title (author)
title (author)
etc
The Problem I am currently getting is a error:
"ifstream infile has incomplete type and cannot be defined"
Following is the program:
#include <iostream>
#include <string>
#include <ifstream>
using namespace std;
string bookTitle [14];
string bookAuthor [14];
int loadData (string pathname);
void showall (int counter);
int main ()
{
int counter;
string pathname;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
}
int loadData (string pathname) // Loads data from infile into arrays
{
ifstream infile;
int counter = 0;
infile.open(pathname); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
infile >> bookTitle [14]; //takes input and puts into parallel arrays
infile >> bookAuthor [14];
counter++;
}
infile.close;
}
void showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
}
File streams are defined in the header <fstream> and you are not including it.
You should add:
#include <fstream>
Here is my code with the previous error fixed Now I get a problem of the program crashing after I input the name of the text file.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string bookTitle [14];
string bookAuthor [14];
int loadData (string pathname);
void showall (int counter);
int main ()
{
int counter;
string pathname;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
}
int loadData (string pathname) // Loads data from infile into arrays
{
fstream infile;
int counter = 0;
infile.open(pathname.c_str()); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
infile >> bookTitle [14]; //takes input and puts into parallel arrays
infile >> bookAuthor [14];
counter++;
}
infile.close();
}
void showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
}

Arrays and Searching Them

I am trying to finish my final debugging tonight. My problem is that I have been writing this code for a couple days and it has a few problems. Previous Post
It now compiles and does not crash, but there are a few issues with my functions not working properly (or at all).
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string bookTitle [50];
string bookAuthor [50];
int loadData (string pathname);
int showall (int counter);
int authorSearch (string bookAuthor [50]);
int main ()
{
string pathname;
int counter=0;
char choice;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
cout<<"\n\n\n\n What would you like to do \n (A for Author Search , T for Title Search, Q to quit):";
cin>>choice;
while (choice != 'Q' , choice != 'q')
{
if (choice == 'A', choice == 'a')
{
int authorSearch (string bookAuthor [50], char choice);
}
if (choice == 'T', choice == 't')
{
int titleSearch (string bookTitle [50], char choice);
}
}
cout<<"Press <Enter> to Exit";
cin.ignore();
cin.get();
return 0;
cout<<"Press <Enter> to Exit";
cin.ignore();
cin.get();
return 0;
}
int loadData (string pathname) // Loads data from infile into arrays
{
fstream infile;
int counter = 0;
infile.open(pathname.c_str()); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
infile >> bookTitle [counter] ; //takes input and puts into parallel arrays
infile >> bookAuthor [counter];
counter++;
}
infile.close();
}
int showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
}
void authorSearch (string bookAuthor [50], char choice) // Function to search Author Array
{
string target = "";
cout<<"Which author would you like to search for: "<<target; //input
for (int count = 0; count++;)
{
if(bookAuthor[count] == target) //tests input against array and outputs result
{
cout<<bookTitle[count]<<bookAuthor[count];
}
}
}
void titleSearch (string bookTitle [50], char choice) // Function to Serch Title Array
{
string target = "";
cout<<"Which author would you like to search for: "<<target; //input
for (int count = 0; count++;)
{
if(bookAuthor[count] == target) //tests input against array and outputs result
{
cout<<bookTitle[count]<<bookAuthor[count];
}
}
}
Latest Version , no major improvements. I am having trouble getting the functions to work after the menu selection. ShowAll seems to work but outputs hex. Thanks again everyone!
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
string bookTitle [50];
string bookAuthor [50];
int loadData (string pathname);
int showall (int counter);
void authorSearch (string bookAuthor [50]);
void titleSearch (string bookTitle [50]);
int main ()
{
string pathname;
int counter=0;
char choice;
cout<<"Input the name of the file to be accessed: ";
cin>>pathname;
loadData (pathname);
showall (counter);
cout<<"\n\n\n\n What would you like to do \n (A for Author Search , T for Title Search, Q to quit):";
cin>>choice;
while (choice != 'Q'|| choice != 'q')
{
if (choice == 'A'|| choice == 'a')
{
void authorSearch (string bookAuthor [50], char choice);
}
if (choice == 'T'|| choice == 't')
{
void titleSearch (string bookTitle [50], char choice);
}
}
cout<<"Press <Enter> to Exit";
cin.ignore();
cin.get();
return 0;
}
int loadData (string pathname) // Loads data from infile into arrays
{
fstream infile;
int counter = 0;
infile.open(pathname.c_str()); //Opens file from user input in main
if( infile.fail() )
{
cout << "File failed to open";
return 0;
}
while (!infile.eof())
{
infile >> bookTitle [counter] ; //takes input and puts into parallel arrays
infile >> bookAuthor [counter];
counter++;
}
infile.close();
}
int showall (int counter) // shows input in title(author) format
{
cout<<bookTitle<<"("<<bookAuthor<<")";
}
void authorSearch (string bookAuthor [50], char choice) // Function to search Author Array
{
string target = "";
cout<<"Which author would you like to search for: "<<target; //input
for (int count = 0; count++;)
{
if(bookAuthor[count] == target)
{
cout<<bookTitle[count]<<bookAuthor[count];
}
}
}
void titleSearch (string bookTitle [50], char choice) // Function to Serch Title Array
{
string target = "";
cout<<"Which title would you like to search for: "<<target; //input
for (int count = 0; count++;)
{
if(bookAuthor[count] == target) //tests input against array and outputs reults
{
cout<<bookTitle[count]<<bookAuthor[count];
}
}
}
The comma operator should be replaced with logical and or or, && and || respectively. See uses of the comma operator. Also, authorSearch is a void function. If you want to call authorSearch, simple write authorSearch(...) instead of int authorSearch(...).
Additionally, you need to make sure your prototypes are consistent with your implementations. int authorSearch (string bookAuthor [50]) is not the same as void authorSearch (string bookAuthor [50], char choice). You've mismatched their types and their parameters.
1) The showall() function outputs hex because you can't display arrays that way, you need some kind of loop. It's just printing the starting address of each array.
2) In your search functions you never read the target string from the user.
3) These for() loops will never execute:
for (int count = 0; count++;)
{
...
}
You set count to 0 and then test the value before incrementing. The test fails and the loop body isn't executed.
4) Take care when you fix the for() loops. I don't see any tests to prevent using an invalid index past the (hardcoded) size of your arrays.

How to get the whole line where a given word is and store it in a variable?

i am a beginner in the C++ world, i need to get the whole line where a given word is and store it into a variable.
my TXt file has this structure :
clients.txt
085958485 Roland Spellman rolandl#gmail.com
090545874 KATHLEEN spellman kathleen1#hotmail.com
056688741 Gabrielle Solis desperate#aol.com
so the program requests to the user to enter the id of the person, the id is always the first number or word in the line.
the user enters then
090545874
the program has to be able to find the 090545874 in the text file and then get the whole line where it is stored into a variable.
i know how to find a word in a text file but i don't know how to get the whole line into a variable. so at the end my variable has to store
variable = 090545874 KATHLEEN spellman kathleen1#hotmail.com 4878554
after that, i am able to delete the entire line or record.
i use this code to enter the data into the txt file
struct person{
char id[10];
char name[20];
char lastname[20];
char email[10];
} clientdata;
ofstream clientsfile;
clientsfile.open ("clientes.dat" , ios::out | ios::app);
if (clientsfile.is_open())
{
cout<<" ENTER THE ID"<<endl;
cin>>clientdata.id;
clientsfile<<clientdata.id<<" ";
cout<<" ENTER THE NAME"<<endl;
cin>>datoscliente.name;
clientsfile<<clientdata.name<<" ";
cout<<" ENTER THE LAST NAME"<<endl;
cin>>clientdata.lastname;
clientsfile<<clientdata.lastname<<" ";
cout<<" ENTER THE LAST EMAIL"<<endl;
cin>>clientdata.email;
clientsfile<<clientdata.email<<" ";
then i request to the eu to enter the id
and what i need to do is not to find the id only, it's to get the whole line where the id is
so if the user enters 090545874 , i need to find it in the text file , but i need to get teh whole line in this case 090545874 KATHLEEN spellman kathleen1#hotmail.com
so i need to store that into a new variable
string newvariable;
newvariable = 090545874 KATHLEEN spellman kathleen1#hotmail.com
To read files one line at a time, you can use the std::getline function defined in the <string> header (I'm assuming you're using the fstream library as well):
#include <fstream>
#include <string>
int main(int argc, char** argv) {
std::ifstream input_file("file.txt");
std::string line;
while (true) {
std::getline(input_file, line);
if (input_file.fail())
break;
// process line now
}
return 0;
}
What's nice about the function std::getline, though, is that it allows for this much cleaner syntax:
#include <fstream>
#include <string>
int main(int argc, char** argv) {
std::ifstream input_file("file.txt");
std::string line;
while (std::getline(input_file, line)) {
// process line now
}
return 0;
}
thank all of you for your answers, I finally figured it out , I used this function :
bool mostshow(int option, string id)
{
if (option== 2 && id== id1)
return true;
if (option== 3 && id== id1)
return true;
return false;
}
and this other one
void showline(string field1, string field2, string field3, string field4, string field5, string field6, string field7)
{
string store;
store = field1+" "+field2+" "+field3+" "+field4+" "+field5+" "+field6+" "+field7;
cout<<endl;
}
and then in the main
ifstream myfile("clients.dat", ios::in);
if (!myfile)
{
cerr <<" CANNOT OPEN THE FILE!!"<<endl;
exit(1);
}
option=2;
myfile >> field1 >> field2 >> field3 >> field4 >>field5 >> field6 >> field7;
while (!myfile.eof())
{
if (mostshow(option, id))
{
showline(field1, field2, field3, field4, field5, field6, field7);
}
myfile >> field1 >> field1 >> field1 >> field1 >>field1 >> field1 >> field1;
}
myfile.close();
option variable is part of a switch statement which asks if you want to delete or modify the record, 2 means modify , 3 delete
You didn't say how you're reading the file, but the fgets function will do what you want.
Use ifstream, getline and unordered_map:
#include <fstream>
#include <string>
#include <sstream>
#include <exception>
#include <unordered_map>
using namespace std;
ifstream infile("mytextfile.txt");
if (!infile) {
cerr << "Failure, cannot open file";
cin.get();
return 0;
}
unordered_map<string, string> id2line;
string id, line;
while (getline(infile, line)) {
stringstream strstm(line);
strstm >> id;
id2line[id] = line;
}
Now you can do
cout << "Please enter an id: " << endl;
string id;
cin >> id;
try {
// unordered_map::at throws an std::out_of_range exception when the key doesn't exist
string line = id2line.at(id);
cout << "Info:\n " << line << endl;
} catch (out_of_range& e) {
cout << "No information by that id." << endl;
}
You could create a structure and have the structure read in its data by overloading the stream extraction operator:
struct Record
{
unsigned int id;
std::string first_name;
std::string last_name;
std::string email_addr;
friend std::istream& operator>>(std::istream& input, Record& r);
};
std::istream& operator>>(std::istream& input, Record&r)
{
input >> r.id;
input >> r.first_name;
input >> r.last_name;
getline(input, r.email_addr);
return input;
}
Edit 1:
Usage:
ifstream input_file("mydata.text");
Record r;
std::map<unsigned int, Record> container;
while (input_file >> r)
{
unsigned int id = r.id;
container[id] = r;
}
As far as storage is concerned look up the std::map structure and copy the ID field and use it as the key.
I still suggest that this work is a better candidate for a database or spreadsheet.