2

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

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

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

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

再澄清一点...

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

  1. 确定它是否仅包含数字,
    在这里我根据最佳拟合将字符串转换为 short 或 int 或 long。(我怎么知道字符串是否可以转换为短整数或长整数?
  2. 只有字母,将其保留为字符串。
  3. 带一个小数点的数字。
    在这里我需要将字符串转换为浮点数或双精度数(这里有同样的问题
  4. 其他。将其保留为字符串
4

4 回答 4

1

首先,检查问题是否尚未为您解决。可能是您用于将字符串转换为数字的库函数已经完成了您需要的检查。

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

例如,如果字符串与正则表达式匹配:

[+-]?\d+

然后你就知道它是一个 int 还是一个 long。将其转换为 long,然后检查其大小。如果您的 long 可以适合 int,请将其转换为 int。

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

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

于 2008-10-12T17:25:11.743 回答
1

尝试使用 sscanf 将其变为 long。如果失败,请尝试使用 sscanf 将其变为双精度。如果失败,它是一个字符串。您可以使用 %n 转换来判断是否所有输入都已成功使用。<limits.h>和中的常量<float.h>可以帮助您确定数字结果是否适合您平台上更窄的类型。如果这不是家庭作业,那么您的目标类型可能是外部定义的——例如通过数据库模式——而后一个注释是无关紧要的。

于 2008-10-12T17:53:01.077 回答
1

在 C(不是 C++)中,我将使用 strtod/strol 和 <limits.h> 和 <float.h> 中的最大值的组合:

#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

对不起我生锈的C。

:-)

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

请注意,查找数字是双精度数还是浮点数有点复杂,因为差异似乎在于精度,即您的数字可以用双精度数还是浮点数表示。大多数“十进制实数”数字不能完全表示为双精度数,我不会打扰。

还要注意,有一个问题,因为 25.0 既可以是实数,也可以是整数。我比较“dValue == (double)(long)dValue”,我想你应该知道是否是一个整数,再一次,没有考虑到计算机使用的二进制实数通常会出现的精度问题。

于 2008-10-12T18:46:05.683 回答
0

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

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

  • -?\d*.\d*([eE]?[+-]?\d*.\d*)?是一个浮点数(几乎,它接受奇怪的东西,比如.e-.你应该定义最适合你的正则表达式)
  • -?\d+是一个整数
  • 0x[0-9A-Fa-f]+是一个十六进制常数

等等。如果您不使用正则表达式库,则必须从头开始为这些表示编写一个小型解析器。

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

例如,如果整数小于SHRT_MAX你可以假设它是一个short.

您可能还必须做出任意决定,例如 54321 只能是 anunsigned short但 12345 可能是 asigned short或 an unsigned short

于 2008-10-12T18:10:31.743 回答