std :: stringをintに変換するにはどうすればよいですか?


484

簡単な質問をしてください。私はインターネットをかなり調べましたが、いくつかの解決策を見つけましたが、どれもまだ機能していません。文字列をintに変換することを見ていて、ASCIIコードを意味しているわけではありません。

簡単に説明すると、方程式に文字列として渡されます。それを分解し、正しくフォーマットし、線形方程式を解きます。さて、と言って、文字列をintに変換することはできません。

文字列が(-5)または(25)などの形式になることを知っているので、それは間違いなくintです。しかし、文字列からそれをどのように抽出しますか?

私が考えていた1つの方法は、文字列をfor / whileループで実行し、数字を確認し、その後にすべての数字を抽出してから、先頭に「-」があるかどうかを確認し、ある場合は、intを-倍します1。

ただし、このような小さな問題では少し複雑に見えます。何か案は?


9
試しましたatoi()か?
i_am_jorf



7
@チャドでは、言語が標準ライブラリで実行できることのために、ライブラリ全体を使用することをお勧めしますか?
ボジャングル、2011年

6
@ブランドン、あなたが持っていてstd::string myString、使いたいなら、あなたはatoi言いたいですatoi(myString.c_str())
Robᵩ

回答:


726

C ++ 11にはstd::string、数値型への新しい変換関数がいくつかあります。

だから代わりに

atoi( str.c_str() )

あなたは使うことができます

std::stoi( str )

どこstrあなたの番号は通りですstd::string

数字のすべての種類のバージョンがあります: long stol(string)float stof(string)double stod(string)、...参照http://en.cppreference.com/w/cpp/string/basic_string/stol


5
std :: stoiの問題については、stackoverflow.com / "11x"a / 6154614/195527を参照してください11。整数に変換されます。
CC。

5
#include <stdlib.h> / * atoi * /
Ulad Kasach

4
また、税引後営業利益の行動だ@CC:cplusplus.com/reference/cstdlib/atoi「文字列は無視される整数を、形成するものの後に追加の文字が含まれており、この関数の動作に影響を与えないことができます。」
Tin Wizard

4
from_charsC ++ 17からこの回答を更新していただけませんか?それは桁違いに速いはずですstoi
NathanOliver

stoi優先する必要があります。atoi()を使用すべきではない理由を
phuclv

57
std::istringstream ss(thestring);
ss >> thevalue;

完全に修正するには、エラーフラグを確認する必要があります。


2
これは-5から抽出されません(-5)
Nawaz、2011年

@Nawaz、かっこは実際にそこにありますか、それともOPが文字列を提示する方法ですか?
Winston Ewert、2011年

知りません。私はアプローチの限界を指摘しているだけです。
Nawaz、2011年

16
@Nawaz、「WERWER」入力に対しても操作できません。かっこが実際に彼の実際の文字列の一部であるとは思いません。また、かっこを解析しないという事実が関連しているとは思いません。
Winston Ewert、2011年

4
@Nawaz、わかりました...私はその言葉をそのように取らないが、私はあなたがどのようにできるかを見ます。
Winston Ewert

44

可能なオプションは次のとおりです。

1.最初のオプション:sscanf()

    #include <cstdio>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        if(sscanf(str.c_str(), "%d", &i) != 1)
            // error management

        // string -> float
        if(sscanf(str.c_str(), "%f", &f) != 1)
            // error management

        // string -> double 
        if(sscanf(str.c_str(), "%lf", &d) != 1)
            // error management

これはエラーです(cppcheckでも表示されます)。「フィールド幅の制限のないscanfは、libcの一部のバージョンで巨大な入力データを使用するとクラッシュする可能性があります」ここここを参照)。

2. 2番目のオプション:std :: sto *()

    #include <iostream>
    #include <string>

        int i;
        float f;
        double d;
        std::string str;

        try {
            // string -> integer
            int i = std::stoi(str);

            // string -> float
            float f = std::stof(str);

            // string -> double 
            double d = std::stod(str);
        } catch (...) {
            // error management
        }   

このソリューションは短くエレガントですが、C ++ 11準拠のコンパイラでのみ使用できます。

3. 3番目のオプション:sstreams

    #include <string>
    #include <sstream>

        int i;
        float f;
        double d;
        std::string str;

        // string -> integer
        std::istringstream ( str ) >> i;

        // string -> float
        std::istringstream ( str ) >> f;

        // string -> double 
        std::istringstream ( str ) >> d;

        // error management ??

ただし、このソリューションでは、不適切な入力を区別することは困難です(参照 ここを)。

4. 4番目のオプション:Boostのlexical_cast

    #include <boost/lexical_cast.hpp>
    #include <string>

        std::string str;

        try {
            int i = boost::lexical_cast<int>( str.c_str());
            float f = boost::lexical_cast<int>( str.c_str());
            double d = boost::lexical_cast<int>( str.c_str());
            } catch( boost::bad_lexical_cast const& ) {
                // Error management
        }

ただし、これはのラッパーにすぎsstreamず、ドキュメントではsstreamエラー管理を改善ため(ここを参照)。

5. 5番目のオプション:strto *()

エラー管理のため、このソリューションは非常に長く、ここで説明します。プレーンなintを返す関数はないため、整数の場合は変換が必要です(参照)この変換を行う方法こちらを)。

6. 6番目のオプション:Qt

    #include <QString>
    #include <string>

        bool ok;
        std::string;

        int i = QString::fromStdString(str).toInt(&ok);
        if (!ok)
            // Error management

        float f = QString::fromStdString(str).toFloat(&ok);
        if (!ok)
            // Error management 

        double d = QString::fromStdString(str).toDouble(&ok);
        if (!ok)
    // Error management     

結論

要約すると、最良のソリューションはC ++ 11、std::stoi()または2番目のオプションとしてQtライブラリの使用です。他のすべての解決策は、推奨されないか、バグがあります。


修繕。ご報告いただきありがとうございます。
クラウディオ

美しい要約、多くの感謝。詳細に関心がある人だけが読み続けることができるように、最終的な解決策を提案する最初のコメントを追加することを提案できますか?
luca

1
これは受け入れられた回答である必要があります。また、忘れた(または古い回答である原因を追加する必要があります)from_chars
xception


9

何についてBoost.Lexical_cast

以下がその例です。

次の例では、コマンドライン引数を一連の数値データとして扱います。

int main(int argc, char * argv[])
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)
    {
        try
        {
            args.push_back(lexical_cast<short>(*argv));
        }
        catch(bad_lexical_cast &)
        {
            args.push_back(0);
        }
    }
    ...
}

リンクが壊れています。直してもらえますか?
Yuchen Zhong

5

確かに、私の解決策は負の整数では機能しませんが、整数を含む入力テキストからすべての正の整数を抽出します。それはnumeric_onlyロケールを利用します:

int main() {
        int num;
        std::cin.imbue(std::locale(std::locale(), new numeric_only()));
        while ( std::cin >> num)
             std::cout << num << std::endl;
        return 0;
}

入力テキスト:

 the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878

出力整数:

 5
25
7987
78
9878

クラスnumeric_onlyは次のように定義されます。

struct numeric_only: std::ctype<char> 
{
    numeric_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
        return &rc[0];
    }
};

完全なオンラインデモ:http : //ideone.com/dRWSj


4

それはおそらく少しやり過ぎですが boost::lexical_cast<int>( theString )、仕事にはかなりうまくいくはずです。


タイプミス。単純にすべきですboost::lexical_cast<int>( theString )theStringは変換したい文字列を含む変数の名前ですint)。
James Kanze、2011年


1

Windowsでは、以下を使用できます。

const std::wstring hex = L"0x13";
const std::wstring dec = L"19";

int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
    std::cout << ret << "\n";
}

strtolstringstream16進数を解釈する必要がある場合は、ベースを指定する必要があります。


1

まあ、たくさんの答え、たくさんの可能性。ここで欠けているのは、文字列を異なるC ++整数型(short、int、long、boolなど)に変換するいくつかのユニバーサルメソッドです。私は次の解決策を思いつきました:

#include<sstream>
#include<exception>
#include<string>
#include<type_traits>

using namespace std;

template<typename T>
T toIntegralType(const string &str) {
    static_assert(is_integral<T>::value, "Integral type required.");
    T ret;
    stringstream ss(str);
    ss >> ret;
    if ( to_string(ret) != str)
        throw invalid_argument("Can't convert " + str);
    return ret;
}

次に使用例を示します。

string str = "123";
int x = toIntegralType<int>(str); // x = 123

str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int

str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception

stringstream出力演算子を使用して文字列を整数型に変換しないのはなぜですか?ここに答えがあります:文字列に、意図した整数型の制限を超える値が含まれているとしましょう。たとえば、Wndows 64では、max intは2147483647です。文字列に値max int + 1を割り当ててみましょう:string str = "2147483648"。今、文字列をintに変換するとき:

stringstream ss(str);
int x;
ss >> x;

xは2147483647になります。これは間違いなくエラーです。文字列 "2147483648"はint 2147483647に変換されるはずではありませんでした。提供されている関数toIntegralTypeは、そのようなエラーを検出して例外をスローします。


0

http://www.cplusplus.com/reference/string/stoi/から

// stoi example
#include <iostream>   // std::cout
#include <string>     // std::string, std::stoi

int main ()
{
  std::string str_dec = "2001, A Space Odyssey";
  std::string str_hex = "40c3";
  std::string str_bin = "-10010110001";
  std::string str_auto = "0x7f";

  std::string::size_type sz;   // alias of size_t

  int i_dec = std::stoi (str_dec,&sz);
  int i_hex = std::stoi (str_hex,nullptr,16);
  int i_bin = std::stoi (str_bin,nullptr,2);
  int i_auto = std::stoi (str_auto,nullptr,0);

  std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
  std::cout << str_hex << ": " << i_hex << '\n';
  std::cout << str_bin << ": " << i_bin << '\n';
  std::cout << str_auto << ": " << i_auto << '\n';

  return 0;
}

出力:

2001、宇宙オデッセイ:2001年と[宇宙オデッセイ]

40c3:16579

-10010110001:-1201

0x7f:127


0

私のコード:

#include <iostream>
using namespace std;

int main()
{
    string s="32";  //String
    int n=stoi(s);  //Convert to int
    cout << n + 1 << endl;

    return 0;
}

0
ll toll(string a){
    ll ret=0;
    bool minus=false;
    for(auto i:a){
        if(i=='-'){ minus=true; continue; }
        ret*=10;
        ret+=(i-'0');
    } if(minus) ret*=-1;
    return ret;
    # ll is defined as, #define ll long long int
    # usage: ll a = toll(string("-1234"));
}

0

文字列表現から整数値に変換するには、std :: stringstreamを使用できます。

変換された値が整数データ型の範囲外の場合、INT_MINまたはINT_MAXを返します。

また、文字列値が有効なintデータ型として表現できない場合、0が返されます。

#include 
#include 
#include 

int main() {

    std::string x = "50";
    int y;
    std::istringstream(x) >> y;
    std::cout << y << '\n';
    return 0;
}

出力:50

上記の出力に従って、文字列番号から整数に変換されたことがわかります。

文字列のソースおよびその他のint c ++


-2

1行バージョン: long n = strtol(s.c_str(), NULL, base);

s文字列であり、baseであるintような2、8、10、16)

の詳細については、このリンクを参照してくださいstrtol


核となるアイデアはstrtol、に含まれている関数を使用することcstdlibです。

以来strtolの唯一のハンドルchar配列、我々は変換する必要があるstringchar配列。このリンクを参照してください

例:

#include <iostream>
#include <string>   // string type
#include <bitset>   // bitset type used in the output

int main(){
    s = "1111000001011010";
    long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string

    cout << s << endl;
    cout << t << endl;
    cout << hex << t << endl;
    cout << bitset<16> (t) << endl;

    return 0;
}

出力されます:

1111000001011010
61530
f05a
1111000001011010

-3

別の簡単な方法があります:次のようなキャラクターがあるとします c='4'あります。次の手順のいずれかを実行できるます。

1番目:int q

q=(int) c ; (q is now 52 in ascii table ) . q=q-48; remember that adding 48 to digits is their ascii code .

2番目の方法:

q=c-'0'; the same , character '0' means 48


1
問題は、からstringintではなく、からcharに変換することstringです。
Yuchen Zhong 2014

バギーで質問に一致しない
caoanan 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.