Hab einfach eine kurze Frage. Ich habe mich ein bisschen im Internet umgesehen und ein paar Lösungen gefunden, aber noch keine davon hat funktioniert. Beim Konvertieren einer Zeichenfolge in ein int und ich meine nicht ASCII - Codes.
Für einen schnellen Ablauf werden wir in einer Gleichung als String übergeben. Wir müssen es aufschlüsseln, richtig formatieren und die linearen Gleichungen lösen. Wenn ich das sage, kann ich eine Zeichenfolge nicht in eine int konvertieren.
Ich weiß, dass der String entweder das Format (-5) oder (25) usw. haben wird, also ist es definitiv ein int. Aber wie extrahieren wir das aus einer Zeichenfolge?
Eine Möglichkeit, über die ich nachgedacht habe, ist, eine for/while-Schleife durch die Zeichenfolge zu führen, nach einer Ziffer zu suchen, alle Ziffern danach zu extrahieren und dann zu sehen, ob es ein führendes '-' gab, falls vorhanden, das int mit multiplizieren. 1.
Für ein so kleines Problem erscheint es jedoch etwas kompliziert. Irgendwelche Ideen?
In C++ 11 gibt es einige nette neue Konvertierungsfunktionen von std::string
in einen Zahlentyp.
Also statt
atoi( str.c_str() )
sie können verwenden
std::stoi( str )
dabei ist str
Ihre Nummer als std::string
.
Es gibt Versionen für alle Arten von Zahlen: long stol(string)
, float stof(string)
, double stod(string)
, ... Siehe http://en.cppreference.com/w/cpp/string/basic_string/stol
std::istringstream ss(thestring);
ss >> thevalue;
Um vollständig korrekt zu sein, sollten Sie die Fehlerflags überprüfen.
verwenden Sie die Funktion atoi, um die Zeichenfolge in eine Ganzzahl zu konvertieren:
string a = "25";
int b = atoi(a.c_str());
Die möglichen Optionen werden nachfolgend beschrieben:
1. Erste Option: 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
Dies ist ein Fehler (wird auch von cppcheck angezeigt), da "scanf ohne Feldbreitenbegrenzungen kann bei einigen libc-Versionen mit großen Eingabedaten abstürzen" (siehe hier und hier ) .
2. Zweite Option: std :: sto * ()
#include <iostream>
#include <string>
int i;
float f;
double d;
std::string str;
try {
// string -> integer
int i = std::stoi(s);
// string -> float
float f = std::stof(s);
// string -> double
double d = std::stod(s);
} catch (...) {
// error management
}
Diese Lösung ist kurz und elegant, sie ist jedoch nur auf C++ 11-Compliants-Compilern verfügbar.
3. Dritte Option: 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 ??
Bei dieser Lösung ist es jedoch schwierig, zwischen fehlerhaften Eingaben zu unterscheiden (siehe hier ).
4. Vierte Option: Boost's 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
}
Dies ist jedoch nur ein Wrapper von sstream, und die Dokumentation schlägt vor, sstrem für ein besseres Fehlermanagement zu verwenden (siehe hier ).
5. Fünfte Option: strto * ()
Diese Lösung ist aufgrund der Fehlerverwaltung sehr lang und wird hier beschrieben. Da keine Funktion ein einfaches int zurückgibt, ist bei Integer eine Konvertierung erforderlich (siehe hier , wie diese Konvertierung erreicht werden kann).
6. Sechste Option: 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
Schlussfolgerungen
Zusammenfassend ist die beste Lösung C++ 11 std :: stoi () oder als zweite Option die Verwendung von Qt-Bibliotheken. Alle anderen Lösungen sind entmutigt oder fehlerhaft.
Was ist mit Boost.Lexical_cast ?
Hier ist ihr Beispiel:
Im folgenden Beispiel werden Befehlszeilenargumente als Folge numerischer Daten behandelt:
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);
}
}
...
}
Zugegeben, meine Lösung würde nicht für negative Ganzzahlen funktionieren, aber sie extrahiert alle positiven Ganzzahlen aus Eingabetext, der Ganzzahlen enthält. Es verwendet numeric_only
locale:
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;
}
Eingabetext:
the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
Ausgabezahlen:
5
25
7987
78
9878
Die Klasse numeric_only
ist definiert als:
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];
}
};
Vollständige Online-Demo: http://ideone.com/dRWSj
Es ist wahrscheinlich ein bisschen übertrieben, aber boost::lexical_cast<int>( theString )
sollte den Job Ziemlich gut.
In Windows können Sie Folgendes verwenden:
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";
}
strtol
, stringstream
muss die Basis angeben, wenn Sie Hexdecimal interpretieren müssen.
atoi
ist eine integrierte Funktion, die eine Zeichenfolge in eine Ganzzahl konvertiert, vorausgesetzt, die Zeichenfolge beginnt mit einer Ganzzahlendarstellung.
Mein Code:
#include <iostream>
using namespace std;
int main()
{
string s="32"; //String
int n=stoi(s); //Convert to int
cout << n + 1 << endl;
return 0;
}
Nun, viele Antworten, viele Möglichkeiten. Was mir fehlt, ist eine universelle Methode, die eine Zeichenfolge in verschiedene C++ - Integraltypen konvertiert (short, int, long, bool, ...) ... und ich habe folgende Lösung gefunden:
#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;
}
Hier sind Beispiele für die Verwendung:
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
Warum nicht einfach den Stringstream-Ausgabeoperator verwenden, um eine Zeichenfolge in einen Integraltyp zu konvertieren? Hier ist die Antwort: Angenommen, eine Zeichenfolge enthält einen Wert, der die Grenze für den beabsichtigten Integraltyp überschreitet. Zum Beispiel ist auf Wndows 64 max int 2147483647 . Ordnen wir einem String einen Wert max int + 1 zu: string str = "2147483648". Wenn Sie nun den String in ein int konvertieren:
stringstream ss(str);
int x;
ss >> x;
x wird zu 2147483647, was definitiv ein Fehler ist: Die Zeichenfolge "2147483648" sollte nicht in das int 2147483647 konvertiert werden. Die bereitgestellte Funktion toIntegralType erkennt solche Fehler und löst eine Ausnahme aus.
Von 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;
}
Ausgabe:
2001, Eine Weltraum-Odyssee: 2001 und [ Eine Weltraum-Odyssee]
40c3: 16579
-10010110001: -1201
0x7f: 127
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"));
}
Einzeilige Version: long n = strtol(s.c_str(), NULL, base);
.
(s
ist die Zeichenfolge und base
ist eine int
, z. B. 2, 8, 10, 16.)
Unter diesem Link finden Sie weitere Details zu strtol
.
Die Grundidee ist die Verwendung von strtol
function, die in cstdlib
enthalten ist.
Da strtol
nur mit char
-Array verarbeitet, müssen wir string
in char
-Array konvertieren. Sie können auf diesen Link verweisen.
Ein Beispiel:
#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;
}
welche ausgegeben werden:
1111000001011010
61530
f05a
1111000001011010