I have this following code:
template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
QFile boxfile;
boxfile.setFileName(filename);
QString line;
QStringList list;
if (!boxfile.open(QIODevice::ReadOnly)){
cout << "Could not open box data file." << endl;
return false;
}
QTextStream stream2( &boxfile );
while (!stream2.atEnd()){
line = stream2.readLine();
list = line.split(',');
mapping[list.front().toInt()]=list.back().toInt();
}
return true;
}
It takes a CSV file and sticks it into a:
map<int, int> mapping
structure. Now this is done as a template so that I can also use to stick data into a
map<string, int> mapping
structure. Now to do this, the final line in the while loop needs to be changed and I am not sure what is the best way to achieve this.
I could think of a few ways:
some how detect the type and have some sort of conditional line in there (I'm not actually sure if this is possible and if so how to do this.
add a class function to QStringList to do this.
I tried option 2 and did this:
void QStringList::cInsert(map<int,int> &mapping){
mapping[this->front().toInt()]=this->back().toInt();
}
void QStringList::cInsert(map<string,int> &mapping){
mapping[(this->front()).toAscii()]=this->back().toInt();
}
This didn't work as I also needed to define these functions in the QStringList class and so this would get a bit messy. Instead. I try to inherit from QStringList:
class myQStringList: public QStringList{
public:
void cInsert(map<int,int> &mapping);
void cInsert(map<string,int> &mapping);
};
void myQStringList::cInsert(map<int,int> &mapping){
mapping[this->front().toInt()]=this->back().toInt();
}
void myQStringList::cInsert(map<string,int> &mapping){
mapping[(this->front()).toAscii()]=this->back().toInt();
}
And then change the code:
template <class T>
bool loadCSV (const QString &filename, map<T,int> &mapping){
QFile boxfile;
boxfile.setFileName(filename);
QString line;
myQStringList list;
if (!boxfile.open(QIODevice::ReadOnly)){
cout << "Could not open box data file." << endl;
return false;
}
QTextStream stream2( &boxfile );
while (!stream2.atEnd()){
line = stream2.readLine();
list = line.split(',');
list.cInsert(mapping);
}
return true;}
BUT. I get an error in relation to the line.split/list assignment:
main.cpp:123: error: no match for 'operator=' in 'list = QString::split(const QChar&, QString::SplitBehavior, Qt::CaseSensitivity) const(((const QChar&)(&QChar(44))), KeepEmptyParts, CaseSensitive)'
I'm not sure what this error is and not sure if it is to do with the assign/copy operator not being inherited?
And in relation to the actual new class, I get this error:
main.cpp:104: error: no match for 'operator[]' in 'mapping[QString::toAscii() const()]'
c:/qt/mingw/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_map.h:332: note: candidates are: _Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = std::string, _Tp = int, _Compare = std::less<std::string>, _Alloc = std::allocator<std::pair<const std::string, int> >]
main.cpp: In function `bool loadCSV(const QString&, std::map<T, int, std::less<_Key>, std::allocator<std::pair<const T,int> > >&) [with T = int]':
Which I simply don't understand. Can anyone please explain?
Also, I'm not sure if the way I'm going about this is correct and would appreciate advice in relation to this also. Thanks.
I solved the problem by explicitly casting:
When it comes to CSV files, Qt provides neat functionality via QString::section function. So, to find out necessary columns I process the header as follows:
to get the index of that column. Then, for forthcoming lines I extract that column's substring:
Hope you'll find section function usefull ;-)
I would move the conversion from QString to type T outside your function. Therefore, have something like:
Then, use this convert function in your loop (inside while):
Instead of
write:
Note: The class converter (and its two specializations) are defined so the convert function can be used as a template function (similar to static_cast or to boost::lexical_cast if you like).
I didn't try to compile the code. It is just an idea.