Reputation: 809
I need to insert data in a search binary tree reading a text file. It works when I use spaces between the data, but it doesn't work if I use commas like I want to. For example I would want my text file to look like this:
New-York,c3,Luke
London,c5,Nathan
Toronto,c1,Jacob
...
My text file right now look like something like this:
New-York c3 Luke
London c5 Nathan
Toronto c1 Jacob
...
I'd also want my program not to think a space means it needs to look at the next data, only with commas.
This is how my code looks like:
void fillTree( BinarySearchTree *b)
{
ifstream file;
file.open("data.txt");
string city;
string tag;
string name;
Person p;
if(!file) {
cout<<"Error. " << endl;
}
while(file >> city >> tag >> name)
{
p.setCity(city);
p.setTag(tag);
p.setName(name);
cout << p.getCity() << " " << p.getTag() << " " << p.getName() << endl;
(*b).insert(p);
}
file.close();
}
What would I need to change in my code so I could use commmas instead of spaces? I feel like it would look more neat in the text file with commas instead of spaces. I'm pretty sure I'd need to edit something in this block of code, but if it could be somewhere else please let me know.
Upvotes: 1
Views: 1085
Reputation: 153945
In C++ you can redefine what a stream considers a space. You could, e.g., change it to mean ','
and '\n'
. The technique to do is to imbue()
the stream with a std::locale
with a modified std::ctype<char>
facet. The infrastructure for the facet looks a bit involved but once this is in place reading the data can conveniently use the input operators:
#include <locale>
template <char S0, char S1>
struct commactype_base {
commactype_base(): table_() {
std::transform(std::ctype<char>::classic_table(),
std::ctype<char>::classic_table() + std::ctype<char>::table_size,
this->table_,
[](std::ctype_base::mask m) -> std::ctype_base::mask {
return m & ~(std::ctype_base::space);
});
this->table_[static_cast<unsigned char>(S0)] |= std::ctype_base::space;
this->table_[static_cast<unsigned char>(S1)] |= std::ctype_base::space;
}
std::ctype<char>::mask table_[std::ctype<char>::table_size];
static std::ctype_base::mask clear_space(std::ctype_base::mask m) {
return m & ~(std::ctype_base::space);
}
};
template <char S0, char S1 = S0>
struct ctype:
commactype_base<S0, S1>,
std::ctype<char>
{
ctype(): std::ctype<char>(this->table_, false) {}
};
int main() {
std::ifstream in("somefile.txt");
in.imbue(std::locale(std::locale(), new ::ctype<',', '\n'>));
std::string v0, v1, v2;
while (in >> v0 >> v1 >> v2) {
std::cout << "v0='" << v0 << "' v1='" << v1 << "' v2='" << v2 << "'\n";
}
}
Upvotes: 0
Reputation: 6371
use getline ( file, value, ',' );
to read string until coma occurs.
string value;
while(file.good())
{
getline ( file, value, ',' );
p.setCity(value);
getline ( file, value, ',' );
p.setTag(value);
getline ( file, value, ',' );
p.setName(value);
cout << p.getCity() << " " << p.getTag() << " " << p.getName() << endl;
(*b).insert(p);
}
Upvotes: 1