So this seems like such a simple problem but i am struggling with it. I have a big file that i want to just go through and put every char in the file into a char array. My problem is i dont know how to deal with the newlines and any whitespace. is there a way to just go through the file and grab all of the chars, skip over newlines, and put them in an array?
Yes, i have searched around on google but with no luck.
Here is how it would be trivially done in C. I am sure it can be done using the C++ interface as well, but the C library is part of C++ too.
#include <stdio.h>
#include <ctype.h>
FILE *f = fopen ("filename", "r");
if (!f)
error ...
char array [BIGENOUGH];
int index = 0;
while (!feof (f))
{
char c = fgetc (f);
if (!isspace (c))
array [index++] = c;
}
fclose (f):
The preferred method would be to use the standard library string. Example of removing whitespace from a string here. How to read from a file line-by-line here.
Example code:
fstream file;
file.open("test.txt",ios::in);
while ( !file.eof() ) {
string str;
file >> str;
remove_if(str.begin(), str.end(), isspace);
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
//save str here
}
file.close();
remove_if sample implementation:
template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
This code is untested.
The key to doing what you want in C++ is to take advantage of the formatted input operations. You want to ignore whitespace; the formatted input methods do exactly that.
Here is one way, using the canonical C++ input loop:
#include <fstream>
#include <iostream>
int main () {
std::ifstream inFile("input.txt");
char c;
std::string result;
while(inFile >> c)
result.push_back(c);
std::cout << result;
}
I prefer standard algorithms to hand-crafted loops. Here is one way to do it in C++, using std::copy. Note that this way and the first way are nearly identical.
#include <vector>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
int main () {
std::ifstream inFile("input.txt");
std::string result;
std::copy(std::istream_iterator<char>(inFile),
std::istream_iterator<char>(),
std::back_inserter(result));
std::cout << result;
}
Another way, this time with std::accumulate. std::accumulate uses operator+ instead of push_back, so we can read the file in a string at a time.
#include <vector>
#include <fstream>
#include <numeric>
#include <iostream>
#include <iterator>
#include <algorithm>
int main () {
std::ifstream inFile("input.txt");
std::string result =
std::accumulate(
std::istream_iterator<std::string>(inFile),
std::istream_iterator<std::string>(),
std::string());
std::cout << result;
}
fgets allows you to read until a newline (notice that the newline still exists in the destination buffer, so make sure to overwrite it with '\0').
Read the file line by line, and each time concatenate your output with the previous output.
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;
}
I am working on creating a program that is supposed to read a text file (ex. dog, buddy,,125,,,cat,,,etc...) line by line and parse it based on commas. This is what I have so far but when I run it, nothing happens. I am not entirely sure what i'm doing wrong and I am fairly new to the higher level concepts.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
std::ifstream file_("file.txt"); //open file
std::string line_; //declare line_ as a string
std::stringstream ss(line_); //using line as stringstream
vector<string> result; //declaring vector result
while (file_.is_open() && ss.good())
{ //while the file is open and stringstream is good
std::string substr; //declares substr as a string
getline( ss, substr, ',' ); //getting the stringstream line_ and substr and parsing
result.push_back(substr);
}
return 0;
}
Did you forget to add a line like std::getline(file_, line_);? file_ was not read from at all and line_ was put into ss right after it was declared when it was empty.
I'm not sure why you checked if file_ is open in your loop condition since it will always be open unless you close it.
As far as I know, using good() as a loop condition is not a good idea. The flags will only be set the first time an attempt is made to read past the end of the file (it won't be set if you read to exactly the end of the file when hitting the delimiter), so if there was a comma at the end of the file the loop will run one extra time. Instead, you should somehow put the flag check after the extraction and before you use the result of the extraction. A simple way is to just use the getline() call as your loop condition since the function returns the stream itself, which when cast into a bool is equivalent to !ss.fail(). That way, the loop will not execute if the end of the file is reached without extracting any characters.
By the way, comments like //declaring vector result is pretty much useless since it gives no useful information that you can't easily see from the code.
My code:
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
int main()
{
std::ifstream file("input.txt");
std::string line, word;
std::vector<std::vector<string>> result; //result[i][j] = the jth word in the input of the ith line
while(std::getline(file, line))
{
std::stringstream ss(line);
result.emplace_back();
while(std::getline(ss, word, ','))
{
result.back().push_back(word);
}
}
//printing results
for(auto &i : result)
{
for(auto &j : i)
{
std::cout << j << ' ';
}
std::cout << '\n';
}
}
I am using STL. I need to read lines from a text file. How to read lines till the first \n but not till the first ' ' (space)?
For example, my text file contains:
Hello world
Hey there
If I write like this:
ifstream file("FileWithGreetings.txt");
string str("");
file >> str;
then str will contain only "Hello" but I need "Hello world" (till the first \n).
I thought I could use the method getline() but it demands to specify the number of symbols to be read. In my case, I do not know how many symbols I should read.
You can use getline:
#include <string>
#include <iostream>
int main() {
std::string line;
if (getline(std::cin,line)) {
// line is the whole line
}
}
using getline function is one option.
or
getc to read each char with a do-while loop
if the file consists of numbers, this would be a better way to read.
do {
int item=0, pos=0;
c = getc(in);
while((c >= '0') && (c <= '9')) {
item *=10;
item += int(c)-int('0');
c = getc(in);
pos++;
}
if(pos) list.push_back(item);
}while(c != '\n' && !feof(in));
try by modifying this method if your file consists of strings..
Thanks to all of the people who answered me. I made new code for my program, which works:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
ifstream ifile(argv[1]);
// ...
while (!ifile.eof())
{
string line("");
if (getline(ifile, line))
{
// the line is a whole line
}
// ...
}
ifile.close();
return 0;
}
I suggest:
#include<fstream>
ifstream reader([filename], [ifstream::in or std::ios_base::in);
if(ifstream){ // confirm stream is in a good state
while(!reader.eof()){
reader.read(std::string, size_t how_long?);
// Then process the std::string as described below
}
}
For the std::string, any variable name will do, and for how long, whatever you feel appropriate or use std::getline as above.
To process the line, just use an iterator on the std::string:
std::string::iterator begin() & std::string::iterator end()
and process the iterator pointer character by character until you have the \n and ' ' you are looking for.
I have .txt file which contains data as follows
[12,25],[36,45] i.e numbers are enclosed in square brackets separated by comma from each other
I want to read such file through C++ program
I referred to string toolkit available,specifically regex facility can be used but i'm not able put in program can someone please help me??
just use scanf or fscanf like this:
if(scanf("[%d,%d]",&a[i],&b[i])==2){
++i;
while(scanf(",[%d,%d]",&a[i],&b[i])==2) ++i;
}
don't forget that C I/O functions are valid C++.
Would I be correct in guessing that those are co-ordinates, if so have you thought about writing a short parser for them? So you could read out a list of vertices?
Alternatively, if your really want to go down the regex path, you might want to look into downloading the boost library, boost.regex works a dream :)
#include <iostream>
#include <iterator>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool isSeparator(const char c){
return c == '[' || c == ']' || c == ',';
}
int main(){
const char filename[] = "data.txt";
ifstream fin(filename);
vector<int> v;
string buff;
while(getline(fin, buff)){
replace_if(buff.begin(), buff.end(), isSeparator, ' ');
istringstream sin(buff);
for(int n;sin >> n;){
v.push_back(n);
}
}
copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\n"));
//for(int i=0;i<v.size();++i) cout << v[i] << endl;
}
What is the minimum code required to read a file and assign its contents to a string in c++?
I did read a lot of tutorials that worked but they were all different in a way so i am trying to see why, so if you could please include some explanatory comments that would be great.
Related: What is the best way to read an entire file into a std::string in C++?
#include <fstream>
#include <string>
int main()
{
std::ifstream file("myfile.txt"); // open the file
std::string line, whole_file;
// Read one line at a time from 'file' and store the result
// in the string called 'line'.
while (std::getline(file, line))
{
// Append each line together so the entire file will
// be in one string.
whole_file += line;
whole_file += '\n';
}
return 0;
// 'file' is closed automatically when the object goes out of scope.
}
A couple of things to note here. getline() returns a reference to the stream object, which fails the while-test if anything bad happens or if you reach the end of the file. Also, the trailing newline is not included in the string, so you have to append it manually.
The shortest code: (not effecient)
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <fstream>
int main()
{
std::ifstream f("plop");
std::string buffer;
std::copy(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>(),
std::back_inserter(buffer));
}
How I would probably do it:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <fstream>
int main()
{
// Find the size of the file
std::ifstream file("Plop");
file.seekg(0,std::ios_base::end);
std::streampos size = file.tellg();
// Read the file in one go.
file.seekg(0);
std::vector<char> buffer(size); // pre-szie the vector.
file.read(&buffer[0],size);
// or
// Until the next version of the standard I don't think string gurantees contigious storage.
// But all the current versions I know do use continious storage so it should workd.
file.seekg(0);
std::string buffer1(size);
file.read(&buffer1[0],size);
}
I'm not seeing as much:
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main() {
ifstream ifs("filename");
stringstream ss;
ss << ifs.rdbuf();
string s = ss.str();
}
... as I'd expect. You'd want some error-checking too.
Konrad Rudolph gave this as the answer to the "related question" linked above. I suppose this isn't a duplicate, since this asks for the shortest code, but the answer is the same either way. So I repost it here as wiki.
I am reading a word from each line.
#include<fstream>
#include<string>
using namespace std;
int main(int argc, char **argv)
{
fstream inFile;
string str;
while(!inFile.eof())
{
inFile.open("file.txt");
infile>>str;
}
inFile.close();
return 0;
}
This is longer than the short solutions, but is possibly slightly more efficient as it does a bit less copying - I haven't done any timing comparisons though:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;;
unsigned int FileRead( istream & is, vector <char> & buff ) {
is.read( &buff[0], buff.size() );
return is.gcount();
}
int main() {
ifstream ifs( "afile.dat", ios::binary );
const unsigned int BUFSIZE = 64 * 1024;
std::vector <char> buffer( BUFSIZE );
unsigned int n;
string s;
while( n = FileRead( ifs, buffer ) ) {
s.append( &buffer[0], n );
}
cout << s;
}
If you know that your file contains text, then you can use STLSoft's platformstl::memory_mapped_file:
platformstl::memory_mapped_file file("your-file-name");
std::string contents(static_cast<char const*>(file.memory()), file.size());
or
platformstl::memory_mapped_file file("your-file-name");
std::wstring contents(static_cast<wchar_t const*>(file.memory()),
file.size() / sizeof(wchar_t));
On WIndows, that will leave your string containing \r\n sequences, so you could instead use the winstl::load_text_file() function:
std::string contents;
winstl::load_text_file("your-file-name", contents);
If you want it loaded into a collection of lines, then use platformstl::read_lines():
platformstl::basic_file_lines<char> lines("your-file-name");
size_t n = lines.size();
std::string line3 = lines[3];