C ++ std :: string и NULL const char *

Я работаю в C ++ с двумя большими кусками кода, один из которых сделан в "С стиль " и один в "Стиль С ++ ".

Код типа C имеет функции, которые возвращают const char *, а код C ++ во многих местах имеет такие вещи, как

const char* somecstylefunction();
...
std::string imacppstring = somecstylefunction();

где он строит строку из const char *, возвращаемого кодом стиля C.

Это работало до тех пор, пока код стиля C не изменился и иногда не начинал возвращать указатели NULL. Это, конечно, вызывает ошибки сегмента.

Вокруг много кода, и поэтому я хотел бы наиболее экономным способом решить эту проблему. Ожидаемое поведение - в этом случае imacppstring будет пустой строкой. Есть ли хорошее, гладкое решение для этого?

Обновить

Const char *, возвращаемый этими функциями, всегда является указателем на статические строки. Они использовались в основном для передачи информативных сообщений (предназначенных для регистрации, скорее всего) о любых неожиданных действиях в функции. Было решено, что при этих возвращаемых значениях NULL "Нечего докладывать" было хорошо, потому что тогда вы могли бы использовать возвращаемое значение в качестве условия, т.е.

if (somecstylefunction()) do_something;

тогда как раньше функции возвращали статическую строку "";

Была ли это хорошая идея, яЯ не собираюсь трогать этот код, и этовсе равно не до меня.

Чего я хотел избежать, так это отслеживания каждой инициализации строки для добавления функции-оболочки.

 Charles Salvia12 нояб. 2009 г., 19:18
@jmucchiello, я думаю, потому что "пустой строки" сильно отличается от указателя, который указывает на адрес памяти 0. Пустая строка"" на самом деле занимает память как один нулевой символ.
 San Jacinto13 нояб. 2009 г., 04:37
@ дядя этоНет смысла ... вы должны вернуться и обновить код.
 jmucchiello12 нояб. 2009 г., 19:14
Может кто-нибудь ответить, почему реализация std :: basic_string не 'считать пустой указатель value_type пустой строкой?
 San Jacinto12 нояб. 2009 г., 19:13
Я хотел бы отметить, что выре "Сопровождающий» как вы упомянули в комментарии, возможно, вы нарушаете некоторые довольно важные правила стиля. Я нене знаю почему тыЯ хочу вернуть указатель на символ, если он не передан в функцию через указатель. Не могли бы вы уточнить это? У вас могут быть большие проблемы.
 UncleBens12 нояб. 2009 г., 20:57
Если функции вернули "", все еще должно быть возможно сделать легкие проверки:if (*somecstylefunction())
 David Thornley12 нояб. 2009 г., 19:54
Вы пытались поговорить с тем, кто принял решение начать возвращать нулевые указатели, и объяснили, что это 'нарушает код C ++?

Ответы на вопрос(7)

выступают за создание подклассов стандартных контейнеров, но в этом случае это может сработать.

class mystring : public std::string
{
    // ... appropriate constructors are an exercise left to the reader
    mystring & operator=(const char * right)
    {
        if (right == NULL)
        {
            clear();
        }
        else
        {
            std::string::operator=(right);  // I think this works, didn't check it...
        }
        return *this;
    }
};
 Walter28 февр. 2014 г., 09:42
В C ++ 11, чтобы семантика перемещения работала междуstd::string а такжеmystring (в любом направлении), какие другие элементы (кроме конструкторов) мне нужно перегрузить? Дон»t мне нужно преобразование rvalue в?std::string&&
 Mark Ransom26 февр. 2014 г., 21:38
@ Уолтер, я никогда не говорил, что этохорошо идея, просто способ сделать лучшее из плохой ситуации. И это работает:ideone.com/2xGd1A
 Walter26 февр. 2014 г., 21:14
Вы все еще думаете, что это хорошая идея?
Решение Вопроса

лучшее, что нужно сделать, - это установить функции библиотеки C в их поведение перед изменением. но, возможно, ты неЯ не могу контролировать эту библиотеку.

Второе, что нужно учитывать, это изменить все случаи, когда выВ зависимости от функций C lib, возвращающих пустую строку, использовать функцию-обертку, которая 'дадимисправить' нулевые указатели:

const char* nullToEmpty( char const* s)
{
    return (s ? s : "");
}

А сейчас

std::string imacppstring = somecstylefunction();

может выглядеть так:

std::string imacppstring( nullToEmpty( somecstylefunction());

Если это'неприемлемо (это может быть много занятой работы, но это должно быть одноразовое механическое изменение), вы могли бы реализовать 'параллельно' библиотека, которая имеет те же имена, что и C lib you 'в настоящее время они используют эти функции, просто вызывая оригинальные функции C lib и исправляя NULL-указатели в зависимости от ситуации. Вы'Мне нужно поиграть в некоторые сложные игры с заголовками, компоновщиком и / или пространствами имен C ++, чтобы заставить это работать, и это имеет огромный потенциал, чтобы вызвать путаницу в будущем, поэтому я 'Я долго думал, прежде чем идти по этому пути.

Но что-то вроде следующего может помочь вам начать:

// .h file for a C++ wrapper for the C Lib
namespace clib_fixer {
    const char* somecstylefunction();
}


// .cpp file for a C++ wrapper for the C Lib
namespace clib_fixer {
    const char* somecstylefunction() {
        const char* p = ::somecstylefunction();

        return (p ? p : "");
    }
}

Теперь вам просто нужно добавить этот заголовок в файлы .cpp, которые в данный момент вызывают функции C lib (и, возможно, удалить заголовок для C lib) и добавить

using namespace clib_fixer;

в файл .cpp, используя эти функции.

Это не может бытьтоже плохой. Может быть."

 Steve Jessop13 нояб. 2009 г., 00:15
и, вероятно, удалить заголовок для C lib " - яЯ уверен, что вы должны удалить его. Я думаю, что в противном случае призыв кsomecstylefunction будет неоднозначным междуnamespace clib_fixer а также .namespace ::

Нечто подобное должно решить вашу проблему.

const char *cString;
std::string imacppstring;

cString = somecstylefunction();
if (cString == NULL) {
  imacppstring = "";
} else {
  imacppstring = cString;
}

Если вы хотите, вы можете вставить логику проверки ошибок в ее собственную функцию. Вы'тогда я должен был бы поместить этот блок кода в меньшее количество мест.

...

std::string makeCppString(const char* cStr)
{
    return cStr ? std::string(cStr) : std::string("");
}

Тогда где у вас есть:

std::string imacppstring = somecstylefunction(); 

замените его на:

std::string imacppstring = makeCppString( somecystylefunction() );

Конечно, это предполагает, что создание пустой строки является приемлемым поведением, когда ваша функция возвращает NULL.

 underscore_d02 июл. 2016 г., 18:50
std::string imacppstring = makeCppString(somecystylefunction); не будет работать, потому что выпередается адрес функции, а не ее возвращаемый.char const *

вы можете просто добавить функцию-обертку, которая проверяет NULL и возвращает пустую строку std :: string. Но что более важно, почему ваши функции C теперь возвращают NULL? Что означает указатель NULL? Если это указывает на серьезную ошибку, вы можете захотеть, чтобы ваша функция-обертка вызвала исключение.

Или, чтобы быть в безопасности, вы можете просто проверить NULL, обработать NULL и только потом создать std :: string.

const char* s = somecstylefunction();
if (!s) explode();
std::string str(s);
 Charles Salvia12 нояб. 2009 г., 19:08
В этом случае вы можете просто использовать встроенную функцию-обертку, которая проверяет NULL и возвращает пустую std :: string, если указатель равен NULL.
 pythonic metaphor12 нояб. 2009 г., 19:06
В этом случае это не указывает на ошибку. Сопровождающий решил, что это чище длянет сообщений" быть указанным с нулевым указателем, а не указателем на статический "", Который неЭто неразумно, но нарушает этот другой код.

(а) определить свой собственный тип строки. Самая большая часть - это поиск и замена по всему проекту - это может быть просто, еслиs всегда std :: string или большая одноразовая боль. (Я'сделал бы единственное требование, чтобы этоs Лисков-заменяемый для std :: string, но также создает пустую строку из нулевого символа *.

Реализация e, asiest публично наследуется от std :: string. Хотя этоНахмурившись (по понятным причинам), это будет нормально в этом случае, а также поможет сторонним библиотекам, ожидающимstd::string, а также инструменты отладки. В качестве альтернативы, срастаться и вперед - гадость.

(b) #define std :: string для вашего собственного строкового типа. Рискованно, не рекомендуется. Я бы неесли я не знал, что кодовые базы очень хорошо задействованы и экономит вам массу работы (а ядобавлю несколько заявлений об отказе от ответственности, чтобы защитить остатки моей репутации;))

(с) ямы обошли несколько таких случаев, переопределивпередача оскорбительного типа в некоторый служебный класс только с целью включения (таким образом, #define намного более ограничен по объему). Тем не менее, я понятия не имею, как это сделать для.char *

(d) Написать импортную оболочку. Если заголовки библиотеки C имеют довольно регулярную разметку и / или вы знаете кого-то, кто имеет некоторый опыт разбора кода C ++, вы можете сгенерировать "заголовок оболочки ".

(д) попросить владельца библиотеки сделать "Нулевая строка значение настраивается как минимум во время компиляции. (Приемлемый запрос, так как переключение на 0 может нарушить совместимость и в других сценариях) Вы можете даже предложить внести изменения самостоятельно, если это 'меньше работы для вас!

std::string инициализируется непосредственно из вызова функции C (чтобы добавить проверку нулевого указателя), единственным решением было бы запретить вашим функциям C возвращать нулевые указатели.

В компиляторе GCC вы можете использовать расширение компилятораУсловные выражения с опущенными операндами » создать макрос-обертку для вашей функции C

#define somecstylefunction() (somecstylefunction() ? : "")

но в общем случае я бы советовал против этого.

 AnT12 нояб. 2009 г., 19:12
@antonmarkov: Да, но комбинация макросова также расширение компилятора, на мой взгляд, слишком много.
 Anton12 нояб. 2009 г., 19:11
Некоторая форма макроса или набор ваших собственных оболочек вокруг библиотеки будет хорошим способом решения проблемы без изменения исходной библиотеки.
 San Jacinto12 нояб. 2009 г., 19:07
да, похоже, что-то яхочу держаться подальше от. Это'Вероятно, лучше устранить причину проблемы, чем симптомы.

Ваш ответ на вопрос