By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,247 Members | 1,287 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,247 IT Pros & Developers. It's quick & easy.

Reading From Files in c++

P: n/a
Hi,
I moved to c++ from c, and wanted to know what the best way to read data
from files is in c++. Any thoughts? fscanf() is possible but fairly painful!

Regards

Michael
Jul 22 '05 #1
Share this Question
Share on Google+
18 Replies


P: n/a
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

//File Start:

*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

Jul 22 '05 #2

P: n/a
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

//File Start:

*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

Jul 22 '05 #3

P: n/a
Michael wrote:
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

<snip>


Check out iostreams, especially std::ifstream.
They can be used just like std::cout.

- Pete
Jul 22 '05 #4

P: n/a
Michael wrote:
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

<snip>


Check out iostreams, especially std::ifstream.
They can be used just like std::cout.

- Pete
Jul 22 '05 #5

P: n/a

"Michael" <sl***********@hotmail.com> wrote in message
news:c4**********@hercules.btinternet.com...
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

//File Start:

*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


#include <algorithm>
using std::copy;

#include <cstdlib>

#include <fstream>
using std::ifstream;

#include <iostream>
using std::cerr;
using std::cout;

#include <iterator>
using std::back_inserter;
using std::istream_iterator;
using std::ostream_iterator;

#include <string>
using std::string;

#include <vector>
using std::vector;
int main()
{
const int status[] = {EXIT_SUCCESS, EXIT_FAILURE};

std::string filename("data.txt");
ifstream input(filename.c_str());
bool err(!input);

if(!err)
{
vector<string> data;

copy(istream_iterator<string>(input),
istream_iterator<string>(),
back_inserter(data));

if(err = (!input && !input.eof()))
cerr << "Error reading input file " << filename << '\n';

cout << "Data read:\n";

copy(data.begin(), data.end(),
ostream_iterator<string>(cout, "\n"));
}
else
cerr << "Cannot open input file " << filename << '\n';

return status[err];
}
-Mike
Jul 22 '05 #6

P: n/a

"Michael" <sl***********@hotmail.com> wrote in message
news:c4**********@hercules.btinternet.com...
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);

it just looks very messy!

TIA

Michael.

//File Start:

*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


#include <algorithm>
using std::copy;

#include <cstdlib>

#include <fstream>
using std::ifstream;

#include <iostream>
using std::cerr;
using std::cout;

#include <iterator>
using std::back_inserter;
using std::istream_iterator;
using std::ostream_iterator;

#include <string>
using std::string;

#include <vector>
using std::vector;
int main()
{
const int status[] = {EXIT_SUCCESS, EXIT_FAILURE};

std::string filename("data.txt");
ifstream input(filename.c_str());
bool err(!input);

if(!err)
{
vector<string> data;

copy(istream_iterator<string>(input),
istream_iterator<string>(),
back_inserter(data));

if(err = (!input && !input.eof()))
cerr << "Error reading input file " << filename << '\n';

cout << "Data read:\n";

copy(data.begin(), data.end(),
ostream_iterator<string>(cout, "\n"));
}
else
cerr << "Cannot open input file " << filename << '\n';

return status[err];
}
-Mike
Jul 22 '05 #7

P: n/a
Michael wrote:
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);


You should never use *any* of these! This is a terrible bug, and a
likely security hole. Never, never use %s or %[ without a (correct)
field width. There's nothing to prevent someone from overflowing the
buffer, in which case the best you can hope for is a program crash. The
comp.lang.c FAQ has some good information on this, and reasons why you
should avoid the scanf() functions even in C. In C++ there's usually no
reason to even consider scanf(), printf(), and friends. The stream
classes are more flexible and much safer.

However, the problem with the code above is (unfortunately) also easy to
introduce when using streams:

char buff[some_size];
std::cin >> buff; // SERIOUS ERROR!

Again, there's nothing to prevent the buffer from being overflowed. Such
an overflow can have all kind of terrible consequences -- in particular,
it can often be exploited by a malicious person (or program) to gain
control of the system. Problems similar to this are probably the single
biggest cause of security holes that allow worms to infect systems.

This is why "strings" should never be represented as character arrays,
unless you know what you are doing and are very, very careful. In C++,
use std::string instead:

std::string buff;
std::cin >> buff; // Go ahead, TRY to overflow it!

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #8

P: n/a
Michael wrote:
so for example reading in the file...

without many
fscanf(fp,"%s",variableAddr);


You should never use *any* of these! This is a terrible bug, and a
likely security hole. Never, never use %s or %[ without a (correct)
field width. There's nothing to prevent someone from overflowing the
buffer, in which case the best you can hope for is a program crash. The
comp.lang.c FAQ has some good information on this, and reasons why you
should avoid the scanf() functions even in C. In C++ there's usually no
reason to even consider scanf(), printf(), and friends. The stream
classes are more flexible and much safer.

However, the problem with the code above is (unfortunately) also easy to
introduce when using streams:

char buff[some_size];
std::cin >> buff; // SERIOUS ERROR!

Again, there's nothing to prevent the buffer from being overflowed. Such
an overflow can have all kind of terrible consequences -- in particular,
it can often be exploited by a malicious person (or program) to gain
control of the system. Problems similar to this are probably the single
biggest cause of security holes that allow worms to infect systems.

This is why "strings" should never be represented as character arrays,
unless you know what you are doing and are very, very careful. In C++,
use std::string instead:

std::string buff;
std::cin >> buff; // Go ahead, TRY to overflow it!

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #9

P: n/a
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
Jul 22 '05 #10

P: n/a
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
Jul 22 '05 #11

P: n/a
Michael wrote:
Hi,
I have tried to implement it but get a problem, thuis is my code at the mo:
(Header includes removed for clarity)
Removing relevant code never adds 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
<snip>

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 about printing the string? Debuggers don't always show things
correctly.
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"??


You can do that. >> is usually used for single input items, not
collections, so it's a bit unconventional, but it should work. You could
also just have a Read() member that does the same thing that the
operator >> would do.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #12

P: n/a
Michael wrote:
Hi,
I have tried to implement it but get a problem, thuis is my code at the mo:
(Header includes removed for clarity)
Removing relevant code never adds 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
<snip>

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 about printing the string? Debuggers don't always show things
correctly.
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"??


You can do that. >> is usually used for single input items, not
collections, so it's a bit unconventional, but it should work. You could
also just have a Read() member that does the same thing that the
operator >> would do.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #13

P: n/a

"Kevin Goodsell" <us*********************@neverbox.com> wrote in message
news:0b****************@newsread2.news.pas.earthli nk.net...
Michael wrote:
Hi,
I have tried to implement it but get a problem, thuis is my code at the mo: (Header includes removed for clarity)


Removing relevant code never adds 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


<snip>

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 about printing the string? Debuggers don't always show things
correctly.
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"??


You can do that. >> is usually used for single input items, not
collections, so it's a bit unconventional, but it should work. You could
also just have a Read() member that does the same thing that the
operator >> would do.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.



Hi,
It seems that

ifstream input(FileName.c_str());
string str;

input >> str;
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str;
* Step to Here: str is ??? */

gives problems but
ifstream input(FileName.c_str());
string str1,str2;

input >> str1
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str2
* Step to Here: str is 200

works as expected. Is it nessesary to flush the str before entering new
data?

Michael
Jul 22 '05 #14

P: n/a

"Kevin Goodsell" <us*********************@neverbox.com> wrote in message
news:0b****************@newsread2.news.pas.earthli nk.net...
Michael wrote:
Hi,
I have tried to implement it but get a problem, thuis is my code at the mo: (Header includes removed for clarity)


Removing relevant code never adds 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


<snip>

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 about printing the string? Debuggers don't always show things
correctly.
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"??


You can do that. >> is usually used for single input items, not
collections, so it's a bit unconventional, but it should work. You could
also just have a Read() member that does the same thing that the
operator >> would do.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.



Hi,
It seems that

ifstream input(FileName.c_str());
string str;

input >> str;
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str;
* Step to Here: str is ??? */

gives problems but
ifstream input(FileName.c_str());
string str1,str2;

input >> str1
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str2
* Step to Here: str is 200

works as expected. Is it nessesary to flush the str before entering new
data?

Michael
Jul 22 '05 #15

P: n/a
>
Hi,
It seems that

ifstream input(FileName.c_str());
string str;

input >> str;
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str;
* Step to Here: str is ??? */

gives problems but
ifstream input(FileName.c_str());
string str1,str2;

input >> str1
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str2
* Step to Here: str is 200

works as expected. Is it nessesary to flush the str before entering new
data?

Michael


No it is not necessary. Either you have a bugged implementation of the
standard library, or you are making some other mistake. Most likely is that
what Kevin told you is true, your debugger is not displaying the string
values correctly. I found exactly the same with my debugger (also MSVC++).

john

Jul 22 '05 #16

P: n/a
>
Hi,
It seems that

ifstream input(FileName.c_str());
string str;

input >> str;
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str;
* Step to Here: str is ??? */

gives problems but
ifstream input(FileName.c_str());
string str1,str2;

input >> str1
/*Step to Here: str is *3DSMAX_ASCIIEXPORT */
input >> str2
* Step to Here: str is 200

works as expected. Is it nessesary to flush the str before entering new
data?

Michael


No it is not necessary. Either you have a bugged implementation of the
standard library, or you are making some other mistake. Most likely is that
what Kevin told you is true, your debugger is not displaying the string
values correctly. I found exactly the same with my debugger (also MSVC++).

john

Jul 22 '05 #17

P: n/a
Michael wrote:
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

Jul 22 '05 #18

P: n/a
Michael wrote:
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

Jul 22 '05 #19

This discussion thread is closed

Replies have been disabled for this discussion.