【问题标题】:Checking if passed string is an integer检查传递的字符串是否为整数
【发布时间】:2014-01-21 18:20:13
【问题描述】:

我正在制作一个记录时间、用户 ID 和体重的应用程序。如何检查传递的第一个令牌是否为整数?我以为我会使用 isdigit,但这仅适用于单个字符。如果第一个标记不是整数,我想输出无效时间。我目前正在使用

sscanf(userInput, "%d %s %f", &timestamp, userID, &weight);

如果第一个标记不是整数(例如有字母),我仍然会得到变量时间戳的数字,这是我不想要的。

int main()
{
   char userInput[99];
   int timestamp, timestampT = 0;
   char userID[31];
   userID[0] = 0;
   float weight, weightT, day, rateW;

   while(fgets(userInput, 99, stdin) != NULL){
       sscanf(userInput, "%d %s %f", &timestamp, userID, &weight);

       if(timestamp == 0 ){
           printf("%s\n", "Invalid time");
       }
       else if(!isalpha(userID[0]) || userID[0]=='_' || userID[0] == 0){
           printf("%s\n", "Illegal userID");
       }
       else if(weight < 30.0 || weight > 300.0){
           printf("%s\n", "Illegal weight");
       }
       else if(timestampT > 0){
           day = timestampT/86400;
           rateW = (weightT -weight)/(day - timestamp/86400);
           if(rateW > 10.0 || rateW < -10.0){
               printf("%s\n", "Suspiciously large weight change");
           }

       }
       else{
           printf("%d %s %f \n", timestamp, userID, weight);
           timestampT = timestamp;
           timestamp = 0;
           weightT = weight;
       }

       userID[0] = 0;
   }
}

【问题讨论】:

  • 使用 sscanf 的结果构建另一个字符串,然后将原始字符串与重建字符串进行比较。如果它们不同,那么某些东西没有正确转换。例如foo = printf('%d %s, %f', the, values, here); if (!strcmp(foo, userinput)) { ruh_roh(); }
  • 首先使用sscanf() 的结果来确定成功解析了多少参数。 Heed the Sixth Commandment
  • 您可以使用isdigit 作为您的时间戳或使用isalpha 作为您的ID 检查字符串的所有字符。 (最好为此编写函数。)或者您可以在第一个 sscanf 中将时间作为字符串读取,然后在该字符串上运行 sscanf(..., "%d", ...)`。

标签: c string integer


【解决方案1】:

简单的方法:

char dummy;
sscanf( userInput, "%d%c %s %f", &timestamp, &dummy, userId, &weight );
if ( !isspace( dummy ))
   // invalid timestamp input, handle as appropriate

%d 转换说明符告诉sscanf 将第一个非数字字符留在输入流中,%c 转换说明符将拾取该字符。如果此字符不是空格,则输入不是有效的整数字符串。

不太容易,但 IMO 是更稳健的方式:

首先,将您的时间戳读取为文本:

char timestampStr[N+1]; // where N is the number of digits in the time stamp
...
sscanf(userInput, "%s %s %f", timestampStr, userID, &weight);

然后使用strtol库函数将文本转换为整数值:

char *chk;
int tmp = (int) strtol( timestampStr, &chk, 10 );

转换后chk会指向timestampStr中的第一个非数字字符;如果此字符不是空格或 0 终止符,则输入字符串 不是有效整数:

if ( *chk == 0 || isspace( *chk ))
{
  timestamp = tmp;
}
else
{
  // invalid timestamp input, handle as appropriate
}

我更喜欢这种方法,因为如果输入无效,它不会为timestamp 分配任何东西;这对您的目的可能很重要,也可能无关紧要。

编辑

正如 chux 指出的那样,您还应该检查 sscanf 的返回值(我很少使用 *scanf 函数进行交互式输入,所以我从没想过)。在第一种情况下,如果结果

实际上,我所做的是使用fgets 读取该行,然后使用strtok 将其分解为标记,然后根据需要使用strtolstrtod 进行任何数字转换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2012-04-27
    • 1970-01-01
    • 2011-03-23
    • 2017-11-28
    相关资源
    最近更新 更多