Hello all,

I am trying to read in the text file but it seems my code cannot read the text file which has tab space

eg

Mine only reads

Sydney NewYork 1300

but

It should read

Sydney New York 1300

( and the space between city name or number can be tab spaced )

can ne1 plz help me???

I'll attach my code with text file..

Attachments
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <map>
#include <queue>
#include <vector>

using namespace std;

class Student
{
public:
   string name;
   double tuition;
};

//This function sorts by tuitions fees
bool SortStudentByTute ( const Student& left, const Student& right )
{
   if ( left.tuition > right.tuition )
   {
      return false;
   }
   else if ( left.tuition < right.tuition )
   {
      return true;
   }
} 

bool SortStudentByName ( const Student& left, const Student& right )
{
   //Here you can define whatever the sort criterion
   //needs to be. It can be as complicated as you wish
 
   if ( left.name > right.name )
   {
      return false;
   }
   else if ( left.name < right.name )
   {
      return true;
   }
   //else //i.e if both are equal
 
}



class Edge;

class Node
{
public:
   string    name;
   list<Edge*> neighbors;
   bool      visited;
   double       cost;
   Node      *back_pointer;

   Node ( string const &n ) : name ( n ), visited ( false ), cost ( 0 )
   {}
};

class Edge
{
public:
   double weight;
   Node * dest;

   Edge ( double c, Node *d = NULL ) : weight ( c ), dest ( d )
   {}

   ~Edge()
   {
      if ( dest ) delete dest;
   }
};

class NodeMap
{
public:
   map<string, Node*> nodemap;

   Node* find_in_nodemap ( string const &name )
   {
      Node* result = nodemap[name];
      if ( result == 0 )
      {
         result = nodemap[name] = new Node ( name );
      }
      return result;
   }
   friend ostream& operator<< ( ostream& o, NodeMap nm )
   {
      map<string, Node*>::iterator im;
      for ( im = nm.nodemap.begin(); im != nm.nodemap.end(); im++ )
      {
         //pair<string,Node*> p = *im;
         //o << p.second->name << endl;
         o << ( *im ).second->name << endl;
         list<Edge*> neighbors = ( *im ).second->neighbors;
         list<Edge*>::iterator e;
      }
      return o;
   }
};

struct compare
{

   bool operator() ( Node * &a, Node * &b ) const
   {
      // least to greatest
      return b->cost < a->cost;
   }
};
// for each solution, reset node information
void reset_nodes ( NodeMap &nm )
{
   map<string, Node*>::iterator im;
   for ( im = nm.nodemap.begin(); im != nm.nodemap.end(); im++ )
   {
      ( *im ).second->cost = 0;
      ( *im ).second->back_pointer = 0;
      ( *im ).second->visited = false;
   }
}

void dijkstra ( string s, NodeMap &nodes )
{
   Student myStudent [500]; //create an array of objects

   int i = 0;

   // check and report or abort
   Node* source = nodes.nodemap[s];
   if ( source == 0 )
   {
      cout << "Sorry we don't fly from " << s << endl;
      return;
   }
   reset_nodes ( nodes );

   // put the source into pq and loop until empty
   priority_queue<Node *, deque<Node*>, compare > pq;
   pq.push ( source );
   while ( !pq.empty() )
   {
      // process least cost node.
      Node* curr = pq.top();
      pq.pop();
      curr->visited = true;
      // process neighbors
      list<Edge*>::iterator edge; 
      for ( edge = curr->neighbors.begin(); edge != curr->neighbors.end(); edge++ )
      {
         Node *ne = ( *edge )->dest;
         if ( !ne->visited )
         {
            ne->cost += ( *edge )->weight + curr->cost;
            ne->visited = true;
            ne->back_pointer = curr;
            //cout << "Cheapest price to "<< ne->name << " = " << ne->cost << endl; 

            myStudent[i].name = ne->name;
            myStudent[i].tuition = ne->cost;
            i++; 


            pq.push ( ne );
         }
      }
   }

   std::sort ( myStudent, myStudent + i, SortStudentByName );
   for ( int j = 0; j < i; j++ )
   {
      cout << "Cheapest price to " << myStudent[j].name << " = " << myStudent[j].tuition << endl;
   }
}

void get_graph ( string const &filename, NodeMap &node_map )
{
   ifstream inf ( filename.c_str() );
   string from, to;
   double weight;
   while ( !inf.eof() )
   {
      inf >> from >> to >> weight;
      if ( inf.good() )
      {
         Node *Target = node_map.find_in_nodemap ( to );
         Node *Source = node_map.find_in_nodemap ( from );
         Edge *connector = new Edge ( weight, Target );
         Source->neighbors.push_back ( connector );
      }
   }
}
int main()
{
   NodeMap nodes;
   ifstream inf;
   string filename;
   cout << "Enter filename : ";
   cin >> filename;
   inf.open ( filename.c_str() );
   get_graph ( filename, nodes );

   string s;
   cout << "Enter start city : ";
   cin >> s;
   dijkstra ( s, nodes );

   system ( "PAUSE" );
   return 0;
}
Sydney	New York	1100
New York	Paris	1200
London	Sydney	1120
Sydney	London	1309
Paris	New York	 905
New York	London	703
London	Paris	201
Sydney	Paris	950
Paris	London	310
Brussels	Paris	101	
London	Brussels	82
Sydney	Brussels	707
Brussels	New York	408
Paris	Brussels	97	
Tokyo	New York	512
Tokyo	Paris	606
Sydney	Tokyo	333
Sydney	Melbourne	120
Brussels	Frankfurt	203
Frankfurt	Rome	121
Rome	Sydney	1255
Rome	New York	509
Paris	Rome	221
London	Rome	320
Zurich	Brussels	122
Melbourne	Sydney	99
Brisbane	Sydney	103
Sydney	Brisbane	77
Singapore	Sydney	777
Melbourne	Singapore	808
Singapore	Tokyo	332
Tokyo	Singapore	301
Singapore	London	499
Bangkok	Singapore	244
Bangkok	London	799
Paris	Bangkok	665
Tokyo	Bangkok	333
Sydney	Bangkok	599
Sydney	Feankfurt	1299
Frankfurt	Melbourne	1403
Paris	Amsterdam	99
Amsterdam	Frankfurt	88
Amsterdam	Rome	122
London	Amsterdam	66
Amsterdam	Brussels	96
Brussels	Zurich	52
Zurich	Amsterdam	44
Perth	Sydney	331
Perth	Melbourne	299
Sydney	Perth	340
Paris	Zurich	99
Paris	Melbourne	1595
Paris	Brisbane	1666
Perth	Singapore	592
Perth	Bangkok	511
Oslo	London	122
London	Oslo	97
London	Athens	164
Athens	Rome	131
Athens	London	155
Paris	Athens	99
Athens	Frankfurt	106
Munich	Frankfurt	44
Frankfurt	Munich	35
London	Munich	97
Munich	London	98
Munich	Zurich	72
Beijing	Sydney	888
Beijing	London	422
London	Beijing	330
Sydney	Beijing	941
Paris	Beijing	333
Beijing	Paris	354
Sydney	Moscow	1660
Moscow	Sydney	1580
Moscow	Frankfurt	244
London	Moscow	194
Moscow	London	222
Moscow	Oslo	94
Oslo	Moscow	112
Singapore	Beijing	395
Beijing	Singapore	403
Hong Kong	Singapore	99
Singapore	Hong Kong	101
Sydney	Hong Kong	562
Hong Kong	Sydney	554
Tokyo	Hong Kong	193
Hong Kong	Tokyo	177
London	Hong Kong	735
Hong Kong	London	720
Sydney	Jakarta	344
Jakarta	Sydney	430
Sydney	Bali	334
Bali	Jakarta	93
London	Jakarta	795
Sydney	Mumbai	488
Mumbai	London	490
London	Mumbai	504
Mumbai	Sydney	510
Perth	Mumbai	440
Mumbai	Perth	480
Zurich	Frankfurt	66
Frankfurt	Zurich	68
Sydney	Dubai	887
Dubai	London	220
London	Dubai	230
Dubai	Amsterdam	182
Dubai	Rome	211
Vancouver	New York	212
New York	Vancouver	224
Sydney	Vancouver	1500
Vancouver	Sydney	1455
Vancouver	London	1102
London	Vancouver	1202
Brisbane	Mumbai	420
Glasgow	London	89
London	Glasgow	99
Glasgow	Oslo	110
Glasgow	Brussels	99
Brussels	Glasgow	99
Edinburgh	Glasgow	35
Glasgow	Edinburgh	33
Glasgow	Amsterdam	85
Amsterdam	Edinburgh	93
Glasgow	New York	884
New York	Edinburgh	761
London	Manchester	55
Manchester	Glasgow	90
Glasgow	Manchester	88
Glasgow	Amsterdam	110
Madrid	Brussels	95
Brussels	Madrid	98
London	Madrid	150
Madrid	London	170
Madrid	Barcelona	44
Barcelona	London	85
Madrid	Lisbon	25
Lisbon	Brussels	75
Lisbon	London	111
Lisbon	Athens	113
Amsterdam	Madrid	99
Amsterdam	Barcelona	99
Perth	Johannesburg	473
Johannesburg	London	513
Nairobi	Johannesburg	178
Nairobi	London	576
Brussels	Nairobi	544

Don't use [B]!inf.eof()[/B] as a condition in a loop for reading a whole file:

void get_graph ( string const &filename, NodeMap &node_map )
{
   ifstream inf ( filename.c_str() );
   string from, to;
   double weight;
   while ( [B]!inf.eof()[/B] )
   {
      inf >> from >> to >> weight;
      if ( inf.good() )
      {
         Node *Target = node_map.find_in_nodemap ( to );
         Node *Source = node_map.find_in_nodemap ( from );
         Edge *connector = new Edge ( weight, Target );
         Source->neighbors.push_back ( connector );
      }
   }
}

You could begin by changing your code to:

void get_graph ( string const &filename, NodeMap &node_map )
{
   ifstream inf ( filename.c_str() );
   string from, to;
   double weight;
   [B]while ([/B] [B]inf >> from >> to >> weight[/B] [B])[/B]
   {
         Node *Target = node_map.find_in_nodemap ( to );
         Node *Source = node_map.find_in_nodemap ( from );
         Edge *connector = new Edge ( weight, Target );
         Source->neighbors.push_back ( connector );
   }
}

By the way: where do you close that file ?

Well, I did a small test to see what your problem is, but with me it works fine, this program reads successfully from a file which contains tabs:

The code I used:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
	string tmp;
	ifstream infile("t.txt");
	while( infile >> tmp )
		cout << tmp << " ";
	infile.close();
	return 0;
}


t.txt file contents:

Hello			beautiful world   1230 		!!!!

The output I'm getting:

Hello beautiful world 1230 !!!!

Just try and adapt it to your program.

Comments
noob error.

I disagree with the above since the OP wants to separate the lines just by tabs. For example New York, should be considered as one but tux4life's code will treat it as two separate entities.

>Can't you read each line in and then use the tab as a delimiter?
It is possible, if you use strtok for example, you could use a TAB as delimiter as follows: strtok(tmp, "[B]\t[/B]"); (assume that tmp is a character string)

Why would you want to mix up c functions with c++?

Remember that it's still a part of C++, I only gave him an advice, do you know something better, then just tell it OK?

> Remember that it's still a part of C++

I'll agree with you on this, but where you can it makes sense to use c++ functions.

Take a look at this excellent snippet and call the Split function as follows:
(I assume you already read a line from the file) Split( [I]string_from_file[/I], [B]"\t"[/B], words ); Remember that string_from_file has to be a c-string :)

> Remember that it's still a part of C++

I'll agree with you on this, but where you can it makes sense to use c++ functions.

Use what's easiest, while keeping an eye on performance and code consistency if possible. If a C solution is easier to program/understand than a C++ solution, why bother with a C++ solution (which would most probably be slower anyway).

For example, dont be afraid to use a non-std::string method in this particular case, but it's things like mixing printf and cout which cause problems.

>By the way: where do you close that file ?
File stream destructor closes that file. That's OK.

I might choose to read each line and then parse tab-delimited fields like this.

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

int main()
{
   std::ifstream file("verging.txt");
   std::string line;
   while ( getline(file, line) )
   {
      std::cout << line << "\n"; // Display the whole input line.

      // Parse fields in 'line' delimited by tabs.
      std::istringstream iss(line);
      std::string field;
      while ( getline(iss, field, '\t') )
      {
         std::cout << " " << field << "\n";
      }
   }
   return 0;
}

/* partial output
Glasgow	New York	884
 Glasgow
 New York
 884
New York	Edinburgh	761
 New York
 Edinburgh
 761
 */
Comments
much better than the other crap in this thread
This article has been dead for over six months. Start a new discussion instead.