подскажите семейство стандартных функций преобразований в строк на С++
я использовал в Windows _itoa_s
думал они стандартны, однако линукс о них ничего не знает
Здравствуйте, avsokolov, Вы писали:
A>подскажите семейство стандартных функций преобразований в строк на С++ A>я использовал в Windows _itoa_s A>думал они стандартны, однако линукс о них ничего не знает
boost::lexical_cast или его аналог на строковых потоках.
Здравствуйте, avsokolov, Вы писали:
A>можно чуть подробнее?
Вот рабочий пример:
#include <iostream>
#include <sstream>
int main() {
int i = 10;
using namespace std;
stringstream str;
str << i;
string s = str.str();
cout << s << endl;
return 0;
}
Компилировал с g++ (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33)
A>есть ли встроенная библиотека в Linux
Ну есть, например, strtod.
A>для меня не главное, чтобы код был портируемым
Лучше сразу писать хороший код. Потоки как минимум, более безопасны, чем использование atoi/strtod-функций — нет необходимости напрямую работать с указателями. А задно еще и портабельно
A>boost мне бы не хотелось использовать...
В бусте есть много вкусного, а lexical_cast можно просто взять за основу и написать свое собственное.
Здравствуйте, avsokolov, Вы писали:
A>подскажите семейство стандартных функций преобразований в строк на С++ A>я использовал в Windows _itoa_s A>думал они стандартны, однако линукс о них ничего не знает
Префикс _ — означает специфичное расширение в данном CRT
_s — синхроннизация (новое слово от MS — лучше б оно его не делало)
Ищи аналог в Linux или
char* itoa(int val, int base)
{
static char buf[32] = {0};
int i = 30;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
return &buf[i+1];
}
UN>char* itoa(int val, int base)
UN>{
UN> static char buf[32] = {0};
UN> int i = 30;
UN> for(; val && i ; --i, val /= base)
UN> buf[i] = "0123456789abcdef"[val % base];
UN> return &buf[i+1];
UN>}
UN>
Не потоко-безопасная функция — нельзя одновременно вызывать эту функцию из двух потоков.
Для корректной работы, base должен быть не менее двух.
Потенциальное переполнение буфера для int с разрядностью больше 106 (например, для 128-битных платформ). Не забывайте, что Линукс не ограничен x86 архитектурой.
Хотя решение элегантное, и если ввести валидацию base и вычисление необходимого размера буфера (например, через логарифмы), то будет вполне неплохим, и более эффективным, чем использование строковых потоков. Однако в любом случае придется использовать строковый класс, т.к. простой указатель не умеет за собой подчищать ресурсы, а использование static не потоко-безопасно.
Если вы не умеете работать потокобезопасно на вышестоящем уровнем со старыми функциями, то боюсь, что наличие МС расширений вас не спасет. Во вторых я пишу сразу кросплатформенно, так что предпочитаю расширениями CRT не пользоваться, а работать исключительно по стандерту в рамках C++ стандарта и POSIX.
Во первых сие накидано побыстрому.
Во вторых потокобезопасность можно осуществлять на другом уровне.
В третьих — сие есть расширение от МС и не является стандартом, а значит никакой кросплатформенности.
N>Не потоко-безопасная функция — нельзя одновременно вызывать эту функцию из двух потоков.
Проблему с потоко-безопасностью легко решить.
Посмотрите как MS решила проблему потокобезопасности для следующих функций/переменных:
Здравствуйте, MShura, Вы писали:
MS>Проблему с потоко-безопасностью легко решить. MS>Посмотрите как MS решила проблему потокобезопасности для следующих функций/переменных:
<skiped> MS>Другое дело, что это придется делать самому
Гм, а куда смотреть? В MSDN-е нашел только одну фразу:
Note Each function uses a static variable for parsing the string into tokens. If multiple or simultaneous calls are made to the same function, a high potential for data corruption and inaccurate results exists. Therefore, do not attempt to call the same function simultaneously for different strings and be aware of calling one of these functions from within a loop where another routine may be called that uses the same function. However, calling this function simultaneously from multiple threads does not have undesirable effects.
Здравствуйте, Uzumaki Naruto, Вы писали:
UN>Если вы не умеете работать потокобезопасно на вышестоящем уровнем со старыми функциями, то боюсь, что наличие МС расширений вас не спасет. Во вторых я пишу сразу кросплатформенно, так что предпочитаю расширениями CRT не пользоваться, а работать исключительно по стандерту в рамках C++ стандарта и POSIX.
Об каких МС-расширениях идет речь?
Насчет CRT полностью с вами согласен, и по стандарту как раз лучше всего пользоваться потоками, либо использовать ваше решение, но, конечно, с некоторыми модификациями.
А что касается strtod, то маны говорят:
CONFORMING TO
C89 describes strtod(), C99 describes the other two functions.
Здравствуйте, avsokolov, Вы писали:
A>подскажите семейство стандартных функций преобразований в строк на С++ A>я использовал в Windows _itoa_s A>думал они стандартны, однако линукс о них ничего не знает
Делов-то ...
class itoa
{
char buffer[38];
public:
itoa(int n, int radix = 10) { ::itoa(n,buffer,radix); }
operator const char*() { return buffer; }
};
В линуксе itoa нет.
Возможно переполнение буфера. Нет валидации radix. А вообще подход интересный — такого рода класс позволяет делать кэширование результатов.
Изначальный вопрос был про Линукс, так что itoa остается за бортом.
N>>А вообще подход интересный — такого рода класс позволяет делать кэширование результатов. CS>Здорово, но непонятно.
При интенсивных преобразований можно загнать передаваемое значение и результат в словарь (скажем, статический член класса), и потом делать по нему поиск.
Здравствуйте, Nuald, Вы писали:
N>Здравствуйте, c-smile, Вы писали:
CS>>есть printf.
N>Небезопасная функция.
Вообще — да.
В конкретной частности очень даже безопастна.
Приведи причины по которым может быть небезопасным вот этот код:
char buf[sizeof(int)*2 + 1];
sprintf(buf,"%x", n);
N>>>Нет валидации radix. CS>>В itoa есть.
N>Изначальный вопрос был про Линукс, так что itoa остается за бортом.
Взять любую из дсступных реализаций itoa. Какие проблемы-то?
Например:
char *itoa(int n, char *s, int b)
{
if(b < 2 || b > 36) return s;
static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int i=0, sign;
if ((sign = n) < 0)
n = -n;
do s[i++] = digits[n % b];
while ((n /= b) > 0);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
return strrev(s);
}
Кстати, в случае моего класса strrev не требуется.
N>>>А вообще подход интересный — такого рода класс позволяет делать кэширование результатов. CS>>Здорово, но непонятно.
N>При интенсивных преобразований можно загнать передаваемое значение и результат в словарь (скажем, статический член класса), и потом делать по нему поиск.
Ага, понятно.
Там вообще-то считать нечего чтобы его кэшировать. Не думаю что такое кэширование имеет особый смысл.
Здравствуйте, c-smile, Вы писали:
CS>Приведи причины по которым может быть небезопасным вот этот код: CS>char buf[sizeof(int)*2 + 1]; CS>sprintf(buf,"%x", n);
В данном конкретном случае все нормально. Однако код не является чем-то застывшим, поэтому при дальнейшей модификации может всплыть:
1. Программист может попытаться вернуть из функции buf. Понятно, что будет ошибка доступа памяти.
2. Формат может расшириться выводом строк и вещественных чисел. Учитывая, что бывают разные локали, и что char в современном линуксе в большинстве случаев представляет собой utf-8, заранее рассчитать размер буфера не всегда удастся.
3. Можно просто допустить элементарную ошибку, и сопоставить формату %s число, а не строку. Хотя такие ошибки выявляются в первом же smoke тесте, однако некоторые ветки программы исполняются довольно-таки редко, и ошибку удается найти только после ввода в программу эксплуатации.
Все это хорошо описано Саттером ("Новые сложные задачи на C++", Задача 2, часть 1, sprintf). Он выделяет следующие преимущества:
1. Простота использования и ясность.
2. Максимальная эффективность.
И недостатки:
1. Безопасность.
2. Безопасность типов.
3. Невозможность работы в шаблонах.
Учитывая, что в подавляющем большинстве случаев эффективность не столь критична, а безопасность, наоборот, довольно-таки важна, мы у себя вообще запретили использовать sprintf на уровне стандартов кодирования.