Doar o întrebare rapidă. Am'am cautat pe internet destul de un pic și m-am'am găsit câteva soluții, dar niciunul dintre ei nu au lucrat încă. Se uită la conversia unui șir la un int și eu nu't înseamnă coduri ASCII.
Pentru o privire de-a alerga în jos, am trecut într-o ecuație ca un șir de caractere. Am să-l rupe în jos, în format corect și de a rezolva ecuații liniare. Acum, în a spune că, am'm nu este capabil de a converti un string la un int.
Știu că șirul va fi în orice format (-5) sau (25) etc. deci's cu siguranta un int. Dar cum putem extrage dintr-un șir?
Un fel mă gândeam se execută o pentru/în timp ce bucla prin șir, verificați pentru o cifră, extract de toate cifrele după aceea și apoi uita-te pentru a vedea dacă există un lider '-', dacă nu există, se înmulțește int cu -1.
Se pare un pic complicata pentru astfel de o mică problemă totuși. Orice idei?
În C++11 există unele noi frumos converti funcții de std::string la un tip de număr.
Deci, în loc de
atoi( str.c_str() )
puteți utiliza
std::stoi( str )
unde str
este ca std::string
.
Există versiuni pentru toate arome de numere:
mult stol(string),
float stof(string)", " dublu stod(string)`,...
a se vedea http://en.cppreference.com/w/cpp/string/basic_string/stol
Opțiunile posibile sunt descrise mai jos:
1. Prima opțiune: 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
Aceasta este o eroare (de asemenea, demonstrat de cppcheck) pentru că "scanf fără lățime câmp limite poate prăbuși cu mare date de intrare pe unele versiuni de libc" (a se vedea aici, aici).
*2. A doua opțiune: 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
}
Această soluție este scurt și elegant, dar este disponibil numai pe la C++11 compliants compilatoare.
3. A treia opțiune: 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 ??
Cu toate acestea, cu această soluție este greu să se facă distincția între rău de intrare (a se vedea aici).
4. Patra opțiune: 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
}
Cu toate acestea, aceasta este doar un înveliș de sstream, și documentația sugerează să utilizați sstrem pentru o mai bună gestionare a erorilor (a se vedea aici).
*5. Cincea opțiune: strto()**
Această soluție este foarte lung, din cauza unei erori de management, și este descris aici. Deoarece nici o funcție returnează un simplu int, o conversie este necesară în caz de număr întreg (a se vedea aici pentru modul în care această conversie poate fi atins).
6. A șasea opțiune: 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
Concluzii
Rezumând, cea mai bună soluție este C++11 std::stoi() sau, ca o a doua opțiune, utilizarea de biblioteci Qt. Toate celelalte soluții sunt descurajați sau buggy.
Ce zici de Boost.Lexical_cast?
Aici este exemplul lor:
exemplul următor tratează argumente în linia de comandă ca o secvență de date numerice:
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);
}
}
...
}
Desigur, soluția mea ar't de lucru pentru numere întregi negative, dar va extrage toate numere întregi pozitive de la intrare text care conține numere întregi. Se face uz de 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;
}
De introducere a textului:
the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
De ieșire numere întregi:
5
25
7987
78
9878
Clasa numeric_only
este definit ca:
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];
}
};
Completați demo on-line : http://ideone.com/dRWSj
L's, probabil, un pic exagerat, dar
boost::lexical_cast<int>( theString )
ar trebui la treaba
destul de bine.
Din 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;
}
Ieșire:
2001, Odiseea Spațială: 2001 și [, O Odisee Spațiu]
40c3: 16579
-10010110001: -1201
0x7f: 127
În Windows, ai putea folosi:
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
trebuie să specificați dacă aveți nevoie pentru a interpreta hexdecimal.
Ei bine, mulțime de răspunsuri, mulțime de posibilități. Ce îmi lipsește aici este o metodă universală, care convertește un șir de caractere diferite C++ integrantă tipuri (short, int, long, bool, ...). Am venit cu următoarea soluție:
#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;
}
Aici sunt exemple de utilizare:
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
De ce nu folosim doar stringstream ieșire operator pentru a converti un șir de caractere într-o integrală de tip? Aici este raspunsul: Las's spun un șir conține o valoare care depășește limita prevăzută de tip integral. Pentru examle, pe Wndows 64 max int este de 2147483647. Las's atribuie un șir o valoare max int + 1: string str = "2147483648". Acum, când se face conversia de la string la un int:
stringstream ss(str);
int x;
ss >> x;
x devine 2147483647, ceea ce este cu siguranta o eroare: string "2147483648" nu trebuia să fie convertite la int 2147483647. Funcția dată toIntegralType pete de astfel de erori și aruncă excepție.
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"));
}
O linie versiune: long n = strtol(s.c_str(), NULL, baza);` .
("s" este șirul, și "de bază" este un int
, cum ar fi 2, 8, 10, 16.)
Puteți consulta acest link pentru mai multe detalii strtol`.
Ideea de bază este de a utiliza [strtol
](http://www.cplusplus.com/reference/cstdlib/strtol/ funcția), care este inclus în cstdlib
.
Din strtol
se ocupă numai cu char
matrice, avem nevoie pentru a converti "string" a char
matrice. Puteți consulta acest link.
Un exemplu:
#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;
}
care va ieșire:
1111000001011010
61530
f05a
1111000001011010
nu există un alt mod simplu : să presupunem că aveți un personaj ca c='4'
prin urmare, puteți face unul dintre acești pași :
1 : int q
q=(int) c ; (q este acum 52 în tabelul ascii ) . q=q-48; amintiți-vă că adăugarea de 48 de cifre este codul ascii .
al doilea mod :
q=c-'0'; la fel , caracterul '0' înseamnă 48