I have a strange problem that seems to happen when I pass an ifstream by reference.
In my main method, I have created an ifstream, and then I pass it to this read method by reference:
void ArrayStorage::read(ifstream& fin)
{
if (fin.is_open())
{
string input;
getline(fin, input, '\n');
}
else
{
}
}
This should work fine, however, I'm getting the following message in the value of the ifstream:
fin {_Filebuffer={_Set_eback=0xcccccccc _Set_egptr=0xcccccccc ...} } std::basic_ifstream > &
Anyone have any ideas?
EDIT: Code that calls the method:
ifstream fin1("data.txt");
ofstream out1("1-In-SortedRead.txt");
if(!fin1.is_open())
{
cout << "FAIL" << endl;
return 1;
}
ArrayStorage arrayStorage1;
// read in values into data structure
arrayStorage1.read(fin1);
Related
#include"std_lib_facilities.h"
void login(){
fstream fin;
fin.open("user.csv",ios::in);
vector<string>data;
string word;
string temp;
string line;
while(fin>>temp){
data.clear();
getline(fin,line);
stringstream s(line);
while(getline(s,word,',')){
data.push_back(word);
}
}
cout<<data.size()<<'\n';
cout<<data[0]<<'\n';
}
int main()
{
login();
}
I am trying to collect data from the user.csv file and the code i have written is a modified version of a working code written by another programmer(https://www.geeksforgeeks.org/csv-file-management-using-c/) but even after trying a lot i am still confused why my code is showing a range error and when i checked the size of vector it is showing 0.....why?? andjust for info the user.csv file contains :
hello,testing,qwerty
Here's a version of your code that might work
void login(){
ifstream fin("user.csv");
if (!fin.is_open()) {
cerr << "file open failed\n";
return;
}
vector<string>data;
string line;
while(getline(fin,line)) {
istringstream s(line);
string word;
while(getline(s,word,',')){
data.push_back(word);
}
}
cout<<data.size()<<'\n';
cout<<data[0]<<'\n';
}
I haven't tested this.
I'm taking a basic OOP in C++ class. One of our assignments is to read lines from a file, run them through a function (parseLine()) that converts a string to a string stream, throw exceptions from that parseLine, catch the exceptions in the readFile function and write the lines that threw exceptions to the console. The lines that did not throw exceptions should be added to a struct array.
The problem: The throws are not being thrown, or not being caught.
I have spent hours playing with the formatting trying to figure out why my try catch statement isn't working. I wish I could ask a more specific question, but I believe the answer will be obvious to a more experienced programmer who sees my code
Note: Formatting style is prescribed by the class.
/**********************************************************************
* struct: Record
* fileName
* user
* time
***********************************************************************/
struct Record
{
string file;
string user;
long time;
};
/**********************************************************************
* function: parseLine
* parse line into struct
***********************************************************************/
void parseLine(const string & line, Record & buffer) throw (string)
{
assert(line.length() > 0);
stringstream ss;
ss.str(line);
// stream string to struct
ss >> buffer.file;
if (ss.fail())
{
ss.clear();
throw string(line);
}
ss >> buffer.user;
if (ss.fail())
{
ss.clear();
throw string(line);
}
ss >> buffer.time;
if (ss.fail() || buffer.time < 1,000,000,000 || buffer.time > 10,000,000,000)
{
ss.clear();
throw string(line);
}
}
/**********************************************************************
* function: readFile
* read from the file name provided by the user
***********************************************************************/
int readFile(const string & fileName, Record record[])
{
// declare fstream variable
ifstream fin(fileName.c_str());
// error check
if (fin.fail())
{
cout << "ERROR: Unable to read file "
<< fileName
<< endl;
return 0;
}
// loop through file and store it
Record buffer;
string line;
int size = 0;
while (getline(fin, line) && size < 500)
{
try
{
parseLine(line, buffer);
record[size] = buffer;
}
catch (string text)
{
cout << "Error parsing line: "
<< text
<< endl;
}
size++;
}
// close the file
fin.close();
return size;
}
Question 1 The file being read purposely contains errors (Empty lines, ints in unexpected places, etc), it seems like the ss.fail() is not being triggered, how could that happen?
Question 2 Is my try/catch block written correctly?
Thank you very much for your help!
Your integer literals should not contain commas.
The comma is actually a C++ operator.
I searched internet and read manuals for hours but I can't figure out this one:
My program gets one optional argument, which is file name. Consider this conditions
std::ifstream file;
if (argc > 1) {
file.open(argv[1]);
}
if (file.is_open()) {
processInput(file);
file.close();
} else {
processInput(std::cin);
}
in function processInput I'm trying to read all lines from input and do something with them like this:
void processInput(std::basic_istream<char> inputStream) {
std::string line;
while (std::getline(inputStream, line)) {
processLine(line);
}
}
but I'm getting an error in basic_istream, so I don't have any clue what type should I pass to this function. I tried only blind shots.
Streams are not copyable. You have to pass the stream by reference:
// v-- here
void processInput(std::basic_istream<char> &inputStream) {
By the way, there's a shorter way to write std::basic_istream<char>, which is
void processInput(std::istream &inputStream) {
I'm trying to write a function that automatically formats XML-Strings; but I'm already failing when I try to read text from a file and write it into another one.
When I use my function sortXMLString()
bool FormatXML::sortXMLString()
{
string XMLString;
ifstream fin("input.txt");
fin.open("input.txt", ios::in);
ofstream fout("output.txt");
fout.open("output.txt", ios::out);
if (fin.is_open() && fout.is_open())
{
if (fin.good()) cout << "good" << endl;
if (fin.fail()) cout << "fail" << endl;
if (fin.bad()) cout << "bad" << endl;
while (getline(fin, XMLString))
{
//TODO: Formatting
fout << &XMLString << endl;
}
fin.close();
fout.close();
}
else return false;
return true;
}
I will get the output "fail", but the function never enters the while-loop. The function returns true.
It doesn't matter what I write into my input.txt (a single letter, a single number, multiple lines of text or even nothing), the failbit will always be set before getline can even be reached.
Why is this/ how can I properly read out of my file?
ifstream fin("input.txt"); will open the file with fin as stream object why calling open member function again ? same goes for fout object too.
Calling open on an already open stream fails, meaning the failbit flag is set to true.
Just open once
ifstream fin("input.txt");
ofstream fout("output.txt");
If I include the if test in my code the error message is returned and I'm not sure why.
and when it's not used, my program get's stuck in a loop where it never reaches the end of the file. I don't understand what's going wrong.
int countlines()
{
fstream myfile;
myfile.open("questions.txt", ios::in);
string contents;
int linenumber = 0;
//if (myfile.is_open())
// {
while (!myfile.eof())
{
getline( myfile, contents );
if (contents != "")
{
linenumber++;
}
}
cout << "there are " << linenumber << " lines.\n";
//}else {cout<<"Unable to get file.\n";}
myfile.close();
return(linenumber);
}
What's going on is that your file is not being opened. That's why is_open fails.
Then, when you comment out the check, you're breaking your loop because you're iterating incorrectly (see my comment) and not detecting stream failures (.eof() will never be true on that stream).
Make sure that the file is in the right place, and that it is accessible.
The correct idiom for reading a file line-by-line in C++ is using a loop like this:
for (std::string line; std::getline(file,line);)
{
// process line.
}
Inserting this in your example (+fixing indentation and variable names) gives something like this:
int countlines(const std::string& path)
{
// Open the file.
std::ifstream file(path.c_str());
if (!file.is_open()) {
return -1; // or better, throw exception.
}
// Count the lines.
int count = 0;
for (std::string line; std::getline(file,line);)
{
if (!line.empty()) {
++count;
}
}
return count;
}
Note that if you don't intend to process the line contents, you can actually skip processing them using std::streambuf_iterator, which can make your code look like:
int countlines(const std::string& path)
{
// Open the file.
std::ifstream file(path.c_str());
if (!file.is_open()) {
return -1; // or better, throw exception.
}
// Refer to the beginning and end of the file with
// iterators that process the file character by character.
std::istreambuf_iterator<char> current(file);
const std::istreambuf_iterator<char> end;
// Count the number of newline characters.
return std::count(current, end, '\n');
}
The second version will completely bypass copying the file contents and avoid allocating large chunks of memory for long lines.
When using std::istream and std::ostream (whose std::fstream implements), the recommended usage is to directly use the stream in a bool context instead of calling eof() function because it only return true when you managed to read until the last byte of the file. If there was any error before that, the function will still return true.
So, you should have written your code as:
int countlines() {
ifstream myfile;
int linenumber = 0;
string linecontent;
myfile.open("question.txt", ios::in);
while (getline(myfile, linecontent)) {
if (!linecontent.empty()) {
++linenumber;
}
}
return linenumber;
}
Try the following code. It will also (hopefully) give you an idea why the file open is failing...
int countlines()
{
ifstream myfile;
myfile.open("questions.txt");
string contents;
int linenumber = 0;
if (myfile.is_open())
{
while (getline(myfile, contents))
{
if (contents != "")
linenumber++;
}
cout << "there are " << linenumber << " lines." << endl;
myfile.close();
}
else
cout << "Unable to get file (reason: " << strerror(errno) << ")." << endl;
return linenumber;
}