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
istringstreamand then split to 2 strings on a':'separator - Insert those 2 strings
line1andline2into an existingstd::mapcontainer - Than I can do more stuff with the
mapand 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?
CodePudding user response:
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;
}
