Issue using FILE* with std::getline() - c++

I would like to get some advice on an issue I've encountered once working on small adjustments to an existing program.
The program itself has to:
Open a file and read it line-by-line preferably
Pack the lines into istringstream and then split to 2 strings on a ':' separator
Insert those 2 strings line1 and line2 into an existing std::map container
Than I can do more stuff with the map and the data from it.
My code looks like that:
int main()
{
FILE *fpFile;
map<string, string>mapOfPci;
std::string tempBuff="";
std::string line1="", line2="";
fpFile = fopen(PCI_MAPPING_PATH, "r");
if(!fpFile)
return false;
while(getline(fpFile, tempBuff)){
istringstream iSs(tempBuff);
iSs >> line1;
iSs.ignore(numeric_limits<std::streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
}
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
fclose(fpFile);
return (0);
}
Now what I'm getting in my compiler feedback is:
mismatched types 'std::basic_istream<_CharT, _Traits>' and 'FILE* {aka _iobuf*}'
while(getline(fpFile, tempBuff))
At this point I presume that this is due to the usage of FILE* file handling method.
I might not be able to use the C++ std::ifstream, std::fstream, so is there any method to move this further with the current FILE* usage?

std::getline() expects an std::istream-derived class, like std::ifstream, so you simply can't pass your own FILE* to it (unless you wrap it inside of a custom std::streambuf-derived object assigned to a standard std::istream object. std::ifstream uses std::filebuf, which uses FILE* internally, but you can't supply it with your own FILE*).
Otherwise, you can use C's getline() function instead, but it doesn't work with std::string, as it allocates its own output char[] buffer which you will then have to free afterwards (you can assign the contents of that buffer to a std::string, though), eg:
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <limits>
#include <cstdio>
using namespace std;
int main()
{
FILE *fpFile = fopen(PCI_MAPPING_PATH, "r");
if (!fpFile)
return false;
map<string, string> mapOfPci;
char *tempBuff = nullptr;
size_t size = 0;
int nRead;
while ((nRead = getline(&tempBuff, &size, fpFile)) != -1){
istringstream iSs(string(tempBuff, nRead));
string line1, line2;
iSs >> line1;
iSs.ignore(numeric_limits<streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
free(tempBuff); tempBuff = nullptr;
size = 0;
}
free(tempBuff);
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
fclose(fpFile);
return 0;
}
But, since you are using other C++ standard classes, there really is no good reason not to use std::ifstream instead, eg:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <limits>
using namespace std;
int main()
{
ifstream fpFile(PCI_MAPPING_PATH);
if (!fpFile.is_open())
return false;
map<string, string> mapOfPci;
string tempBuff;
while (getline(fpFile, tempBuff)){
istringstream iSs(tempBuff);
string line1, line2;
iSs >> line1;
iSs.ignore(numeric_limits<streamsize>::max(), ':');
iSs >> line2;
mapOfPci.insert(make_pair(line1, line2));
}
for(const auto &m : mapOfPci){
cout << m.first << " : " << m.second << "\n";
}
return 0;
}

Related

Copying read value from txt to a vector [duplicate]

I am attempting to write a program which can read in a text file, and store each word in it as an entry in a string type vector. I am sure that I am doing this very wrong, but it has been so long since I have tried to do this that I have forgotten how it is done. Any help is greatly appreciated. Thanks in advance.
Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> input;
ifstream readFile;
vector<string>::iterator it;
it = input.begin();
readFile.open("input.txt");
for (it; ; it++)
{
char cWord[20];
string word;
word = readFile.get(*cWord, 20, '\n');
if (!readFile.eof())
{
input.push_back(word);
}
else
break;
}
cout << "Vector Size is now %d" << input.size();
return 0;
}
One of the many possible ways is a simple:
std::vector<std::string> words;
std::ifstream file("input.txt");
std::string word;
while (file >> word) {
words.push_back(word);
}
operator >> takes care of only words divided by whitespaces (including new-lines) being read.
And in case you would be reading it by lines, you might also need to explicitly handle empty lines:
std::vector<std::string> lines;
std::ifstream file("input.txt");
std::string line;
while ( std::getline(file, line) ) {
if ( !line.empty() )
lines.push_back(line);
}
#include <fstream>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
vector<string> input;
ifstream readFile("input.txt");
copy(istream_iterator<string>(readFile), {}, back_inserter(input));
cout << "Vector Size is now " << input.size();
}
Or, shorter:
int main()
{
ifstream readFile("input.txt");
cout << "Vector Size is now " << vector<string>(istream_iterator<string>(readFile), {}).size();
}
I'm not going to explain, because there's about a zillion explanations on StackOverflow already :)

How to use instream and ofstream to read and output a text file?

#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
ifstream in ("input.txt");
ofstream out ("output.txt");
int main(){
char collection [30];
while ( in.good() ){
in >> collection;
}
cout << collection[0] <<endl;
in.close();
out.close();
return 0;
}
I'm trying to read a text file in C++ programming.But it certainly is not working since it doesn't print anything. It's just a single line containing some operands. Can someone help me out?
Put those definitions of in and out inside main. Don't create global variables unless you absolutely have to.
The code loops through the input, and overwrites the contents of collection each time through the loop. When it reaches the end of the input, it writes out the first character in collection. It should either display what it read each time through the loop, or add each string that it reads into a container. If it's the former, the code would look like this:
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("input.txt");
std::string input;
while (in >> input)
std::cout << input << '\n';
return 0;
}
Note that the original code didn't use out, so I left it out here. Also, when in is an auto object (i.e., defined inside main), when main returns it gets destroyed. One of the things that the destructor does is close the file, so there is no need to call in.close();.
If you want to put the input into some kind of collection, that's a straightforward change:
#include <fstream>
#include <iostream>
#include <vector>
int main() {
std::ifstream in("input.txt");
std::string input;
std::vector<std::string> collection;
while (in >> input) {
collection.push_back(input);
std::cout << input << '\n';
}
std::cout << "Contents of collection:\n";
for (auto& x : collection)
std::cout << x << '\n';
return 0;
}
If you want to write the text to an output file, just do it:
#include <fstream>
int main() {
std::ifstream in("input.txt");
std::ofstream out("output.txt");
std::string input;
while (in >> input)
out << input << '\n';
return 0;
}
That will write each word from the input onto a separate line in the output file. If you just want to copy the file unchanged, that's even easier:
#include <fstream>
int main() {
std::ifstream in("input.txt");
std::ofstream out("output.txt");
out << in.rdbuf();
return 0;
}

How to parse table of numbers in C++

I need to parse a table of numbers formatted as ascii text. There are 36 space delimited signed integers per line of text and about 3000 lines in the file. The input file is generated by me in Matlab so I could modify the format. On the other hand, I also want to be able to parse the same file in VHDL and so ascii text is about the only format possible.
So far, I have a little program like this that can loop through all the lines of the input file. I just haven't found a way to get individual numbers out of the line. I am not a C++ purest. I would consider fscanf() but 36 numbers is a bit much for that. Please suggest practical ways to get numbers out of a text file.
int main()
{
string line;
ifstream myfile("CorrOut.dat");
if (!myfile.is_open())
cout << "Unable to open file";
else{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
return 0;
}
Use std::istringstream. Here is an example:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
string line;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
istringstream strm(line);
while ( strm >> num )
cout << num << " ";
cout << "\n";
}
}
Live Example
If you want to create a table, use a std::vector or other suitable container:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string line;
// our 2 dimensional table
vector<vector<int>> table;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
vector<int> vInt;
istringstream strm(line);
while ( strm >> num )
vInt.push_back(num);
table.push_back(vInt);
}
}
The table vector gets populated, row by row. Note we created an intermediate vector to store each row, and then that row gets added to the table.
Live Example
You can use a few different approaches, the one offered above is probable the quickest of them, however in case you have different delimitation characters you may consider one of the following solutions:
The first solution, read strings line by line. After that it use the find function in order to find the first position o the specific delimiter. It then removes the number read and continues till the delimiter is not found anymore.
You can customize the delimiter by modifying the delimiter variable value.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
string delimiter = " ";
size_t pos = 0;
string token;
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
pos = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
token = line.substr(0, pos);
std::cout << token << std::endl;
line.erase(0, pos + delimiter.length());
temp.push_back(atoi(token.c_str()));
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}
The second solution make use of regex and it doesn't care about the delimiter use, it will search and match any integers found in the string.
#include <iostream>
#include <string>
#include <regex> // The new library introduced in C++ 11
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
std::smatch m;
std::regex e("[-+]?\\d+");
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
while (regex_search(line, m, e)) {
for (auto x : m) {
std::cout << x.str() << " ";
temp.push_back(atoi(x.str().c_str()));
}
std::cout << std::endl;
line = m.suffix().str();
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}

Initializing a vector from a text file

I am attempting to write a program which can read in a text file, and store each word in it as an entry in a string type vector. I am sure that I am doing this very wrong, but it has been so long since I have tried to do this that I have forgotten how it is done. Any help is greatly appreciated. Thanks in advance.
Code:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> input;
ifstream readFile;
vector<string>::iterator it;
it = input.begin();
readFile.open("input.txt");
for (it; ; it++)
{
char cWord[20];
string word;
word = readFile.get(*cWord, 20, '\n');
if (!readFile.eof())
{
input.push_back(word);
}
else
break;
}
cout << "Vector Size is now %d" << input.size();
return 0;
}
One of the many possible ways is a simple:
std::vector<std::string> words;
std::ifstream file("input.txt");
std::string word;
while (file >> word) {
words.push_back(word);
}
operator >> takes care of only words divided by whitespaces (including new-lines) being read.
And in case you would be reading it by lines, you might also need to explicitly handle empty lines:
std::vector<std::string> lines;
std::ifstream file("input.txt");
std::string line;
while ( std::getline(file, line) ) {
if ( !line.empty() )
lines.push_back(line);
}
#include <fstream>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
vector<string> input;
ifstream readFile("input.txt");
copy(istream_iterator<string>(readFile), {}, back_inserter(input));
cout << "Vector Size is now " << input.size();
}
Or, shorter:
int main()
{
ifstream readFile("input.txt");
cout << "Vector Size is now " << vector<string>(istream_iterator<string>(readFile), {}).size();
}
I'm not going to explain, because there's about a zillion explanations on StackOverflow already :)

C++ Putting text from a text file into an array as individual characters

I want to put some text from a text file into an array, but have the text in the array as individual characters.
How would I do that?
Currently I have
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
using namespace std;
int main()
{
string line;
ifstream myfile ("maze.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
// --------------------------------------
string s(line);
istringstream iss(s);
do
{
string sub;
iss >> sub;
cout << "Substring: " << sub << endl;
} while (iss);
// ---------------------------------------------
}
myfile.close();
}
else cout << "Unable to open file";
system ("pause");
return 0;
}
I'm guessing getline gets one line at a time. Now how would I split that line into individual characters, and then put those characters in an array?
I am taking a C++ course for the first time so I'm new, be nice :p
std::ifstream file("hello.txt");
if (file) {
std::vector<char> vec(std::istreambuf_iterator<char>(file),
(std::istreambuf_iterator<char>()));
} else {
// ...
}
Very elegant compared to the manual approach using a loop and push_back.
#include <vector>
#include <fstream>
int main() {
std::vector< char > myvector;
std::ifstream myfile("maze.txt");
char c;
while(myfile.get(c)) {
myvector.push_back(c);
}
}