I'm creating this simple program which would save me alot of time, but I'm kinda stuck.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> tempfile;
string line;
ifstream oldfile("old.lua");
if (oldfile.is_open())
{
while (oldfile.good())
{
getline(oldfile, line);
tempfile.push_back(line + "\n");
}
oldfile.close();
}
else
{
cout << "Error, can't find old.lua, make sure it's in the same directory as this program, and called old.lua" << endl;
}
ofstream newfile("new.lua");
if (newfile.is_open())
{
for (int i=0;i<tempfile.size();i++)
{
for (int x=0;x<tempfile[i].length();x++)
{
newfile << tempfile[i][x];
}
}
newfile.close();
}
return 0;
}
So, what this does now, is just copies a file. But I've tried to do it, so it changes fe. every "function" word to "def", I've tried everything and googled already, couldn't find anything useful enough, only thing I found was using sstream, but it didn't work after all, or maybe I'm just not skilled enough to do it, so if anyone could give me any tips or help, cause I really am stuck? :d
boost has a replace all function, and it's much more efficient than the naive search-replace-repeat algorithm. This is what I would do:
std::string file_contents = LoadFileAsString("old.lua");
boost::replace_all(file_contents, "function", "def");
std::ofstream("new.lua") << file_contents;
LoadFileAsString is my own function that looks something like this:
std::string LoadFileAsString(const std::string & fn)
{
std::ifstream fin(fn.c_str());
if(!fin)
{
// throw exception
}
std::ostringstream oss;
oss << fin.rdbuf();
return oss.str();
}
http://www.boost.org/doc/libs/1_33_1/doc/html/replace_all.html
I didn't really understand your problem. I think you need to edit your post and ask it clearly.
But still you can do one major improvement in your code. You should be reading file using C++ stream, in this way:
while (getline(oldfile, line))
{
tempfile.push_back(line + "\n");
}
which is more idiomatic way of reading file using C++ stream!
Read this excellent blog by #Jerry Coffin (an SO user) :
http://coderscentral.blogspot.com/2011/03/reading-files.html
EDIT:
You want to find and replace text in your file, then see the accepted answer in this topic:
String Replace in C++
Try this http://www.boost.org/doc/libs/1_46_1/libs/regex/doc/html/boost_regex/ref/regex_replace.html , http://www.cppreference.com/wiki/string/basic_string/replace
Related
This question already has answers here:
Read file line by line using ifstream in C++
(8 answers)
Closed 3 years ago.
I cant write a words from a file to an array.
I have tried to use char and strings, but i have problem with both of them.
FILE *file = fopen("films.txt", "r");
string FILMS[500];
while (!feof(file))
{
fscanf(file, "%s", FILMS);
//fgets(FILMS, 500, file);
}
I expect that in each cell there will be a word.
Use the C++ classes and functions to make it easier. Instead of a fixed C style array of exactly 500 films, use a std::vector<std::string>> that will grow dynamically when you put film titles in it.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> get_films() {
std::ifstream file("films.txt");
std::vector<std::string> FILMS;
if(file) { // check that the file was opened ok
std::string line;
// read until getline returns file in a failed/eof state
while(std::getline(file, line)) {
// move line into the FILMS vector
FILMS.emplace_back(std::move(line));
// make sure line is in a specified state again
line.clear();
}
}
return FILMS;
} // an fstream is automatically closed when it goes out of scope
int main() {
auto FILMS = get_films();
std::cout << "Read " << FILMS.size() << " film titles\n";
for(const std::string& film : FILMS) {
std::cout << film << "\n";
}
}
As I'm not sure why you tried using c style arrays and files, I posted a 'not too elegant' solution like that one, too, hoping it might help. You could always try to make it more dynamic with some malloc (or new), but I sticked with the easy solution for now.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
void readcpp(const char* fname, std::vector<std::string>& data)
{
std::ifstream file_in(fname, std::ios::in);
if (file_in.is_open())
{
std::string film;
while (std::getline(file_in, film))
{
data.push_back(film);
}
file_in.close();
}
else std::cerr << "file cant be opened" << std::endl;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
void readc(const char* fname, char data[500][500])
{
FILE* file_in = fopen(fname, "r");
if (file_in)
{
char film[500];
for (unsigned int i = 0; fgets(film, 500, file_in) && i < 500; i++)
{
memcpy(data + i, film, 500);
}
fclose(file_in);
}
else fprintf(stderr, "file cant be opened\n");
}
int main()
{
const char* fname = "films.txt";
char cFilms[500][500];
std::vector<std::string> cppFilms;
readc(fname, cFilms);
readcpp(fname, cppFilms);
return 0;
}
And as the others mentioned before, do not use feof or for that matter, ifstream's eof member function either, for checking wheter you reached the end of file, as it may be unsafe.
Hm, I see a lot of code in answers.
The usage of algorithm will drastically reduce coding effort.
Additionally it is a "more modern" C++ approach.
The OP said, that he want to have words in some array. OK.
So we will use a std::vector<std::string> for storing those words. As you can see in cppreference, the std::vector has many different constructors. We will use number 4, the range constructor.
This will construct the vector with a range of similar data. The similar data in our case are words or std::string. And we would like to read the complete range of the file, beginning with the first word and ending with the last word in the file.
For iterating over ranges, we use iterators. And for iterating of data in files, we use the std::istream_iterator. We tell this function what we want to read as template parameter, in our case a std::string. Then we tell it, from which file to read.
Since we do not have files on SO, I use a std::istringstream. But that's the same reading from a std::ifstream. If you have na open file stream, then you can hand it over to the std::istream_iterator.
And the result of using this C++ algorithms is that we read the complete file into the vector by just defining the varaible with its constructer as a one-liner.
We do similar for the debug output.
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <sstream>
std::istringstream filmFile{ R"(Film1 Film2
Film3 Film4 Film5
Film6
)" };
int main()
{
// Define the variable films and use its range constructor
std::vector<std::string> films{ std::istream_iterator<std::string>(filmFile), std::istream_iterator<std::string>() };
// For debug pruposes, show result on console
std::copy(films.begin(), films.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
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 5 years ago.
Improve this question
Hi i am trying to pass a whole file into a string. This is my Code but the program is always exiting on the first if(). I just can't get behind what i am doing wrong here.
#include <iostream>
#include <fstream>
#include <string>
std::string readFile (std::string filename);
int main() {
std::string filename;
std::string Eingabestring;
std::cout << "Geben Sie eine Datei an" << std::endl;
std::cin >> filename;
Eingabestring = readFile(filename);
std::cout << Eingabestring << std::endl;
return 0;
}
std::string readFile (std::string filename)
{
std::string zeile,inhalt ;
std::ifstream quelle;
quelle.open(filename.c_str());
if (!quelle)
{
std::cerr << filename << " kann nicht geƶffnet werden!\n";
return exit(-1);
}
while (!quelle.eof())
{
getline(quelle,zeile);
inhalt = inhalt + zeile;
}
return inhalt;
}
Already thanks for your help!
Edit: I just noticed that i put the file into a wrong folder.. But the code still isn't reading the whole file. Just the first line, but i thought with the loop i could get every line of my file into the string?
And i fixed the second return 0 to exit(-1). Thats better right?
Other than checking to see why the open() failed as explained in the comments also keep in mind that there are easier ways to check for when you have hit the end of file in a while loop where you are reading from an istream.
The idiomatic way to loop and read from an istream in C++ is to embed the read expression that returns a reference to the istream in the loop condition, so change your code to
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
auto character = char{};
auto file_string = string{};
while (cin.get(character)) {
file_string += character;
}
cout << file_string << endl;
return 0;
}
I've used cin above but just replace cin with your file stream object and everything should work normally.
Note that the while terminating condition is now an istream reference, and that is convertible to bool, so the loop will exit when the istream object is done reading or when the stream encounters any errors besides EOF. You don't have to check for eof() yourself.
Also another thing is to pass strings that you do not intend to modify by const reference instead of by value, so the readFile() function should accept a const string& instead of a string, this will help save you string copying. When C++17 is available replace that const string& with std::string_view
Try something like this to read your file instead:
std::string readFile (std::string filename)
{
std::ifstream quelle(filename);
std::string content( (std::istreambuf_iterator<char>(quelle) ),
(std::istreambuf_iterator<char>()) );
return content;
}
In Lua, I have such a function to read a file into an array:
function readFile(file)
local output = {}
local f = io.open(file)
for each in f:lines() do
output[#output+1] = each
end
f:close()
return output
end
Now in C++, I tried to write that like this:
string * readFile(file) {
string line;
static string output[] = {};
ifstream stream(file);
while(getline(stream, line)) {
output[sizeof(output)+1] = line;
}
stream.close();
return output;
}
I know you can't return arrays from functions, only pointers. So I did this:
string *lines = readFile("stuff.txt");
And it threw me the error cannot convert 'std::string {aka std::basic_string<char>} to' std::string* {aka std::basic_string<char>*}' in intialization string *lines = readFile("stuff.txt");
Can anyone tell me what is wrong here, and is there a better way to read files into arrays?
EDIT:
I'm going to be using the returned array to do value matching using a for loop. In Lua this would be written as:
for _, each in ipairs(output) do
if each == (some condition here) then
--Do Something
end
end
How can this be done in C++, using vectors (according to the answer by Jerry Coffin)?
EDIT 2:
I can't match the vectors correctly for some reason. I wrote the code in a separate test file.
int main() {
vector<string> stuff = read_pass();
cout << stuff.size() << endl;
cout << stuff[0] << endl;
if (stuff[0] == "admin") {
cout << "true";
}
else {
cout << "false";
}
return 0;
}
read_pass() looks like this:
vector<string> read_pass() {
ifstream stream("stuff.txt");
string line;
vector<string> lines;
while(getline(stream, line)) {
lines.push_back(line);
}
stream.close();
return lines;
}
And stuff.txt looks like this:
admin
why?
ksfndj
I just put it some random lines to test the code. Every time I compile and run main.cpp the output I get is
3
admin
false
So why isn't the code being matched properly?
EDIT 3:
So instead of forcing myself down the vectors method of doing things, I decided to try this instead:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include "basefunc.h"
using namespace std;
int main() {
string storedUsrnm;
string storedPw;
string pw = "admin";
string usrnm = "admin";
ifstream usernames("usrnm.accts");
ifstream passwords("usrpw.accts");
while(getline(usernames, storedUsrnm)) {
getline(passwords, storedPw);
print("StoredUsrnm " + storedUsrnm);
print("StoredPw: " + storedPw);
if (storedUsrnm == usrnm && storedPw == pw) {
print("True!");
return 0;
}
}
print("False!");
return 0;
}
Where print() is
void print(string str) {
cout << str << endl;
}
This still prints false, at the end, and it leads me to believe that for some reason, the "admin" read by the ifstream is different from the "admin" string. Any explanations for how this is so? Or does this code not work either?
Doesn't look to me like your current code should even compile. Anyway, I'd probably do something like this:
std::vector<std::string> read_file(std::istream &infile) {
std:string line;
std::vector<std::string> lines;
while (std::getline(infile, line))
lines.push_back(line);
return lines;
}
So the basic idea here is to read a line from the file, and if that succeeded, add that line (with push_back) to the vector of results. Repeat until reading a line from the file fails. Then return the vector of all the lines to the caller.
A few notes: especially at first, it's fairly safe to presume that any use of pointers is probably a mistake. That shouldn't be taken as an indication that pointers are terribly difficult to work with, or anything like that--just that they're almost never necessary for the kinds of things most relative beginners do in C++.
Likewise with arrays--at first, assume that what you might think of as an array in some other language translates to a std::vector in C++. C++ does also have arrays, but using them can wait a while (a long while, IMO--I've been writing C++ for decades now, and virtually never use raw pointers or arrays at all).
In the interest of simplicity, I've consolidated the data into the program, so it reads the data from the stringstream, like this:
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
vector<string> read_pass(istream &is) {
string line;
vector<string> lines;
while (getline(is, line)) {
lines.push_back(line);
}
return lines;
}
int main() {
istringstream input{ "admin\nwhy?\nksfndj" };
// To read from an external file, change the preceding line to:
// ifstream input{ "stuff.txt" };
vector<string> stuff = read_pass(input);
cout << stuff.size() << endl;
cout << stuff[0] << endl;
if (stuff[0] == "admin") {
cout << "true";
}
else {
cout << "false";
}
return 0;
}
At least for me, this produces:
3
admin
true
...indicating that it has worked as expected. I get the same with an external file. If you're not getting the same with an external file, my immediate guess would be that (at least the first line of) the file contains some data you're not expecting. If the problem continues, you might consider writing out the individual characters of the strings you read in numeric format, to give a more explicit idea of what you're really reading.
After a long time, I finally came up with the answer
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <map>
using namespace std;
typedef map<int, string> strArr;
strArr readFile(string file) {
ifstream stream(file);
string line;
strArr output;
while(getline(stream, line)) {
output[output.size()+1] = line;
}
stream.close();
return output;
}
It doesn't read the file into an array, but it does return a map that does basically the same thing
I'm a new student of the c++ language and I'm having trouble understanding...well, frankly, a whole lot of things. I've been given this assignment to read text from a text file and output it to the screen, and I'm having quite a bit of trouble. I've spent several hours on this now already researching and testing, and this is the code that I've got so far, and it's not working, and I'm not really sure why. Any and all help or insights anyone would be willing to share with me would be very much appreciated. I'm sorry I don't recall all the errors I've encountered as I worked on this by name...but I assure you there were plenty of them. Like trying to use "fopen" in my compiler...it didn't like that, so I tried "fopen_s" like it suggested, but then it said that it wouldn't accept any arguments anymore...then I found that I needed to add "#define _CRT_SECURE_NO_DEPRECATE" as a header(?) file at the top of the program, and that problem did get solved and the program actually compiled...but then it gave me a fatal error, not sure what I did that was so fatal, but there you are. Please help.
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *pf;
char ch;
pf = fopen("C:\\lowerCase\anyOldTextFile.txt", "r");
feof(pf);
if (pf == NULL)
{
printf("Unable to open the file.\n");
}
else
{
while (!feof(pf))
{
ch = fgetc(pf);
printf("%c", ch);
}
fclose(pf);
}
system("pause");
}
Try this, which I pasted from this site:
// 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;
}
I didn't test this code, but it looks fine. They also explain the code on the website. I suggest visiting that page and reading all of it. Then you should be able to understand how this is working.
Here is what I got so far:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int characterList = 0;
char* dynamo = new char[1000];
char* buffer = dynamo;
ifstream input("wordlist.txt");
if (input.is_open())
{
input >> dynamo[characterList];
while (input.eof())
{
characterList++;
input >> dynamo[characterList];
cout << dynamo[characterList];
}
}
else
{
cout << "File not opened" << endl;
}
return;
}
I'm a beginner so I do apologize if this looks like terrible coding practice. I created a text file with a quote from Bill Cosby that I'm trying to read one word at a time. The quote is "I don't know the key to success, but the key to failure is trying to please everybody." I'm trying to read one word at a time from a text document ignoring punctuation. I know there are a lot of questions similar to this, but they are using code that I have not learned so I'm sorry for having a repeating question. I have not learned getline (I used cin.getline) and #include <string>.
Edit: I forgot to mention, so I'm sorry for not doing so earlier, but I'm studying dynamic memory allocation which is why I'm using the new char[1000].
I'd suggest you to use std::string instead of manually allocating buffers on the heap with new[] and trying to read text manually from the file into those buffers (and don't forget to free the buffer with proper delete[] calls!).
C++ input stream classes like std::ifstream can simply read text into std::string instances thanks to a proper overload of operator<<.
The syntax is as simple as:
string word;
while (inFile >> word)
{
cout << word << endl;
}
Here's a complete compilable sample code for you to experiment and learn:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream inFile("test.txt");
if (inFile.is_open())
{
string word;
while (inFile >> word)
{
cout << word << endl;
}
}
else
{
cout << "Can't open file." << endl;
}
}
This is the output I got on a test text file having the content specified in your question:
I
don't
know
the
key
to
success,
but
the
key
to
failure
is
trying
to
please
everybody.
NOTE
Of course, once you have your words read into a std::string instance, you can store them in a container like std::vector<std::string>, using its push_back() method.
I would do something like this:
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string array[6];
std::ifstream infile("Team.txt");
std::string line;
int i = 0;
while (std::getline(infile, line)) {
array[i++] = line;
}
return 0;
}
based on this answer.
Here, we assume we have to read 6 lines from the file "Team.txt". We use std:::getline() and we put inside a while so that we read all the file.
At every iteration, line holds the current line of the file read. Inside the body we store it in array[i].