[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: