I have a C++ function that reads a .txt file, however, when I run it, std::getline returns nothing. Therefore, the while loop on line 22 does not run.
How do I fix this function to return a vector where each line is a different item in the vector?
The file I am reading from a .txt file that has two lines:
testing
123
Here is my code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
std::vector<std::string> readf(std::string filename)
{
std::ifstream file(filename);
file.open(filename);
// Check if file is open
if (!file.is_open())
{
std::cout << "Error opening file: " << filename << std::endl;
exit(EXIT_FAILURE);
}
std::vector<std::string> lines;
std::string line;
// Read the file
while (std::getline(file, line))
{
if (line.size() > 0)
lines.push_back(line);
}
return lines;
}
You don't need to invoke file.open(filename); because you already opened the file using the constructor std::ifstream file(filename);.
Invoking file.open(filename); after opening the file using the constructor causes the stream to enter an error state, because the file has not been closed yet.
See The difference between using fstream constructor and open function.
Related
I have a txt file, named mytext.txt, from which I want to read and save every line in C++. When I run the binary, I do ./file <mytext.txt
I'd like to do something
std::string line;
while(std::getline(std::cin,line)){
//here I want to save each line I scan}
but I have no clue on how to do that.
You can use a std::vector<string> to save the lines as so:
///your includes here
#include <vector>
std::vector<std::string> lines;
std::string line;
while(std::getline(std::cin,line))
lines.push_back(line);
You can look at the following documentation and example:
http://www.cplusplus.com/doc/tutorial/files/
Edit upon recommendation:
In the provided link below they explain how to open and close a text file, read lines and write lines and several other functionalities. For completeness of this answer an example will be given below:
// writing on a text file
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile ("example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
The above script will write the 2 lines into the text file named example.txt.
You can then read these lines with a somewhat similar script:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Best regards
Ruud
I'm trying to read a text file and output the contents. It's just I can't seem to find the right method and the ones I've used (including this one), seems to wipe the text file. The code:
std::string Line;
std::ifstream File("Account.txt");
if (File.is_open()) {
while (getline(File, Line)) {
std::cout << Line << std::endl;
}
}
else {
std::cout << "Unable to open File" << std::endl;
}
File.close();
I'm also using:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
I'm using this code (below) every time the program runs to create the file which might be the error, if so can anyone recommend a way to create the file only if it doesn't already exist
std::ofstream File("Account.txt");
File.close();
Your file is being wiped by your file creating code.
std::ofstream File("Account.txt");
File.close();
To create a file without wiping existing contents try this
std::ofstream File("Account.txt", std::ios_base::app);
File.close();
I am trying to read two files "ListEmployees01.txt" and "ListEmployees02.table". But the program reads only the "ListEmployees01.txt" file and cout is just from that file.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
int main()
{
freopen("ListEmployees01.txt", "r", stdin);
string s;
while (getline(cin, s))
cout << s<<endl;
fclose(stdin);
freopen("ListEmployees02.table", "r", stdin);
while (getline(cin, s))
cout << s<<endl;
}
You can use std::ifstream instead of changing std::cin's behavior.
I would do the following using fstream
#include <fstream>
void readAndPrint(const char *filename) {
std::ifstream file(filename);
if (file.is_open()) {
std::string line;
while (getline(file, line)) {
printf("%s\n", line.c_str());
}
file.close();
}
}
int main() {
readAndPrint("ListEmployees01.txt");
readAndPrint("ListEmployees02.table");
return 0;
}
If you must use freopen, then have a look at man freopen, or the C++ reference http://www.cplusplus.com/reference/cstdio/freopen .
In your case , in the case of second file you are using the stdin which is already closed by below line , hence it is a dangling pointer after file close
fclose(stdin)
You can use fopen instead of freopen for the second file.
Please check the below paragraph from www.cplusplus.com/reference/cstdio/freopen/
If a new filename is specified, the function first attempts to close
any file already associated with stream (third parameter) and
disassociates it. Then, independently of whether that stream was
successfuly closed or not, freopen opens the file specified by
filename and associates it with the stream just as fopen would do
using the specified mode.
I am looking for a way to search for a specific character in a text file and add a new-line after every ;
It's a pretty big document (2,7MB) if that matters.
You can't insert new characters into the middle of an existing file, only append to the end. You will have to create a new file, copying characters from the old file to the new file, inserting new characters as needed. For example:
#include <string>
#include <fstream>
int main()
{
std::ifstream inFile("input.txt");
if (!inFile.is_open())
{
std::cerr << "Failed to open input file";
return 1;
}
std::ofstream outFile("output.txt");
if (!outFile.is_open())
{
std::cerr << "Failed to create output file";
return 1;
}
std::string line;
while (std::getline(inFile, line, ';'))
{
outFile << line;
if (!inFile.eof())
outFile << ";\n";
}
return 0;
}
As SomeProgrammerdude points out in the comments, inserting into an existing file isn't really feasible and one of your options is to read it all into a single std::string and write back into the same text file.
Here is an example implementation. We read a charter at a time and check if it is a semicolon, and add a newline after every semicolon. Notice the reserve part, although advised, it is not mandatory:
#include <string>
#include <fstream>
#include <stdexcept>
int main()
{
std::fstream f("test.txt", std::ios::in);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
std::string contents;
contents.reserve(10000); // reserve some space for better efficiency
char ch;
while (f.get(ch)) {
contents.push_back(ch);
if (ch == ';')
contents.push_back('\n');
}
f.close();
f.open("test.txt", std::ios::out);
if (!f.is_open()) {
throw std::runtime_error("Failed to open file");
}
f << contents;
f.close();
return 0;
}
Input:
line line line line; line line line line; line line line; line line
Output:
line line line line;
line line line line;
line line line;
line line
Note the leading spaces before lines. This is because we appended '\n' after every ';', did not replace the spaces.
Please see my code below.
ifstream myLibFile ("libs//%s" , line); // Compile failed here ???
I want to combine the path string and open the related file again.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("libs//Config.txt");
// There are several file names listed in the COnfig.txt file line by line.
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
// Read details lib files based on the each line file name.
string libFileLine;
ifstream myLibFile ("libs//%s" , line); // Compile failed here ???
if (myLibFile.is_open())
{
while (! myLibFile.eof() )
{
cout<< "success\n";
}
myLibFile.close();
}
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Assume my [Config.txt] include the content below. And all the *.txt files located in libs folder.
file1.txt
file2.txt
file3.txt
The ifstream constructor does not work that way. Its first parameter is a C string to the file you want to open. Its second parameter is an optional set of mode flags.
If you want to concatenate the two strings, just concatenate the two strings:
std::string myLibFileName = "libs/" + line;
ifstream myLibFile(myLibFileName.c_str());
// Or, in one line:
ifstream myLibFile(("libs/" + line).c_str());
(the call to c_str() is required because the ifstream constructor takes a const char*, not a std::string)