Подтвердить что ты не робот

Как работает atoi() на С++?

Итак... Я знаю, что функция atoi в стандартной библиотеке С++ должна преобразовывать строку в целое число... как это работает?... (Я пытаюсь изучить материал, и я был просто интересно)... если бы вы могли показать мне код из него или сделать свой собственный, который будет выполнять ту же задачу, это было бы очень полезно... спасибо заранее.

4b9b3361

Ответ 1

Что-то вроде этого:

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), результатом будет undefined.

Ответ 2

Цифры по цифре:

A char *, строго говоря, является указателем на a char. Указатель - это просто адрес в какое-то место в памяти. В C/С++ (и Java) строки состоят из символов, которые могут индивидуально рассматриваться как целые числа (обычно один байт), благодаря ASCII.

В C (и С++) указатель на элемент некоторого типа такой же, как указатель на массив элементов этого типа. Строки в чистом C - это просто массивы char s, с '\0' (NUL) в конце, чтобы вы знали, когда попадете в конец строки, не обойдя всю ее длину (указатель только адрес, он ничего не знает о том, на что он указывает).

Игнорировать ключевые слова const.

Версия C atoi выполняет цикл каждого символа в строке. *str++ делает несколько вещей (важно понять, как это работает, но это ужасный способ писать C). Это эквивалентно *(str++). str++ возвращает значение str (указатель), а затем увеличивает его на единицу (но возвращает старое значение!). * "разыгрывает" указатель, в основном читающий в char из памяти. Этот char хранится в digit, а затем сравнивается с NUL. Символы хранятся в ASCII, который представляет цифры смежно, поэтому мы можем просто проверить, что digit находится между 0 и 9. Мы знаем теперь, что мы читаем новую цифру, поэтому мы умножаем предыдущее значение на 10 на "сдвиг" "значение над, а затем добавить в цифру.

Версия Pure 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;
}

Строка С++ - это объект, облегчающий работу со строками. Вы можете получить char * из строки С++ с помощью .c_str().

Версия на С++ (скорее всего, встроенный вызов версии char * с "return atoi (str.c_str());" ):

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;
}

Изменить: Исправлена ​​проблема, когда < > не отображалась должным образом.

Изменить: Добавлена ​​версия строки в С++

Изменить: Исправлено, так что он возвращает 123 в 123a случае.

Изменить: Изменено число без изменений в версии С++

Ответ 3

Поверните вопрос: как вы это делаете? Когда вы видите "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
...

Ну, вы можете это исправить.


На самом деле это часто реализуется с самого правого персонажа для удобного использования с потоками. Как вы можете это сделать?

Ответ 5

Мы используем atoi() для преобразования числовой строки в свое целочисленное значение. Это функция библиотеки c. Он принимает строку в качестве аргумента и возвращает целое значение.

В приведенном ниже примере я описываю метод для реализации собственной функции atoi.

#include<stdio.h>
#include<stdint.h>

/*Macro to check numeric character*/
#define Is_NUMERIC_STRING(d) (*(char*)d >= 48) && (*(char*)d<= 57)


uint32_t
StringToInt(const char *pszBuffer) {

uint32_t u32Number=0;

while( Is_NUMERIC_STRING(pszBuffer)) { //Loop terminate When alphabetic character occur.     

u32Number=(u32Number*10)+ (*pszBuffer-48);
pszBuffer++;
}

return u32Number;
}

int main() {
uint32_t d;

d=StringToInt("1230");

printf("%u\n",d);

return 0;
}

Для получения дополнительной информации вы можете увидеть эту ссылку: http://www.aticleworld.com/

Note: This code is only for the string whose value within the range of integer.

Ответ 6

В основном, вычитая 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;
}

Ответ 7

Здесь реализована реализация, которая также проверяет условия ошибки и работает для любых целых типов.

#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;
}