atoi在C ++中如何工作?

问题描述

| 所以...我知道C ++标准库中的atoi函数应该将字符串转换为整数...它是如何工作的?...(我正在尝试学习东西,我只是想知道) ...如果您可以向我展示其中的代码,或者自己编写完成相同任务的代码,将不胜感激... ...预先感谢。

解决方法

像这样:
int atoi( const char *c ) {
    int value = 0;
    int sign = 1;
    if( *c == \'+\' || *c == \'-\' ) {
       if( *c == \'-\' ) sign = -1;
       c++;
    }
    while ( isdigit( *c ) ) {
        value *= 10;
        value += (int) (*c-\'0\');
        c++;
    }
    return value * sign;
}
您可以遍历字符串中的字符,只要它们是数字即可。对于每个计数器,将其添加到要保留的计数器中-要添加的值是字符的整数值。这是通过从相关数字的ascii值中减去\'0 \'的ascii值来完成的。 请注意,此代码不处理溢出。如果您传入\“ 887452834572834928347578423485273 \”(不适合
int
),则结果不确定。,一位数字: 严格来讲,
char *
是指向
char
的指针。指针只是内存中某个位置的地址。在C / C ++(和Java)中,字符串由字符组成,由于使用了ASCII,因此可以将它们分别视为整数(通常为一个字节)。 在C(和C ++)中,指向某种类型的项的指针与指向该类型的元素数组的指针相同。纯C中的字符串只是
char
的数组,结尾是
\'\\0\'
(NUL),这样您就知道何时到达字符串的末尾而不必在各处传递其长度(指针只是一个地址,它对其指向的内容一无所知)。 现在忽略
const
关键字。 version7ѭ的C版本遍历字符串中的每个字符。
*str++
做几件事(了解它的工作原理很重要,但这是实际编写C的一种可怕方法)。相当于ѭ9。
str++
返回
str
(指针)的值,然后将其递增1(但它返回旧值!)。
*
“取消引用”指针,基本上从内存中读取basically3ѭ。
char
存储在
digit
中,然后与
NUL
进行比较。字符以ASCII形式存储,它连续表示数字,因此我们只需检查ѭ150在0到9之间即可。我们现在知道我们正在读取一个新数字,因此我们将先前的值乘以10即可得出“ shift” \“值结束,然后添加数字。 纯C版本:
int atoi(const char* str) {
  int num = 0;
  char digit;
  while ((digit = *str++) != \'\\0\') {
    if (digit < \'0\' || digit > \'9\') {
      return num;  /* No valid conversion possible */
    }
    num *= 10;
    num += c - \'0\';
  }
  return num;
}
C ++字符串是使处理字符串更容易的对象。您可以从带有
.c_str()
的C ++字符串中获得
char *
。 C ++版本(更可能使用\“ return atoi(str.c_str()); \”内联调用char *版本):
int atoi(const std::string& str) {
  int n = 0;
  for (int i = 0; i < str.size(); i += 1) {
    char digit = str.at(i);   /* Could probably use iterator here,* but this is more explicit. */
    if (digit < \'0\' || digit > \'9\') {
      return n;  /* No valid conversion possible. */
    }
    n *= 10;
    n += digit - \'0\';
  }
  return n;
}
编辑:修复了<>无法正确显示的问题。 编辑:添加了C ++字符串版本 编辑:固定为在
123a
情况下返回123。 编辑:在C ++版本中将杂散数更改为n,扭转问题:您如何做到?当您看到记下“ 31”时,您如何理解需要计数多少X才能等于?
    1 * the value in the leftmost column
+  10 * the value in the next column to the right
+ 100 * the value in the next column to the right
...
好吧,您可以编写代码。 实际上,通常是从最右边的字符实现的,以便于流使用。你会怎么做?,逻辑很简单,就是将每个字符处理成它的整数值(根据字符串中的位置进行调整)。 这是我在C#中所做的事情。大致相同的想法。,基本上是通过减去ASCII零(\'0 \')并检查它是否为数字来实现的。您需要知道职位:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int atoi( const char* nptr )
{
    int result   = 0;
    int position = 1;

    const char* p = nptr;
    while( *p )
    {
        ++p;
    }
    for( --p; p >= nptr; p-- )
    {
        if( *p < 0x30 || *p > 0x39 )
        {
            break;
        }
        else
        {
            result += (position) * (*p - 0x30);
            position *= 10;
        }
    }
    result = ((nptr[0] == \'-\')? -result : result);
    return result;
}

int main()
{
    char buffer[BUFSIZ] = {0};

    printf( \"Enter an integer: \" );
    fgets( buffer,BUFSIZ,stdin );
    buffer[strlen(buffer)-1] = 0;

    printf( \"You entered %d\\n\",atoi( buffer ) );

    return 0;
}
,这是一个实现,还可以检查错误条件并适用于任何整数类型。
#include <limits>
#include <string>
#include <cctype>
#include <cassert>
#include <type_traits>

template<typename TChar,typename TNumber> bool my_atoi(const std::basic_string<TChar>& str,TNumber& result)
{
    typedef std::make_unsigned<TNumber>::type TNumberUnsigned;

    // check if result type is integer
    assert(std::numeric_limits<TNumber>::is_integer);

    auto currChar = str.cbegin();

    // use corresponding unsigned type to accumulate number to avoid overflows for numbers such as -128
    TNumberUnsigned number = 0;

    bool isNegative = *currChar == \'-\';
    if (isNegative) {
        // negative numebers can only be parsed into signed types
        if (!std::numeric_limits<TNumber>::is_signed)
            return false;
        ++currChar;
    }

    // empty string or string containing just - sign are not valid integers
    if (currChar == str.cend())
        return false;

    while (currChar != str.cend()) {
        auto digit = *currChar - \'0\';

        // check that the next digit is valid
        if (digit < 0 || digit > 9)
            return false;

        // check for overflow
        if (number > std::numeric_limits<TNumberUnsigned>::max() / 10)
            return false;
        number *= 10;

        // check for overflow
        if (number > std::numeric_limits<TNumberUnsigned>::max() - digit)
            return false;
        number += digit;

        ++currChar;
    }

    if (isNegative) {
        // correctly check for negative overflow (-128)
        if (number > static_cast<TNumberUnsigned>(std::numeric_limits<TNumber>::max()) + 1)
            return false;

        result = static_cast<TNumber>(-1 * number);
    }
    else {
        if (number > static_cast<TNumberUnsigned>(std::numeric_limits<TNumber>::max()))
            return false;

        result = static_cast<TNumber>(number);
    }

    return true;
}