Konwersja string na double

0

Witam
mam do napisania funkcję, która konwertuje string na double. Poniżej kod źródłowy

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

struct maybe_double {
  bool value_exists;
  double value;
};

struct maybe_double parse_float(const char *input) {
  struct maybe_double out = {.value_exists = false};
  if(strcmp(input,"0.0")==0)
    {
      out.value_exists=true;
      out.value=0.0;
  }
  else if(strtod(input,NULL)!=0)
    {
      out.value_exists=true;
      out.value=strtod(input,NULL);
    }
  else if(strtod(input,NULL)==0.0)
    out.value_exists=false;  
  return out;
}

wywala mi dwa błędy w testach:
parse_float("-12-34") should fail
parse_float("-85,.0000") should fail
nie wiem co jest nie tak. Może ktoś pomóc

0

Funkcja strtod połyka "ile może", ale pozostałość nie jest błędem.
W twoim przypadku skonsumowanie do końca możesz sprawdzić z drugiego argumentu, który masz niestety NULL

http://www.cplusplus.com/reference/cstdlib/strtod/

Taki "bezstressowy" design funkcji z tej gruyp w C jest odmienny od Javy/C# gdzie leci wyjątek

0

Z opisu wnioskuję, że cały łańcuch znakowy ma być liczbą zmiennoprzecinkową. strtod jak napotka , albo -, to skończy parsowanie i zwróci to co wczytał jako double.
Musisz przemyśleć co dokładnie ma być potraktowane jako input, czy część łańcucha znakowego jest OK, czy nie.

Zauważ, że możesz sprawdzić ile znaków sparsowało strtod używając drugiego parametru funkcji. Jeżeli go (drugiego parametru funkcji) odpowiednio użyjesz, to będziesz mógł pozbyć się porównania łańcucha z "0.0" i drugiego zawołania strtod . W zupełności wystarczy pojedyncze wywołanie w.w. funkcji i zweryfikowanie pozycji do której łańcuch został odczytany, aby stwierdzić czy całość to poprawna liczba.

0

Poprawiłem kod

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

struct maybe_double {
  bool value_exists;
  double value;
};

struct maybe_double parse_float(const char *input) {
  struct maybe_double out = {.value_exists = false};
  char *endptr;
  if((out.value=strtod(input,&endptr)))
      if(*endptr=='\0')
        out.value_exists=true;
  else
    out.value_exists=false;  
  return out;
}

ale teraz kiedy pozbyłem się sprawdzenia czy string=="0.0" wyrzuca mi błąd

parse_float("0.0") should not fail
Jak mogę obejść sprawdzenie przez funkcję strcmp?

0

strtod dobrze sparsowało input, ale out.value to 0.0, które będzie potraktowane jako false. W skutek czego nie wejdziesz do bloku pod ifem.
Możesz spróbować tak:

struct maybe_double parse_float(const char *input) {
  struct maybe_double out = {.value_exists = false};
  char *endptr = NULL;
  
  if (input != NULL) {
    out.value = strtod(input, &endptr);
    out.value_exists = (endptr != NULL && *endptr=='\0');
  }

  return out;
}
0

Dziękuję za odpowiedzi. Program już wysłałem na serwer jest ok. Zadziałał poniższy kod

#include <stdbool.h>

struct maybe_double {
  bool value_exists;
  double value;
};

struct maybe_double parse_float(const char *input) {
  struct maybe_double out = {.value_exists = false};
  char *endptr;
  if(out.value=strtod(input,&endptr))
      if(*endptr=='\0')
        out.value_exists=true;
  if(out.value==0.0)
    if((*endptr=='\0')&&(strlen(input)>0))
      out.value_exists=true;
  else
    out.value_exists=false;  
  return out;
}
0

Po kiego tak kombinować?

#include <stdbool.h>
#include <stdlib.h>
#include <string>
using namespace std;

enum parseResult { prOk,prHaveMore,prBad };

enum parseResult parseDouble(const char *str,double *value)
{
	char *out;
	*value=strtod(str,&out);
	if(out==str) return prBad;
	if(*out) return prHaveMore;
	return prOk;
}

// jeżeli poprawne liczymy tylko kiedy cały wiersz jest liczbą
bool isDouble(const char *str)
{
	char *out;
	strtod(str,&out);
	return (*str)&&(!*out);
}

// lub jeżeli potrzebna również liczba
bool isDouble(const char *str,double *value)
{
	char *out;
	*value=strtod(str,&out);
	return (*str)&&(!*out);
}

int main()
{
	double value;
	if(parseDouble("x",&value)==prBad) printf("Bad double value\n");
	if(parseDouble("7t",&value)==prHaveMore) printf("value=%lf; and more data in input\n",value);
	if(parseDouble("3.5.",&value)==prHaveMore) printf("value=%lf; and more data in input\n",value);
	if(parseDouble("666.13",&value)==prOk) printf("value=%lf;\n",value);
	if(parseDouble("1.34E1",&value)==prOk) printf("value=%lf;\n",value);
	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1