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


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

[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/.




Follow-Ups: