views:

1110

answers:

8

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:

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!

+3  A: 

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);
1800 INFORMATION
Don't forget to test. I like naming my files.like.this
veefu
A: 

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)

DougN
Why suggest C style methods when the code is C++?
Greg Domjan
+3  A: 

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.

Eclipse
+3  A: 

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.

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.

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.

Alan
Alright, I think there options are more along the lines of what I was looking for as we just recently learned about string methods. Thanks for the input!
Mr. Ben
Better rfind() as it will find the last "." instead of the first in the case that 'a.b.c.txt' is a valid filename
David Rodríguez - dribeas
.open( ) takes a const char*, not a std::sting unfortunately.
MSalters
A: 

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:

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

Hope that helps.

Neal S.
Since it is a homework question, please do not give away everything
1800 INFORMATION
+6  A: 

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.

Pukku
A: 

why not using the string method 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");
yves Baumes
A: 

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.

John Dibling