Как изменить расширение имени файла, хранящееся в строке в C++?
-
09-09-2019 - |
Вопрос
Хорошо, вот в чем дело: я прохожу вводный курс C++ в своем университете, и мне не удается понять, как изменить расширение файла.Во-первых, нам нужно прочитать файл .txt и посчитать слова, предложения, гласные и т. д.Ну, я это понял, но меня беспокоит следующий шаг.Затем мы предполагаем создать новый файл, используя то же имя файла, что и входной файл, но с расширением .code вместо .txt (затем в этом новом файле мы должны закодировать строку, добавляя случайные числа к ASCII-коду каждого файла). персонаж, если вам было интересно).Будучи новичком в программировании, я не совсем понимаю, как это сделать.Я использую следующий фрагмент кода, чтобы сначала получить входной файл:
cout << "Enter filename: ";
cin >> filename;
infile.open(filename.c_str());
Я предполагаю создать новый файл, который буду использовать что-то вроде:
outfile.open("test.code");
Но я не узнаю имя файла, пока пользователь не введет его, поэтому я не могу сказать «test.txt».Так что, если кто-нибудь знает, как изменить это расширение при создании нового файла, я был бы очень признателен!
Решение
Есть несколько подходов к этому.
Вы можете использовать очень ленивый подход и попросить их ввести только имя файла, а не расширение .txt.В этом случае вы можете добавить к нему .txt, чтобы открыть входной файл.
infile.open(filename + ".txt");
Тогда ты просто позвони
outfile.open(filename + ".code");
Следующий подход — взять все имя файла, включая расширение, и просто добавить к нему .code, чтобы получился test.txt.code.
Немного двусмысленно, приемлемо это или нет.
Наконец, вы можете использовать std::string
методы find
, и replace
чтобы получить имя файла без расширения и использовать его.
Другие советы
Иногда я задаю себе этот вопрос и попадаю на эту страницу, поэтому на будущее привожу однострочный синтаксис:
string newfilename=filename.substr(0,filename.find_last_of('.'))+".code";
Конечно, если бы это было не домашнее задание, а реальный проект, вы, вероятно, оказали бы себе, а также другим людям, читающим ваш код, услугу, используя Boost.Файловая система's replace_extension()
вместо того, чтобы катить свой собственный.Просто не существует настолько простой функциональности, в которой нельзя было бы найти ошибку, по крайней мере, в каком-то крайнем случае.
Не хочу этого выдавать, поскольку в обучении и заключается весь смысл упражнения, но вот подсказка.Вероятно, вам понадобится комбинация find_last_of
и replace
.
Вот несколько советов.У вас уже введено имя файла — вам нужно получить часть имени файла, которая не включает расширение:
std::string basename(const std::string &filename)
{
// fill this bit in
}
Написав эту функцию, вы можете использовать ее для создания имени нового файла:
std::string codeFile = basename(filename) + ".code";
outFile.open(codeFile);
Псевдокод должен был бы сделать что-то вроде
outFilename = filename;
<change outFilename>
outfile.open(outFilename);
Для изменения outFilename посмотрите на strrchr и strcpy как на отправную точку (возможно, это более подходящие методы - хотя они отлично работают с char*)
В Windows (по крайней мере) вы можете использовать _splitpath чтобы отделить базовое имя от остальных частей, а затем собрать их заново с помощью любимого средства форматирования строк.
почему бы не использовать строковый метод find_last_of()
?
std::string new_filename = filename;
size_type result = new_filename.find_last_of('.');
// Does new_filename.erase(std::string::npos) working here in place of this following test?
if (std::string::npos != result)
new_filename.erase(result);
// append extension:
filename.append(".code");
Я бы просто добавил «.code» к имени файла, введенному пользователем.Если они введут «test.txt», то выходной файл будет «test.txt.code».Если они введут имя файла без расширения, например «test», то выходным файлом будет «test.code».
Я постоянно использую этот метод с программами, которые генерируют выходные файлы и какие-то соответствующие выходные данные для регистрации/диагностики.Его просто реализовать, и, на мой взгляд, он делает отношения между файлами более явными.
Как насчет использования strstr:
char* lastSlash;
char* newExtension = ".code";
ChangeFileExtension(char* filename) {
lastSlash = strstr(filename, ".");
strcpy(lastSlash, newExtension);
}
Вам нужно будет скопировать исходное имя файла в новую переменную, где вы сможете изменить расширение.Что-то вроде этого:
string outFilename;
size_t extPos = filename.rfind('.');
if (extPos != string::npos)
{
// Copy everything up to (but not including) the '.'
outFilename.assign(filename, 0, extPos);
// Add the new extension.
outFilename.append(".code");
// outFilename now has the filename with the .code extension.
}
Возможно, вы можете использовать переменную «имя файла», если вам не нужно сохранять исходное имя файла для дальнейшего использования.В этом случае вы можете просто использовать:
size_t extPos = filename.rfind('.');
if (extPos != string::npos)
{
// Erase the current extension.
filename.erase(extPos);
// Add the new extension.
filename.append(".code");
}
Главное — взглянуть на определение строкового класса C++ и понять, что делает каждая функция-член.Использование rfind будет выполнять поиск по строке в обратном направлении, и вы случайно не встретите какие-либо расширения в именах папок, которые могут быть частью исходного имени файла (например,«C:\MyStuff.School\MyFile.txt»).При работе со смещениями find, rfind и т. д. вам также следует быть осторожными и правильно использовать их при передаче в качестве счетчиков другим методам (например,вы используете назначение (имя файла, 0, extPos-1), назначение (имя файла, 0, extPos), назначение (имя файла, 0, extPos + 1)).
Надеюсь, это поможет.
size_t pos = filename.rfind('.');
if(pos != string::npos)
filename.replace(pos, filename.length() - pos, ".code");
else
filename.append(".code");
Очень просто:
string str = "file.ext";
str[str.size()-3]='a';
str[str.size()-2]='b';
str[str.size()-1]='c';
cout<<str;
Результат:"файл.abc"