Michael said:
Hi,
I have tried to implement it but get a problem, thuis is my code at the mo:
(Header includes removed for clarity)
{
string str
char junk[100];
int MaxLineLength =100;
const int status[] = {EXIT_SUCCESS, EXIT_FAILURE};
ifstream input(FileName.c_str());
bool err(!input);
input >> str;
/* Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str;
/* Step to Here: str is ??? */
input >> str;
}
start of Source File:
*3DSMAX_ASCIIEXPORT 200
*COMMENT "AsciiExport Version 2.00 - Tue Apr 06 19:00:45 2004"
*SCENE {
*SCENE_FILENAME "City_vertex_paint.max"
*SCENE_FIRSTFRAME 0
*SCENE_LASTFRAME 500
*SCENE_FRAMESPEED 30
*SCENE_TICKSPERFRAME 160
*SCENE_BACKGROUND_STATIC 0.0000 0.0000 0.0000
*SCENE_AMBIENT_STATIC 0.9804 0.9804 0.9804
}
*MATERIAL_LIST {
*MATERIAL_COUNT 13
*MATERIAL 0 {
*MATERIAL_NAME "SF Building"
*MATERIAL_CLASS "Multi/Sub-Object"
*MATERIAL_AMBIENT 0.1000 0.1000 0.1000
*MATERIAL_DIFFUSE 0.0392 0.0392 0.0392
*MATERIAL_SPECULAR 0.9000 0.9000 0.9000
*MATERIAL_SHINE 0.2500
*MATERIAL_SHINESTRENGTH 0.0500
*MATERIAL_TRANSPARENCY 0.0000
*MATERIAL_WIRESIZE 1.0000
*NUMSUBMTLS 6
*SUBMATERIAL 0 {
*MATERIAL_NAME "Top"
*MATERIAL_CLASS "Standard"
*MATERIAL_AMBIENT 0.1000 0.1000 0.1000
*MATERIAL_DIFFUSE 0.0392 0.0392 0.0392
*MATERIAL_SPECULAR 0.9000 0.9000 0.9000
*MATERIAL_SHINE 0.2500
*MATERIAL_SHINESTRENGTH 0.0500
*MATERIAL_TRANSPARENCY 0.0000
*MATERIAL_WIRESIZE 1.0000
*MATERIAL_SHADING Blinn
*MATERIAL_XP_FALLOFF 0.0000
*MATERIAL_SELFILLUM 0.0000
*MATERIAL_FALLOFF In
*MATERIAL_XP_TYPE Filter
}
*SUBMATERIAL 1 {
*MATERIAL_NAME "Bottom"
*MATERIAL_CLASS "Standard"
Now the code compiles fine, but when I step through it in the debugger, the
first string reads: *3DSMAX_ASCIIEXPORT, but the next time MSVC++ debugger
gives its value as ???
What am i doing wrong?
Also what is the best way to read this into relevant structures, If i define
a class material for instance, can i overload the >> operator for it and
call that after the reading function had read "*MATERIAL 0"??
I'm not yet a great fan of streams
Thanks & Regards
Michael
Sorry about posting so late, but I've had other work to do.
You are parsing a file that is made up of text lines. The text lines
are delineated by a newline character ('\n'). In these scenarios,
the easier approach would be to read in the whole text line into
a string, then extract the information from a string. The std::string
has better facilities for searching than the I/O streams do.
Here is a sample to get you started:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using std::ifstream;
using std::string;
using std::cout;
using std::endl;
using std::cerr;
int main(void)
{
ifstream source_file("Source_File.txt");
if (!source_file)
{
cerr << "Error opening \"Source_File.txt\"" << endl;
return EXIT_FAILURE;
}
string text;
string::size_type posn;
while (getline(source_file, text))
{
posn = text.find("3DSMAX_ASCIIEXPORT");
if (posn == string::npos)
{
continue; // Skip lines until that one is found.
}
posn = text.find_first_of(" \t"); // skip past the identifier.
istringstream temp_string_stream(text.substr(posn));
int value;
temp_string_stream >> value; // extract the value.
cout << "Value found is: " << value << endl;
}
return EXIT_SUCCESS;
}
A next step in this evolution would be to have a std::map
container of <string, function pointer>. The strings would
be the identifiers in the data file. The function pointer
would point to a function that processed the identifier.
Example:
#include <map>
using std::map;
typedef void (*Function_Ptr)(const string& s,
const string::size_type& posn);
void AsciiExport(const string& s, const size_type& posn)
{
istringstream temp_string_stream(s.substr(posn));
int value;
temp_string_stream >> value; // extract the value.
cout << "Value found is: " << value << endl;
return;
}
typedef std::map<string, Function_Ptr> Processing_Map;
Processing_Map function_map;
int main(void)
{
function_map["3DSMAX_ASCIIEXPORT"] = AsciiExport;
ifstream source_file("Source_File.txt");
if (!source_file)
{
cerr << "Error opening \"Source_File.txt\"" << endl;
return EXIT_FAILURE;
}
string text;
string::size_type posn;
while (getline(source_file, text))
{
posn = text.find("3DSMAX_ASCIIEXPORT");
if (posn == string::npos)
{
continue; // Skip lines until that one is found.
}
string::size_type end_posn = text.find_first_of(" \t", posn);
Processing_Map::iterator iter;
iter = function_map.find(text.substr(posn, end_posn - posn));
if (iter != function_map.end())
{
(iter->second)(text, end_posn); // execute the processing
// function.
}
}
return EXIT_SUCCESS;
}
After this step, you may want to research the Factory design
pattern (search the web for "Design Pattern Factory").
--
Thomas Matthews
C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq:
http://www.parashift.com/c++-faq-lite
C Faq:
http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book