Solved

ofstream headache!!

Posted on 2004-04-23
4
1,125 Views
Last Modified: 2012-08-14
ok, I admit I haven't touched C for a while, so it could be a really obvious mistake. But im starting to write a simple html builder that reads in a script file (.txt format), looks for tags and outputs html pages.

So far, It reads in the script, parses it and produces a html page, when it loops back round to make the 2nd file, this is where it doesnt work, and its drivin me mad!

Source code
--------------

#include <iostream>
#include <istream>
#include <fstream>
#include <string>
using namespace std;

// the below will need to be changed, open an output file for each script
// just ask for a path

int main()
{
      
      ////////////////////////////////////////////////////////////////////////////////////////
      // do some kinda menu eventually, allow user to fine tune global variables, directories etc
      ////////////////////////////////////////////////////////////////////////////////////////
      /*
      int quit=0;
      
        while (quit!=1)
        {
        // do the menu here
        
            }
            
      */
      
      
      ////////////////////////////////////////////////////////////////////////////////////////
      // declare an output file, will be dynamic eventually!
      ofstream myFile("c:\\out.html");

      if (! myFile)
      {
            // if it buggers up, exit
            cout<< "Error Setting file" << endl << endl;
            return -1;
      }
      
      char buffer[4096];
      int nbuf=1024; // buffer
      
      string inputFile;
      
      // do some kinda menu thing
      cout << "Please give the path of the script file (must be txt file)" << endl << endl;
      cout << "-:";
      cin >> inputFile;
      cout << endl << endl;
      
      ifstream readFile;
      readFile.open(inputFile.c_str());
      if (!readFile.is_open())
      {
            cout << "Error Opening File, try again" << endl << endl;
      }
      //readFile.getline (buffer,100);
      //string test;
      
      /*
      This is the logic code for the main program loop....
      take the entire script.txt file. See the additional code format file
      to see what special characters need to be included.
      
        open file..
        
            read first line
            go through each character to check for trigger codes.
            if code = <course> set course name
            if code = <modulename> set modulename to this
            if code = <submodule> name set submodule name to this
            if code = <page> set page num to this, or add one on to last page counter
            after this all the content goes in,
            
              finally loop until a <closepage> tag is found, then close file,
              and go back to main loop. This will work because everything between
              the <page> and <closepage> tags will be page content :)
              works in theory!!!!
             
      */
      string temp;
      
      // read a line in from the source file.
      readFile.getline (buffer,nbuf);
      // output it (debug only)
      cout << buffer << endl;
      // check buffer to see if it contains a trigger element
      // some debug code
      temp=buffer;

      ////////////////////////////////////////
      // variables
      ////////////////////////////////////////
      string coursename, modulename, submodulename;
      // depends on how the page attribute will be used
      string strpage;
//      int numpagetags, closepagetags;
      int noclose=0;
      int pagenumber=0;
      string outputpath;
      
      unsigned int loc = temp.find( "<course>", 0 );
      if( loc != string::npos )
      {
            cout << "Course name found!" << endl;
            noclose=1;
            
            // found course, therefore file is ok...
            // now do a loop to go thru the entire file
            while (!readFile.eof())
            {
                  // start readin in file
                  readFile.getline (buffer,nbuf);
                  cout << buffer << endl;
                  temp=buffer;
                  myFile << "TEST";
                  myFile << temp.capacity();
                  cout << "From the buffer: " << temp << endl;
                  //myFile << "This is a new line";
                  ////////////////////////////////////////////
                  // do element checking first
                  ////////////////////////////////////////////
                  // if a main module
                  loc = temp.find( "<modulename>", 0 );
                  if( loc != string::npos )
                  {
                        // is a mainmodule
                        cout << "Module name found!" << endl;
                        // now parse the name from the string
                        // and set to variable
                        // Set module name, erase first 12 chars from string
                        temp.erase(0, 12);
                        modulename=temp;
                        noclose=1;
                  }
                  // if a sub module
                  loc = temp.find( "<submodule>", 0 );
                  if( loc != string::npos )
                  {
                        // is a mainmodule
                        cout << "Sub Module name found!" << endl;
                        // now parse the name from the string
                        // and set to variable
                        // erase first 11 chars
                        temp.erase(0,11);
                        submodulename=temp;
                        noclose=1;
                  }
                  // look for page tag
                  loc = temp.find( "<page>", 0 );
                  if( loc != string::npos )
                  {
                        // is a mainmodule
                        cout << "Page found!" << endl;
                        //numpagetags=numpagetags+1;
                        // now parse the name from the string
                        // and set to variable
                        //////////////////////////////////
                        // When a new page is encountered, set
                        // to new location
                        // will need variables to keep track
                        // now create a page
                        
                        // the file is now open can can be output to
                        // generic header information. Used when <page> is called
                        myFile << temp;
                        cout << "Should be outputting file info" << endl;
                        cout << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">" << endl;
                        myFile << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">";
                        myFile << endl;
                        myFile << "<HTML lang=\"en\">";
                        myFile << endl;
                        myFile << "<HEAD>";
                        myFile << endl;
                        myFile << "<TITLE>" << modulename << "</TITLE>";
                        myFile << endl;
                        myFile << "<LINK rel=\"stylesheet\" href=\"../../../includes/custom.css\" type=\"text/css\">";
                        myFile << endl;
                        myFile << "</head>";
                        myFile << endl;
                        myFile << "<body>";
                        myFile << endl;
                        myFile << "<h2>" << submodulename << "</h2>";
                        myFile << endl;
                        ///////////////////////////////////////////////////////////
                        noclose=1;
                  }
                  loc = temp.find( "<closepage>", 0 );

                  if( loc != string::npos )
                  {
                        // output content
                        ///////////////////////////////////////////////////////////
                        // end of generic html content
                        myFile << "</body>";
                        myFile << endl;
                        myFile << "</html>";
                        noclose=1;
                        // add one to page num and change output file
                        pagenumber=pagenumber+1;
                        outputpath="c:\\out" && pagenumber && ".html";
                        // close old file, and reopen under different name
                        myFile.close();
                        myFile.open("c:\\out2.html");
                        // line below works...
                        myFile << "FFS, WORK!" << endl;
                        noclose=0;
                  }
                  
                  
                  /////////////////////////////////////////////
                  // End of element search
                  /////////////////////////////////////////////

                  /////////////////////////////////////////////
                  /////////////////////////////////////////////
                  /************CONTENT************************/
                  // else is page content
                  if (noclose==0)
                  {
                        //cout << temp.length() << endl;
                        // all the work on the content will go in this if statement....
                        
                        //      cout << temp << endl;
                              // at the mo using a closed p tag
                              myFile << "<p>" << temp  << "</p>";
                  }
                  /**************END OF CONTENT **************/
                  /////////////////////////////////////////////
                  /////////////////////////////////////////////
                  noclose=0; // reset
            
                  
                  
            }
      }
      else
      {
            cout << "Didn't find Course, invalid file!" << endl;
            // therefore quit
            
            return -1;
      }
      
      
      // close files
      myFile.close();
      readFile.close();
      return 0;
}



----------------------------------------------

The script.txt file contains:

<course> This is an example script file
<modulename> tempmod name
<submodule> name of submodule
<page>
all this crap will go on the page
include a picture etc. The program will load each page and work out
the best template for it, if not it will try to create one.
(not yet implemented)
end of file!
<closepage>
<modulename> it nay work!
<page>
this is another page
2 lines

and a blank.
<closepage>


--------------------

From the code you should hopefully be able to work out my logic. If u copy the script.txt file to C:, then when you run the program type in:
c:\script.txt, it loads the file and creates 2 html files, out and out2 (on c:)

The first file is fine, but the 2nd doesnt contain what it should! i can output code to myFile but not from the input buffer of the script file. I've used various buffer sizes but has no effect. Im using ms vis studio 6. you will see i have output the stuff to the console window, and that temp and buffer are not null, and i know it performs certain If statements, but wont output certain code! AAARH!

Its a 350 pointer just cos its killing me and I need to get this sorted pronto just so I can carry on developing it.

Any help would be greatly appreciated!

James
0
Comment
Question by:jaydeeuk
  • 2
4 Comments
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
ID: 10898737
What do you expect to find in out2.html?
I've compiled your program with the GNU C++ compiler, and I'm getting this output:

FFS, WORK!
<p><closepage></p>TEST20<p></p>TEST20<p></p>

0
 
LVL 4

Expert Comment

by:oumer
ID: 10899010
I stepped into your code, your problem lies in these lines

myFile << "</body>";
                    myFile << endl;
                    myFile << "</html>";
                    noclose=1;
                    // add one to page num and change output file
                    pagenumber=pagenumber+1;
                    outputpath="c:\\out" && pagenumber && ".html";
                    // close old file, and reopen under different name
                    myFile.close();
                    myFile.open("c:\\out2.html");

The first time, you started with myFile as out.html and then myFile is closed and you open it with out2.html

Now when you are working with out2.html, you close it and then you reopen it again with the same file name

That is why you dont see the expected output. If you are using some debugger, stop it just after myFile.close, and at that point out2.html looks pretty cool , but after you reopen it and write again, things get screwed
0
 
LVL 4

Accepted Solution

by:
oumer earned 350 total points
ID: 10899074
To make it clear instead of myFile.open("c:\\out2.html") use
myFile.open("c:\\out2.html", ios_base::app); //so that you append in the file opened

And I put a global variable call counter that is increamented each time you call myFile.open in the main loop

So now your code is like:


if( loc != string::npos )
               {
                    // output content
                    ///////////////////////////////////////////////////////////
                    // end of generic html content
                    myFile << "</body>";
                    myFile << endl;
                    myFile << "</html>";
                    noclose=1;
                    // add one to page num and change output file
                    pagenumber=pagenumber+1;
                    outputpath="c:\\out" && pagenumber && ".html";
                    // close old file, and reopen under different name
                    myFile.close();
                    myFile.open("c:\\out2.html",  ios_base::app);
                  myFile << "Writing " << counter++ << endl;
                  // line below works...
                    myFile << "FFS, WORK!" << endl;
                    noclose=0;
               }
               
And out2.html will look like



Writing 0
FFS, WORK!
<p><closepage></p>TEST31TEST31<page><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML lang="en">
<HEAD>
<TITLE> it nay work!</TITLE>
<LINK rel="stylesheet" href="../../../includes/custom.css" type="text/css">
</head>
<body>
<h2> name of submodule</h2>
TEST31<p>this is another page</p>TEST31<p>2 lines</p>TEST0<p></p>TEST31<p>and a blank.</p>TEST31</body>
</html>Writing 1    ----->see comment below
FFS, WORK!
<p><closepage></p>

//You see, here you started writing again, in your original program you didn't use ios_base::app for a ppending, so you loose everything before this line





0
 

Author Comment

by:jaydeeuk
ID: 10916438
Cheers, new it would be something stupid!
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now