2 Stimmen

Konvertierung einer Zeichenkette in ihren zugrundeliegenden Datentyp

Ich habe eine Zeichenfolge (char*), und ich brauche, um seine zugrunde liegende Datentyp wie int, float, double, kurz, lang, oder nur ein Zeichen-Array mit Alphabeten mit oder ohne Ziffern (wie varchar in SQL) zu finden. Zum Beispiel:

    char* str1 = "12312"
    char* str2 = "231.342"
    char* str3 = "234234243234"
    char* str4 = "4323434.2432342"
    char* str5 = "i contain only alphabets"

Angesichts dieser Zeichenfolgen, ich brauche zu finden, dass die erste Zeichenfolge vom Typ int ist und typecast es zu einem int, und so weiter ex:

int no1 = atoi(str1)
float no2 = atof(str2)
long no3 = atol(str3)
double no4 = strtod(str4)
char* varchar1 = strdup(str5)

Ein bisschen mehr Klarheit...

Ich habe eine Zeichenkette, deren Inhalt aus Buchstaben und/oder Ziffern und/oder Sonderzeichen bestehen kann. Im Moment kann ich die Zeichenkette parsen und

  1. Ermitteln Sie, ob sie nur Ziffern enthält,
    Hier konvertiere ich die Zeichenkette in short, int oder long, je nachdem, was am besten passt. ( Woher weiß ich, ob die Zeichenfolge in eine kurze int oder lange konvertiert werden kann? )
  2. Nur Alphabete, als Zeichenkette belassen.
  3. Ziffern mit einem einzigen Dezimalpunkt.
    Hier muss ich den String in Float oder Double umwandeln ( Dieselbe Frage hier )
  4. andere. als Zeichenfolge belassen

1voto

Pitarou Punkte 2195

Prüfen Sie zunächst, ob das Problem nicht bereits für Sie gelöst wurde. Es könnte sein, dass Ihre Bibliotheksfunktionen für die Umwandlung von Zeichenketten in Zahlen bereits die von Ihnen benötigten Prüfungen durchführen.

Andernfalls müssen Sie einen Mustervergleich für Zeichenketten durchführen, und dafür sind reguläre Ausdrücke da!

Zum Beispiel, wenn die Zeichenfolge mit dem Regexp übereinstimmt:

[+-]?\d+

dann wissen Sie, dass es ein int oder ein long ist. Konvertieren Sie ihn in einen long und überprüfen Sie dann seine Größe. Wenn Ihr long in einen int passt, konvertieren Sie ihn in einen int.

Sie können dasselbe für Floats und Doubles tun, obwohl der reguläre Ausdruck etwas komplizierter ist.

Achten Sie auf schwierige Fälle wie eine leere Zeichenkette, ein einzelnes Dezimalkomma, Zahlen, die zu groß für einen Long sind, und so weiter. Sie müssen auch entscheiden, ob Sie die Notation von Exponenten zulassen wollen.

1voto

fizzer Punkte 13343

Versuchen Sie, ihn mit sscanf in eine lange Datei zu verwandeln. Wenn das fehlschlägt, versuchen Sie, es mit sscanf in einen double zu verwandeln. Wenn das fehlschlägt, ist es ein String. Sie können die %n-Konvertierung verwenden, um festzustellen, ob die gesamte Eingabe erfolgreich verarbeitet wurde. Die Konstanten in <limits.h> y <float.h> kann Ihnen bei der Entscheidung helfen, ob die numerischen Ergebnisse in engere Typen auf Ihrer Plattform passen. Wenn dies keine Hausaufgabe ist, sind Ihre Zieltypen wahrscheinlich extern definiert - z. B. durch ein Datenbankschema - und die letzte Bemerkung ist irrelevant.

1voto

paercebal Punkte 78198

In C (nicht in C++) würde ich eine Kombination von strtod/strol und max-Werten aus <limits.h> und <float.h> verwenden:

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <float.h>

/*    Now, we know the following values:
      INT_MAX, INT_MIN, SHRT_MAX, SHRT_MIN, CHAR_MAX, CHAR_MIN, etc.    */

typedef union tagMyUnion
{
   char TChar_ ; short TShort_ ; long TLong_ ; double TDouble_ ;
} MyUnion ;

typedef enum tagMyEnum
{
   TChar, TShort, TLong, TDouble, TNaN
} MyEnum ;

void whatIsTheValue(const char * string_, MyEnum * enum_, MyUnion * union_)
{
   char * endptr ;
   long lValue ;
   double dValue ;

   *enum_ = TNaN ;

   /* integer value */
   lValue = strtol(string_, &endptr, 10) ;

   if(*endptr == 0) /* It is an integer value ! */
   {
      if((lValue >= CHAR_MIN) && (lValue <= CHAR_MAX)) /* is it a char ? */
      {
         *enum_ = TChar ;
         union_->TChar_ = (char) lValue ;
      }
      else if((lValue >= SHRT_MIN) && (lValue <= SHRT_MAX)) /* is it a short ? */
      {
         *enum_ = TShort ;
         union_->TShort_ = (short) lValue ;
      }
      else if((lValue >= LONG_MIN) && (lValue <= LONG_MAX)) /* is it a long ? */
      {
         *enum_ = TLong ;
         union_->TLong_ = (long) lValue ;
      }

      return ;
   }

   /* real value */
   dValue = strtod(string_, &endptr) ;

   if(*endptr == 0) /* It is an real value ! */
   {
      if((dValue >= -DBL_MAX) && (dValue <= DBL_MAX)) /* is it a double ? */
      {
         *enum_ = TDouble ;
         union_->TDouble_ = (double) dValue ;
      }

      return ;
   }

   return ;
}

void studyValue(const char * string_)
{
   MyEnum enum_ ;
   MyUnion union_ ;

   whatIsTheValue(string_, &enum_, &union_) ;

   switch(enum_)
   {
      case TChar    : printf("It is a char : %li\n", (long) union_.TChar_) ; break ;
      case TShort   : printf("It is a short : %li\n", (long) union_.TShort_) ; break ;
      case TLong    : printf("It is a long : %li\n", (long) union_.TLong_) ; break ;
      case TDouble  : printf("It is a double : %f\n", (double) union_.TDouble_) ; break ;
      case TNaN     : printf("It is a not a number : %s\n", string_) ; break ;
      default       : printf("I really don't know : %s\n", string_) ; break ;
   }
}

int main(int argc, char **argv)
{
   studyValue("25") ;
   studyValue("-25") ;
   studyValue("30000") ;
   studyValue("-30000") ;
   studyValue("300000") ;
   studyValue("-300000") ;
   studyValue("25.5") ;
   studyValue("-25.5") ;
   studyValue("25555555.55555555") ;
   studyValue("-25555555.55555555") ;
   studyValue("Hello World") ;
   studyValue("555-55-55") ;

   return 0;
}

Daraus ergibt sich das Folgende:

[25] is a char : 25
[-25] is a char : -25
[30000] is a short : 30000
[-30000] is a short : -30000
[300000] is a long : 300000
[-300000] is a long : -300000
[25.5] is a double : 25.500000
[-25.5] is a double : -25.500000
[25555555.55555555] is a double : 25555555.555556
[-25555555.55555555] is a double : -25555555.555556
[Hello World] is a not a number
[555-55-55] is a not a number
Entschuldigung für mein eingerostetes C.

-)

Im Wesentlichen wird also nach dem Aufruf von whatIsTheValue der Typ über das Enum MyEnum abgerufen, und dann wird entsprechend dem Wert in diesem Enum der richtige, korrekt typisierte Wert aus der Union MyUnion abgerufen.

Die Feststellung, ob es sich bei der Zahl um ein Double oder ein Float handelt, ist etwas komplizierter, denn der Unterschied scheint in der Genauigkeit zu liegen, d. h. ob die Zahl als Double oder als Float darstellbar ist. Die meisten "dezimalen reellen" Zahlen lassen sich nicht genau als Double darstellen, daher würde ich mir die Mühe nicht machen.

Beachten Sie auch, dass es einen Haken gibt, da 25,0 sowohl eine reelle als auch eine ganzzahlige Zahl sein kann. Wenn ich "dValue == (double)(long)dValue" vergleiche, sollten Sie wissen, ob es sich um eine ganze Zahl handelt, wobei die üblichen Präzisionsprobleme bei binären reellen Zahlen, die von Computern verwendet werden, unberücksichtigt bleiben.

0voto

Remo.D Punkte 15552

Zunächst einmal sollten Sie entscheiden, welche Darstellungen Sie erkennen wollen. Ist zum Beispiel 0xBAC0 eine vorzeichenlose Kurzbezeichnung in Hexadezimal? Dasselbe gilt für 010 (in oktal) und 1E-2 (für 0,01).

Wenn Sie sich für eine Repräsentation entschieden haben, können Sie reguläre Ausdrücke verwenden, um die allgemeinen Formen zu bestimmen. Zum Beispiel:

  • -?\d*.\d*([eE]?[+-]?\d*.\d*)? ist eine Fließkommazahl (fast, es akzeptiert seltsame Dinge wie .e-. Sie sollten die Regex definieren, die für Sie am besten geeignet ist)
  • -?\d+ eine ganze Zahl ist
  • 0x[0-9A-Fa-f]+ ist eine Hex-Konstante

und so weiter. Wenn Sie keine Regex-Bibliothek verwenden, müssen Sie einen kleinen Parser für diese Repräsentationen von Grund auf neu schreiben.

Nun können Sie ihn in den größtmöglichen Typ umwandeln (z. B. long long für Ganzzahlen, double für Fließkommazahlen) und verwenden dann die Werte in limits.h um zu sehen, ob der Wert in eine kleinere Schrift passt.

Wenn zum Beispiel die ganze Zahl kleiner ist als SHRT_MAX können Sie davon ausgehen, dass es sich um eine short .

Möglicherweise müssen Sie auch willkürliche Entscheidungen treffen, zum Beispiel kann 54321 nur ein unsigned short aber 12345 könnte ein signed short oder ein unsigned short .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X