string (char *) to double

General help with the eC language.
Post Reply
D.Bane
Posts: 78
Joined: Thu Jul 29, 2010 2:51 pm

string (char *) to double

Post by D.Bane »

Hi to all..again.. :)

So this time I can't figure out how to transfer numbers from string to double..

To be exact, what I need is to add two numbers (double) that are previously entered in Label control and display it on another Label.. so how do one does this? And is it the same process for EditControl (from contents) too?
Now I already tried next functions which ended with my program crashing down, either in it's own module or msd...(something), believe ecere.dll too..:

Code: Select all

atof() // first tried this one
FloatFromString()
strtod()
sprintf()
Now I went first (like I always do) trough the internet, but atof (somewhere atoi too) is the most common..
Thank you for your time and help. :)
D.Bane
No army is to big, if the heart is beating strong.
There's no bad luck, it's just easier to blame someone else.
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: string (char *) to double

Post by jerome »

Hi D.Bane! :)

Labels are read only... Why are numbers entered in them? :?

Anyways, both EditBox::contents and Label::text are String/char *, so you can use either the same way to convert it to a double. Both strings returned by the controls' properties are ensured to be valid string and not to be null, so I'm a bit puzzled how you got it to crash.

And again this can be done exactly like in regular C.
atof() and strtod() both work, the latter being preferred.

sprintf however is for the reverse operation (it's used e.g. to make a string representation of a number). sscanf() however, will also work, but I would advise against using it.

FloatFromString in the Ecere library should work as well.

I will show you some code how to do it with each of the functions:

Code: Select all

//Suppose you have an edit box with your string:
EditBox editBox { /* I'm omitting its properties for the sake of the example */ };
String s = editBox.contents;
double d;
 
// Using atof
d = atof(s);
 
// Using strtod
d = strtod(s, null);
 
// Using FloatFromString
d = FloatFromString(s);
 
// Using sscanf (This one might depend on the platform... Maybe "%lf" doesn't work for Windows)
sscanf(s, "%lf", &d);
 
// This is also supposed to work, but broken at the moment :(
d.OnGetDataFromString(s);
Ah I forgot to suggest you can also use a DataBox to have the user enter numbers.
You give it the address of a variable of your data type of choice inside your form, and it will automatically update it for you.

Code: Select all

class MyForm : Window
{
   size = { 640, 480 };
   hasClose = true;
   SavingDataBox control
   {
      this, size = { 80, 20 }, position = { 10, 10 };
      type = class(double), data = &d;
   };
   double d;
}
It requires a bit of clean up though... DataBox vs SavingDataBox... (The latter might be renamed to 'DataBox' and DataBox to something else to be used internally)

Hope this helps!

Jerome
D.Bane
Posts: 78
Joined: Thu Jul 29, 2010 2:51 pm

Re: string (char *) to double

Post by D.Bane »

Hi Jerome :)

Thank you for help.I'm sorry, I saw it later on, and wanted first to test all (to see if it gives me crashes again) and than come and thank you (so I know the problem is solved) :).

Crashes..It has something with MS C run-time component.. :| .. If you want a crash call me :ugeek: .. :(

Ok, so I guess the problem before was that I did "strtod(label.text,null);" which resulted with an error...
Well some labels have numbers cause the user should do only some of the stuff and other should be acquired/retrieved/calculated with app..and I find them doing all I need.. It's a program that was made earlier in vb, so now I'm recreating it in eC..It was easier to code it in vb.. but still,eC has me hooked up.. (I love challenges :D ) and of course, that means more questions.. :)

Now, similar one (and I looked at web...it seams they are doing it like I am too :/ but still.. " MS - Don't Send")

So I did this..

Code: Select all

      String result;
      double d;

      result = "";
..
     // calculations to get d
     // even simple ones do error (d = 7.0000000)
..
      sprintf(result,null,d);// <-- Gives error

// in module ModName: msvcrt.dll
so what am I doing wrong this time? :/ and thanks.
No army is to big, if the heart is beating strong.
There's no bad luck, it's just easier to blame someone else.
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: string (char *) to double

Post by jerome »

D. Bane, Could you please post all your code that is crashing?

The only code you pasted is calling sprintf...
I said in my first message that sprintf is *NOT* to convert to a double, it's to convert to a string...
And the second parameter where you pass 'null' is the format string which should never be null.
EDIT: I don't know if your sprintf code is to write a double to a string or not, but you should be writing into an 'allocated' string. This would properly print a double to a string:

Code: Select all

char result[256];
sprintf(result, "%f", d);
strtod(label.text, null) however is perfectly fine, as the following full (compilable as is) code snippet demonstrates:

Code: Select all

import "ecere"
 
class Form1 : Window
{
   text = "Form1";
   background = activeBorder;
   borderStyle = sizable;
   hasMaximize = true;
   hasMinimize = true;
   hasClose = true;
   size = { 640, 480 };
 
   Button button1
   {
      this, text = "button1", position = { 152, 112 };
 
      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         double d = strtod(label.text,null);
         return true;
      }
   };
   Label label { this, text = "7.0000", position = { 56, 64 } };
}
 
Form1 form1 {};
I realize eC has a steeper learning curve than VB, partly because some of its polish to accomplish its aim of making C easier and more accessible is still missing. However, once you're familiar with it it shouldn't be much harder to code anything in eC than coding it in VB, and you'll have mastered a lot of the C programming language as well.

Good luck. Please let us know ASAP if you have any other issues regarding this. We can help you on IRC as well.

Regards,

Jerome
D.Bane
Posts: 78
Joined: Thu Jul 29, 2010 2:51 pm

Re: string (char *) to double

Post by D.Bane »

Hi :)

Yes..I did try first "sprintf(result, "%f" ,d);".. tried with "%c" too...tried than with "null" also, and it left in the code I pasted.. It crashed down cause I used String class.. :? when I replaced "String result" with "char result[256]" it started working..
..And I was looking, all I found that my sprintf() call is the same as on net yet it crashed.. Ok, one more thing learned :D

Yes, thanks to your help, I got to do what I needed to turn the text to double, but I needed to put it back at some other place (the calculations..), hence the sprintf();.

Here is a simple piece that crashes the exe..

Code: Select all

import "ecere"

Form1 frmMM {};

class Form1 : Window
{
   size = { 500, 500 };
   hasClose = true;

   void Calculate(String field1, String field2)
   {

      /*char*/ String result;//[256];
      double d;

      d = strtod(field1,null) + strtod(field2,null);
      sprintf(result, "%f" ,d);// <-- Gives error if "String result;" not if "char result[256];"
       
      label3.text = result;

   }

   Label label3 { this, text = "label3", position = { 96, 256 } };
   Button button1
   {
      this, text = "button1", position = { 320, 208 };

      bool NotifyClicked(Button button, int x, int y, Modifiers mods)
      {
         Calculate(label1.text,label2.text);
         return true;
      }
   };
   Label label1 { this, text = "12", position = { 48, 96 } };
   Label label2 { this, text = "54", position = { 208, 96 } };
It was crashing when I had char * as parameter and feed it with label.text..now it doesn't.. which is great (I corrected it to receive the String)..

It's great (the eC), I already see big difference in speed..I know about the curve, it's steep, but who goes on hiking on some small hill, it's always nicer to conquer the mountain. :D

Thank you for your time, and help, hope to ask you something not basic next time :) Until then.
Oh, jea, I ask on forum, cause (I figure) only someone on chat would see that, and here when ecere starts being very popular you already have the answers, as basic as they came :).
No army is to big, if the heart is beating strong.
There's no bad luck, it's just easier to blame someone else.
jerome
Site Admin
Posts: 608
Joined: Sat Jan 16, 2010 11:16 pm

Re: string (char *) to double

Post by jerome »

Yes. Your original question was how to turn a String into a double.
But your crash was actually turning the double *back* into a string, hence my confusion.

sprintf, like PrintBuf and a bunch of other functions, expect a pre-allocated string buffer.
Any C/eC function you'll see outputting a string to an output parameter, will require the string to be pre-allocated memory. On the other hand, functions like PrintString will 'return' a newly allocated string in the return value. Others might return a newly allocated string in a parameter as a "double" pointer (e.g. char ** or String *).

So, when you need a pre-allocated string buffer you need either a static array (which will become invalid outside of its scope):

char result[256];

Or a dynamically allocated string (on the heap):

char * result = new char[256];
Same thing as:
String result = new char[256];

If you allocate memory yourself dynamically however it needs to be freed (with delete).

When you did simply:

String result;

Here result is 'unitialized'. Unlike VB, local variables in eC are not initialized to anything in particular, but rather contain whatever junk was left at the memory location where they happen to be. So when you passed 'result' to sprintf, it had a random value and that's why it was crashing.

You can also use the eC function PrintBuf instead of sprintf:

double d = 7;
char result[256];
PrintBuf(result, sizeof(s), d);

Or if you want it dynamically allocated:

double d = 7;
String result = PrintString(d);

(You need to delete that string later on)

To conveniently allocate and make a copy of a string on the heap at the same time, you can use the CopyString function:

String ConvertToDouble(double d)
{
char result[256];
PrintBuf(result, sizeof(s), d);
return CopyString(result);
}

This will allocate a string of the exact right size on the heap to hold the string.
Post Reply