How can I write C++ fstream to file? - c++

I have a problem with this code. Could you please help me to find out why it does not save new total donation values (total) to the file (donation_total.txt)? It should be noted that the default value saved in the file is zero, but it keeps it for each iteration. I need the new value is saved at the last line each time.
Thanks
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
fstream records;
records.open("donation_total.txt", ios_base::in | ios_base::out | ios_base::app);
if (records.is_open())
{
cout << "The record file is open!" << endl;
string line;
while (!records.eof())
{
getline(records, line);
}
int total = stoi(line);
cout << "Total donation is: "<<total << endl;
cout << "Is there any new record?" << endl;
string str,newname;
stringstream field;
string name;
int donation;
getline(cin , str);
while (str=="Yes" | str=="yes")
{
cout << "Enter name and donation value: ";
getline(cin, newname);
field.str(newname);
field >> name >> donation;
total += donation;
field.clear();
cout << name << " donates " << donation << "$" << endl;
cout << "Total donation is: " << total << endl;
records << endl << total;
cout << "Is there any new record?" << endl;
getline(cin, str);
}
}
else
{
cerr << "Could not find the file!" << endl;
}
records.close();
return 0;
}

Your program has many logical incorrectness. When a name is entered with no donation amount, it takes the previously donated value.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
int main()
{
fstream records;
records.open("donation_total.txt", ios_base::in | ios_base::out | ios_base::app);
if (records.is_open())
{
cout << "The record file is open!" << endl;
string line;
while (getline(cin, line))
{
int total = stoi(line);
cout << "Total donation is: "<<total << endl;
cout << "Is there any new record?" << endl;
string str,newname;
stringstream field;
string name;
int donation;
getline(cin , str);
while (str=="Yes" || str=="yes")
{
cout << "Enter name and donation value: ";
getline(cin, newname);
field.str(newname);
field >> name >> donation;
total += donation;
field.clear();
cout << name << " donates " << donation << "$" << endl;
cout << "Total donation is: " << total << endl;
records << endl << total;
cout << "Is there any new record? ";
getline(cin, str);
}
break;
}
}
else
{
cerr << "Could not find the file!" << endl;
}
records.close();
return 0;
}

Related

How delete a record from a file

I am working on a code that creates a binary file that holds structures of student data. One of the things i need to do is to delete a record from a file but I don't know how to do that. I'm not sure how I would go about identifying a record based on the ID number and then delete that file. I would appreciate any help, advice or instructions on what to do.
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <string.h>
using namespace std;
const int NAME_SIZE = 5;
struct Student{
char fname[NAME_SIZE];
char id;
};
int main() {
int choice;
fstream file;
int number;
Student person;
cout << "Choose an option on what to do."<< endl;
cout << "Option 1: Create a Binary File." << endl;
cout << "Option 2: Check if a file exist." << endl;
cout << "Option 3: Populate the records of the file." << endl;
cout << "Option 4: Display contents of the file." << endl;
cout << "Option 5: Append a record to the file." << endl;
cout << "Option 6: Delete a record from the file." << endl;
cout << "Option 7: Search for a record in the file." << endl;
cout << "Option 8: Modify a record from the file." << endl;
cout << "Option 9: Sort the file." << endl;
cout << "Option 10: Wipe a file." << endl;
cin >> choice;
if (choice==1){
char strdata[10000];
file.open("output", ios::binary|ios::app|ios::out);
if(file.is_open())
{
cin.getline(strdata, 10000);
file.seekg(ios_base::end);
file.write(strdata, strlen(strdata));
}
file.close();
cout << "Binary File named output has been created."<< endl;
}
if (choice==2){
file.open("output", ios::in | ios::binary);
if (file.fail()) {
cout << "File could not be opened." << endl;
}
else {
cout << "The file is there" << endl;
}
}
if (choice==3){
file.open("output", ios::out | ios::binary);
file.read(reinterpret_cast<char *>(&person), sizeof(person));
cout << "Populating the record with information."<< endl;
cout << "Enter the following data about a person " << endl;
cout << "First Name: "<< endl;
cin.getline(person.fname, NAME_SIZE);
cout << "ID Number: "<< endl;
cin >> person.id;
file.write(reinterpret_cast<char *>(&person), sizeof(person));
file.close();
}
if (choice==4){
fstream MyFile("output",ios::binary|ios::out);
Student person[3];
for(int i = 0; i < 3; i++)
MyFile.read((char *) &person[i], sizeof(Student));
MyFile.close();
}
if (choice==5){
int i;
char fname;
int id;
fstream file;
file.read(reinterpret_cast<char *>(&person), sizeof(person));
cout << "How many records do you want to append?" << endl;
cin >> number;
file.open("output",ios::out|ios::app|ios::binary);
file.write(reinterpret_cast<char *>(&person), sizeof(person));
for(i=1; i<=number; i++)
{
cout<<"Enter the name: "<< endl;
cin >> fname;
cout<<"Enter ID : "<<endl;
cin >> id;
file<<fname<<endl;
file<<id<<endl;
}
file.close( );
}
if (choice==6){
}
if (choice==7){
}
if (choice==8){
}
if (choice==9){
}
if (choice==10){
char answer;
cout << "Are you sure you want to wipe the file? 1 for Yes or 2 for No" << endl;
cin >> answer;
if (answer==1){
std::ofstream ofs;
ofs.open("output", std::ofstream::out | std::ofstream::trunc|ios::binary);
cout << "Output File has succesfully been deleted"<< endl;
ofs.close();
}
if (answer!=1)
{
cout << "File has not been deleted"<< endl;
}
}
}
```

How to read from a specific line in a file (C++)

I need to find enter a number and find the specific line in my text file to correspond with the number, and I am having a little trouble, heres what I have so far:
cout << "Please enter the ID number of the student, to view their grades: ";
cin >> number;
ifstream myfile;
myfile.open("grades.txt");
if (myfile)
{
cout << " ID exam1 exam2 exam3" << endl;
cout << "---------------------------------" << endl;
getline(myfile, number);
myfile >> number >> exam1 >> exam2 >> exam3;
cout << setw(5) << number << setw(9) << exam1
<< setw(9) << exam2 << setw(9) << exam3 << endl;
cout << "---------------------------------" << endl;
total = exam1 + exam2 + exam3;
cout << "TOTAL: " << setw(25) << total << endl << endl;
}
myfile.close();
return 0;
}
Yes, you use a for loop to loop until you reach the line number, while incrementing.
#include <iostream>
#include <fstream>
#include <string>
int main()
{
// Line #
int line;
// File
std::ifstream f("_");
// Text
std::string s;
// Prompt
std::cout << "Line #: " << std::endl;
// Store line #
std::cin >> line;
// Loop, while less than line
for (int i = 1; i <= line; i++)
std::getline(f, s);
// Output text at line
std::cout << s;
return 0;
}
This will helps : )
#include<iostream>
#include<vector>
#include<fstream>
#include<string.h>
#include<iomanip>
using namespace std;
int main()
{
int number;
cout << "Please enter the ID number of the student, to view their grades: ";
cin >> number;
ifstream myfile;
myfile.open("grades.txt");
if (myfile)
{
string string_obj;
string delimiter = " ";
int id,exam1,exam2,exam3;
size_t pos = 0;
cout << " ID exam1 exam2 exam3" << endl;
cout << "---------------------------------" << endl;
getline(myfile, string_obj);
//Split string into tokens
string token[4];
int i=0;
while ((pos = string_obj.find(delimiter)) != string::npos)
{
token[i++] = string_obj.substr(0, string_obj.find(delimiter));
string_obj.erase(0, pos + delimiter.length()); // move string for next iteration
}
token[i] = string_obj.substr(0, string_obj.find(delimiter));
id = stoi(token[0]);
if (id == number)
{
exam1 = stoi(token[1]); // convert string into int
exam2 = stoi(token[2]);
exam3 = stoi(token[3]);
}
cout << setw(5) << number << setw(9) << exam1
<< setw(9) << exam2 << setw(9) << exam3 << endl;
cout << "---------------------------------" << endl;
int total = exam1 + exam2 + exam3;
cout << "TOTAL: " << setw(25) << total << endl << endl;
}
myfile.close();
return 0;
}

How can i display the array without other array with no value? C++

So i set my array value as 100 and when i want to display my array,the others array with no value will also display. Any ways to remove it ? Thanks!
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<fstream>
#include<limits>
#include<sstream>
using namespace std;
char add();
char list();
struct Book //structure for the book
{
char title[50];
char author[50];
int price;
void display() {
cout << "Name:" << title << endl
<< "Author:" << author<< endl
<< "Price:" << price << endl << endl;
}
};
Book book[100];
void main()
{
int selection;
do {
cout << "Activity Selection: " << endl;
cout << "1. Add book" << endl;
cout << "2. List all books" << endl;
cout << "3. Search book" << endl;
cout << "4. Check total book purchased and total spent" << endl;
cout << "5. Quit" << endl;
cout << "Please enter your selection(1/2/3/4/5): ";
cin >> selection;
cin.ignore();
switch (selection)
{
case 1:
add();
break;
case 2:
list();
break;
case 3:
cout << "number 3" << endl;
break;
case 4:
cout << "number 4" << endl;
break;
default:
exit(1);
break;
}
} while (selection <= 4);
system("pause");
}
char add()
{
int i;
ofstream outFile;
outFile.open("Records.dat", ios::app);
if (!outFile.is_open())
{
cout << "Can’t open file.";
system("pause");
exit(1);
}
cout << "Please enter the book title:";
cin.getline(book[i].title, 51);
cout << "Please enter the author name of the book:";
cin.getline(book[i].author, 51);
cout << "Please enter the price of the book RM: ";
cin >> book[i].price;
cout << "\nThe book\""<< book[i].title <<"\"has been added to the system.\n" <<
endl;
outFile << book[i].title << "," << book[i].author << "," << book[i].price <<
endl;
outFile.close();
}
char list() //second solution but still doesnt work need some fixing here i think
{
int i;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile,line))
{
inFile.get(data);
if (!(data == 0));
cout << data;
}
cout << endl;
inFile.close();
}
when i debug something like this come out :
ss
this is the second solution i come out with but still does not work
char list()
{
int i , count = 0;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile, line))
{
stringstream ss(line);
getline(ss, token, ',');
stringstream(token) >> book[i].title;
getline(ss, token, ',');
stringstream(token) >> book[i].author;
getline(ss, token, ',');
stringstream(token) >> book[i].price;
i++;
}
cout << endl;
inFile.close();
for (int count = 0; count < i; count++)
book[i].display();
}
The problem is i dont really know how to display the array using the dat file and i successfully display it but theres error
You are reading the CSV as a text file and just printing it.
So, the solution is to make a record class, read it from stream, then check it whether it is empty or no.
#include <iostream>
#include <sstream>
using namespace std;
class Record {
private:
std::string title;
std::string shortTitle;
int number;
public:
Record(std::string title, std::string shortTitle, int number): title(title),
shortTitle(shortTitle),
number(number){
}
inline std::string getTitle() const { return title; }
inline std::string getShortTitle() const { return shortTitle; }
inline int getNumber() const { return number; }
};
// Make this function capable of handling any stream by making it template
// (anything that could be passed to a `getline` as a first parameter and have
// an operator >> overloaded that accepts an integer)
template<typename Stream>
Record readFromStream(Stream &str) {
std::string title;
std::string shortTitle;
int number;
std::string line;
// Read a line from the stream
getline(str, line);
// Make a new stream from that line
std::stringstream lineStream(line);
// Read until the comma
getline(lineStream, title, ',');
getline(lineStream, shortTitle, ',');
// The last one is an integer, simply read it
lineStream >> number;
return Record(title, shortTitle, number);
}
int main() {
Record rec = readFromStream(cin);
// Check for emptiness, if is NOT empty write it
if (rec.getTitle().size() && rec.getShortTitle().size()) {
cout << rec.getTitle() << "\n";
cout << rec.getShortTitle() << "\n";
cout << rec.getNumber() << "\n";
}
return 0;
}

C++ console crashes after running

guys, i have a problem.
After i run the program, the console just crashes.
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::replace: __pos (which is 4294967295) > this->size() (which is 9)
I mean, you will see.In the program there is an option "Add person", and when i add one, its all okay.But when i enter the program to add second person it crashes.Please, help!
The source code of the programs is:
#include <iostream>
#include <windows.h>
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;
int main(){
system("chcp 1251 > nul");
system("title PeopleData");
string firstName;
string midName;
string lastName;
string fullName;
string line;
long ID = 27560000;
int age;
char gender;
cout << "1.Add person" << endl;
cout << "2.Read file" << endl;
cout << "3.Exit" << endl << endl;
cout << "Please, enter your choice: ";
int choice;
cin >> choice;
if(choice == 1)
{
system("cls");
ofstream myfile("Data.txt", ios::app);
ifstream file("Data.txt");
string IDLine;
int numberOfLines = 0;
if (myfile.is_open())
{
while (getline (file, line) )
{
numberOfLines ++;
}
file.close();
ifstream file("Data.txt");
int y = 0;
line = "";
while(getline(file, line))
{
IDLine = line;
if(y == numberOfLines - 5)
{
goto NextStep;
}
y++;
}
}
else
{
cout << "Unable to open file";
}
NextStep:
string LastID = IDLine;
if(LastID != "")
{
LastID.replace(LastID.find("ID: "), string("ID: ").length(), "");
ID = atoi(LastID.c_str()) + 1;
}
else
{
ID = 27560000;
}
cout << "First Name: ";
cin >> firstName;
cout << endl << endl;
cout << "Middle Name: ";
cin >> midName;
cout << endl << endl;
cout << "Last Name: ";
cin >> lastName;
cout << endl << endl;
cout << "Age: ";
cin >> age;
cout << endl << endl;
cout << "Gender (m / f): ";
cin >> gender;
fullName = firstName + " " + midName + " " + lastName;
myfile << "First Name: " << firstName << "\n";
myfile << "Middle Name: " << midName << "\n";
myfile << "Last Name: " << lastName << "\n";
myfile << "Full Name: " << fullName << "\n";
myfile << "Age: " << age << "\n";
myfile << "Gender: " << gender << "\n";
myfile << "ID: " << ID << "\n";
myfile << "\n---------------\n\n";
myfile.close();
file.close();
return 0;
}
if(choice == 2)
{
system("cls");
ifstream myfile ("Data.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else
{
setcolor(12);
cout << "Unable to open file";
}
}
if(choice == 3)
{
return 0;
}
system("pause > nul");
return 0;
}
`

Iterating through a text file and assigning variables for each line

having a difficult time finding a way to assign each line of the text file being read to a different variable, i commented above the variables displaying how a line from the text file displaying that variable would look. I want to know what way i can use a forloop to be able to iterate through the entire text file and store data to each of the variables I commented above based on the type of data it needs to store. The three sets of variables all have to be stored by species and in a way they can be manipulated. How can i split up a vector into a set of three variables?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string getInputFileName()
//retrieves the inputfile
{
string fileName;
ifstream inputfile;
//prompting user for filename to be opened
cout << "Enter the file name to be opened: ";
cin >> fileName;
//opening the file for input
inputfile.open(fileName, ios::in);
//checks to see if writing the input file failed
if (inputfile.fail())
{
cout << "Opening file..." << fileName;
cout << "\n";
cout << "The " << fileName << "could not be opened! \n";
cout << "1. Check if file exists. \n";
cout << "2. Check file path. \n;";
}
else
{
cout << "File: " << fileName << " was successfully opened!" << endl;
return fileName;
}
}
string getOutputFileName()
//retrieves the inputfile
{
string fileName;
ofstream outputfile;
//prompting user for filename to be opened
cout << "Enter the file name to be opened: ";
cin >> fileName;
//opening the file for input
outputfile.open(fileName, ios::in);
//checks to see if writing the input file failed
if (outputfile.fail())
{
cout << "Opening file..." << fileName;
cout << "\n";
cout << "The " << fileName << "could not be opened! \n";
cout << "1. Check if file exists. \n";
cout << "2. Check file path. \n;";
}
else
{
cout << "File: " << fileName << " was successfully opened!" << endl;
return fileName;
}
}
int main()
{
//opens clasfication file
ifstream inputFile(getInputFileName());
//declaring year and numberOfSpecies
int year, numberOfSpecies;
string line;
if (inputFile.is_open())
{
//year of file
inputFile >> year;
//echo for year
cout << year << endl;
//number of species of file
inputFile >> numberOfSpecies;
//echo for number of species
cout << numberOfSpecies << endl;
string line;
//variables i need to assign line by line and be able to manipulate
//region of species would look like this in text file: 84
//nameOfspecies would like like this in the text file: Spotted Gecko
//regionSightings would look like this in the text file: 84 95 30 25
vector<string> linesOfData;
for (int i = 0; (!inputFile.eof()) || (i <= numberOfSpecies) ; i++)
{
getline(inputFile, line, '\n');
linesOfData.push_back(line);
//echo vector!
cout << linesOfData[i] << "\n";
}
ofstream outputFile(getOutputFileName());
}
return 0;
}
Pseudo code for your requirements. You will have to fill in the code and do the required testing.
I have used similar logic many times for my requirements. I see this to be more maintainable and scalable.
class spotted_species{
private:
int first_val[];
string species_name;
int locations[];
// Private methods
private:
void assign_species_firstVal (String first_line){
Assign the first line after performing required transformations;
}
int assign_species_name (String Second_Line){
if (the species name exists in predefined array or file) {
assign the name;
}
else {
return -1; // to ignore all 3 lines.
}
}
void assign_species_locations (String third_line){
tokenize by space
convert each token to int and assign. hardly 2 lines code.
}
// Public methods
public:
void show_species(){
std::cout<< "First val";
std::cout<< "Species name";
std::cout<< "Spotted locations";
}
int init(String firstline, String secondline, String ThirdLine){
assign_species_firstVal(firstline);
int status = assign_species_name (secondline);
if (status) {
assign_species_locations (ThirdLine);
}
return status_accordingly;
}
}
int main(int argc, char *argv[])
{
// Create an array of spotted_species to ensure you can hold the required number of
// species from the file.
run a OS command "WC -l" which gives the total number of line in your file.
All file handling could be done here based on the output of the above command.
// Calculate the number of objects you would need based on the number of lines.
// Rough estimate would be fine for these requirements.
int num_species = lines_in_file/3 + 10; // +10 is used to be on safer side.
// Create the objects
spotted_species species_spotted_in_africa[num_species];
int ctr;
while (read file until the last line)
// Read 3 lines at a go,
// store them in 3 variables.
// call init with all 3 arguments.
}
// Now you have all the species information in seperate objects.
// you can access them in a loop or by any other means.
// If you need to perform any additional processing on these objects,
// you always can extend this class or
// you could write another class which can process this class data.
// Flexible, simple, Maintainable and scalable.
return 0;
}
You will have to make some changes as per your exact requirements. I hope this helps.
Based on the fact that you have 3 lines of data per species, eg:
84
Spotted Gecko
84 95 30 25
I would suggest using a vector of struct values instead of string values, where each struct holds the data for a single species. While looping through the input file, read 3 lines at a time, parse them into an instance of the struct, and then push it into* the vector.
Try this:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
struct species
{
int region;
string name;
std::vector<int> regionSightings;
};
bool openInputFile(ifstream &inputfile)
{
string fileName;
//prompting user for filename to be opened
cout << "Enter the input file to be opened: ";
getline(cin, filename);
//opening the file for input
cout << "Opening file: " << filename << endl;
inputfile.open(fileName);
//checks to see if opening the input file failed
if (!inputfile)
{
cout << "File: " << fileName << " could not be opened!" << endl;
cout << "1. Check if file exists." << endl;
cout << "2. Check file path." << endl;
return false;
}
cout << "File: " << fileName << " was successfully opened!" << endl;
return true;
}
bool openOutputFile(ofstream &outputfile)
{
string fileName;
//prompting user for filename to be opened
cout << "Enter the output file to be opened: ";
getline(cin, filename);
//opening the file for input
cout << "Opening file: " << fileName << endl;
outputfile.open(fileName);
//checks to see if opening the output file failed
if (!outputfile)
{
cout << "File: " << fileName << " could not be opened!" << endl;
cout << "1. Check if file exists." << endl;
cout << "2. Check file path." << endl;
return false;
}
cout << "File: " << fileName << " was successfully opened!" << endl;
return true;
}
int main()
{
//opens clasfication file
ifstream inputFile;
if (openInputFile(inputFile))
{
//declaring year and numberOfSpecies
int year, numberOfSpecies;
string line;
//year of file
inputFile >> year;
//echo for year
cout << "Year: " << year << endl;
//number of species in file
inputFile >> numberOfSpecies;
//echo for number of species
cout << "# species: " << numberOfSpecies << endl;
//there are three lines per species
//region of species, eg: 84
//nameOfspecies, eg: Spotted Gecko
//regionSightings, eg: 84 95 30 25
vector<species> speciesData;
for (int i = 0; i < numberOfSpecies; ++i)
{
species s;
if (!getline(inputFile, line))
{
cout << "File: " << fileName << " could not read a species region!" << endl;
break;
}
if (!(istringstream(line) >> s.region))
{
cout << "File: " << fileName << " could not parse a species region!" << endl;
break;
}
if (!getline(inputFile, s.name))
{
cout << "File: " << fileName << " could not read a species name!" << endl;
break;
}
if (!getline(inputFile, line))
{
cout << "File: " << fileName << " could not read a species sightings!" << endl;
break;
}
istringstream iss(line);
int num;
while (iss >> num)
s.regionSightings.push_back(num);
if (!iss.eof())
{
cout << "File: " << fileName << " could not parse a species sightings!" << endl;
break;
}
speciesData.push_back(s);
//echo vector!
cout << s.region << " " << s.name << " " << line << endl;
}
cout << "Closing input file" << endl;
inputFile.close();
ofstream outputFile;
if (openOutputFile(outputFile))
{
for (std::vector<species>::iterator iter = speciesData.begin();
iter != speciesData.end();
++iter)
{
species &s = *iter;
// write species data to outputFile as needed...
}
cout << "Closing output file" << endl;
}
cout << "Finished" << endl;
}
return 0;
}