H R
H R

Reputation: 103

Sscanf a double value

I need scan a double from a string, can you help me? It need to be something like this:

#include <stdio.h>
#include <string.h>
int main()
{
    const char *key="infinity";
    const char *str = malloc(2*sizeof(double*));
    double a;
    printf("Write the value: "
    scanf("%s",str);
    if (strcmp(str,key)==0)
        printf ("ok");
    else
    {
        sscanf(str,"%lf",&a);
        printf("ok, a is %lf",a);
    }
    return 0;

When I put infinity, it works properly. But when I enter with some double value (like 1.25), it doesn't.

1.25
ok, a is 0.000000

Upvotes: 0

Views: 1889

Answers (1)

user2736738
user2736738

Reputation: 30926

First all, there is a way you should check if the line of code runs successfully or not.

You are using sscanf(), check it's return value to be sure if it is being successful in what it is supposed to do. (To get the double from str).

Also why const char*. It is pointing to an immutable character string. You can't change it's value. So the first scanf will fail. You can simply use char* here, that will be sufficient for your requirement.

Allocating 2*sizeof(double*) doesn't ensure that you will be able to hold all the digits of a double number. That's a wrong idea. You can consider a rough value to hold (like upto 12 digits after decimal point) and then scan it.

Considering the return value of malloc is another good practice. In case it fails it returns NULL. And after getting NULL if you go on accessing it, then it invokes undefined behavior.

Whatever you allocate using malloc, it's need to be freed after you are done working with it.

Also read some good books. There are plenty of them.

A small example:

#include <stdio.h>
#include <string.h>
#include <float.h>
#include <stdlib.h>
#include <ctype.h>
char *trimwhitespace(char *str)
{
  char *end;


  while(isspace((unsigned char)*str)) str++;

  if(*str == 0)
    return str;

  end = str + strlen(str) - 1;
  while(end > str && isspace((unsigned char)*end)) end--;

  *(end+1) = 0;

  return str;
}
int main()
{
    const char *key="infinity";
    char *str = malloc(sizeof(char)*(3 + DBL_MANT_DIG - DBL_MIN_EXP+1));
    if( str == NULL){
        fprintf(stderr,"Error in malloc");
        exit(1);
    }
    char *store = str;
    double a;
    printf("Write the value: ");
    if( fgets(str, (3 + DBL_MANT_DIG - DBL_MIN_EXP+1), stdin) == NULL){           
        fprintf(stderr,"Error in string input");
        exit(1);
    }
    str = trimwhitespace(str);
    if( strlen(str) == 0){
         printf("Empty line detected.\n");
         return EXIT_FAILURE;
    }
    for(size_t i = 1; i < strlen(str); i++){
        if( !isspace(str[i]) && isspace(str[i-1])){
            printf("Error extra input detected\n");
            return EXIT_FAILURE;
        }

    }
    if (strcmp(str,key)==0)
        printf ("ok");
    else
    {
        char *err;

        a = strtod(str, &err);
        if (*err!=0 && !isspace((unsigned char)*err)) { 
            printf("Error extra input detected ");
        }
        else{
            printf("ok, a is %lf",a);
        }

    }
    free(store);
    return 0;
}

Reference:

After finding a bit I could finally cite the correct reference for the 3 + DBL_MANT_DIG - DBL_MIN_EXP part. Check this answer.

Upvotes: 1

Related Questions