Передать содержимое stringstream в функцию, принимая char* в качестве аргумента

У меня есть функция для записи файлов ppm (формат изображения) на диск. Он принимает имя файла как массив char*. В моей основной функции я собрал имя файла, используя поток строк и оператор <<. Затем я хочу передать результаты этого в мою функцию ppm. Я видел, что это обсуждалось в другом месте, часто с очень запутанными методами (многие промежуточные шаги преобразования).

То, что я сделал, показано в коде ниже, и сложная часть, которую другие обычно делают во многих шагах с временными переменными: (char*) (PPM_file_name.str().data()), Это позволяет извлечь строку из строкового потока PPM_file_name с помощью.str(), затем получить указатель на ее фактическое содержимое с помощью.data() (это const char*), а затем преобразовать ее в обычный (char*). Более полный пример ниже.

До сих пор я обнаружил, что следующее работает нормально, но меня это беспокоит, потому что обычно, когда другие люди делают что-то более запутанное, это потому, что это более безопасный способ сделать это. Итак, кто-нибудь может сказать мне, если то, что я делаю здесь, безопасно, а также насколько оно портативно?

Благодарю.

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>
using namespace std;

int main(int argc, char *argv[]){

    // String stream to hold the file name so I can create it from a series of other variable
    stringstream PPM_file_name; 

    // ... a bunch of other code where int ccd_num and string cur_id_str are created and initialized

    // Assemble the file name
    PPM_file_name << "ccd" << ccd_num << "_" << cur_id_str << ".ppm";

    // From PPM_file_name, extract its string, then the const char* pointer to that string's data, then cast that to char*
    write_ppm((char*)(PPM_file_name.str().data()),"ladybug_vidcapture.cpp",rgb_images[ccd_num],width,height);                   

    return 0;
}

6 ответов

Решение

Это похоже на типичный случай, когда кто-то не пишет const-правильный код и у него есть эффект "зацепки". У вас есть несколько вариантов:

  • Если write_ppm находится под вашим контролем или под контролем кого-либо из ваших знакомых, попросите их сделать его более корректным

  • Если это не так, и вы можете гарантировать, что он никогда не изменит имя файла, тогда const_cast

  • Если вы не можете этого гарантировать, скопируйте вашу строку в std::vector плюс нулевой терминатор и передайте &vec[0] (где vec представляет имя вашей векторной переменной)

Спасибо всем. Итак, следуя советам нескольких людей, я сделал следующее, так как у меня есть контроль над write_ppm:

Модифицированный write_ppm для принятия const char*:

void write_ppm(const char *file_name, char *comment, unsigned char *image,int width,int height)

И теперь я передаю ppm_file_name следующим образом:

write_ppm((PPM_file_name.str().c_str()),"A comment",rgb_images[ccd_num],width,height);

Есть ли что-то, что я должен сделать здесь, или это в основном проясняет проблемы с тем, как это проходило раньше? Должны ли все остальные аргументы char для write_ppm быть константами? Это очень короткая функция, и она, похоже, не изменяет ни один из аргументов. Благодарю.

Это абсолютно безопасно и переносимо, если write_ppm фактически не меняет аргумент, и в этом случае это неопределенное поведение. Я бы порекомендовал использовать const_cast<char*> вместо броска в стиле C Также рассмотрите возможность использования c_str() член вместо data() член. Первый гарантирует возврат строки с нулевым символом в конце

  1. Вы должны использовать PPM_file_name.str().c_str(), поскольку data() не гарантируется возврат строки с нулевым символом в конце.

  2. Или write_ppm() должен принять свой первый аргумент const char* (обещая не изменять содержимое строки) или вы не должны передавать поток строки (потому что вы не должны изменять его содержимое таким образом).

Вы не должны использовать приведения в стиле C в C++, потому что они не различают разные причины приведения. Твое изгнание const, что, если вообще, должно быть сделано с помощью const_cast<>, Но, как правило, const_cast<> обычно требуется только для компиляции кода, который не const-правильно, что я считаю ошибкой.

Почему бы просто не использовать const_cast<char *>(PPM_file_name.str().c_str())?

Использование c_str() вместо data() (c_str() вернуть NULL-terminated sequence of characters).

Другие вопросы по тегам