[A89] Re: what is wrong with atof()?!


[Prev][Next][Index][Thread]

[A89] Re: what is wrong with atof()?!




In read_string() there is one of those pesky "only in C"-bugs:

/* maybe...
end = index;
for(index = 0; index <= end; index++)
{
 if(buffer[index] == ';')
 {
  comment = 1;
 }
 if(comment = 1)            <= NEEDS AN EXTRA '=' HERE... OR?
 {
  buffer[index] = '\0';
 }
}
*/

...but that code is inactive...

As you say, assuming the rows of the file contain valid floats, it
should work the same as in the -pi test... is the 'buffer' string
really valid all the time? Do the numbers follow the TIOS standard,
i.e. '-' is '(-)' and the TIOS exponent char instead of 'e' or 'E'?

--
 / Niklas Brunlid
Check out Prosit for the TI-89 / TI-92+ at http://prosit.ticalc.org
Random PQF v5.1 Quote follows:

"Chain letters," said the Tyrant. "The Chain Letter to the Ephebians.
Forget Your Gods. Be Subjugated. Learn to Fear. Do not break the chain --
the last people who did woke up one morning to find fifty thousand armed
men on their lawn."
        -- (Terry Pratchett, Small Gods)

----- Original Message ----- 
From: <the_juggernaut@juno.com>
To: <assembly-89@lists.ticalc.org>
Sent: Friday, December 07, 2001 3:49 AM
Subject: [A89] what is wrong with atof()?!


> 
> A break from virii / something a little more on topic:
> 
> Either I am missing some subtle point or there is something wrong with
> the atof() function in TIGCC.  It's probably the former, but you never
> know.  
> 
> Here's the thing: I'm reading from a text variable, and from what I can
> tell, the problem is in converting strings to floats.  The contents of
> the string seem to be valid for an argument of atof(), but it isn't
> working!  It always returns zero.
> 
> I'm including the whole program below, which is really just a stripped
> down version of another program (that's why some things have weird
> out-of-place names).  Here's what it does: there is a structure called
> 'params' that holds various numbers.  F4 will show the values of these
> numbers, which are fixed in this test program.  STO-> will save the
> numbers to a text variable, and RCL will load them from the text variable
> and print them on the screen.  ESC exits.
> 
> The problem is in the read_parameters() function.  Read comments there
> for more specifics.
> 
> This thing is driving me nuts; Please help me!
> 
> Jon K.
> 
> /*******************************************************************\
> C Source File for TIGCC
> Created  October 16, 2001
> Modified (date)
> 
> File Test 2
> By Jonathan Kotta
> the_juggernaut@juno.com
> 
> a test program to learn how to work with files
> \*******************************************************************/
> 
> /******************** DEFINITIONS AND INCLUDES *********************/
> #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization
> #define SAVE_SCREEN           // Save/Restore LCD Contents
> #include <tigcclib.h>         // Include All Header Files
> short _ti89;                  // Produce .89Z File
> 
> //defines a new type 'PARAMETER' which stores all
> //numbers needed to plot a given orbit
> typedef struct
> {
>  float Cx, Cy;
>  float x_center, y_center;
>  float zoom_factor;
>  unsigned int iter;
> // Bool circle_on, line_on;  for later use
> } PARAMETER;
> 
> /************************ GLOBAL VARIABLES *************************/
> //NONE
> 
> /*********************** FUNCTION PROTOTYPES ***********************/
> /*  these don't work yet; they're from TIGCC faq
> HANDLE CreateFile (char *FileName);
> void AppendCharToFile (HANDLE h, unsigned char c);
> void AppendBlockToFile (HANDLE h, void *addr, unsigned short len);
> void CloseFile (HANDLE h);
> */
> 
> //saves current parameters to a (TIOS) text variable 
> //named 'orbsave.text'
> void save_parameters(PARAMETER params);
> 
> //reads data in orbsave.text and returns a parameter structure
> //containing that data
> PARAMETER read_parameters(PARAMETER params);
> 
> //function meant to work just like fgets() but not keep carriage 
> //returns in the output 
> char *read_string(char *buffer, int length, FILE *file_ptr);
> 
> /************************** MAIN FUNCTION **************************/
> void _main(void)
> {
> //declares a new variable 'params' of type 'parameter'
> //(see orbit_f.h) and initializes it
> //{Cx, Cy, x_center, y_center, zoom_factor, iter}
> PARAMETER params = {0, 1, 1.5, -2, -1.5, 250};
> 
> //for keyboard reading
> void *kbq = kbd_queue();
> unsigned int key = 0;
> 
> char *view_params_text = 
> "CURRENT PARAMETERS
> 
> C REAL = %.16f
> C IMAG = %.16f
> 
> SCREEN CENTER X = %.16f
> SCREEN CENTER Y = %.16f
> 
> ZOOM MAGNITUDE = %.16f
> 
> ITERATION LIMIT = %d";
> 
> //for saving and restoring screen
> LCD_BUFFER screen;
> memset(screen, 0, sizeof(LCD_BUFFER));
> 
> //clear the screen
> ClrScr();
> //set the font to small
> FontSetSys(F_4x6);
> 
> //loop forever (if escape is pressed, code within the
> //while loop will exit the program)
> while(1)
> {
>  //reset the key variables
>  key = 0;
>  //this makes sure the loop doesn't repeat too fast
>  //it's a 1/20 second delay
>  OSFreeTimer(USER_TIMER);
>  OSRegisterTimer(USER_TIMER, 1);
>  while(!OSTimerExpired(USER_TIMER));
>  //check if a key was pressed
>  //OSdequeue moves what's in the keyboard queue to variable 'key'
>  //it returns TRUE if NO keys were pressed
>  if(OSdequeue(&key, kbq))
>  { 
>   //if not, go into idle mode
>   idle();
>  }
>  //if a key was pressed...
>  else
>  {
>   //some non-arrow key was pressed
>   switch(key)
>   {
>    //if escape is pressed, ask for exit confirmation
>    case KEY_ESC:
>     LCD_save(screen);
>     clrscr();
>     FontSetSys(F_6x8);
>     puts("\n\n\n\n\n\n    PRESS ENTER TO EXIT");
>     key = GKeyIn(NULL, 0);
>     if(key == KEY_ENTER)
>     {
>      //exit confirmed
>      return;
>     }
>     else
>     {
>      //exit not confirmed, go back to program
>      LCD_restore(screen);
>      FontSetSys(F_4x6);
>      break;
>     }
>    //display current parameters if F4
>    case KEY_F4:
>     LCD_save(screen);
>     clrscr();
>     printf(view_params_text, params.Cx, params.Cy, params.x_center,
>     params.y_center, params.zoom_factor, params.iter);
>     GKeyIn(NULL, 0);
>     LCD_restore(screen);
>     break;
>    //if STO-> is pressed, save parameters
>    case KEY_STO:
>     save_parameters(params);
>     break;
>    //if RCL (2ND STO->), recall parameters
>    case KEY_RCL:
>     params = read_parameters(params);
>     //pushkey(KEY_F4);
>     break;
>    //if some other key was pressed, ignore and start over
>    default:
>     break;
>   } //end switch
>  } //end else
> } //end while
> } //end main
> 
> 
> /********************** FUNCTION DEFINITIONS ***********************/
> 
> /************************** NEXT FUNCTION **************************/
> void save_parameters(PARAMETER params)
> {
> //file_ptr is a pointer to the target file
> //param_string is going to hold what we want to put in the file
> //each set of parameters shouldn't be more than 173 bytes
> //a float has up to about 18 chars
> #define OUT_STRING_LEN 200
> FILE *file_ptr;
> char param_string[OUT_STRING_LEN];
> int index;
> 
> //the carriage return after %d is very important
> //without it, there is an EOF error when that line is read, and that
> //number is skipped
> sprintf(param_string, 
> ";Cx
> %f
> ;Cy
> %f
> ;screen center x
> %f
> ;screen center y
> %f
> ;zoom factor
> %f
> ;max iterations
> %d
> ", 
> params.Cx, params.Cy, params.x_center, params.y_center, 
> params.zoom_factor, params.iter);
> 
> //this loop changes all '-' (subtract, 45) to '(-)' (negation, 173)
> //because atof() recognizes (-) but not -
> //IMHO, atof() should recognize both, but maybe there is a good 
> //reason it doesn't
> for(index = 0; index < OUT_STRING_LEN; index++)
> {
>  if(param_string[index] == 45)
>  {
>   param_string[index] = 173;
>  }
> }
> 
> file_ptr = fopen("orbsave", "w");
> 
> fputs(param_string, file_ptr);
> fclose(file_ptr);
> }
> 
> /************************** NEXT FUNCTION **************************/
> PARAMETER read_parameters(PARAMETER params)
> {
> //temp holds data until we're finished
> //index indicates what element in the temp array we are 
> //  currently working with
> #define TEMP_SIZE 6
> float temp[TEMP_SIZE];
> int temp_index = 0;
> int buffer_index;
> 
> //buffer holds an entire line of the parameter file 
> //a float is about 18 char long (maximium)
> //a line in the text editor is 23 char long
> #define BUF_SIZE 30
> char buffer[BUF_SIZE];
> char *c;
> 
> //pointer to file
> FILE *file_ptr;
> 
> //clear temp array
> memset(temp, 0, TEMP_SIZE*sizeof(float));
> 
> //open file and check for errors
> file_ptr = fopen("orbsave", "rb");
> if(ferror(file_ptr))
> {
>  fclose(file_ptr);
>  puts("error opening file");
>  return params;
> }
> 
> clrscr();
> while((read_string(buffer, BUF_SIZE, file_ptr) != NULL)&&(temp_index <
> TEMP_SIZE))
> {
>  c = strchr(buffer, ';');
>  //c = NULL iff there are no semicolons in buffer
>  //strlen = 0 iff the length of buffer is zero (not including '\0')
>  //in other words, ignore buffer if it has a semicolon or is empty
>  if((c == NULL)&&strlen(buffer))
>  {
>   buffer_index = 0;
>   //while((!isdigit(buffer[buffer_index])/*||!(buffer[buffer_index] !=
> 173)||(buffer[buffer_index] != '.')*/)&&(buffer_index < BUF_SIZE))
>   {
>    //look at the increment carefully.  it will use the current
>    //value of buffer_index in the assignment and THEN increment
>    //buffer[buffer_index++] = ' ';
>   }
> /*
> there is something horribly, horribly wrong here.
> the while loop prints out the ascii code of each character in buffer
> the latter printf() prints buffer as a string then as a float 
> converted by atof().  the ascii codes are right, the string is right
> but atof() is ALWAYS ZERO.  This function is taking forever to write 
> and it's driving me nuts.  what is going on?
> */
>   while(buffer[buffer_index] != '\0')
>   {
>    printf("%d ", (int)buffer[buffer_index++]);
>   }
>   temp[temp_index++] = atof(buffer);
>   //is_nan() returns true iff its argument is NAN (Not_a_Number)
>   //if(is_nan(temp[temp_index]))
>   {
>    //puts("error reading number\n");
>    printf("\n%s  %f\n", buffer, temp[temp_index]);
>   }
>  }
> }
> 
> //why will this work, but above it won't?
> strcpy(buffer, "  3.1415926");
> buffer[1] = (char)173;
> buffer_index = 0;
> while(buffer[buffer_index] != '\0')
> {
>  printf("%d ", (int)buffer[buffer_index++]);
> }
> temp[0] = atof(buffer);
> printf("\n%s  %f\n", buffer, temp[0]);
> fclose(file_ptr);
> //params = (PARAMETER){temp[0], temp[1], temp[2], temp[3], temp[4],
> (int)temp[5]};
> return params;
> }
> 
> /************************** NEXT FUNCTION **************************/
> //meant to replace fgets()
> char *read_string(char *buffer, int length, FILE *file_ptr)
> {
> char c;
> int index = 0;
> //int end, comment = 0;
> 
> //initialize c and clear the buffer
> //there seemed to be problems when buffer wasn't cleared
> c = (char)getc(file_ptr);
> memset(buffer, '\0', length - 1);
> 
> //copy a line from text to buffer
> while((c != '\r')&&(c != EOF)&&(length > index))
> {
>  buffer[index++] = c;
>  c = (char)getc(file_ptr);
> }
> 
> /* maybe...
> end = index;
> for(index = 0; index <= end; index++)
> {
>  if(buffer[index] == ';')
>  {
>   comment = 1;
>  }
>  if(comment = 1)
>  {
>   buffer[index] = '\0';
>  }
> }
> */
> 
> if(c == EOF)
> {
>  return NULL;
> }
> else
> {
>  return buffer;
> }
> }
> ________________________________________________________________
> GET INTERNET ACCESS FROM JUNO!
> Juno offers FREE or PREMIUM Internet access for less!
> Join Juno today!  For your FREE software, visit:
> http://dl.www.juno.com/get/web/.
> 





References: