File Handling not working in while loop - c++

Code:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
void main()
{
ofstream f("C:\\TC\\1.dat");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
}
sometimes the code works fine
but at the other times , when i look at the output file,it is empty , the problem has come up many times , and i ant to know whether there is a precaution regarding loops with file handling
for eg. in other program
.....
while(ch!=4)
{
cout << "\nBANK MANAGEMENT SYSTEM \n";
cout << "enter choice ";
cout << "\n1.add\n2.search\n3.delete and overwrite ";
cin >> ch;
if (ch == 1)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
.....
the file is empty

I guess you may have used a very old compiler older than gcc 4.5.3.
I tried your code and it has no problem.
#include <iostream> //use header file without using deprecated iostream.h
#include <fstream> //same reason as above
#include <string>
using namespace std;
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
int main() //usually main returns int. void was kind of old now
{
ofstream f("test.txt");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
f.flush();
f.close();
return 0;
}
I compiled the code in gcc 4.5.3 and ran it. the file has all the stuff I entered.
However, it will be better to use the << operator when you use file i/o stream to write to file.
You can find more information about and from top of this link:
http://members.gamedev.net/sicrane/articles/iostream.html
Another point, wen you have done writing to a file, remember to flush and close the file handle, otherwise, sometimes it will cause some annoying problems.

The code doesn't seem very C++-like to me...
To answer the last question, there aren't any gotchas about fstreams in loops specifically, no.
I suggest first trying to do f.write with the members name and amt themselves—compilers might add padding between name and amt, creating unwanted garbage output.
Are you sure you have write permission to the filepath all the time? Try opening a local file, as in the path being simply "1.dat".
Also try opening the file as f("/* file name */", ofstream::out | ofstream::app). "out" sets it as an output stream, and "app" makes it add to the end of the file. www.cplusplus.com/ofstream details more flags.

since you are using c++, I suggest you use a formal way to use ofstream, in your code, it should be f << s.name << s.amt.
remember, you are using c++, so keep using i/o stream.

Related

Evaluating expression statements from a text file in C++

I am altering a (well, my first) C++ program that evaluates expressions. For example, by inputting this:
(x + (y * 3)), x = 2, y = 6;
It should output the following:
Value = 20
The program works when the user types the expression into the console, but I want it to read and evaluate expressions from a text file (each on a separate line). I have successfully read the file in, and can even print its contents in the console, but I'm having trouble parsing and evaluating each line. There are many more header and source files that accompany this project, but I think all of the relevant information is in the main function:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
SymbolTable symbolTable;
void parseAssignments();
int main()
{
Expression* expression;
char paren, comma;
string program;
ifstream myfile("expressions.txt");
if (myfile.is_open())
{
while (getline(myfile, program))
{
cout << program << '\n'; //confirms that file was read properly
//code to parse expressions and print results
}
myfile.close();
}
else cout << "Unable to open file";
//original code that parses expression the user inputs
/*cout << "Enter expression: ";
cin >> paren;
expression = SubExpression::parse();
cin >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate() << end1;*/
cin.get(); //added this so the window doesn't close automatically
return 0;
}
I have tried numerous approaches over the last couple days, and I think it comes down to my C++ ignorance of what exactly is happening on these two lines. My theory is that it parses everything to the right of the parenthesis in the first line, and everything to the right of the comma in the second line (ignoring the fact that the scopes would overlap).
cin >> paren;
cin >> comma;
Therefore, among other approaches, I tried including the following in the while loop. I am using MS Visual Studio, and when I click "> Local Windows Debugger" it will open up a console window with the first expression printed and a blinking line like it's waiting for me to input something. I close out of the window, and instead of a "> Continue" in place of "> Local Windows Debugger" it will just end the program. It is entirely possible that I'm just using Visual Studio incorrectly.
myfile >> paren;
expression = SubExpression::parse();
myfile >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
And this:
std::istringstream iss(program);
iss >> paren;
expression = SubExpression::parse();
iss >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
And of course this:
getline(myfile, program) >> paren;
expression = SubExpression::parse();
getline(myfile, program) >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
Am I taking the completely wrong approach here, or worse should I be focusing on changing other functions as well? Thank you!!
EDIT: It appears that cin >> was being called in parse() and a few other .cpp files, which prevented my three attempts above from having much of an effect. Right now I'm looking into including the line as an argument in functions like below. I will report any errors if it doesn't work.
string parseName()
{
char alnum;
string name = "";
cin >> ws;
while (isalnum(cin.peek()))
{
cin >> alnum;
name += alnum;
}
return name;
}
EDIT 2: IT WORKS!!! Since cin >> was being used throughout the program, I had to create a new variable std::stringstream in(program); and then use that as arguments in functions as seen below:
void parseAssignments(stringstream& in);
int main()
{
Expression* expression;
char paren, comma;
string program;
ifstream myfile("expressions.txt");
if (myfile.is_open())
{
while (getline(myfile, program))
{
cout << program << '\n'; //confirms that file was read properly
std::stringstream in(program);
in >> paren;
expression = SubExpression::parse(in);
in >> comma;
parseAssignments(in);
cout << "Value = " << expression->evaluate() << '\n\;
}
myfile.close();
}
else cout << "Unable to open file";
cin.get(); //added this so the window doesn't close automatically
return 0;
}
Thanks for your help guys! I think I'm going to go back to something a bit simpler with C++ and build up from there...
Lets start with this
cin >> paren;
expression = SubExpression::parse();
cin >> comma;
This code reads a single character from cin (the terminal), then calls parse, then reads another single character. It never reads your expression. It also never does anything with the two single characters, it just throws them away.
This says to me that the code that reads the expression from the terminal is in SubExpression::parse() -- that code (which you don't show) apparently reads directly from cin.
This indicates immediately why all your attempts have failed -- you have your expression in a file or a string, but your parse routine is still stubbornly reading from cin. You need to change that routine to read from somewhere else.

What does clearing of input buffer mean?

I was going through a code in my school textbook, wherein there is a line who's function is to clear the input buffer (mentioned as a comment in the code).
I couldn't quite understand its purpose. It is definitely required as its removal messes up the console input process.
Please explain what its function is, and what is happening when I remove it.
I have also tried using cin.ignore(); and it works just fine too. How is the function used here, is it an exact replacement of cin.ignore()?
P.S. In school we are using the older version of C++. Hence the ".h" extension, clrscr();, etc.
#include <iostream.h>
#include <fstream.h>
#include <conio.h>
void main(){
clrscr();
ofstream fout("student.txt", ios::out);
char name[30], ch;
float marks = 0.0;
for(int i = 0; i < 5; i++){
cout << "Student " << (i+1) << ":\tName: ";
cin.get(name,30);
cout << "\t\tMarks: ";
cin >> marks;
cin.get(ch); //for clearing input buffer (This thing!)
fout << name << '\n' << marks << '\n';
}
fout.close();
ifstream fin("student.txt", ios::in);
fin.seekg(0);
cout << "\n";
for(int i = 0; i < 5; i++){
fin.get(name,30);
fin.get(ch); //Again
fin >> marks;
fin.get(ch); //Same
cout << "Student Name: " << name;
cout << "\tMarks: " << marks << "\n";
}
fin.close();
getch();
}
cin >> marks;
cin.get(ch); //for clearing input buffer (This thing!)
This is a not-so-robust way of clearing the input buffer. If you type a number followed by Enter, the first line will consume the number and put the value in marks while the second line will read the newline character and discard it.
It is not robust since it does not account for spaces a user might have entered after the number. A more robust method would be to use istream::ignore.
cin >> marks;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
I just want to start with pointing out that you are not using "the older version of C++". You are just using some c code (like clrscr()) and c styled programming, and indeed probably not cpp11 or cpp14. Also header files for C++ are often still just .h.
Now the answer to your question:
cin.get(ch);
The '\n' character gets read into ch. '\n' is one character, a newline character.
does indeed do the same thing as
cin.ignore();
It is used to clear the input buffer, which means that the empty end of line ('\n') is being deleted from the input buffer.
Why is this done you ask? This is a good example of why you would do that. Hope this helped you!

Writing to a file in C++

I'm trying to make a program that will get the user input of a new file name, create the file, and write to it. It works but it will only write the first word of the string to the file. How can i get it to write the full string? thanks.
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
for (;;)
{
char *myFile = " ";
string f = " ";
string w = " ";
cout <<"What is the name of the file you would like to write to? " <<endl;
cin >>f;
ofstream myStream(f,ios_base::ate|ios_base::out);
cout <<"What would you like to write to " <<f <<" ? ";
cin >>w;
myStream <<w;
if (myStream.bad())
{
myStream <<"A serious error has occured.";
myStream.close();
break;
}
}
}
According to this post, you should consult this reference to use a method like getline().
Also, when you are writing out I recommend that you flush the output (cout.flush()) before ending the program, especially in this case, since I presume you are ending the program with a ctrl-C break.
In formulating a suggestion, I will read data into char*, and convert them to "string" in case you will use them elsewhere in your program.
I tested this code in MS Visual C++ Express.
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
for (;;)
{
char *myFile = new char[200]; // modified this line
//added this line
char *myInput = new char[200];
string f = " ";
string w = " ";
cout << "What is the name of the file you would like to write to? " << endl;
cin.getline(myFile, 200);//modified this line
f = (myFile);//added this line
cin.clear(); //added this line
ofstream myStream(f, ios_base::ate | ios_base::out);
cout << "What would you like to write to " << f << " ? ";
cin.getline(myInput, 200);//edited this line
w = string(myInput);//added this line
myStream << w;
myStream.flush();//added this line
if (myStream.bad())
{
myStream << "A serious error has occured.";
myStream.close();
break;
}
delete myFile;
delete myInput;
}
}
You have to use std::getline() to read the entire line:
std::getline(std::cin >> std::ws, w);
The >> std::ws part gets rid of leading whitespace which is needed because the newline left in the stream from the previous extraction will prevent std::getline() from fully consuming the input.
When inserting data into the stream you need to make sure it gets flushed (because, as the other answer said, you're probably using Ctrl+C to terminate the program and you may not see output during the program run). You can use the std::flush manipulator to flush the output:
myStream << w << std::flush;
cin<<w; cin would stop consuming input character when it encounter whitespace tab and other unseeable characters.
you should probably use std::getline() instead.
take a look at this page for ref.
http://en.cppreference.com/w/cpp/string/basic_string/getline
Or you can use manipulator to not skip whitespace.

std::fstream File prints junk at end of reading

Im writing a program to practice with the language, but im getting some pretty weird output from code that seems right to me.
The code:
#include <iostream>
#include <fstream>
#include <list>
struct Car
{
std::string make;
std::string model;
int partNo;
double price;
int quantity;
std::string partname;
};
void AddItem();
void _Update(int PartNo, int quantity);
void UpdateList(std::list<Car>& _Car);
int main()
{
std::list<Car> _Car;
UpdateList(_Car);
for(std::list<Car>::iterator iter = _Car.begin(); iter != _Car.end(); iter++)
{
std::cout << iter->make << " " << iter->model << " " << iter->partNo << " " << iter->price << " " << iter->quantity << " " << iter->partname << std::endl;
}
}
void UpdateList(std::list<Car>& _Car)
{
std::ifstream File("CarParts.txt");
if(!File.is_open())
std::cerr << "Bad file input....... closing....";
while(!File.eof())
{
Car tempObj;
File >> tempObj.make >> tempObj.model >> tempObj.partNo >> tempObj.price >> tempObj.quantity;
getline(File,tempObj.partname);
_Car.push_back(tempObj);
}
File.close();
}
Outpost given:
Pajero NA1H25 1 3.65 11 BLADE W/S WIPER Honda_Sivic R34gFk 2 4.97 15
ENGINE CHANGE 2 4.97 15
Notepad file:
Pajero NA1H25 1 3.65 11 BLADE W/S WIPER
HondaSivic R34gFk 2 4.97 15 ENGINE CHANGE
what is with the three numbers under the two lines i actually wanted printed out? It's really confusing me... Thanks if you can help!
This is a common issue people run into while reading file data in C++. The issue is your usage of eof. That flag is only set after an attempt to read data has failed.
Because of that, after reading the first two lines, it still has not hit the end of the file. It has read right up to it, but eof has not been set. Then it will loop around a third time, attempt to read 2 lines, and then exit after that. The problem is that you never check for eof before pushing the results of that third loop into your car list.
In your case, you can either move your eof check to after the getline call, or make use of the getline return value.
For example:
while(true)
{
Car tempObj;
File >> tempObj.make >> tempObj.model >> tempObj.partNo
>> tempObj.price >> tempObj.quantity;
if (!getline(File,tempObj.partname)) break;
_Car.push_back(tempObj);
}
This will check whether the data was read successfully before pushing.
For starters, set the namespace of the program to std to avoid the nasty std::string etc syntax.
Near the top of your file, under your imports, insert:
using namespace std;
It looks like the objective is to populate a list from a file.
Looking at this part:
File >> tempObj.make >> tempObj.model >> tempObj.partNo >> tempObj.price >> tempObj.quantity;
getline(File,tempObj.partname);
I think a better solution would be to parse each line withgetLine, and then parse the data accordingly with a space delimeter or a comma. Whitespace delimiters can be finiky.

Reading data from file created from outside

I'm trying to read from files created outside of the program, but am having some trouble. The program has the user create a file. Then it reads words from two .txt files created outside of the program, and then writes the words to the created file.
#include "std_lib_facilities.h"
int main()
{
string word;
cout << "Create file.\n";
char name[20];
cin >> name;
ofstream ost(name, ios::out);
cout << "Open first file.\n";
char filename[20];
cin >> filename;
ifstream ist(filename);
while(ist >> word) ost << word << " ";
ist.close();
cout << "Open second file.\n";
cin >> filename;
ifstream isttwo(filename);
while(isttwo >> word) ost << word << " ";
isttwo.close();
ost.close();
keep_window_open();
}
However, when I open the created file in notepad, it comes out blank. Is this because reading into a string is impossible because the files being read were created separately? I'm not really sure. Any help is appreciated.
The code is correct. Just make sure when you write the name of the first file and the second one you write their extensions as well.
For example :
first.txt
second.txt
A potential problem is your use of cin instead of getline.
Imagine this input:
Open second file.
>>file one.txt
This obviously won't open the file you want, since cin stops reading once you hit a space.
Try explicitly opening name, such as:
ost.open(name);
I also don't like your implicit use of the >> operator in the while loops. Try this:
while (!ist.eof())
{
getline(ist, word);
ost << word;
}
Maybe you should null terminate the filename[20] string . Like filename[20]={0}; before getting it from the standard input ; Then try printing out the filename on the console to check if the file name is OK .
Trikker,
The code compiled with insignificant changes and I came across the same problem you are having, though actually it works. Here's what happened with me. It has to do with how you are running the program. The exe file is saved in ../ProjectDir/Debug directory. If you save the two input files in Debug directory, you should run the program from the command prompt, NOT from the IDE (assuming Visual Studio 2008). However, if you run it from the IDE, save the two input files in ../ProjectDir/ProjectDir. Once I did that everything was ok with me.
Just to be sure about this directory thing, I have printed the directory from which the program is being run from the IDE. Though, the prompt shows that it is running the exe from the Debug directory, the working directory was actually ProjectDir/ProjectDir.
Anyway, please, give the following code a shot and do let us know?
//#include "std_lib_facilities.h"
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
system("cd");
//string word;
char word[80];
cout << "Create file.\n";
char name[20];
cin >> name;
ofstream ost(name, ios::out);
cout << "Open first file.\n";
char filename[20];
cin >> filename;
ifstream ist(filename);
while(ist >> word) ost << word << " ";
ist.close();
cout << "Open second file.\n";
cin >> filename;
cout << filename;
ifstream isttwo(filename);
while(isttwo >> word) ost << word << " ";
isttwo.close();
ost.close();
//keep_window_open();
}
This directory issue also probably explains why you didn't get anything, when tried to print out if it was reading anything at all. You probably should have checked if the input file creation was successful. To do that, just add ...
if ( ist.fail() ){
cout << "file open failed\n";
}
after
ifstream ist(filename)
What happens if you use absolute paths? e.g. on Windows try c:\file.txt and so on.