C 将字符字符串转换为其基础数据类型

C 将字符字符串转换为其基础数据类型,c,types,C,Types,我有一个字符串(char*),我需要找到它的底层数据类型,比如int、float、double、short、long,或者只是一个字符数组,其中包含带或不带数字的字母表(比如SQL中的varchar)。 例如: 给定这些字符串,我需要找到第一个字符串的类型为int,并将其类型转换为int,依此类推ex: int no1 = atoi(str1) float no2 = atof(str2) long no3 = atol(str3) double no4 = strtod(str4) char*

我有一个字符串(char*),我需要找到它的底层数据类型,比如int、float、double、short、long,或者只是一个字符数组,其中包含带或不带数字的字母表(比如SQL中的varchar)。 例如:

给定这些字符串,我需要找到第一个字符串的类型为int,并将其类型转换为int,依此类推ex:

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

再澄清一点

我有一个字符串,它的内容可以是字母和/或数字和/或特殊字符。现在,我能够解析字符串和

  • 确定它是否只包含数字,
    在这里,我根据最佳拟合将字符串转换为short、int或long。(如何知道字符串可以转换为短整型还是长整型?
  • 只使用字母表,将其保留为字符串
  • 带一个小数点的数字。
    在这里,我需要将字符串转换为float或double(这里有相同的问题
  • 其他的。把它当作一根绳子

  • 首先,检查问题是否已经为您解决。可能是用于将字符串转换为数字的库函数已经执行了所需的检查

    如果做不到这一点,您将需要对字符串进行一些模式匹配,这就是正则表达式的用途

    例如,如果字符串与regexp匹配:

    [+-]?\d+

    然后你知道它是一个int或long。将其转换为长形,然后检查其大小。如果您的long可以放入int,请将其转换为int

    您可以对浮点和double执行相同的操作,尽管正则表达式有点复杂


    注意一些尴尬的情况,比如空字符串、一个单独的小数点、太大而不能太长的数字等等。您还需要决定是否允许使用指数表示法。

    尝试使用sscanf进行长时间的计算。如果失败了,试着用sscanf把它变成双人。如果失败,那就是一个字符串。您可以使用%n转换来判断是否已成功使用所有输入。
    中的常量可以帮助您确定数值结果是否适合您平台上更窄的类型。如果这不是家庭作业,那么您的目标类型可能是外部定义的(例如,由数据库架构定义的),而后面的注释是不相关的。

    首先,您应该决定要识别哪些表示。例如,0xBAC0是用十六进制表示的无符号短字符吗?010(八进制)和1E-2(0,01)也是如此

    一旦确定了表示形式,就可以使用正则表达式来确定一般形式。例如:

    • -?\d*\d*([eE]?[+-]?\d*\d*)?
      是一个浮点数(几乎可以接受像
      .e-.
      这样奇怪的东西。您应该定义最适合自己的正则表达式)
    • -?\d+
      是一个整数
    • 0x[0-9A-Fa-f]+
      是一个十六进制常量
    等等。如果您不使用正则表达式库,您必须从头开始为这些表示编写一个小型解析器

    现在,您可以将其转换为可能的最大类型(例如,整数为
    long
    ,浮点为double),然后使用
    limits.h
    中的值查看该值是否适合较小的类型

    例如,如果整数小于
    SHRT\u MAX
    ,则可以假定它是
    short

    您可能还必须做出任意决定,例如54321只能是
    无符号短
    ,但12345可以是
    有符号短
    无符号短
    ,在C(而不是C++)中,我将使用和中的strod/strol和max值的组合:

    对不起,我生锈了

    :-)

    因此,实质上,在调用whatIsTheValue之后,通过MyEnum枚举检索类型,然后根据此枚举中的值,从union MyUnion检索正确类型的正确值

    请注意,查找数字是双精度还是浮点数要复杂一些,因为差异似乎在于精度,即数字是可以表示为双精度还是浮点数。大多数“十进制实数”的数字不能精确地表示为双精度数,我不想麻烦


    也请注意,这里有一个陷阱,因为25.0既可以是实数,也可以是整数。我比较“dValue==(double)(long)dValue”,我想你应该知道它是否是一个整数,同样,没有考虑到计算机使用的二进制实数通常会带来的精度问题。

    只是澄清一下,char*的基本数据类型是char。您只能将字符串的内容解析为您想要的类型,但您必须事先知道.1E-2通常是0.01,不是吗?使用“%ld”的sscanf()将很高兴地将“0.1234E-39”中的零转换为整数,因此它没有多大帮助。如果没有扫描格式字符串中“0x%ld”形式的帮助,它也不会转换0xABCD。等等,第一点-这就是为什么我说使用%n。第二点-%x将愉快地转换为0xABCD。OP的示例不包括十六进制输入;如果他需要它,他显然会需要一个额外的电话(就像他与斯特图和朋友一样)。我不会发布家庭作业问题的完整解决方案。对于长左值的哪些值,将进行测试(左值>=long_MIN)&&(左值该示例并不完整:它只是提供了一个结合枚举、并集和类型查找器函数的正确模式。用户应根据需要调整这些符号,如支持的类型、如何处理整数、十六进制表示法等。。
    int no1 = atoi(str1)
    float no2 = atof(str2)
    long no3 = atol(str3)
    double no4 = strtod(str4)
    char* varchar1 = strdup(str5)
    
    #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;
    }
    
    [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