0

I'm making a parser for .obj files . I'm using scanf but I'm getting really strange results.

void loader::readIn()
{
    //!takes in the all the data and 
    //!puts in string first.
    std::string myString;     //!save string
    float tmpX,tmpY,tmpZ;     //!storing the floats in here .
    while(!myFile.eof())
    {

        std::getline(myFile,myString);                 //!intake string
        if(myString[0] == 'v' && myString[1] == ' ')   //!check value
            {
                    scanf_s(myString.c_str(), "v %f %f %f" ,&tmpX,&tmpY,&tmpZ);
                    std::cout<< tmpX <<" "<< tmpY <<" "<<tmpZ <<std::endl;
            }   
    }       
}

This is my code.

Below this is what i am trying to read in

v  0.0  0.0  0.0
v  0.0  0.0  1.0
v  0.0  1.0  0.0
v  0.0  1.0  1.0
v  1.0  0.0  0.0
v  1.0  0.0  1.0
v  1.0  1.0  0.0
v  1.0  1.0  1.0

And this is the result when I cout the answers.

-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008
-1.07374e+008 -1.07374e+008 -1.07374e+008

Grateful for any help.

Student123
  • 323
  • 1
  • 5
  • 14
  • 2
    `scanf_s` is not the same as `sscanf_s`. –  Nov 30 '13 at 18:33
  • 1
    This is your punishment for using a variant of `scanf` in C++. – Jerry Coffin Nov 30 '13 at 18:36
  • @JerryCoffin Almost. Primarily a punishment for not R'ing the FM. (Look, `scanf()` is not only harmful in C++, it isn't ever appropriate to use in C either, I swear!) –  Nov 30 '13 at 18:41
  • there are *two* whitespaces after v, one after vt, vn, in standard OBJ syntax – melak47 Nov 30 '13 at 18:51
  • @H2CO3: Agreed -- it's not exactly wonderful, regardless. C simply doesn't give you many other choices. C++ does. – Jerry Coffin Nov 30 '13 at 19:20
  • @JerryCoffin C does provide alternatives as well. Parsing and I/O should be separated; `scanf()` tries to do these at once, that's why it's horrible. In C, one can use `fgets()` and/or `getc()` for obtaining user input, then parse it with `strtok_r()`, `strchr()`, etc. –  Nov 30 '13 at 19:34

1 Answers1

0

Let me shortly explain to you the problem. First, and as commenters have written, you should not use any scanf-type function in C++. And even not in C. They are error prone and insecure (candidate for cyber attacs). Please use C++ iostreams for input and output from/to streams.

Then, I am programming in C++ since the language exists. I never heard of scanf_s. So, wow, thank you for making me aware. Reading the documentation, you would even not need it for your implementation. You try to read 3 floats, so, the _s version will not help you here.

Then, and this is the major bug, you are using scanf instead of sscanf. Scanf reads from stdin and not from string, as you expected. I was first wondering, why the function does not block and waits for user input. But it is of course clear why not. Your assumed input string is used as the formatting string. And, according to the defined behavior, the function does not detect formatting fields and stops immediately.

If you would have checked the return value of the function (what you should do), then you would have detected that.

Then, you did never initialize the 3 float values. You should always initialize variables. But now, the variables contain random values. And there is never an assignment by scanf. So, the output is random.

Hope, I could explain the problem

A M
  • 14,694
  • 5
  • 19
  • 44