Извлечение строки - PullRequest
       12

Извлечение строки

2 голосов
/ 15 декабря 2008

В настоящее время я работаю над очень простой игрой, использующей среду C ++. Раньше игра была школьным проектом, но теперь, когда я закончил с этим уроком программирования, я хотел расширить свои навыки и придать еще большее значение этому старому заданию.

Я уже внес много изменений, которые меня порадовали. Я централизовал все данные в иерархии папок и получил код для чтения этих мест.

Однако моя проблема проистекает из очень фундаментального недостатка, который озадачил меня.

Чтобы получить доступ к данным изображения, которые я использую, я использовал код:

string imageLocation = "..\\DATA\\Images\\";

string bowImage = imageLocation + "bow.png";

Проблема в том, что, когда игрок поднимает предмет на игровой доске, мой код должен использовать код:

hud.addLine("You picked up a " + (*itt)->name() + "!");

чтобы напечатать в командной строке: «Ты взял лук!». Но вместо этого он показывает «Вы подобрали .. \ DATA \ Images \!».

До того, как я централизовал свои данные, я использовал:

name_(item_name.substr(0, item_name.find('.')))

в моем конструкторе класса Item, чтобы разделить имя элемента на что-то вроде лука или свечи. После того, как я изменил структуру моих данных, я понял, что мне придется изменить способ свертывания имени до того же простого «банта» или «свечи».

Я изменил приведенный выше код, чтобы отразить мои изменения в структуре данных:

name_(item_name.substr(item_name.find("..\\DATA\\Images\\"), item_name.find(".png")))

но, к сожалению, как я упоминал ранее, это изменение кода не работает так, как я планировал.

Итак, теперь, когда я дал действительно длинное многословное введение в мою проблему, вот мой вопрос.

Как вы извлекаете середину строки между двумя секциями, которые вам не нужны? Также та средняя часть, которая является вашей целью, имеет неизвестную длину.

Большое спасибо за любую помощь, которую вы, ребята, можете оказать. Если вам нужна дополнительная информация, пожалуйста, спросите; Я буду более чем рад загрузить часть или даже весь мой код для получения дополнительной помощи. Еще раз большое спасибо.

Ответы [ 6 ]

7 голосов
/ 15 декабря 2008

Во всей честности, вы, вероятно, подходите к этому не с того конца.

Ваш класс предметов должен иметь строку "лук" в приватном члене. Функция Item :: GetFilePath тогда (во время выполнения) будет делать ".. \ DATA \ Images \" + this-> name + ".png".

Фундаментальным свойством объекта объекта "лук" является не имя файла bow.png, а тот факт, что это "лук". Имя файла - это просто производное свойство.

3 голосов
/ 15 декабря 2008

с использованием файловой системы boost:

#include "boost/filesystem.hpp"

namespace fs = boost::filesystem;

void some_function(void)
{
    string imageLocation = "..\\DATA\\Images\\";
    string bowImage = imageLocation + "bow.png";
    fs::path image_path( bowImage  ); 
    hud.addLine("You picked up a " + image_path.filename() + "!");  //prints: You picked up a bow!
3 голосов
/ 15 декабря 2008

Предполагая, что я вас правильно понимаю, краткая версия вашего вопроса: как разделить строку, содержащую путь к файлу, чтобы я удалил путь и расширение, оставив только "title"?

Вам нужен метод find_last_of. Это избавляет от пути:

std::size_type lastSlash = filePath.find_last_of('\\');
if (lastSlash == std::string::npos)
    fileName = filePath;
else
    fileName = filePath.substr(lastSlash + 1);

Обратите внимание, что вы можете определить константу как \\ на случай, если вам потребуется изменить ее для других платформ. Не все файловые системы ОС используют \\ для разделения сегментов пути.

Также обратите внимание, что вам также необходимо использовать find_last_of и для точки расширения, потому что имена файлов в общем случае могут содержать точки по всему пути. Только самый последний указывает на начало расширения:

std::size_type lastDot = fileName.find_last_of('.');
if (lastDot == std::string::npos)
{
    title = fileName;
}
else
{
    title = fileName.substr(0, lastDot);
    extension = fileName.substr(lastDot + 1);
}

См. http://msdn.microsoft.com/en-us/library/3y5atza0(VS.80).aspx

2 голосов
/ 15 декабря 2008

Итак, объединяя мысли Павла и мои мысли, попробуйте что-то вроде этого (разбитое на удобочитаемость):

string extn = item_name.substr(item_name.find_last_of(".png"));
string path = item_name.substr(0, item_name.find("..\\DATA\\Images\\"));
name_ = item_name.substr( path.size(), item_name.size() - extn.size() );

Вы можете немного упростить его, если знаете, что имя элемента всегда начинается с "..DATA" и т. Д. (Вы можете хранить его в константе и не искать его в строке)

Редактировать: изменено расширение для поиска детали, чтобы использовать find_last_of, как предложено EarWicker (это позволяет избежать случая, когда ваш путь включает в себя «.png» где-то перед расширением)

1 голос
/ 15 декабря 2008

item_name.find (".. \ DATA \ Images \") вернет индекс, с которого начинается подстрока ".. \ DATA \ Images \" , но, похоже, вы захотите индекс, где он заканчивается , поэтому вы должны добавить длину ".. \ DATA \ Images \" к индексу, возвращенному функцией find.

Кроме того, как указал hamishmcn, вторым аргументом к substr должно быть число возвращаемых символов, которое будет индексом, где начинается ".png", минус индекс, в котором заканчивается ".. \ DATA \ Images \", Я думаю.

0 голосов
/ 15 декабря 2008

Одна вещь, которая выглядит неправильно, заключается в том, что вторым параметром для substr должно быть количество копируемых символов, а не позиция.

...