I can't read a single line using getline() [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I've got a class:
class DataBase{
private:
fstream db_file;
public:
DataBase(){
db_file.open("db.txt", std::ios::in | std::ios::out);
}
void couteverything(){
string line;
if(db_file.good() && db_file.is_open()){
getline(db_file, line);
cout << line;
cout << "ok";
}
}
~DataBase(){
db_file.close();
}
};
and a file db.txt with some content.
I'd like to cout it to the console, but it's not working - as if the file was empty (nothing appears on the screen).

In your constructor, you do not test whether the file opened successfully. Therefore, you have no idea if the file opened successfully. Thus, your couteverything method can't distinguish EOF from "failed to open." You might consider adding a check:
DataBase(){
db_file.open("db.txt", std::ios::in | std::ios::out);
if (!db_file.is_open() || !db_file.good()) {
// put an error message here, or throw an exception. Up to you.
}
}
Once you're in couteverything(), presumably you want to loop over the entire file. You need a loop for that, not an if statement. Something like this:
while (getline(db_file, line)) {
cout << line;
cout << "ok";
}
Even if you did not want to loop here (in which case coutnextline() might be a better name for the method), you still want to test the result of getline() directly, rather than testing good() and is_open() before each read. You need to test whether getline() succeeds, otherwise your code will try to process one line beyond EOF or a read error.
if (getline(db_file, line)) {
cout << line;
cout << "ok";
}
If you do only want to output a line at a time, I'm not sure how the code that calls this would know when to stop. But, that's a different problem. (Hint: You could solve that by returning a bool from this line-at-a-time method.)

Related

How to fix this code to read this file in C++? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Here's my code, which should be able to read the file, but it gives me this:
Error: Invalid format in file
What's wrong in this code?
int main()
{
std::map<std::string, std::vector<std::string>> routes;
print_rasse();
std::string inp;
std::cout << "Give a name for input file: ";
std::getline(std::cin, inp);
std::ifstream file(inp);
std::string row;
if ( not file ) {
std::cout << "Error: File could not be read." << std::endl;
return EXIT_FAILURE;
}
while(getline(file, row)){
if (count(row.begin(), row.end(),';'+!1)){
std::cout << "Error: Invalid format in file." << std::endl;
return EXIT_FAILURE;
}
}
}
The .txt file which I'm trying to read contains this:
West;Pyynikintori;0
West;Tuulensuu;0.5
West;Keskustori;1.5
West;Koskipuisto;1.8
West;Rautatieasema;2.2
West;Tulli;2.5
West;Sammonaukio;2.8
East;Sammonaukio;
East;Kaleva;0.2
East;Uintikeskus;0.3
East;Kalevanrinne;0.6
East;Hakametsa;1
East;Turtola;3
East;Hallila;5
East;Hervanta;7
East;Hervannan kampus;7.1
South;Hervannan kampus
South;Etela-Hervanta;0.4
South;Hervantajarvi;0.7
Hospital;Sammonaukio
Hospital;Kalevan kirkko;0.1
Hospital;Hippos;0.4
Hospital;TAYS;0.6
Hospital;Kaupin kampus;0.7
In this statement:
if (count(row.begin(), row.end(),';'+!1))
!1 is effectively the same as 0, so ';'+0 is just ';'. The statement is effectively this:
if (count(row.begin(), row.end(), ';'))
It is counting the number of ; characters in the row. An integer implicitly converts to a bool, where 0 is false and non-0 is true. So, if there are any matching characters in the row, the if will evaluate as true, otherwise as false.
Since each line in the .txt file shown has 2 ; characters in it, count() will return 2, thus the if will be true, and so the code will display the error message.
You probably meant to do this instead:
if (count(row.begin(), row.end(), ';') != 2)

Why is stream::ignore not working as intended?

As far as I know, stream.ignore(n, 'n') should ignore an (n) amount of characters or if ‘\n’ is reached, and skip over to the next line, however, when I run the next code:
// include...
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
while (!stream.eof()) {
std::string a{};
// getline(stream, a); <--- Tried this, didn't work either
stream.ignore(99, '\n');
} // Skip to the last line without any number, in theory
std::cout << info << std::endl; // Check if the output it's correct (Which is)
stream << info; // Insert the info
stream.close(); // Close the file
}
void main() //Main
{
std::cout << "Enter your name, followed by the info you want to add to infoFile:" << std::endl;
std::string info, temp = "";
std::getline(std::cin, temp); // Get the info input
std::stringstream sstream;
sstream << temp;
sstream >> temp >> info; // Remove the name keeping only the info
temp = ""; // ^
std::string::size_type sz;
insertInfo(stoi(info, &sz)); // Convert info string into an integer and insert it in infoFile
}
The console prints out the "info" correct value, however, when I check info.txt, in which I previously wrote a '0' on, you don't see any change.
I tried removing the "ignore" function and it overwrites the 0, which is exactly what I was trying to prevent.
I also tried using "getline" function but the same thing happens.
What is the error here?
Problem
Cannot write to file.
Why
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
Opens file with default permissions, which includes reading. The C++ Standard says I should expect "r+" behaviour and the C Standard says a file opened with "r+" behaviour must exist in order to be read (Someone please add a link if you have one). You cannot create a new file. This is problem 1. The Asker has dealt with this problem by providing a file.
Note: take care when working with files via relative paths. The program's working directory may not be where you think it is. This is problem 1a. It appears that the Asker has this taken care of for the moment.
while (!stream.eof()) {
Common bug. For more details see Why is iostream::eof inside a loop condition considered wrong? In this case since all you're looking for is the end of the file, the fact that the file hasn't been opened at all or has encountered any read errors is missed. Since a file in an error state can never reach the end of the file this quickly becomes an infinite loop. This is problem 2.
std::string a{};
// getline(stream, a); <--- Tryied this, didn't work neither
stream.ignore(99, '\n');
Always test IO transactions for success. This call can fail unchecked.
} // Skip to the last line without any number, in theory
Assuming nothing has gone wrong, and since we're not checking the error state assuming's all we can do, the file has reached the end and is now in the EOF error state. We can't read from or write to the stream until we clear this error. This is problem number 3 and likely the problem the Asker is struggling with.
std::cout << info << std::endl; // Check if the output it's correct (Wich is)
stream << info; // Insert the info
This can fail unchecked.
stream.close(); // Close the file
This is not necessary. The file will be closed when it goes out of scope.
}
Solution
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
while (!stream.eof()) {
stream.ignore(99, '\n');
} // Skip to the last line without any number, in theory
std::cout << info << std::endl; // Check if the output it's correct (Wich is)
stream.clear(); // Added a call to clear the error flags.
stream << info; // Insert the info
stream.close(); // Close the file
}
Now we can write to the file. But let's improve this shall we?
void insertInfo(int info) {
std::fstream stream("infoFile.txt");
while (stream.ignore(99, '\n')) // moved ignore here. now we ignore, then test the result
{
}
stream.clear();
stream << info << '\n'; // added a line ending. Without some delimiter the file
// turns into one big number
}
Note that this isn't exactly kosher. If any ignore fails for any reason, we bail out and possibly write over data because the code blindly clears and writes. I'm not spending much time here trying to patch this up because we can get really, really simple and solve the problem of creating a non-existent file at the same time.
void insertInfo(int info) {
std::fstream stream("infoFile.txt", std::ios::app);
stream << info << '\n';
}
Two lines and pretty much done. With app we append to the file. We do not need to find the end of the file, the stream automatically points at it. If the file does not exist, it is created.
Next improvement: Let people know if the write failed.
bool insertInfo(int info) {
std::fstream stream("infoFile.txt", std::ios::app);
return static_cast<bool>(stream << info << '\n');
}
If the file was not written for any reason, the function returns false and the caller can figure out what to do. The only thing left is to tighten up the stream. Since all we do is write to ti we don't need the permissiveness of a fstream. Always start with the most restrictive and move to the least. This helps prevent some potential errors by making them impossible.
bool insertInfo(int info) {
std::ofstream stream("infoFile.txt", std::ios::app);
return static_cast<bool>(stream << info << '\n');
}
Now we use an ofstream and eliminate all the extra overhead and risk brought in by the ability to read the stream when we don't read the stream.

Why does this line not output my text file? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am currently reading a book that is teaching me about C++ and I have run into a problem. I looked around the Internet a bit to see if I can find an answer but I don't seem to understand them to well. I wrote this code...
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
// Writing the poem
string poem = "\n\tI never saw a man who looked";
poem.append("\n\tWith such a wistful eye");
poem.append("\n\tUpon that little tent of blue");
poem.append("\n\tWhich prisoners call the sky");
// More stuff
ofstream writer("poem.txt");
if(!writer) {
cout << "Error opening file for output" << endl;
return -1; // Signal a termination
}
writer << poem << endl;
writer.close();
// Teminates the program
return 0;
}
I think the problem specifically is this line writer << poem << endl;. But I am not sure what it is I am doing wrong. I am fairly certain I did the exercise correct.
Let me restate my issue. I have a text file that is generated with a poem. What I am trying to do is output the lines of text in the file to the console (terminal). The book that I am reading to do writer << poem << endl;. I did that but nothing is output, it just generates the file with the text and thats it.
A few long moments later.
As it turns out I was just being dumb and I later realized that the problem was more of me not reading/understanding the text to it's fullest. I was under the impression that this code was meant to output the text. I was wrong, but the following answer really helped me! Thanks.
Class ofstream writes to files not to the screen so to get the content of the file to your program then use class ifstream.
In your program if you want the text to be written to a file then read back to your program:
add this code right after closing the file after writting writer.close():
ifstream inFile("poem.txt");
string sLine;
while(getline(inFile, sLine))
cout << sLine << endl;
inFile.close();
Or simply use an object of class fstream doing the two tasks once: writting/reading.

how to read data in c++ from a file stored in any other structure e-g: .text file [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
i gotta read data in c++ from a text file stored in computer
and then tokenize the data on the basis of space so that each word becomes a separate string
i have tried a code but it doesn't print anything as an output instead of a black blank screen
// basic file operations
#include <iostream.h>
#include <fstream.h>
#include <conio.h>
//using namespace std;
int main ()
{
ofstream myfile;
myfile.open ("example.txt");``
myfile << "Writing this to a file.\n";
// myfile.close();`
getch();
return 0;
}
please help :(
The code you have posted does not attempt to write anything to standard output (std::cout). It opens a file (example.txt) and writes "Writing this to a file" in it, closes the file, and then waits for you to press a button before exiting the program. You are seeing no output because you've provided no output operations, nor does it attempt to read anything from the file.
First use ifstream since you want this file as input not output
Second what is this code you posted has to do with the question?
Try this:
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::ifstream file("example.txt");
if (file.is_open())
{
std::string str;
while (std::getline(file, token, ' '))
{
//here str is your tokenized string
}
} else
{
std::cout << "Unable to open file";
}
}
getline will get the next string until the end of line or ' ' is met
This code WRITES to a file...maybe there's a C++ way to do it but strtok does what you describe.
Found within a minute of googling :)
using namespace std;
string STRING;
ifstream myReadFile;
myReadFile.open("Test.txt");
char output[100];
if (myReadFile.is_open())
{
while (!myReadFile.eof())
{
getline(myReadFile,STRING);
cout << STRING;
}
myReadFile.close();
}
Edit: Fixed the thing and tested it with success.

How to properly read from a .csv? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am having memory trouble with my code, and figured out that my code was being read wrong. For example the last value is adding numbers, not sure why. Also the names aren't coming out right.
This is what the output is looking like:
4101,BRAEBURN02.07682e-3172.07691e-317
4021,DELICIOUS02.07682e-3172.07691e-317
4020,DELICIOUS02.07682e-3172.07691e-317
4015,DELICIOUS02.07682e-3172.07691e-317
4016,DELICIOUS02.07682e-3172.07691e-317
4167,DELICIOUS02.07682e-3172.07691e-317
4124,EMPIRE,1,1.14,145.202.07682e-3172.07691e-317
4129,FUJI02.07682e-3172.07691e-317
4131,FUJI02.07682e-3172.07691e-317
As you can see the Empire was separated properly with the exception of the the last value.
Here's my code: the cout part was just for my personal use to see if the values were being inputted properly.
int main()
{
string name;
double price;
int by_weight;
double inventory;
int plu_code;
ifstream infile;
infile.open("inventory.csv");
while(!infile.eof())
{
stringstream ss;
string line = "";
getline(infile,line);
Tokenizer tok(line, ",");
ss << line;
ss >> plu_code >> name >> by_weight >> price >>inventory;
cout << plu_code<<"" <<name<<"" << by_weight<<"" << price <<""<<inventory<<"\n";
table[plu_code] = new Product(plu_code, name,by_weight, price,inventory);
numProducts++;
}
return 0;
}
The Empire line works because it's the only one whose name contains no whitespace. When you read strings from a stream, they are delimited by whitespace, so you only get the first word. If there are more words after that, then reading a double or other numeric type will fail because the stream is still pointing at non-numeric characters. You are not testing that your input operations succeeded, but it should have been obvious from your output.
I'm not sure what effect your Tokeniser class is supposed to have here. But perhaps have a look at this SO question for tokenising commas out of the stream. You can use a single getline call with a comma delimiter to read the name, and then normal << operator for the others.
[Edit] In fact, after cleaning up your question layout I notice that the Empire line doesn't work. It's reading the rest of the line as the name, and then still outputting uninitialised values. Which suggests to me your Tokeniser doesn't do anything at all.