Remoção não-inteiros de uma string em C ++
-
03-07-2019 - |
Pergunta
Houve um comentário passando em um livro meu sobre pessoas introduzir vírgulas em números inteiros e bagunçar o seu programa, mas não deu mais detalhes. Isso me fez pensar, então eu tentei escrever um pouco algoritmo para tomar uma std :: string e remover todos os caracteres não-inteiros. Este código compila mas ignora mais saída. Por que não é qualquer coisa que está sendo atribuído a NewString? Faz se (isdigit (fstring [i])) avaliar a verdade do endereço ele está apontando para segurar um dígito?
//little algorithm to take the non-integers out of a string
//no idea on efficiency
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter a number with non-integer characters: ";
std::string fstring;
getline(std::cin, fstring);
std::string newstring;
int i = 0, x = 0;
while (i != fstring.length())
{
if (isdigit(fstring[i]))
{
newstring[x] = fstring[i];
i++;
x++;
}
else
{
i++;
}
}
std::cout << std::endl;
std::cout << newstring;
system("PAUSE");
}
questão secundária, que talvez pertence em outros lugares: como você converter uma string para um int (ou um número de ponto flutuante)
Solução
newString é de comprimento 0, de modo NewString [x] em que x = 0 é realmente ilegal. Você deve anexar a string usando: newstring.append (1, fstring [i])
Para a questão secundária, olhar para atoi (), atof (), strtol (0, strtof () funções.
Outras dicas
Cordas são como matrizes, mas o construtor padrão para uma string cria uma cadeia vazia. Por que deveria alocar mais memória do que ele precisa? Mesmo se isso acontecer, não há nenhuma dizendo o quanto, ou se ele vai ser grande o suficiente para uma cópia filtrada da fstring. Estou impressionado que não falha.
Uma modificação simples seria mudar:
std::string newstring;
para:
std::string newstring(fstring.length(), '\0')
E após o add loop:
newstring.resize(x);
Isto irá assegurar que newstring
terá pelo menos o suficiente quarto (provavelmente mais) durante a filtração e serão aparadas para baixo para o tamanho apropriado quando você está filtragem acabado. Você pode também estar interessado na função std::remove_copy_if
em <algorithm>
.
por exemplo.
struct isnotdigit { bool operator()(char c) { return !isdigit(c); } };
std::string newstring(fstring.length(), '\0');
std::string::iterator i = std::remove_copy_if(fstring.begin(),
fstring.end(), newstring.begin(), isnotdigit());
newstring.erase(i, newstring.end());
Como para converter uma string para um inteiro / float, além de atoi
, strtol
, atof
, strtof
, etc. funções já mencionado você também pode fazer uso da biblioteca iostream:
#include <sstream>
std::string integer("23");
std::istringstream iss(integer);
int result;
iss >> result;
std::string floatingpoint("3.14");
std::istringstream iss2(floatingpoint);
double result2;
iss2 >> result2;
Além disso, se você estiver familiarizado com a família printf de funções que você pode estar interessado em scanf
, sscanf
const char *s = "23";
int result;
sscanf(s, "%d", &result);
Expansão da resposta do Shing Yip:
Para remover os não-dígitos:
#include <iostream>
#include <functional>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string fstring;
getline(cin, fstring);
fstring.erase(
remove_if(fstring.begin(), fstring.end(),
not1(ptr_fun(static_cast<int(*)(int)>(isdigit)))
),
fstring.end()
);
cout << fstring << "\n";
}
Eu não sei por que isso static_cast é necessário, no entanto. Eu acho que algo de ambíguo sobre isdigit sem ele. [Edit: Se você não fizer "usando namespace std", então você não precisa dele, por isso é minha culpa por ser preguiçoso escrever código exemplo.]
discutível É se este é mais simples do que rolando seu próprio loop:
#include <iostream>
#include <string>
using namespace std;
int main() {
string fstring, ins;
getline(cin, ins);
for (string::iterator it = ins.begin(); it != ins.end(); ++it) {
if (isdigit(*it)) fstring.push_back(*it);
}
cout << fstring << "\n";
}
E C ++ 0x terá copy_if, que foi deixado de fora, basicamente, por acidente, e é trivial para implementar:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
std::string fstring, ins;
std::getline(std::cin, ins);
std::copy_if(ins.begin(), ins.end(),
std::back_inserter(fstring), isdigit);
std::cout << fstring << "\n";
}
Para converter para int (ou float):
int i = boost::lexical_cast<int>(fstring);
Ou se você não tem impulso:
#include <sstream>
int i = 0;
std::stringstream(fstring) >> i;
Note que você tem que inicializar i, caso contrário não será definido se fstring está vazio.
Para remover dígitos:
fstring.erase(
std::remove_if(fstring.begin(), fstring.end(), &isdigit),
fstring.end());
Para converter string para int / float /...:
int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
- string de número de ponto flutuante:
Você precisa #include <cstdlib>
float strtof(const char *nptr, char **endptr);
Por exemplo:
float f = strtof("3.4",NULL);
- string para inteiro
Você precisa #include <cstdlib>
int atoi(const char *numPtr);
Observe que estes são C -. Funções, e não C ++, então você precisa usar o método c_str () em std :: string para obter o C-string
const char* c_str ( ) const;