qwerty
qwerty

Reputation: 9

Using atof() function in C with multiple input values

The goal of this program is to create a function which reads in a single string, user typed, command (ultimately for program to be used in conjunction with a robot) which consists of an unknown command word(stored and printed as command), and an unknown number of decimal parameters(the quantity is stored and printed as num, and the parameters are to be stored as float values in the array params). In the User input, the command and parameters will be separated by spaces. I believe my issue is with the atof function when I go to extract the decimal values from the string. What am I doing wrong? Thank you for the help!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func(char *input, char *command, int *num, float *params);

int main()
{
    char input[40]={};
    char command[40]={};
    int num;
    float params[10];

    printf("Please enter your command: ");
    gets(input);

    func(input,command,&num,params);

    printf("\n\nInput: %s",input);
    printf("\nCommand: %s",command);
    printf("\n# of parameters: %d",num);
    printf("\nParameters: %f\n\n",params);

    return 0;
}

void func(char *input, char *command, int *num, float *params)
{
    int i=0, k=0, j=0, l=0;
    int n=0;
    while(input[i]!=32)
    {
        command[i]=input[i];
        i++;
    }
    for (k=0; k<40;k++)
    {
        if ((input[k]==32)&&(input[k-1]!=32))
        {
            n++;
        }
    }
    *num=n;

    while (j<n)
    {
        for (l=0;l<40;l++)
        {
            if((input[l-1]==32)&&(input[l]!=32))
            {
                params[j]=atof(input[l]);
                j++;
            }
        }
    }
}

A Sample Output Screen:

Please enter your command: Move 10 -10

Input: Move 10 -10
Command: Move
# of parameters: 2
Parameters: 0.000000

The Parameters output should, ideally, read "10 -10" for the output. Thanks!

Upvotes: 0

Views: 1143

Answers (3)

Tim Čas
Tim Čas

Reputation: 10867

Other people have already remarked the problem in your code, but may I suggest that you have a look at strtod() instead?

While both atof() and strtod() discard spaces at the start for you (so you don't need to do it manually), strtod() will point you to the end of the number, so that you know where to continue:

while(j < MAX_PARAMS) // avoid a buffer overflow via this check
{
    params[j] = strtod(ptr, &end); // `end` is where your number ends
    if(ptr == end) // if end == ptr, input wasn't a number (say, if there are none left)
        break;
    // input was a number, so ...
    ptr = end; // continue at end for next iteration
    j++; // increment number of params
}

Do note that the above solution does not differentiate between invalid arguments (say, foo instead of 3.5) and missing ones (because we've hit the last argument). You can check for that by doing this: if(!str[strspn(str, " \t\v\r\n\f")]) --- this checks if we're at the end of string (but allowing trailing whitespace). See the second side-note for what it does.


SIDE-NOTES:

  • You can use ' ' instead of 32 to check for space; this has two advantages:

    1. It is clearer to the reader (it's very clear that it's a whitespace, instead of "some magic number that happens to have meaning")
    2. It works in non-ASCII encodings (and the standard allows other encodings, though ASCII is by far the most popular; one common encoding is EBCDIC)
  • For future reference, this trick can help you skip whitespace: ptr += strspn(ptr, " \t\v\r\n\f");. strspn returns the number of characters at the start of the string that match the set (in this case, one of " \t\v\r\n"). Check documentation for more info.

Example for strspn: strspn("abbcbaa", "ab"); returns 3 because you have aab (which match) before c (which doesn't).

Upvotes: 1

i486
i486

Reputation: 6573

Change atof(input[l]) to atof(input + l). input[l] is single char but you want to get substring from l position. See also strtod() function.

Upvotes: 1

Sridhar Nagarajan
Sridhar Nagarajan

Reputation: 1105

you are trying to convert a char into a float,

params[j]=atof(input[l]);

you should get the entire word(substring) of the float.

Example, "12.01" a null terminated string with 5 characters and pass it to atof, atof("12.01") and it will return a double of 12.01.

so, you should first extract the string for each float parameter and pass it to atof

Avoid comparing character to ascii value, rather you could have use ' ' (space) directly.

Instead of using for loop with a fixed size, you can use strlen() or strnlen() to find the length of the input string.

Upvotes: 0

Related Questions