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.
Related
Im having issues displaying the output. There is always and extra line being printed. I did some research and it turns out that its because my getline. Also I apologize for the format
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct menuItemType
{
string menuItem;
double menuPrice;
};
int main()
{
menuItemType plainEgg;
menuItemType baconEgg;
menuItemType muffin;
menuItemType frenchToast;
menuItemType fruitBasket;
menuItemType cereal;
menuItemType coffee;
menuItemType tea;
ifstream infile;
infile.open("Ch9_Ex5Data.txt");
while(infile)
{
getline(infile,plainEgg.menuItem);
infile >> plainEgg.menuPrice;
getline(infile,baconEgg.menuItem);
infile >> baconEgg.menuPrice;
getline(infile,muffin.menuItem);
infile >> muffin.menuPrice;
getline(infile,frenchToast.menuItem);
infile >> frenchToast.menuPrice;
getline(infile,fruitBasket.menuItem);
infile >> fruitBasket.menuPrice;
getline(infile,cereal.menuItem);
infile >> cereal.menuPrice;
getline(infile,coffee.menuItem);
infile >> coffee.menuPrice;
getline(infile,tea.menuItem);
infile >> tea.menuPrice;
cout << plainEgg.menuItem << plainEgg.menuPrice << endl;
cout << baconEgg.menuItem << baconEgg.menuPrice << endl;
cout << muffin.menuItem << muffin.menuPrice << endl;
cout << frenchToast.menuItem << frenchToast.menuPrice << endl;
cout << fruitBasket.menuItem << fruitBasket.menuPrice << endl;
cout << cereal.menuItem << cereal.menuPrice << endl;
cout << coffee.menuItem << coffee.menuPrice << endl;
cout << tea.menuItem << tea.menuPrice << endl;
}
infile.close();
return 0;
}
Contents in the file
Plain Eggs
1.45
Bacon and Eggs
2.45
etc.
I tried using
if (infile.eof())
cout << endl;
this is my output
Plain Egg1.45 // <-- this is the only correct output
Bacon
and Egg2.45
Muffin
0.99
French
Toast1.99
Fruit
Basket2.49
Cereal
0.69
Coffee
0.50
Tea
0.75
Only thing that printed correctly was the very first line. (Note)I have to use structure.
There are at least three major problems in the shown code. The first one is not properly checking for an end of file condition:
while(infile)
This checks if the input stream already entered a failed state.
After reading the last line in your file, your input stream hasn't failed yet. Everything, up until point, has went exactly according to plan.
So, after the last line in the file, this condition will still evaluate to true, running the loop one more time. Of course, it will fail miserably.
And explicitly checking if (infile.eof()) will, again, if the file has already encountered an end-of-file condition.
What you probably want to do is to try to start reading the next line from the file, and if it fails, then you've reached the end of it:
while (getline(infile,plainEgg.menuItem))
{
// The code that reads the next set of items.
But this, alone, won't solve all of your problems.
getline(infile,plainEgg.menuItem);
infile >> plainEgg.menuPrice;
This is mixing an unformatted input operation, std::getline(), with a formatted input operation, the >> operator.
Such combination is fragile, and has several non-obvious failure modes, as explained here, so I won't repeat that; just see this earlier question for more information.
Although there are ways to do this correctly, it's going to be easier for you to rewrite your code to use only std::getline(), or the >> operator to read everything, until you fully understand how to correctly combine unformatted and formatted input operations.
The last problem is a minor quibble. The shown code fails to properly handle incomplete input, and error checking. As shown, as long as it successfully reads the first piece in a set of data, it assumes that the remaining data will be there. You should verify that every input operation (whether you choose to use formatted or unformatted input operations) is properly checked for success.
This is for a homework assignment, but what I am presenting is a small test program for a chunk of my assignment.
Starting out, I am to have a list of songs in file "songs.txt". My current file looks like this.
Maneater;4;32
Whip It;2;41
Wake Me Up Before You Go-Go;3;45
The file simply contains a song title, and the duration in minutes and seconds, with the title, minutes, and seconds separated by semicolons. The full file is supposed to contain the Artists and Album as well, all separated by semicolons. Anyways, the code.
#include<iostream>
#include<cstring>
#include<fstream>
#include<cstdlib>
using namespace std;
const int CAP = 100;
const int MAXCHAR = 101;
struct songInfo
{
char title[CAP];
char durMin[CAP];
char durSec[CAP];
};
void getData(songInfo Song[], int listSize, int charSize);
int main()
{
string fileName;
songInfo Song[CAP];
ifstream inFile;
cout << "What is the file location?: ";
cin >> fileName;
inFile.open(fileName.c_str());
if (inFile.fail())
{
cout << "Cannot open file " << fileName << endl;
exit(1);
}
getData(Song, CAP, MAXCHAR);
for (int i=0;i<CAP;i++)
{
cout << Song[i].title << " - "
<< Song[i].durMin << ":"
<< Song[i].durSec << endl;
}
cout << "Press any button to continue..." << endl;
cin.get(); cin.get();
return 0;
}
void getData(songInfo Song[], int listSize, int charSize)
{
for (int i = 0; i < listSize; i++)
{
cin.get(Song[i].title, charSize, ';');
cin.get(Song[i].durMin, charSize, ';');
cin.get(Song[i].durSec, charSize, '\n');
i++;
cin.ignore();
}
}
The program compiles correctly without incident, but the output is not what I want it to be. What should happen:
Test.cpp opens songs.txt
Read the first char array into Song[i].title, delimited by ';'
Read the second char into Song[i].durMin, delimited by ';'
Read the third char into Song[i].durSec, delimited by newline
After compiling the code and running it, I get this as my output:
~/project2Test> ./test
What is the file location?: songs.txt
The program then hangs here and I have to ctrl+C out
First, what am I doing wrong?
Second, how do I go about fixing what I screwed up?
Also, as a note for class rules, I am not allowed to use any strings except for the filename. Other than that, all words must be chars.
A debugger is definitely a good thing to use for a problem like this.
Your hanging problem is occurring because in your get_data function you are using cin.get instructing your program to get input from the standard input file. You intended to use the file you defined, "inFile" not the standard input cin.
As an aside it is not clear to me why you are incrementing i twice per iteration of the for loop.
Use inFile.get() instead of cin. You need to pass inFile to the function first.
Put a print statement in the for loop to see what is happening.. A future issue that might crop up is that if you are on a Windows machine and have \r\n line endings. Unix uses \n, Windows uses \r\n
I'm a beginner C++ user and I have tried collaborating with my classmates and such but we haven't been able to find an answer to this question. Our instructor has provided us with a linker that runs the main function for us and provides a simple text file for us to read from, and for the time being the second const char* in the heading is unimportant, for now all I need is to read the data from the file const char* saifFile and display it on-screen. When I run my program I have found that it stops the reading early. And I understand that you may not be able to help because you do not have access to the linker, but any help would be much appreciated.
Here is all my code:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
const int DESC_SIZE = 37;
struct Item
{
int itemId;
char description[DESC_SIZE];
double cost, price;
};
int processFile(const char* saifFile, const char* raofFile)
{
fstream outFile, inFile;
Item Inventory;
inFile.open(saifFile, ios::in);
while (inFile)
{
inFile >> Inventory.itemId >> Inventory.cost >> Inventory.price;
inFile.getline(Inventory.description, DESC_SIZE);
cout << " " << Inventory.itemId << " " << setw(5) << Inventory.cost << " " << setw(5) << Inventory.price <<" " << Inventory.description << endl;
}
return 0;
}
Make sure that the data type you have set to receive from inFile matches the type that inFile reads. If not, you will get a stream error and that will cause your program to stop reading.
After every read, try to inFile.clear() and see if your program hangs or stops early. Alternatively, after each read try
if(inFile.fail())
{
cout << "Read error in file\n";
}
This may not be the answer, but I'd start debugging here.
Try changing the while statement to:
while(!inFile.eof())
And also make sure that you have stored the data in the file in proper order.
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.
First task of the tutorial and I'm already stumped,
Right, I'm supposed to write down 3 numbers into a text file, open that file up, output all 3 numbers and the average. Managed to get the first 2 parts done but I've hit a wall at the actual output part.
Here is the contents of the text file exactly as it appears within the file:
25
10
12
And here is the code I have so far:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
// Create an ifstream input stream for reading of data from the file
ifstream inFile;
inFile.open("ProgrammingIsFun.txt");
// Create an ofstream output stream for writing data to a file
ofstream outFile;
outFile.open("Results.out");
cout << "The first integer is " << endl;
cout << "The second integer is " << endl;
cout << "The third integer is " << endl;
cout << "The average is " << endl;
// Close the files since we're done with them
outFile.close();
inFile.close();
system("Pause");
return 0;
}
From what I understand the contents of the txt file can only contain those 3 numbers and nothing else (I could be wrong though)
Any help would be much appreciated.
I'm guessing that the preferred C++ way of reading integers from files would be:
int first, second, third;
inFile >> first;
inFile >> second;
inFile >> third;
You can then analogously output using the << operator on outFile.