C — stringstream << "перезапись"

#c #ostringstream

#c #std #stringstream

Вопрос:

Я создаю игру OpenGL на C . Я довольно неопытен в C , в отличие от других языков. В любом случае, я создаю stringstream с «базовым» каталогом для некоторых изображений. Затем я передаю этот stringstream в качестве параметра функции конструктору. Конструктор добавляет имя файла изображения, затем пытается загрузить результирующий путь. Однако…

 D:CodeBlocks ProjectsSnakeRoidbinDebugTexts <-- before appending the filename
Ship01.tgacks ProjectsSnakeRoidbinDebugTexts <-- After.
  

Очевидно, неверно! Результат должен быть D:CodeBlocks ПроектыSnakeRoidbin DebugTextsShip01.tga

Соответствующие части моего кода:

 std::stringstream concat;
std::string txtFullPath = "Path here";

...

concat.str(""); //Reset value (because it was changed in ...)
concat << texFullPath; //Restore the base path
PS = new PlayerShip(amp;TexMan, concat); //Call the constructor
  

Код конструктора

 PlayerShip::PlayerShip(TextureManager * TexMan, std::stringstream amp;path)
{
    texId = 2;
    std::cout << path.str(); //First path above
    path << "Ship01.tga";
    std::cout  << path.str(); //Second - this is the messed up one
    //Do more fun stuff
}
  

У кого-нибудь есть идеи, почему он «перезаписывает» то, что уже есть в stringstream?

Комментарии:

1. Трудно следить за вашими фрагментами кода. Не могли бы вы создать короткую (20 строк или около того), полную (чтобы мы могли загрузить и скомпилировать ее) программу, которая демонстрирует проблему? См . sscce.org для получения дополнительной информации.

2. @CppLearner Разве это не очевидно?

3. @ Seth Carnegie: но не помешало бы быть более наглядным.:)

4. Мой плохой, я поторопился при публикации этого, когда у меня будет шанс, я отредактирую лучший код.

5. Отредактировано. Это понятнее?

Ответ №1:

почему он «перезаписывает» то, что уже есть в stringstream

Потому что вывод помещает символы в позицию «поместить указатель» в выходной буфер. В только что созданном потоке указатель put установлен равным нулю (за исключением потоков вывода файлов, открытых в режиме добавления), таким образом, ваш вывод перезаписывает символы, уже находящиеся в буфере.

Если вам действительно нужно добавлять строки таким образом, вам нужно переместить указатель put в конец буфера:

 std::cout << p.str(); //First path above
std::stringstream path;
path.str(p.str());
path.seekp(0, std::ios_base::end); // <-- add this
path << "Ship01.tga";
std::cout << "Loading player ship from " << path.str(); 
  

РЕДАКТИРОВАТЬ: вопрос был отредактирован, и код после редактирования работает, потому что он больше не используется path.str(p.str()); для создания выходного буфера без использования операции вывода (и без продвижения указателя put): различия см. В ideone.

В любом случае сами строки могут быть объединены, что упростит отслеживание кода:

 std::string p = path.str()   "Ship01.tga";
std::cout << p;
  

Не говоря уже о том, что для работы с файлами и путями у нас есть boost.файловая система.

Комментарии:

1. Да, кажется, это работает. Я пришел из C #, где вы можете использовать для объединения большинства значений (string, int, ect), а в C вам нужно использовать StringStream для преобразования mutlitype и обработки char*, поэтому мне никогда не приходило в голову просто использовать для двух строк C , хотя этотеперь определенно имеет больше смысла. Спасибо.

2. @Xcelled194: stringstream предназначен для сериализации объектов в строки. Нам это не нужно для string->string 😀

3. @MooingDuck Итак, я обнаружил xD Я просто (ошибочно) предположил, что любая конкатенация C была выполнена с помощью SS.

4. @Xcelled194: понятно, поскольку многие новые языки имеют неизменяемые строки,

5. @Cubbi упс, не хотел редактировать, чтобы сделать недействительной часть вашего ответа. Однако в отредактированном коде присутствовала та же проблема с перезаписью. Я готов поспорить, что установка позиции (как вы сказали) также исправит это.