#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 упс, не хотел редактировать, чтобы сделать недействительной часть вашего ответа. Однако в отредактированном коде присутствовала та же проблема с перезаписью. Я готов поспорить, что установка позиции (как вы сказали) также исправит это.