Передать содержимое stringstream в функцию, принимая char * в качестве аргумента - PullRequest
3 голосов
/ 11 ноября 2010

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

То, что я сделал, показано в приведенном ниже коде, и хитрая часть, которую другие обычно делают во многих шагах с временными переменными, - (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 ]

3 голосов
/ 12 ноября 2010

Спасибо всем.Итак, следуя советам нескольких людей здесь, я сделал следующее, так как у меня есть контроль над 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 быть константными?Это очень короткая функция, и она, похоже, не изменяет ни один из аргументов.Спасибо.

2 голосов
/ 11 ноября 2010

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

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

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

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

1 голос
/ 11 ноября 2010

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

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

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

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

0 голосов
/ 11 ноября 2010

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

0 голосов
/ 11 ноября 2010

Используйте c_str() вместо data() (c_str() возвращает последовательность символов, определенную NULL).

...