如何在C ++中更改存储在字符串中的文件扩展名?

时间:2022-09-02 09:04:59

Alright here's the deal, I'm taking an intro to C++ class at my university and am having trouble figuring out how to change the extension of a file. First, what we are suppose to do is read in a .txt file and count words, sentences, vowels etc. Well I got this but the next step is what's troubling me. We are then suppose to create a new file using the same file name as the input file but with the extension .code instead of .txt (in that new file we are then to encode the string by adding random numbers to the ASCII code of each character if you were interested). Being a beginner in programming, I'm not quite sure how to do this. I'm using the following piece of code to at first get the input file:

好的,这是交易,我正在我的大学介绍C ++课程,并且无法弄清楚如何更改文件的扩展名。首先,我们要做的是在.txt文件中读取并计算单词,句子,元音等。我得到了这个,但下一步是令我不安的。然后我们假设使用与输入文件相同的文件名创建一个新文件,但扩展名为.code而不是.txt(在新文件中,我们将通过向每个ASCII码添加随机数来对字符串进行编码你感兴趣的角色)。作为编程的初学者,我不太清楚如何做到这一点。我正在使用以下代码来获取输入文件:

cout << "Enter filename: ";
cin >> filename;
infile.open(filename.c_str());

I'm assuming to create a new file I'm going to be using something like:

我假设要创建一个新文件,我将使用类似的东西:

outfile.open("test.code");

But I won't know what the file name is until the user enters it so I can't say "test.txt". So if anyone knows how to change that extenstion when I create a new file I would very much appreciate it!

但是在用户输入之前我不知道文件名是什么,所以我不能说“test.txt”。因此,如果有人知道在创建新文件时如何更改该扩展,我将非常感激!

13 个解决方案

#1


There are several approaches to this.

有几种方法可以解决这个问题。

You can take the super lazy approach, and have them enter in just the file name, and not the .txt extension. In which case you can append .txt to it to open the input file.

您可以采用超级惰性方法,让它们只输入文件名,而不是.txt扩展名。在这种情况下,您可以将.txt附加到它以打开输入文件。

infile.open(filename + ".txt");

Then you just call

然后你就打电话

outfile.open(filename + ".code");

The next approach would be to take the entire filename including extension, and just append .code to it so you'd have test.txt.code.

接下来的方法是获取整个文件名,包括扩展名,然后将.code附加到它,这样你就有了test.txt.code。

It's a bit ambiguous if this is acceptable or not.

如果这是可以接受的话,这有点模棱两可。

Finally, you can use std::string methods find, and replace to get the filename with no extension, and use that.

最后,您可以使用std :: string方法查找,并使用replace来获取没有扩展名的文件名,并使用它。

#2


Of course, if this were not homework but a real-world project, you'd probably do yourself -- as well as other people reading your code -- a favor by using Boost.Filesystem's replace_extension() instead of rolling your own. There's just no functionality that is simple enough that you couldn't come up with a bug, at least in some corner case.

当然,如果这不是家庭作业而是现实世界的项目,你可能会自己做 - 以及其他人阅读你的代码 - 通过使用Boost.Filesystem的replace_extension()而不是自己滚动来帮助你。没有足够简单的功能,你无法想出一个bug,至少在一些极端情况下。

#3


I occasionally ask myself this question and end up on this page, so for future reference, here is the single-line syntax:

我偶尔会问自己这个问题并最终在这个页面上,所以为了将来的参考,这里是单行语法:

string newfilename=filename.substr(0,filename.find_last_of('.'))+".code";

#4


Not to give it away since learning is the whole point of the exercise, but here's a hint. You're probably going to want a combination of find_last_of and replace.

不要放弃,因为学习是练习的重点,但这是一个暗示。你可能想要find_last_of和replace的组合。

#5


Here is a few hints. You have a filename already entered - what you want to do is get the part of the filename that doesn't include the extension:

这里有一些提示。您已经输入了文件名 - 您要做的是获取不包含扩展名的文件名部分:

std::string basename(const std::string &filename)
{
  // fill this bit in
}

Having written that function, you can use it to create the name of the new file:

编写该函数后,您可以使用它来创建新文件的名称:

std::string codeFile = basename(filename) + ".code";
outFile.open(codeFile);

#6


Pseudo code would be to do something like

伪代码就是做类似的事情

outFilename = filename;
<change outFilename>
outfile.open(outFilename);

For changing outFilename, look at strrchr and strcpy as a starting point (might be more appropriate methods -- that would work great with a char* though)

要更改outFilename,请查看strrchr和strcpy作为起点(可能是更合适的方法 - 虽然可以很好地使用char *)

#7


In Windows (at least) you can use _splitpath to dissect the base name from the rest of the pieces, and then reassemble them using your favorite string formatter.

在Windows(至少)中,您可以使用_splitpath从其余部分中剖析基本名称,然后使用您喜欢的字符串格式化程序重新组合它们。

#8


why not using the string method find_last_of() ?

为什么不使用字符串方法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");

#9


I would just append ".code" to the filename the user entered. If they entered "test.txt" then the output file would be "test.txt.code". If they entered a file name with no extension, like "test" then the output file would be "test.code".

我只是将“.code”附加到用户输入的文件名中。如果他们输入“test.txt”,那么输出文件将是“test.txt.code”。如果他们输入的文件名没有扩展名,例如“test”,那么输出文件将是“test.code”。

I use this technique all the time with programs that generate output files and some sort of related logging/diagnostic output. It's simple to implement and, in my opinion, makes the relationships between files much more explicit.

我一直使用这种技术生成输出文件和某种相关的日志/诊断输出的程序。它实现起来很简单,在我看来,它使文件之间的关系更加明确。

#10


How about using strstr:

如何使用strstr:

char* lastSlash;
char* newExtension = ".code";
ChangeFileExtension(char* filename) {
    lastSlash = strstr(filename, ".");
    strcpy(lastSlash, newExtension);
}

#11


size_t pos = filename.rfind('.');
if(pos != string::npos)
    filename.replace(pos, filename.length() - pos, ".code");
else
    filename.append(".code");

#12


What you'll need to do is copy the original filename into a new variable where you can change the extension. Something like this:

您需要做的是将原始文件名复制到一个新变量中,您可以在其中更改扩展名。像这样的东西:

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.
}

It's possible you could use the "filename" variable if you don't need to keep the original filename around for later use. In that case you could just use:

如果您不需要保留原始文件名以供以后使用,则可以使用“filename”变量。在这种情况下,您可以使用:

size_t extPos = filename.rfind('.');
if (extPos != string::npos)
{
    // Erase the current extension.
    filename.erase(extPos);
    // Add the new extension.
    filename.append(".code");
}

The key is to look at the definition of the C++ string class and understand what each member function does. Using rfind will search backwards through the string and you won't accidentally hit any extensions in folder names that might be part of the original filename (e.g. "C:\MyStuff.School\MyFile.txt"). When working with the offsets from find, rfind, etc., you'll also want to be careful to use them properly when passing them as counts to other methods (e.g. do you use assign(filename, 0, extPos-1), assign(filename, 0, extPos), assign(filename, 0, extPos+1)).

关键是要查看C ++字符串类的定义并理解每个成员函数的作用。使用rfind将向后搜索字符串,您不会意外地访问可能是原始文件名的一部分的文件夹名称中的任何扩展名(例如“C:\ MyStuff.School \ MyFile.txt”)。当使用find,rfind等的偏移时,你还需要小心地将它们作为计数传递给其他方法时使用它们(例如你使用assign(filename,0,extPos-1),assign (filename,0,extPos),assign(filename,0,extPos + 1))。

Hope that helps.

希望有所帮助。

#13


Very Easy:

string str = "file.ext";

str[str.size()-3]='a';
str[str.size()-2]='b';
str[str.size()-1]='c';

cout<<str;

Result: "file.abc"

#1


There are several approaches to this.

有几种方法可以解决这个问题。

You can take the super lazy approach, and have them enter in just the file name, and not the .txt extension. In which case you can append .txt to it to open the input file.

您可以采用超级惰性方法,让它们只输入文件名,而不是.txt扩展名。在这种情况下,您可以将.txt附加到它以打开输入文件。

infile.open(filename + ".txt");

Then you just call

然后你就打电话

outfile.open(filename + ".code");

The next approach would be to take the entire filename including extension, and just append .code to it so you'd have test.txt.code.

接下来的方法是获取整个文件名,包括扩展名,然后将.code附加到它,这样你就有了test.txt.code。

It's a bit ambiguous if this is acceptable or not.

如果这是可以接受的话,这有点模棱两可。

Finally, you can use std::string methods find, and replace to get the filename with no extension, and use that.

最后,您可以使用std :: string方法查找,并使用replace来获取没有扩展名的文件名,并使用它。

#2


Of course, if this were not homework but a real-world project, you'd probably do yourself -- as well as other people reading your code -- a favor by using Boost.Filesystem's replace_extension() instead of rolling your own. There's just no functionality that is simple enough that you couldn't come up with a bug, at least in some corner case.

当然,如果这不是家庭作业而是现实世界的项目,你可能会自己做 - 以及其他人阅读你的代码 - 通过使用Boost.Filesystem的replace_extension()而不是自己滚动来帮助你。没有足够简单的功能,你无法想出一个bug,至少在一些极端情况下。

#3


I occasionally ask myself this question and end up on this page, so for future reference, here is the single-line syntax:

我偶尔会问自己这个问题并最终在这个页面上,所以为了将来的参考,这里是单行语法:

string newfilename=filename.substr(0,filename.find_last_of('.'))+".code";

#4


Not to give it away since learning is the whole point of the exercise, but here's a hint. You're probably going to want a combination of find_last_of and replace.

不要放弃,因为学习是练习的重点,但这是一个暗示。你可能想要find_last_of和replace的组合。

#5


Here is a few hints. You have a filename already entered - what you want to do is get the part of the filename that doesn't include the extension:

这里有一些提示。您已经输入了文件名 - 您要做的是获取不包含扩展名的文件名部分:

std::string basename(const std::string &filename)
{
  // fill this bit in
}

Having written that function, you can use it to create the name of the new file:

编写该函数后,您可以使用它来创建新文件的名称:

std::string codeFile = basename(filename) + ".code";
outFile.open(codeFile);

#6


Pseudo code would be to do something like

伪代码就是做类似的事情

outFilename = filename;
<change outFilename>
outfile.open(outFilename);

For changing outFilename, look at strrchr and strcpy as a starting point (might be more appropriate methods -- that would work great with a char* though)

要更改outFilename,请查看strrchr和strcpy作为起点(可能是更合适的方法 - 虽然可以很好地使用char *)

#7


In Windows (at least) you can use _splitpath to dissect the base name from the rest of the pieces, and then reassemble them using your favorite string formatter.

在Windows(至少)中,您可以使用_splitpath从其余部分中剖析基本名称,然后使用您喜欢的字符串格式化程序重新组合它们。

#8


why not using the string method find_last_of() ?

为什么不使用字符串方法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");

#9


I would just append ".code" to the filename the user entered. If they entered "test.txt" then the output file would be "test.txt.code". If they entered a file name with no extension, like "test" then the output file would be "test.code".

我只是将“.code”附加到用户输入的文件名中。如果他们输入“test.txt”,那么输出文件将是“test.txt.code”。如果他们输入的文件名没有扩展名,例如“test”,那么输出文件将是“test.code”。

I use this technique all the time with programs that generate output files and some sort of related logging/diagnostic output. It's simple to implement and, in my opinion, makes the relationships between files much more explicit.

我一直使用这种技术生成输出文件和某种相关的日志/诊断输出的程序。它实现起来很简单,在我看来,它使文件之间的关系更加明确。

#10


How about using strstr:

如何使用strstr:

char* lastSlash;
char* newExtension = ".code";
ChangeFileExtension(char* filename) {
    lastSlash = strstr(filename, ".");
    strcpy(lastSlash, newExtension);
}

#11


size_t pos = filename.rfind('.');
if(pos != string::npos)
    filename.replace(pos, filename.length() - pos, ".code");
else
    filename.append(".code");

#12


What you'll need to do is copy the original filename into a new variable where you can change the extension. Something like this:

您需要做的是将原始文件名复制到一个新变量中,您可以在其中更改扩展名。像这样的东西:

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.
}

It's possible you could use the "filename" variable if you don't need to keep the original filename around for later use. In that case you could just use:

如果您不需要保留原始文件名以供以后使用,则可以使用“filename”变量。在这种情况下,您可以使用:

size_t extPos = filename.rfind('.');
if (extPos != string::npos)
{
    // Erase the current extension.
    filename.erase(extPos);
    // Add the new extension.
    filename.append(".code");
}

The key is to look at the definition of the C++ string class and understand what each member function does. Using rfind will search backwards through the string and you won't accidentally hit any extensions in folder names that might be part of the original filename (e.g. "C:\MyStuff.School\MyFile.txt"). When working with the offsets from find, rfind, etc., you'll also want to be careful to use them properly when passing them as counts to other methods (e.g. do you use assign(filename, 0, extPos-1), assign(filename, 0, extPos), assign(filename, 0, extPos+1)).

关键是要查看C ++字符串类的定义并理解每个成员函数的作用。使用rfind将向后搜索字符串,您不会意外地访问可能是原始文件名的一部分的文件夹名称中的任何扩展名(例如“C:\ MyStuff.School \ MyFile.txt”)。当使用find,rfind等的偏移时,你还需要小心地将它们作为计数传递给其他方法时使用它们(例如你使用assign(filename,0,extPos-1),assign (filename,0,extPos),assign(filename,0,extPos + 1))。

Hope that helps.

希望有所帮助。

#13


Very Easy:

string str = "file.ext";

str[str.size()-3]='a';
str[str.size()-2]='b';
str[str.size()-1]='c';

cout<<str;

Result: "file.abc"