web-dev-qa-db-fra.com

Pourquoi n'y a-t-il pas de strtoi dans stdlib.h?

Je me suis habitué à strtod et aux variantes. Je me demande pourquoi aucun strtoi n'est livré avec stdlib.h. Pourquoi est-ce que l'entier est exclu de ce parti?

Plus précisément, je me demande pourquoi il n'y a pas de version d'atoi avec les fonctionnalités de sécurité de strtod.

58
Eli

strtol() convertit une chaîne en un entier, un entier long mais néanmoins un entier. Il y a atoi() mais il doit être évité dans la plupart des cas car il manque un mécanisme de rapport d'erreurs provenant d'une entrée invalide.

46
Wiz

Pourquoi n'y a-t-il pas de strtoi dans stdlib.h?

Aucun besoin critique.

Au début de C, il n'y avait pas de type signé standard plus large que long et toutes les conversions plus étroites, comme int, pouvaient être effectuées à partir de strtol() - comme ci-dessous.

OMI, ceux-ci et leurs homologues unsigned manquent désormais de fonctions C et d'un défaut de conception dans la bibliothèque C standard actuelle.


Sur de nombreux systèmes, long et int ont la même plage et il y a donc un besoin réduit d'une strtoi() distincte. De plus, la fonction atoi() répond au besoin de code rapide et sale, mais peut manquer de détection d'erreur. Il n'y a pas non plus de strto_short() ni strto_signchar(), etc.

Il est assez facile de créer un substitut strtoi(). Des simplifications existent.

#include <errno.h>
#include <limits.h>
#include <stdlib.h>

static long strto_subrange(const char *s, char **endptr, int base, 
    long min, long max) {
  long y = strtol(s, endptr, base);
  if (y > max) {
    errno = ERANGE;
    return max;
  }
  if (y < min) {
    errno = ERANGE;
    return min;
  }
  return y;
}

// OP's goal
int strtoi(const char *s, char **endptr, int base) {
  #if INT_MAX == LONG_MAX && INT_MIN == LONG_MIN
    return (int) strtol(s, endptr, base);
  #else
    return (int) strto_subrange(s, endptr, base, INT_MIN, INT_MAX);
  #endif
}

short strtoshort(const char *s, char **endptr, int base) {
  return (short) strto_subrange(s, endptr, base, SHRT_MIN, SHRT_MAX);
}

signed char strtoschar(const char *s, char **endptr, int base) {
  return (signed char) strto_subrange(s, endptr, base, SCHAR_MIN, SCHAR_MAX);
}

#include <stdint.h>
int16_t strtoint16(const char *s, char **endptr, int base) {
  return (int16_t) strto_subrange(s, endptr, base, INT16_MIN, INT16_MAX);
}
22
chux

L'entier n'est pas en reste: il y a strtol, qui convertit une chaîne en long, qui est un type entier.

5
James McNellis

C'est ce que j'utilise.

long long_val;
int  int_value;

errno = 0;
long_val = strtol (theString, NULL, 10);
if (errno)
   handle_error;
if ((long) someIntMin > long_val || long_val > (long) someIntMax)
   handle_invalid;
int_value = (int) long_val;
2
Marc K.