简体   繁体   English

atoi() 接受与数字混合的字符串

[英]atoi() accepting strings mixed with number

For a task I need use if atoi(INPUT) == 0 to check that a users input is a valid integer and not 0. The problem is when I enter any string that starts with an integer, it is automatically accepted, even if there are non-integer characters after the integer, for example "1aaaabcc" is accepted.对于我需要使用if atoi(INPUT) == 0来检查用户输入是否有效的 integer 而不是 0 的任务。问题是当我输入任何以 integer 开头的字符串时,它会自动被接受,即使有是 integer 之后的非整数字符,例如接受“1aaaabcc”。

I understand that atoi() is in the example I just stated, would take the 1 and ignore it, but theortically this should be wrong input from the user since it is not a valid integer. Would there be something to add to my code (without adding any libraries) or change something with atoi to fix this?我知道 atoi() 在我刚才说的例子中,会取 1 并忽略它,但理论上这应该是用户输入的错误,因为它不是有效的 integer。我的代码中是否可以添加一些东西(不添加任何库)或用 atoi 改变一些东西来解决这个问题?

Please let me know if you need sample code in case its not clear.如果您需要示例代码以防不清楚,请告诉我。

The function atoi is an "alias" for this function call function atoi是此 function 调用的“别名”

atoi: (int)strtol(nptr, (char **)NULL, 10)

So in your case you should use the function strtol and pass the second argument unequal to NULL that points to a pointer.因此,在您的情况下,您应该使用 function strtol并传递不等于指向指针的NULL的第二个参数。 In this case you can check whether the pointer points to the end of the corresponding string.在这种情况下,您可以检查指针是否指向相应字符串的末尾。

Here is a demonstration program这是一个演示程序

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

int main( void )
{
    char *endptr;

    int n = ( int )strtol( "A", &endptr, 10 );

    printf( "n = %d, *endptr = %d\n", n, *endptr );

    n = ( int )strtol( "10A", &endptr, 10 );

    printf( "n = %d, *endptr = %d\n", n, *endptr );

    n = ( int )strtol( "10", &endptr, 10 );

    printf( "n = %d, *endptr = %d\n", n, *endptr );
}

Its output is它的 output 是

n = 0, *endptr = 65
n = 10, *endptr = 65
n = 10, *endptr = 0

As you can see only in the third call of the function strtol the pointer endptr points to the terminating zero character '\0' .正如您只能在 function strtol的第三次调用中看到的那样,指针endptr指向终止零字符'\0' In all preceding calls it points to the letter 'A' that has the ASCII code 65 .在所有前面的调用中,它指向具有 ASCII 代码65的字母'A'

You can also accept or deny strings like for example "10 " .您还可以接受或拒绝字符串,例如"10 " If to accept such a string then in this case you need to check that the tail of the string contains only white space characters.如果要接受这样的字符串,那么在这种情况下,您需要检查字符串的尾部是否只包含空白字符。

You should attentively read the description of the function strtol .您应该仔细阅读 function strtol的描述。

aoti() is useful for quick and dirty code but not up to the task for robust error handling. aoti()对于快速和肮脏的代码很有用,但不能胜任强大的错误处理任务。

Non-integer characters after the integer, as in "1aaaabcc" is best detected with strtol() . integer 之后的非整数字符,如"1aaaabcc"中的字符,最好使用strtol()检测。

With strtol() , we can detect more.使用strtol() ,我们可以检测到更多。

  1. Out of range for an int like "12345678901234567890" , but not the same length "00000000000000000001" .超出了像"12345678901234567890"这样的int的范围,但不是相同长度的"00000000000000000001"

  2. Allow non-integer characters after the integer when text is all white-space.当文本全部为空白时,允许在 integer 之后使用非整数字符。 This is reasonable as strtol()/atoi() accept optional leading white-space.这是合理的,因为strtol()/atoi()接受可选的前导空白。 It also allows passing an entire line of input like "1234\n" .它还允许传递整输入,例如"1234\n"

  3. No conversion as in "asd" , " " , "" .没有像"asd"" """那样的转换。

I recommend a helper function我推荐一个帮手 function

// Return true on success    
bool convert_string_to_int(int *dest, const char *s) {
  errno = 0;
  char *endptr;  // Gets updated to point to the end of the conversion.
  long lvlaue = strtol(s, &endptr, 0);
  if (s == endptr) {
    *dest = 0;
    return false;  // No conversion
  }
  if (errno == ERANGE || lvalue < INT_MIN || lvalue > INT_MAX) {
    errno = ERANGE;
    *dest = lvalue < 0 ? INT_MIN : INT_MAX; 
    return false;  // Out of range.
  }
  *dest = (int) lvalue;
  if (errno) {
    return false;  // Implementation specific errors like s == NULL
  }
  while (isspace(*((unsigned char *)endptr))) {
    endptr++;
  }
  if (*endptr) {
    return false;  // Junk at the end.
  }
  return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM