簡體   English   中英

at ++()函數在C ++中是如何工作的?

[英]How does atoi() function in C++ work?

所以...我知道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值中減去ascii值'0'來完成的。

請注意,此代碼不處理溢出。 如果傳入“887452834572834928347578423485273”(不適合int ),則結果未定義。

數字:

嚴格來說, char *是指向char的指針。 指針只是內存中某個地方的地址。 在C / C ++(和Java)中,字符串由字符組成,這些字符可以單獨地被視為整數(通常是一個字節),這要歸功於ASCII

在C(和C ++)中,指向某種類型的項的指針與指向該類型的元素數組的指針相同。 純C中的字符串只是char的數組,末尾有一個'\\0' (NUL),這樣你就可以知道你何時到達字符串的末尾而不必在任何地方傳遞它的長度(指針只是一個地址,它對它指向的內容一無所知

暫時忽略const關鍵字。

atoi的C版本循環遍歷字符串中的每個字符。 *str++做了幾件事(了解它是如何工作的很重要,但實際編寫C是一種可怕的方式)。 它相當於*(str++) str++返回str (指針)的值,然后將其遞增1(但它返回值!)。 * “取消引用”指針,基本上從內存中讀取一個char char存儲在digit ,然后與NUL進行比較。 字符以ASCII格式存儲,它連續表示數字,因此我們可以檢查該digit是否在0到9之間。我們現在知道我們正在讀取一個新數字,所以我們將前一個值乘以10來“移位”超過然后加上數字。

純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 ++版本中將stray num更改為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#中的表現。 同樣的一般想法。

這是一個實現,它還檢查錯誤條件並適用於任何整數類型。

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

基本上通過減去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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM