Warum gibt es kein strtoi in stdlib.h?

Lesezeit: 7 Minuten

Elis Benutzeravatar
Eli

Ich habe mich daran gewöhnt strtod und Varianten. Ich frage mich, warum es keine gibt strtoi versendet mit <stdlib.h>. Warum bleibt der Integer-Typ bei dieser Party außen vor?

Insbesondere frage ich, warum es keine Version von gibt atoi mit den Sicherheitsmerkmalen von strtod?

Benutzeravatar von Wiz
Zauberer

strtol() wandelt einen String in einen Integer um, einen Long Integer aber trotzdem einen Integer. Es gibt atoi() aber es sollte in den meisten Fällen vermieden werden, da es keinen Mechanismus zur Fehlerberichterstattung bei ungültigen Eingaben gibt.

  • Wenn die Reichweite von long überschreitet den Bereich von int, strtol() setzt nicht errno auch nicht zurück INT_MIN/MAX an int nur Überlauf negiert den Wert dieses Sicherheitsmerkmals.

    – chux – Wiedereinsetzung von Monica

    12. Dezember 2015 um 17:40 Uhr


  • @chux bin mir nicht sicher, was du sagen willst. Natürlich ist es kein Fehler, wenn der übergebene Wert den Bereich von int überschreitet.

    – Wiz

    20. Dezember 2015 um 1:01 Uhr

  • Da die Antwort nicht genau beschreibt, wie man es benutzt strtol() beim Versuch, in eine umzuwandeln intder darauf hinweist, dass Zeichenfolgen, die einen Wert außerhalb von darstellen int Bereich, (aber nicht long) nicht festlegen errno noch einen begrenzten Wert erhalten. Dies ist ein anderes Verhalten als Zeichenfolgen, die einen Wert außerhalb von darstellen long Bereich: was setzt errno und erhalten einen begrenzten Wert.

    – chux – Wiedereinsetzung von Monica

    20. Dezember 2015 um 2:44 Uhr

  • Und aus dem gleichen Grund strtol() sollte bei der Umstellung vermieden werden int aufgrund der Tatsache, dass es keinen Mechanismus zum Melden von Fehlern bei Eingaben gibt, die überlaufen würden int.

    – Jonathan Holz

    17. September 2019 um 16:31 Uhr

  • @chux-ReinstateMonica Ich habe verstanden, was du überhaupt meinst: Bei der Verwendung strtol um eine Zeichenkette in eine umzuwandeln intund der Wert in der Zeichenfolge überschreitet den Bereich von an intlong hat gleichzeitig eine größere Reichweite als int – Es wird kein Fehler oder irgendetwas geworfen, was den Coder alarmieren könnte, was natürlich Sicherheitsmängel verursacht. Aber ich verstehe nicht, was du mit meinst “…Strings, die einen Wert außerhalb von darstellen int Bereich, (aber nicht long)…” – Was ist ein Beispiel für einen Wert, der den Bereich von an überschreitet? int liegt aber nicht im Bereich von a long aber…

    – RobertS unterstützt Monica Cellio

    14. Februar 2020 um 14:50 Uhr


chux – Stellt Monicas Benutzeravatar wieder her
Chux – Wiedereinsetzung von Monica

Warum gibt es kein strtoi in stdlib.h?

Keine kritische Notwendigkeit.

Im frühen C gab es keinen Standard-Integer-Typ mit Vorzeichen, der breiter als war long und alle engeren Umbauten, wie intkönnte daraus gemacht werden strtol() – wie unten ausgeführt.

Diese und ihre unsigned Gegenstücken fehlen jetzt C-Funktionen und ein Designmangel in der aktuellen Standard-C-Bibliothek (C17/18).


Auf vielen Systemen long und int haben die gleiche Reichweite und es besteht daher weniger Bedarf an einem separaten strtoi(). atoi() erfüllt die Notwendigkeit für Quick-and-Dirty-Code zur Konvertierung in eine int, kann aber Fehlererkennung vermissen lassen. Bei Fehler, atoi() entsteht undefiniertes Verhalten (UB). Es gibt auch keine strto_short() Noch strto_signchar()etc.

Es ist ziemlich einfach, einen Ersatz zu schaffen strtoi(). Vereinfachungen bestehen.

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

static long str2subrange(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 str2i(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) str2subrange(s, endptr, base, INT_MIN, INT_MAX);
  #endif
}

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

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

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

[Edit 2021]

Um Konflikte zu vermeiden Zukünftige BibliotheksrichtungenNamen geändert von strto...() zu str2...().
2 impliziert to.

Funktionsnamen, die mit beginnen str, memoder wcs und ein Kleinbuchstabe kann den Deklarationen in hinzugefügt werden <string.h> Header. C17dr § 7.31.13 1

  • Ich bin mir nicht sicher, warum dies nicht die akzeptierte Antwort ist. Irgendwie hat Ihr Kommentar zur akzeptierten Antwort nicht genügend Anklang gefunden.

    – Verrückter Physiker

    2. November 2018 um 6:07 Uhr

  • @MadPhysicist Ich war 4 Jahre später und OP war seit 3 ​​Jahren vor dieser Antwort nicht mehr da. Doch es geht langsam aufwärts.

    – chux – Wiedereinsetzung von Monica

    2. November 2018 um 6:10 Uhr


  • Beachten Sie auch, dass BSD strtonum() bereitstellt, was mehr oder weniger genau dies tut, obwohl Sie die Basis nicht angeben können. linux.die.net/man/3/strtonum

    – Jetski S-Typ

    13. November 2018 um 1:26 Uhr


  • strtonum hat eine kontraproduktive Semantik: es kehrt zurück 0 Bei allen Fehlern ist die Rückgabe von min oder max bei Überlauf eine Funktion von strtol() was es einfach macht, die Ursache des Problems zu ermitteln. Das behauptet die Manpage Die vorhandenen Alternativen, wie z atoi(3) und strtol(3)sind entweder unmöglich oder schwierig sicher zu verwenden. Dies gilt für atoi() aber es gibt keine Schwierigkeiten bei der Verwendung strtol() sicher.

    – chqrlie

    19. Mai 2021 um 17:57 Uhr

  • “Auf vielen Systemen haben long und int den gleichen Bereich” – Auf 64-Bit-Windows sind sie gleich. Auf 64-Bit-LInux/unix-ähnlich sind sie es nicht. en.cppreference.com/w/cpp/language/types

    – Asmund

    29. März um 11:52 Uhr

Die Ganzzahl wird nicht aus der Party ausgelassen: Es gibt sie strtoldas eine Zeichenfolge in a konvertiert longbei dem es sich um einen ganzzahligen Typ handelt.

Benutzeravatar von Marc K
Markus K.

Dies ist, was ich verwendet habe.

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;

Es ist Anruf atoi. Siehe auch Wikipedia für Details, einschließlich seines Nachfolgers strol.

  • atoi sollte nicht benutzt werden.

    – James McNellis

    30. Mai 2011 um 23:02 Uhr

  • @James McNellis atoi sollte nicht verwendet werden – Sie haben diese Aussage gemacht, als ob Ihr Grund offensichtlich sein sollte, aber da mehrere Antworten alle zuzustimmen scheinen, dass atoi() die richtige Lösung ist, muss es nicht so offensichtlich sein. Möchten Sie allen mitteilen, warum Sie der Meinung sind, dass atoi nicht verwendet werden sollte, oder sollte es am besten ein Rätsel bleiben?

    – mah

    30. Mai 2011 um 23:07 Uhr

  • @mah: Wenn atoi kehrt zurück 0, INT_MINoder INT_MAXkönnen Sie nicht feststellen, ob die Konvertierung erfolgreich war.

    – James McNellis

    30. Mai 2011 um 23:11 Uhr

  • @James McNellis: Es ist eigentlich viel schlimmer als das – die Spezifikation ist “Wenn der Wert des Ergebnisses nicht dargestellt werden kann, ist das Verhalten undefiniert.”.

    – Café

    30. Mai 2011 um 23:33 Uhr

  • In der Tat, mit atoi ist theoretisch fast so schlimm wie konsumieren gets: Es sei denn, Sie haben eine sehr strenge Kontrolle über die Eingabe, führt dies zu undefiniertes Verhalten. Glücklicherweise nehmen sich die meisten Implementierungen diese Freiheit nicht, und atoi einfach produziert unsigned-ähnliches Umbrechen bei Überlauf, aber darauf sollten Sie sich nicht verlassen. Nur nicht verwenden atoi.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    31. Mai 2011 um 0:10 Uhr

Benutzeravatar von sarnold
Sarnold

Übersehen Sie nicht die SEE ALSO Abschnitt Ihrer Manpages 🙂

SEE ALSO
       atof(3), atoi(3), atol(3), strtol(3), strtoul(3)

Du schaust nach atoi(3). 🙂

  • atoi sollte nicht benutzt werden.

    – James McNellis

    30. Mai 2011 um 23:02 Uhr

  • @James McNellis atoi sollte nicht verwendet werden – Sie haben diese Aussage gemacht, als ob Ihr Grund offensichtlich sein sollte, aber da mehrere Antworten alle zuzustimmen scheinen, dass atoi() die richtige Lösung ist, muss es nicht so offensichtlich sein. Möchten Sie allen mitteilen, warum Sie der Meinung sind, dass atoi nicht verwendet werden sollte, oder sollte es am besten ein Rätsel bleiben?

    – mah

    30. Mai 2011 um 23:07 Uhr

  • @mah: Wenn atoi kehrt zurück 0, INT_MINoder INT_MAXkönnen Sie nicht feststellen, ob die Konvertierung erfolgreich war.

    – James McNellis

    30. Mai 2011 um 23:11 Uhr

  • @James McNellis: Es ist eigentlich viel schlimmer als das – die Spezifikation ist “Wenn der Wert des Ergebnisses nicht dargestellt werden kann, ist das Verhalten undefiniert.”.

    – Café

    30. Mai 2011 um 23:33 Uhr

  • In der Tat, mit atoi ist theoretisch fast so schlimm wie konsumieren gets: Es sei denn, Sie haben eine sehr strenge Kontrolle über die Eingabe, führt dies zu undefiniertes Verhalten. Glücklicherweise nehmen sich die meisten Implementierungen diese Freiheit nicht, und atoi einfach produziert unsigned-ähnliches Umbrechen bei Überlauf, aber darauf sollten Sie sich nicht verlassen. Nur nicht verwenden atoi.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    31. Mai 2011 um 0:10 Uhr

1417280cookie-checkWarum gibt es kein strtoi in stdlib.h?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy