Вопрос

В моей книге был мимолетный комментарий о том, что люди вводят запятые в целые числа и портят вашу программу, но в нем не было подробностей.Это заставило меня задуматься, поэтому я попытался написать небольшой алгоритм, чтобы взять 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");
}

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

Это было полезно?

Решение

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

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

Другие советы

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

Простой модификацией было бы изменить:

std::string newstring;

Для:

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

И после завершения цикла добавьте:

 newstring.resize(x);

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

Например.

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

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

Чтобы удалить не-цифры:

#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.Я думаю, что в isdigit без него есть что-то двусмысленное.[Править:Если вы не выполняете "using 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);

Или если у вас нет boost:

#include <sstream>

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

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

Чтобы удалить цифры:

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");
  • строка с числом с плавающей запятой:

Тебе нужно #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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top