C++ : **Solved** STL string variables just aren't loading...

Started by
2 comments, last by random_thinker 18 years, 8 months ago
I've developed an number of state machines for text processing. I noted a lot of code repetition, so I decided to create a new class to interface with the functionoid. This class is called 'Echo'. From tests, I know that the state machines are processing and sending the characters correctly, but the private string variables in Echo (used as temporary buffers for width, justification, precision, and key) do not appear to be loading them. Here's the code (unnecessary aspects are removed):

class Echo
{
   public:
   Echo();
   .
   . 
   .
   void makeWidth(char);                          // Sets width_.
   void makeJustification(char);                  // Sets justification_
   void makePrecision(char);                      // Sets precision_.
   void makeKey(char);                            // Sets key_ for string map.
      
   private:
   string width_;
   string justification_;
   string precision_;
   string key_;
   .
   .
   .
   // digitch_, lrch_, keych_ are static Echo class members that contain reference strings.
};

void Echo::makeWidth(char ch)
{
   if (digitch_.find( ch ) != string::npos)
   {
      cout << ch; // outputs correct characters for width_
      width_.push_back(ch); // Also tried width_ += ch; and width_ = width_ + ch;
   }
}

void Echo::makeJustification(char ch)
{
   if (lrch_.find( ch ) != string::npos)
   {
      cout << ch; // outputs correct characters for justification_
      justification_.push_back( ch );
   }
}

void Echo::makePrecision(char ch)
{
   if (digitch_.find( ch ) != string::npos)
   {
      cout << ch; // outputs correct characters for precision_
      precision_.push_back( ch );
   }
}

void Echo::makeKey(char ch)
{
   if (keych_.find( ch ) != string::npos)
   {
      cout << ch; // outputs correct characters for key_
      key_.push_back( ch );
   }
}

// All the following result in blank output, so it appears as though the strings aren't loading. 
cout << width_ << endl;
cout << justification_ << endl;
cout << precision_ << endl;
cout << key_ << endl;
I'm probably missing something simple, but I can't see it. Any help would be appeciated. --random [Edited by - random_thinker on August 24, 2005 3:23:17 AM]
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Advertisement
Where are the cout's being called from? How are you filling in the string data? How are you calling your set methods? Are the variables in the cout the same private variables from the class? Is it within a class method?
Quote:Original post by visage
Where are the cout's being called from? How are you filling in the string data? How are you calling your set methods? Are the variables in the cout the same private variables from the class? Is it within a class method?


Hi Visage,

I've placed the couts in another Echo method as follows:

void Echo::echo(const string_map & smap,ostream & out){   // All the following 4 lines result in blank output.   cout << width_ << endl;   cout << justification_ << endl;   cout << precision_ << endl;   cout << key_ << endl;   // Because the key_ is blank, this always gives a lot of unformatted OOPS! output.   if ( smap.find(key_) != smap.end() )   {      echo( smap.find(key_)->second,width_,justification_,precision_,out);   }   else   {      echo("OOPS!",width_,justification_,precision_,out);   }}// Base echo method.void Echo::echo(const string & strg,		const string & width,		const string & justification,		const string & precision,		ostream & out){   // Set width.   out.width(atoi(width.c_str()));   // Set justification.   if ( justification == "R" || justification == "r" )   {      out.setf(ios_base::right,ios_base::adjustfield);   }   else   {      out.setf(ios_base::left,ios_base::adjustfield); // Default is left.   }   // Set precision   out.precision(atoi(precision.c_str()));   // Output formatted result.   if (isInteger(strg))   {      // Convert to integer.      out.setf(ios::dec,ios::basefield);	       out << atoi(strg.c_str());   }      else if (isNumber(strg))   {      // Convert to float.      out.setf(ios::dec,ios::basefield);	       out << atof(strg.c_str());   }      else   {      // Keep as a string.      out << strg;   }   clearFormats();  // Uses the clear() string method to clear width_ etc. }


The state machine parses the input file using the istream get(ch) method, then uses Echo class methods to send to the ostream or feeds the correct width_ etc. characters to Echo via makeWidth(char) etc. When the format and key strings are constructed, the state machine exits with a call to the Echo method 'echo(const string_map & smap,ostream & out)'. The key_ is then used to find the paired value and send the value to the ostream, formatted as requested.

I originally wrote this using a large switch statement with all of the echo statements built in to the same class, and it worked great. When I started building other state machines I realized that I should separate some functionality into a new class called Echo, that could be accessed by all machines. Otherwise there was a possiblity that code rot would set in. I also used functionoids for the state machines which was another great improvement.

As I indicated, everything is working fine on a character by character basis, but loading the Echo strings width_ etc. just doesn't seem to happen. Outputting the characters as shown in the previous listing shows that the state machine is parsing and sending exactly the right characters.

--random

As a follow on note, here's the output as is (I hope that formatting is preserved):

                        UNITS         QTY         COV         PDFMass                     kg     OOPS! OOPS! OOPS!Density                  kg/m3  OOPS! OOPS! OOPS!Actual Moisture          m/m    OOPS! OOPS! OOPS!Absorption               m/m    OOPS! OOPS! OOPS!Halide                   m/m    OOPS! OOPS! OOPS!Sulfate                  m/m    OOPS! OOPS! OOPS!


And here is the output when the "cout << ch;" statements are placed in the makeWidth(char), makeXXX...etc. methods:

                        UNITS         QTY         COV         PDFMass                     kg     12R1ssd_mass.valueOOPS! 12R3ssd_mass.covOOPS! 12R0ssd_mass.pdfOOPS!Density                  kg/m3  12R1ssd_density.valueOOPS! 12R3ssd_density.covOOPS! 12R0ssd_density.pdfOOPS!Actual Moisture          m/m    12R3moisture.valueOOPS! 12R3moisture.covOOPS! 12R0moisture.pdfOOPS!Absorption               m/m    12R3absorption.valueOOPS! 12R3absorption.covOOPS! 12R0absorption.pdfOOPS!Halide                   m/m    12R3total_halide.valueOOPS! 12R3total_halide.covOOPS! 12R0total_halide.pdfOOPS!Sulfate                  m/m    12R3total_sulfate.valueOOPS! 12R3total_sulfate.covOOPS! 12R0total_sulfate.pdfOOPS!


The correct format is read, i.e '12R1ssd_mass.value' width_ = 12, justification_ = R, precision_ = 1, key_ = ssd_mass.value. These are '|' delimited values in the input template file and it confirms to me that the state machine is doing its job; the problem must be in the Echo class. I've gone round and round on this without finding the problem -- premature baldness is a distinct possibility here.

[Edited by - random_thinker on August 23, 2005 12:46:36 PM]
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Problem solved.

After posting, I realized that I hadn't tracked the content of width_, precision_, etc. I did this and found that the problem was that the strings were storing too much info for some reason (they weren't clearing as they should be).

That reason turned out to be the initialization of the Echo object defined in the superclass, which was initialized for each instance of each state (sub)class. By instead initializing Echo as a static object in the superclass, and removing constructor initializations in the sub-classes, the code works beautifully.

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.

This topic is closed to new replies.

Advertisement