Автоматически объединять строки и Int С++

-4

В Lua (извините, мне нравится работать с ним лучше), преобразование между int и string выполняется автоматически, поэтому

"hi"..2

приведет к

"hi2"

В C++ (потому что я не могу заставить работать по умолчанию C++ 11 stoi() и to_string()) я определил их для себя:

int stoi(string str) {
char* ptr;
strtol(str.c_str(), &ptr, 10);
}

string to_string(int i) {
char* buf;
sprintf(buf, "%d", i);
return buf;
}

которые в основном определяются по умолчанию.

Тогда я сделал это:

string operator+ (string& stuff, int why) {
stuff.append(to_string(why));
}

Я попробовал его по следующему коду:

void print(string str) {
cout << str << endl;
}

int main() {
cout << stoi("1") + 2 << endl;
print("die" + 1);
return 0;
}

И он выводит

3
ie

Почему это так, и как я могу это исправить?

EDIT: Вот как выглядит код сейчас:

using namespace std;    

string to_string(int i) {
char* buf;
sprintf(buf, "%d", i);
return buf;
}

string operator+ (string stuff, int why) {
stuff.append(to_string(why));
return stuff;
}

int main() {
cout << string("die") + 2 << endl;
return 0;
}

И он просто продолжает давать мне стопки.

спросил(а) 2015-03-23T13:44:00+03:00 5 лет, 6 месяцев назад
0
57

перегружая operator+ в отличие от ваших собственных типов, это в лучшем случае опасно.

Просто используйте std::to_string в сочетании с operator+ или +=, например

std::string x = "hi";
x += std::to_string(2);

ответил(а) 2015-03-23T14:27:00+03:00 5 лет, 6 месяцев назад
58

std::string s1("h1");
std::string s2("2");
s1 += s2;

Если вы используете C++ 11-совместимый компилятор, вы можете преобразовать int в строку следующим образом:

int i = 2;
std::string s = std::to_string(i);

Если вы используете библиотеку Boost:

#include <boost/lexical_cast.hpp>

int i = 2;
std::string s = boost::lexical_cast<std::string>(i);

Пожалуйста, не используйте указатели raw char в C++ для строк.

ответил(а) 2015-03-23T14:03:00+03:00 5 лет, 6 месяцев назад
57

std::string to_string(int i) {
char buf[(sizeof(int)*CHAR_BIT+2)/3+3];
sprintf(buf, "%d", i);
return buf;
}

Вам нужно сделать фактический буфер для печати. Математика - это быстрая переоценка большого наибольшего десятичного числа int в символах; 3 бита могут вписываться в 1 десятичный символ, плюс нуль, плюс отрицание, плюс округление, плюс 1 для хорошей меры. Надеюсь, я не ошибался: сделайте некоторое тестирование.

Также используйте snprintf вместо sprintf пока вы на нем: переполнение буфера не должно быть связано с.

Следующая проблема заключается в том, что "hello" не является std::string, это char const[6] - массив из 6 char. Он может быть преобразован в tom std::string, но +1 вместо этого преобразует его в указатель на первый символ, затем +1 символу.


Передайте его в std::string before.

Наконец, это неоднозначно в стандарте (действительно) pverloading оператора на std::string + int является законным. Это определенно неудовлетворительная практика, поскольку вы не можете сделать это в std законных основаниях, и вы должны перегружать операторов в пространстве имен типов (так работает ADL): эти два конфликта. Кроме того, если std в будущем добавит такой + ваш код начнет вести себя странно. Кроме того, операторы являются частью интерфейса класса, а изменение интерфейса класса, которым вы не являетесь, является грубым и плохой привычкой.

Напишите свой собственный класс строк, которому принадлежит std::string. Или строковое представление.

Наконец, подумайте о том, чтобы сообщить вашему компилятору использовать c+ +1 1, вам, вероятно, просто нужно передать ему флаг, например -std=c++11.

ответил(а) 2015-03-23T14:00:00+03:00 5 лет, 6 месяцев назад
58

Заменить print("die" + 1); cout << std::string("die") + 1;

print() не знает, что делать со строками. Используйте std::cout. "die" - это char*, +1 будет увеличивать указатель.

ответил(а) 2015-03-23T13:49:00+03:00 5 лет, 6 месяцев назад
40

С++ 14 вводит определяемый пользователем литерал, который принимает строковый литерал (для его преобразования используются преобразования) и возвращает std::string. В С++ 11 вы можете просто написать свой собственный (это взято из libstdc++):

inline std::string
operator""_s(const char* str, size_t len)
{
return std::string{str, len};
}

(Примечание: UDL без предшествующего подчеркивания являются зарезервированными именами)

И вы можете использовать его так:

// Assumes operator+ is overloaded
print("die"_s + 1);

демонстрация

ответил(а) 2015-03-23T14:05:00+03:00 5 лет, 6 месяцев назад
-4

"die" не является std::string. Это строковый литерал.

Таким образом, когда вы добавляете 1 в строковый литерал, он распадается на const char* а + 1 просто увеличивает этот указатель - на следующий символ, 'i'.

Затем вы вызываете print с помощью инкрементного указателя, который вызывает построение std::string с использованием этого указателя. Так как он указал на символ 'i', построенная строка инициализируется "ie".

Сначала вы должны сделать std::string из строкового литерала, чтобы вызвать его operator+:

std::cout << std::string("die") + 1;

И затем сделайте несколько исправлений для вашего operator+:

string operator+ (string stuff, int why) {
return stuff.append(to_string(why));
}

Теперь это работает.

ответил(а) 2015-03-23T13:47:00+03:00 5 лет, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема