Convert string to float (not quite typical! =) - solved

Started by
13 comments, last by Puzzler183 18 years, 4 months ago
Blah blah asked a million times. Anyways, I'm making a level loading system and need to load in some floating point numbers from a text file. A 3D vertex coordinate is stored like this in the file: [0 0 0] I've been using sprintf to convert it to 3 floating point errors, or trying to. The code looks like this, where "c" is a pointer to the character array of the vertex (it has the proper values - I checked): //c is created as a new character array on the heap, given the string loaded from //the file. sprintf(c, "[%f %f %f]", vertex.x, vertex.y, vertex.z); delete [] c; However, when I call delete on "c", the program segfaults and crashes. I checked the value of "c" in the debugger, and it changes like this: Loaded from file: [0 0 0] After sprintf: [0.000000 0.000000 0.000000] So when I call delete on it, the program crashes. I'm thinking that I would like a different method to convert "c" to a set of floating points in a similar manner to what I'm doing above. However, I would also like to avoid crashing the program. Any hints? Thanks! [Edited by - silverphyre673 on November 26, 2005 2:21:36 PM]
my siteGenius is 1% inspiration and 99% perspiration
Advertisement
Some possible reasons:
_ You mixed malloc () with delete
_ The allocated memory is not large enough for sprintf ()
_ Mistakes in calling new [] (I don't know for sure, please post your code)
_ The program stack segment is probably broken before sprintf () is executed, sprintf and c are just victims[smile].

sprintf () requires a char * pointer to be passed but it doesn't matter what is your real pointer type, just provide a cast for sprintf () and the compiler will silently compile your code.

Unless you intented to do something with c after used it to store floating point values, it's best to declare c as float * .

[Edit]
Are vertex.[x/y/z] 3 chars ?
What is the purpose of '[' and ']' in
sprintf(c, "[%f %f %f]", vertex.x, vertex.y, vertex.z);

--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
I don't see how you're loading and not saving - you have a char array containing vertices and you want to load it into vertex.[xyz], correct? Then you want to use sscanf, not sprintf. Or better yet, a stringstream. If you really do want to put the vertices into c, then continue reading below.

First - make sure that vertex.[xyz] are all floats and not some other data type. (unlikely, but with printf you just have to be sure)

Second - I would be leery of using sprintf. If you're using C++ (which you are - you have delete[]) then use a stringstream. Just create a new stringstream, do << "[ " << vertex.x << " " << vertex.y and so on. Then you can grab a string out of it using >> (some string) and doing .c_str() on the string. If you have a preexisting char array you can then do a strncpy to it.

If you must use sprintf, use snprintf instead (it's called something like _snprintf on msvc) That way if you are accidentally overwriting your buffer then you will get an incomplete string instead of a blown away stack.

You've confused sprintf with sscanf. Try the following:
sscanf (c, "[%f %f %f]", &vertex.x, &vertex.y, &vertex.z);
"I just wanted to hang a picture on my wall, but somehow now I'm in the Amazon Jungle looking for raw materials." - Jekler
I'm using C++, not C, and I might have gotten you, or you gotten me, confused between the variable "c" and the language =)

Anyways, I won't post my loading code, but suffice to say that the vertex coordinates are stored in the text file between brackets for readability. So if you were going to store a vertex, you would store it like this:

[0 15 3]

It is loaded into an std::string buffer, and I do this to store the string in a char *, so I can use it with sprintf:

struct Vertex{    float x, y, z;};//...//In loading function:Vertex vertex;std::string buffer = GetVertex(); //Load vertex value from text file, storechar * temp = new char[buffer.length() + 1]; //For sprintfstd::strcpy(temp, buffer.c_str()); //Copy string stored in "buffer" into "temp"//temp now has the value "[0 15 3]"sprintf(temp, "[%f %f %f]", vertex.x, vertex.y, vertex.z);delete [] temp; //Program actually crashes on this line, but value of temp appears to change on the last line.


EDIT:

Ah, yes... I do want to put the string values into the float... Oops! Thanks!
my siteGenius is 1% inspiration and 99% perspiration
std::stringstream s << GetVertex();s >> std::ws;char p= s.peek();if(p != '[')   std::error();s.ignore();s >> vertex.x >> vertex.y >> vertex.z;s >> std::ws;p= s.peek();if(p != ']')   std::error();//done


not tested, but you get the idea... boost has such stuff already in function form, but i dont use boost frequently enough to tell you the functionnames

and now: pls stop using c functions ;)

T2k
Actually, say what you want about type safety BUT:

1) C functions can be largely checked for type safety by the compiler.
2) C functions are significantly faster - not like twice as fast but orders of magnitude
3) C functions are simpler to use (if you know the formatting commands); why do you think they made boost::format? (which by the way, is still slow)
Quote:Original post by Puzzler183
Actually, say what you want about type safety BUT:
1) C functions can be largely checked for type safety by the compiler.


void* and varargs, which C uses all over the place, are the anitithesis of type safety. In most cases they cannot be checked by the compiler, although in a few instances it's possible. Not to mention that printf has it's own vulnerability named after it. There's a reason you get "printf format string vulnerabilty" but never "iostream manipulater vulnerability".

Quote:Original post by Puzzler183
2) C functions are significantly faster - not like twice as fast but orders of magnitude


That has nothing to do with them being "C" functions, it's just because they're either less safe, less general, or less extensible.

The String Formatters of Manor Farm
by Herb Sutter

Quote:Original post by Puzzler183
3) C functions are simpler to use (if you know the formatting commands); why do you think they made boost::format? (which by the way, is still slow)


No, C functions have more succinct operations for formatting. However, they are still resticted to built-in types, so are not simpler to use with custom data types:
Vector3D v( 3, 4, 5 );
printf( "%?", v ); // uhoh. Dies no matter what you put for ?
cout << v; // works fine
cout << boost::format( "%+05s" ) % v; // also works fine

Also, c-style I/O can only be used for the limited cases that it allows for. In C++, you can have cout write zlib-compressed data with just:
zlib_ostreambuf<char> zsb( cout.rdbuf() );
cout.rdbuf( zsb );
And then using cout as you normally would.
Quote:Original post by me22
In most cases they cannot be checked by the compiler, although in a few instances it's possible. Not to mention that printf has it's own vulnerability named after it.
Really? GCC's format string validator works great, except perphaps for dynamic formats (but such things are very rare, and there's no equivalent functionality in standard C++ library).
Just don't forget to mark your functions as such when making a printf wrapper.
Quote:Original post by doynax
Quote:Original post by me22
In most cases they cannot be checked by the compiler, although in a few instances it's possible. Not to mention that printf has it's own vulnerability named after it.
Really? GCC's format string validator works great, except perphaps for dynamic formats (but such things are very rare, and there's no equivalent functionality in standard C++ library).
Just don't forget to mark your functions as such when making a printf wrapper.
Checking the %? parts of the string passed to printf is only a weak compiler extension. Without having actually used it, I assume it wont work when your format string isn't a constant string, written directly into the function call, but is stored in some variable instead.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

This topic is closed to new replies.

Advertisement