Удаление нецелых из строки в C ++ - PullRequest
2 голосов
/ 03 мая 2009

В моей книге был мимолетный комментарий о том, что люди вводят запятые в целые числа и путают вашу программу, но это не уточняло. Это заставило меня задуматься, поэтому я попытался написать небольшой алгоритм, чтобы взять std :: string и удалить все нецелые символы. Этот код компилируется, но пропускает вывод. Почему ничего не присваивается newstring? Оценивает ли if (isdigit (fstring [i])) значение true для адреса, на который указывает указатель для хранения цифры?

//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");
}

Вторичный вопрос, который, возможно, принадлежит другому: как преобразовать строку в целое число (или число с плавающей запятой)?

Ответы [ 5 ]

6 голосов
/ 03 мая 2009

newstring имеет длину 0, поэтому newstring [x], где x = 0, фактически недопустимо. Вы должны добавить к строке, используя: newstring.append (1, fstring [i])

По второму вопросу ищите функции atoi (), atof (), strtol (0, strtof ()).

5 голосов
/ 03 мая 2009

Строки похожи на массивы, но конструктор по умолчанию для строки создает пустую строку. Зачем ему выделять больше памяти, чем нужно? Даже если это произойдет, невозможно сказать, сколько, или если он будет достаточно большим для отфильтрованной копии fstring. Я впечатлен, что он не падает.

Простая модификация - изменить:

std::string newstring;

до:

 std::string newstring(fstring.length(), '\0')

И после цикла добавить:

 newstring.resize(x);

Это гарантирует, что newstring будет иметь по крайней мере достаточно места (возможно, больше) во время фильтрации и будет обрезан до соответствующего размера, когда вы закончите фильтрацию. Вас также может заинтересовать функция std::remove_copy_if в <algorithm>.

1019 * Е.Г. *

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());

Что касается преобразования строки в целое число / число с плавающей точкой, в дополнение к уже упомянутым функциям atoi, strtol, atof, strtof и т. Д. Вы также можете использовать библиотеку 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;

Также, если вы знакомы с семейством функций printf, вас могут заинтересовать scanf, sscanf

 const char *s = "23";
 int result;
 sscanf(s, "%d", &result);
2 голосов
/ 03 мая 2009

Расширение ответа Шинга Ипа:

Для удаления не цифр:

#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";
}

Я не уверен, зачем нужен этот static_cast. Я думаю, что что-то неоднозначное в исдигите без этого. [Редактировать: если вы не используете «namespace std», тогда вам это не нужно, поэтому я виноват в том, что ленивый, пишу пример кода.]

Это спорный вопрос, является ли это какой-либо проще, чем прокатки свой собственный цикл:

#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";
}

И C ++ 0x будет иметь copy_if, который был пропущен в основном случайно, и реализовать его тривиально:

#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";
}

Чтобы преобразовать в int (или float):

int i = boost::lexical_cast<int>(fstring);

Или, если у вас нет повышения:

#include <sstream>

int i = 0;
std::stringstream(fstring) >> i;

Обратите внимание, что вам нужно инициализировать i, иначе он не будет установлен, если fstring пуст.

1 голос
/ 03 мая 2009

Для удаления цифр:

fstring.erase(
      std::remove_if(fstring.begin(), fstring.end(), &isdigit), 
      fstring.end());

Чтобы преобразовать строку в int / float /...:

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
0 голосов
/ 03 мая 2009
  • Строка в число с плавающей запятой:

Вам нужно #include <cstdlib>

float strtof(const char *nptr, char **endptr);

Например:

 float f = strtof("3.4",NULL);
  • строка в целое число

Вам нужно #include <cstdlib>

int atoi(const char *numPtr);

Обратите внимание, что это C-функции, а не C ++, поэтому вам нужно использовать метод c_str () в std :: string для получения C-строки.

const char* c_str ( ) const;
...