Link to home
Start Free TrialLog in
Avatar of jimdgar
jimdgar

asked on

Error in function returning string value.

I have this function which takes a double value and returns the engineering notation as a string. Two problems: 1) it can't be called multiple times in a printf, see run results below. Two, if I remove the static declaration I get a compile error (I wrote this code long ago and don't know why I made it static).

#define  true            1
#define  false           0
#define  len            32

char *dtos_engr (double value, char *units, short precision)
/*******************************************************************************************
 Returns the string equivalent to <value> in engineering units, i.e.,
 <value> = 3.14e-9 and <units> = 'S' will return 3.14nS.
 *******************************************************************************************/
{
  double lvalue;
  short neg=false;
  static char str1[len],str2[len];

  lvalue = value;
  if (lvalue < 0.0) {
    lvalue = -lvalue;
    neg = true;
  }

  if (precision == 6) {
    if (lvalue == 0.0)
      strcpy (str1,"0");
    else if (lvalue >= 1.0e9) {
      sprintf (str1, "%-.6f",(lvalue/1.0e9));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"G");
    } else if (lvalue >= 1.0e6) {
      sprintf (str1, "%-.6f",(lvalue/1.0e6));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"M");
    } else if (lvalue >= 1.0e3) {
      sprintf (str1, "%-.6f",(lvalue/1.0e3));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"K");
    } else if (lvalue >= 1.0) {
      sprintf (str1, "%-.6f",lvalue);
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
    } else if (lvalue >= 1.0e-3) {
      sprintf (str1, "%-.6f",(lvalue/1.0e-3));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"m");
    } else if (lvalue >= 1.0e-6) {
      sprintf (str1, "%-.6f",(lvalue/1.0e-6));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"u");
    } else if (lvalue >= 1.0e-9) {
      sprintf (str1, "%-.6f",(lvalue/1.0e-9));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"n");
    } else {
      sprintf (str1, "%-.6f",(lvalue/1.0e-12));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"p");
    }
  } else if (precision == 3) {
    if (lvalue == 0.0)
      strcpy (str1,"0");
    else if (lvalue >= 1.0e9) {
      sprintf (str1, "%-.3f",(lvalue/1.0e9));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"G");
    } else if (lvalue >= 1.0e6) {
      sprintf (str1, "%-.3f",(lvalue/1.0e6));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"M");
    } else if (lvalue >= 1.0e3) {
      sprintf (str1, "%-.3f",(lvalue/1.0e3));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"K");
    } else if (lvalue >= 1.0) {
      sprintf (str1, "%-.3f",lvalue);
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
    } else if (lvalue >= 1.0e-3) {
      sprintf (str1, "%-.3f",(lvalue/1.0e-3));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"m");
    } else if (lvalue >= 1.0e-6) {
      sprintf (str1, "%-.3f",(lvalue/1.0e-6));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"u");
    } else if (lvalue >= 1.0e-9) {
      sprintf (str1, "%-.3f",(lvalue/1.0e-9));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"n");
    } else {
      sprintf (str1, "%-.3f",(lvalue/1.0e-12));
      while (str1[strlen(str1)-1] == '0')
      str1[strlen(str1)-1] = '\0';
      if (str1[strlen(str1)-1] == '.')
      strcat (str1,"0");
      strcat (str1,"p");
    }
  } else {
    if (lvalue == 0.0)
      strcpy (str1,"0");
    else if (lvalue >= 1.0e9)
      sprintf (str1, "%-.1fG",(lvalue/1.0e9));
    else if (lvalue >= 1.0e6)
      sprintf (str1, "%-.1fM",(lvalue/1.0e6));
    else if (lvalue >= 1.0e3)
      sprintf (str1, "%-.1fK",(lvalue/1.0e3));
    else if (lvalue >= 1.0)
      sprintf (str1, "%-.1f",lvalue);
    else if (lvalue >= 1.0e-3)
      sprintf (str1, "%-.1fm",(lvalue/1.0e-3));
    else if (lvalue >= 1.0e-6)
      sprintf (str1, "%-.1fu",(lvalue/1.0e-6));
    else if (lvalue >= 1.0e-9)
      sprintf (str1, "%-.1fn",(lvalue/1.0e-9));
    else
      sprintf (str1, "%-.1fp",(lvalue/1.0e-12));
  }
  if (!strcmp(str1,"0") && !strcmp(units,"S")) {
    strcat (str1,"n");
    strcat (str1,units);
  } else
    strcat (str1,units);
  if (neg) {
    strcpy (str2,"-");
    strcat (str2,str1);
    strcpy (str1,str2);
  }
  return (str1);
}   /* end of dtos_engr */


main (int argc, char *argv[])
{
  double value[6];

  value[0] = 1.6e-9;
  value[1] = 1.6e-8;
  value[2] = 1.6e-7;
  value[3] = 1.6e-6;
  value[4] = 1.6e-5;
  value[5] = 1.6e-4;

  printf ("Engr values = %s, %s, %s, %s, %s, %s\n",
        dtos_engr(value[0],"S",1),dtos_engr(value[1],"S",1),
        dtos_engr(value[2],"S",1),dtos_engr(value[3],"S",1),
        dtos_engr(value[4],"S",1),dtos_engr(value[5],"S",1));
}

Output:
Engr values = 160.0uS, 160.0uS, 160.0uS, 160.0uS, 160.0uS, 160.0uS
Avatar of ddunlea
ddunlea

Hi jimdgar,

You are having trouble because of pointers and variable scoping. What you should do is call the funtion with a char** as an arg.

So in main, have

char str1[LEN];

And then call the function with str1 as an argument.

If you remove the static declaration, then when you return, the char* you are returning goes out of scope and no longer references memory. By having the str1 variable defined within main, it remains in scope and is not destroyed when the function exists. Static variables are persistent between calls, which is why the compile error went away, but that really is not what they are meant for.

ASKER CERTIFIED SOLUTION
Avatar of imladris
imladris
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Not to be a stickler, but I am curious to know why the person who posted after me, with the same answer as me, was awared the points?
Avatar of jimdgar

ASKER

ddunlea,

The two responses arrived almost simultaneously (yours was first). Even tho you pointed out the root problem your solution didn't work; passing str1 six times returned the same value. imladris' solution to define six separate vars worked right off the bat.

jimdgar
Fair enough. I suspect it was the implementation as opposed to my solution that didn't work though as it worked for me.