Tengo un archivo que almacena valores como 2.32x7 . Leí la parte de coma flotante usando:
fscanf(file, "%lf", &value); Funciona perfectamente... excepto cuando el archivo almacena algo como 0x2 . En ese caso, lee la cadena completa como un valor hexadecimal.
¿Cómo puedo evitar que esto suceda? Me gustaría que fscanf solo lea 0 e ignore x2 .
Editar: según lo sugerido por @dbush , estoy agregando un archivo de entrada de muestra.
Estoy analizando polinomios. Entonces, el archivo de entrada será algo como:
0x2+2.32x7-4x-9Leer la línea con fgets() y luego analizarla con código creado es la más robusta.
Para leer texto como un único número de coma flotante con fscanf() hasta una 'x' , primero lea con un scanset y luego convierta.
char buf[400 + 1]; // Something large - consider DBL_MAX may be 1e308 // Scanset of expected FP characters #define FP_FMT " %400[-+.eE0-9]" // or maybe simply #define FP_FMT " %400[^x]" if (fscanf(FP_FMT, buf) == 1 && sscanf(buf, "%lf", &value) == 1) { // Success El código pedante usaría strtod() en lugar de sscanf(buf, "%lf", &value) .
Otras consideraciones incluyen el uso local de ',' como el punto decimal, NAN, infinito, texto incluso más ancho como pequeños valores FP exactos, cómo manejar texto mal formateado, errores de entrada, EOF, ...
Considere escanear el par de valor y exponente en 1 paso.
if (fscanf(FP_FMT "x%d, buf, &power) == 2 && sscanf(buf, "%lf", &value) == 1) {Para su propósito, debe leer el polinomio completo con fgets() y analizarlo con código as hoc usando strtod() y strtol() :
#include <errno.h> #include <stdlib.h> int parse_polynomial(struct polynomial *p, const char *s) { for (;;) { double factor = 1; int exponent = 0; char *p; while (isspace((unsigned char)*s) { s++; } if (*s == '\0') break; if (*s == '+') { s++; } else if (*s == '-') { factor = -1; } if (*s != 'x') { errno = 0; factor *= strtod(s, &p); if (p == s || errno != 0) { /* parse error */ break; } s = p; } if (*s == 'x') { exponent = 1; s += 1; if (isdigit((unsigned char)*s) { unsigned long ul; errno = 0; ul = strtoul(s, &p, 10); if (p == s || errno != 0 || ul > INT_MAX) break; exponent = (int)ul; s = p; } } add_component(p, factor, exponent); } return (*s == '\0') ? 0 : -1; }❗❗❗ Maneja incorrectamente los números con puntos...
Pensando, cómo arreglar eso.
Puede leer los caracteres numéricos y luego analizar el número de la cadena: ejemplo
#include <stdio.h> int main() { double value; char s[32]; *s = 0; scanf("%31[0-9]", s); sscanf(s, "%lf", &value); printf("%f\n", value); scanf("%3s", s); puts(s); }Si también necesitas números negativos: ejemplo
#include <stdio.h> int main() { double value; char s[32]; *s = 0; scanf("%1[-+]", s); scanf("%30[0-9]", s+!!*s); sscanf(s, "%lf", &value); printf("%f\n", value); scanf("%3s", s); puts(s); }Tenga en cuenta que el último código se come el signo incluso si no va seguido de dígitos.