簡體   English   中英

std::stoi 是如何實現的?

[英]How is std::stoi implemented?

大多數日常用例已經轉換為標准庫中可用的函數。 但是,我想知道其中一些是如何在幕后工作的。 比如std::stoi背后的實際代碼是什么?

最直接的方法是調用適當的 C 函數,在本例中為strtol ,檢查發生了什么,如果失敗則拋出適當的異常,然后返回結果。

我想知道他們中的一些人是如何在幕后工作的。 就像 std::stoi 背后的實際代碼是什么?

我認為您可以通過類似以下的搜索找到“實際”代碼:

  • 在 Ubuntu 上,我的 makefile 創建了一個 .depends 文件,其中包含:

    g++-5 -m64 -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon- virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual -O0 -M *.cc > .depends

    (我嘗試使該命令的編譯器選項與我的正常編譯相匹配。)

  • 在瀏覽器中,我查看

    http://en.cppreference.com/w/cpp/string/basic_string/stol

    確定

    std::stoi 包含在 std::basic_string 中(在頁面頂部)

  • 在我的編輯器中,(或)使用 grep,我在 .depends 文件中搜索“basic_string”

    grep --color -nH -e "basic_string" .depends

    grep 在我當前的依賴文件中報告字符串 214 次,當我更改代碼時它會改變大小。

    一份報告的例子:

    .depends:14105: /usr/include/c++/5/bits/basic_string.h \

  • 在我的編輯器中,我打開指定的文件

    "/usr/include/c++/5/bits/basic_string.h",

    然后搜索“stoi”,它似乎只存在兩次。

    這表示編譯器的 v5。

我認為您應該能夠在您的系統上進行類似的搜索。

祝你好運。

它是對strtoi的引用,但我假設您想要一個關於它如何工作的實際解釋。 其實很簡單。 腳步:

  1. 查找最大乘數 (exp(base, strlen(number)-1)
  2. 在字符串上運行 for 循環並將其乘以乘數
  3. 每次迭代將乘數除以基數

strtoi在 C 中的實現:

#include <string.h>

int ipow(int base, int exp)
{
    int result = 1;
    for (;;)
    {
        if (exp & 1)
            result *= base;
        exp >>= 1;
        if (!exp)
            break;
        base *= base;
    }

    return result;
}

int charToDigit(char ch) {
    switch (ch) {
        case '0':
            return 0;
            break;
       case '1':
            return 1;
            break;
        case '2':
            return 2;
            break;
        case '3':
            return 3;
            break;
        case '4':
            return 4;
            break;
        case '5':
            return 5;
            break;
        case '6':
            return 6;
            break;
        case '7':
            return 7;
            break;
        case '8':
            return 8;
            break;
        case '9':
            return 9;
            break;
        default:
            throw "0-9";
            break;
    }
};

int stoi(const char* string) {
    int basenum = 0;
    int pos = ipow(10, strlen(string)-1);
    const int len = strlen(string);

    // first is biggest, pos
    for (int i = 0; i<len; i++) {
        basenum += charToDigit(string[i])*pos;
        pos /= 10;
    };
    return basenum;
};

要轉換一個字符串(假設它的所有字符都是從 0 到 9 的整數):

  1. 您必須獲得字符串的長度。
  2. 遍歷字符串(您選擇向前或向后)並將每個冪添加到結果變量。

我將從一個乘數變量和一個結果變量開始: int multiplier = 1, result = 0 ,然后我將使用std::string::length函數獲取字符串長度。 通過字符串向后循環,我會將每個元素乘以乘數並將其添加到結果中。 請確保當您訪問 char 時,您應該減去 char 0 的 ASCII 值。這可以通過減去 48 來完成,或者如果您不想查找 ASCII 值,您可以將 0 包含在單個括號。 例如,如果您不執行從 char 到 int 的轉換,那么訪問字符“1”將導致程序讀取 49,這是不好的。 至於乘數,在循環的每次迭代結束時將其乘以 10。

我從后面迭代的原因是為了避免使用使用 double/float 的 pow() 函數。 我覺得它更簡單,但這是你的選擇。 當然,您也可以通過手動循環乘以 10 與字符串長度相同的次數來避免 pow(),但這樣效率會低一些。

這是一個可以使用的簡單實現:

#include <string>
#include <iostream>

int stoi(std::string s) {
  int multiplier = 1, result = 0;
  for (int i = s.length() - 1; i >= 0; i--) {
    result += multiplier * (s[i] - '0');
    multiplier *= 10;
  }
  return result;
}

int main() {
  std::cout << stoi("1235") + 1;
  return 0;
}

如果你運行這個程序,它應該輸出 1236,因為字符串“1235”已經被轉換成一個整數。

當然,這只是我自己的實現; 如果您想要官方的,那么本文包含一些相關信息。

暫無
暫無

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

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