преобразование в строку в Linux, Windows
От: avsokolov  
Дата: 18.01.08 03:03
Оценка:
подскажите семейство стандартных функций преобразований в строк на С++
я использовал в Windows _itoa_s
думал они стандартны, однако линукс о них ничего не знает
Re: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 18.01.08 03:23
Оценка:
Здравствуйте, avsokolov, Вы писали:

A>подскажите семейство стандартных функций преобразований в строк на С++

A>я использовал в Windows _itoa_s
A>думал они стандартны, однако линукс о них ничего не знает

boost::lexical_cast или его аналог на строковых потоках.
Re[2]: преобразование в строку в Linux, Windows
От: avsokolov  
Дата: 18.01.08 03:54
Оценка:
Здравствуйте, Nuald, Вы писали:

N>boost::lexical_cast или его аналог на строковых потоках.


можно чуть подробнее?
есть ли встроенная библиотека в Linux
для меня не главное, чтобы код был портируемым

boost мне бы не хотелось использовать...
Re[3]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 18.01.08 05:03
Оценка:
Здравствуйте, 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 можно просто взять за основу и написать свое собственное.
Re: преобразование в строку в Linux, Windows
От: Uzumaki Naruto Ниоткуда  
Дата: 18.01.08 06:36
Оценка:
Здравствуйте, 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];
}

Re[2]: преобразование в строку в Linux, Windows
От: Uzumaki Naruto Ниоткуда  
Дата: 18.01.08 06:41
Оценка:
Кстати — есть еще одна замечательная функция sprintf

Re[2]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 18.01.08 07:19
Оценка:
Здравствуйте, Uzumaki Naruto, Вы писали:

UN>
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 не потоко-безопасно.
Re[3]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 18.01.08 07:22
Оценка:
Здравствуйте, Uzumaki Naruto, Вы писали:

UN>Кстати — есть еще одна замечательная функция sprintf


Одна из самых небезопасных функций, какая только может быть
Лучше уж snprintf — но и у этой функции есть свои недостатки.
Re[4]: преобразование в строку в Linux, Windows
От: Uzumaki Naruto Ниоткуда  
Дата: 18.01.08 10:01
Оценка:
Если вы не умеете работать потокобезопасно на вышестоящем уровнем со старыми функциями, то боюсь, что наличие МС расширений вас не спасет. Во вторых я пишу сразу кросплатформенно, так что предпочитаю расширениями CRT не пользоваться, а работать исключительно по стандерту в рамках C++ стандарта и POSIX.

Re[3]: преобразование в строку в Linux, Windows
От: Uzumaki Naruto Ниоткуда  
Дата: 18.01.08 10:08
Оценка:
Во первых сие накидано побыстрому.
Во вторых потокобезопасность можно осуществлять на другом уровне.
В третьих — сие есть расширение от МС и не является стандартом, а значит никакой кросплатформенности.

Re[3]: преобразование в строку в Linux, Windows
От: MShura  
Дата: 18.01.08 12:27
Оценка:
UN>>
UN>>char* itoa(int val, int base) 
UN>>{
UN>>    static char buf[32] = {0};
....
UN>>}
UN>>


N>Не потоко-безопасная функция — нельзя одновременно вызывать эту функцию из двух потоков.

Проблему с потоко-безопасностью легко решить.
Посмотрите как MS решила проблему потокобезопасности для следующих функций/переменных:

— errno
— rand()
— strtok()
— wcstok()
— _mbstok()
— strerror()/_strerror()
— tmpnam()
— _wtmpnam()
— tmpfile()
— _wtmpfile()
— asctime()
— _wasctime(
— gmtime()
— ecvt()/fcvt()

Другое дело, что это придется делать самому
Re[4]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 19.01.08 00:58
Оценка:
Здравствуйте, 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.


Или где-то можно найти исходники CRT?
Re[5]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 19.01.08 01:03
Оценка:
Здравствуйте, Uzumaki Naruto, Вы писали:

UN>Если вы не умеете работать потокобезопасно на вышестоящем уровнем со старыми функциями, то боюсь, что наличие МС расширений вас не спасет. Во вторых я пишу сразу кросплатформенно, так что предпочитаю расширениями CRT не пользоваться, а работать исключительно по стандерту в рамках C++ стандарта и POSIX.


Об каких МС-расширениях идет речь?
Насчет CRT полностью с вами согласен, и по стандарту как раз лучше всего пользоваться потоками, либо использовать ваше решение, но, конечно, с некоторыми модификациями.

А что касается strtod, то маны говорят:

CONFORMING TO
C89 describes strtod(), C99 describes the other two functions.

Так что это вполне стандартная функция.
Re: преобразование в строку в Linux, Windows
От: c-smile Канада http://terrainformatica.com
Дата: 19.01.08 01:28
Оценка:
Здравствуйте, 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; }
  };


Используем например так:

std::string s = itoa(123,16);
Re[2]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 19.01.08 01:55
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>
CS>  class itoa 
CS>  {
CS>    char buffer[38];
CS>  public:
CS>    itoa(int n, int radix = 10) { ::itoa(n,buffer,radix); }
CS>    operator const char*() { return buffer; }
CS>  };
CS>


В линуксе itoa нет.
Возможно переполнение буфера. Нет валидации radix. А вообще подход интересный — такого рода класс позволяет делать кэширование результатов.
Re[3]: преобразование в строку в Linux, Windows
От: c-smile Канада http://terrainformatica.com
Дата: 19.01.08 03:37
Оценка:
Здравствуйте, Nuald, Вы писали:

N>Здравствуйте, c-smile, Вы писали:


CS>>
CS>>  class itoa 
CS>>  {
CS>>    char buffer[38];
CS>>  public:
CS>>    itoa(int n, int radix = 10) { ::itoa(n,buffer,radix); }
CS>>    operator const char*() { return buffer; }
CS>>  };
CS>>


N>В линуксе itoa нет.


есть printf.

N>Возможно переполнение буфера.


1) Максимальная длина последовательности получается при radix == 2.
2) Соответсвенно пишем:
   char buffer[ sizeof(int) * 8 + 1 ];

и всех делов-то.

N>Нет валидации radix.


В itoa есть.

N>А вообще подход интересный — такого рода класс позволяет делать кэширование результатов.

Здорово, но непонятно.
Re[4]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 19.01.08 03:54
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>есть printf.


Небезопасная функция.

N>>Нет валидации radix.

CS>В itoa есть.

Изначальный вопрос был про Линукс, так что itoa остается за бортом.

N>>А вообще подход интересный — такого рода класс позволяет делать кэширование результатов.

CS>Здорово, но непонятно.

При интенсивных преобразований можно загнать передаваемое значение и результат в словарь (скажем, статический член класса), и потом делать по нему поиск.
Re[5]: преобразование в строку в Linux, Windows
От: c-smile Канада http://terrainformatica.com
Дата: 19.01.08 06:09
Оценка:
Здравствуйте, 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>При интенсивных преобразований можно загнать передаваемое значение и результат в словарь (скажем, статический член класса), и потом делать по нему поиск.


Ага, понятно.

Там вообще-то считать нечего чтобы его кэшировать. Не думаю что такое кэширование имеет особый смысл.
Re[5]: преобразование в строку в Linux, Windows
От: Sergey Chadov Россия  
Дата: 19.01.08 12:31
Оценка:
Здравствуйте, Nuald, Вы писали:


N>Или где-то можно найти исходники CRT?


В папке /VC/crt/src вестимо.
--
Sergey Chadov

... << RSDN@Home 1.2.0 alpha rev. 685>>
Re[6]: преобразование в строку в Linux, Windows
От: Nuald Россия http://nuald.blogspot.com
Дата: 21.01.08 00:45
Оценка:
Здравствуйте, 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 на уровне стандартов кодирования.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.