open file by its full path - c++

I want to ask user the full path where the file exists and then keep the path in an array. So during the program I want to open the file that is exists in that place.
but unfortunately I don't know how to open the file.
I tried the following code but it's not true.
string address;
cin>>address;
ifstream file(address);
How do I open the file this way?

Actually that code works as it is – at least in the current version, C++11.
Before that, you need to convert the string to a C-style string:
ifstream file(address.c_str());
Although you should beware of spaces in the file’s path as CapelliC mentioned in his (now-deleted) answer; in order to ensure that the user can enter paths with spaces (such as “~/some file.txt”), use std::getline instead of the stream operator:
getline(cin, address);

ofstream myfile;
myfile.open (adresse.c_str());

possibily a problem could be the presence of space in address.
Try using getline(cin, address) instead (thanks to Konrad to spot the problem, my C++ it's a bit rusty...)

Related

The program doesn't seem to be saving the input data correctly (c++)

So, I want my program to read data from a file, and save it into different quarter1, quarter2,quarter3, quarter4 depending of it's date, but it doesn't seem to work properly and still don't know why, I've been trying to debug and I'm pretty sure it fails when saving at saveQuarters or existeix which is basically a dichothomic search which returns if the code exists and if it exists, it returns the position. This is the code:
I just skimmed through some of the stuff you had so this suggestion may not work, but you can try declaring your file as input or output. Perhaps that could be the problem.
Some thing like:
string fileName = "data.txt";
ifstream dataFile;
dataFile.open(fileName, ios::in);
Doing this:
fitxerCens >> taulaCens[i].stateName;
Will grab an entire line of the data file until it sees a space is correct.

File Path Name and User Input

I am trying to have the user input the file path of a file to be read by my program. However, when I try to compile the code, it errors, with the following error: no matching function to call to 'std::basic_ifstream::open(std::string&)'. The code works correctly with no errors when I directly enter the file instead of using getline or cin. I don't know what is the problem. Any suggestions?
int main()
{
ifstream input_file;
string file_name;
cout<< "Please input file path to PostFix arithmetic expressions file\n";
getline(cin, file_name);
input_file.open(file_name);
read_and_evaluate(input_file);
}
You need to compile as C++11 in order to get an ifstream constructor or open member function that takes a std::string argument. With g++ use the -std=c++11 option.
In C++03 iostream constructors only supported C strings, which you can get via std::string::c_str().
Do note that regardless of C string or std::string, in Windows this will fail to open a file with non-ANSI characters in the path, unless you first shorten the path to DOS 8.3 path items (which are pure ASCII).

Brought a Linux C++ Console Application to a Win32 C++ App using VS2010 and the search function from <algorithm> is no longer working

Just like the title says, I've been working on a fairly large program and have come upon this bug. I'm also open to alternatives for searching a file for a string instead of using . Here is my code narrowed down:
istreambuf_iterator<char> eof;
ifstream fin;
fin.clear();
fin.open(filename.c_str());
if(fin.good()){
//I outputted text to a file to make sure opening the file worked, which it does
}
//term was not found.
if(eof == search(istreambuf_iterator<char>(fin), eof, term.begin(), term.end()){
//PROBLEM: this code always executes even when the string term is in the file.
}
So just to clarify, my program worked correctly in Linux but now that I have it in a win32 app project in vs2010, the application builds just fine but the search function isn't working like it normally did. (What I mean by normal is that the code in the if statement didn't execute because, where as now it always executes.)
NOTE: The file is a .xml file and the string term is simply "administration."
One thing that might or might not be important is to know that filename (filename from the code above) is a XML file I have created in the program myself using the code below. Pretty much I create an identical xml file form the pre-existing one except for it is all lower case and in a new location.
void toLowerFile(string filename, string newloc, string& newfilename){
//variables
ifstream fin;
ofstream fout;
string temp = "/";
newfilename = newloc + temp + newfilename;
//open file to read
fin.open(filename.c_str());
//open file to write
fout.open(newfilename.c_str());
//loop through and read line, lower case, and write
while (fin.good()){
getline (fin,temp);
//write lower case version
toLowerString(temp);
fout << temp << endl;
}
//close files
fout.close();
fin.close();
}
void toLowerString(string& data){
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
}
I'm afraid your code is invalid - the search algorithm requires forward iterators, but istreambuf_iterator is only an input iterator.
Conceptually that makes sense - the algorithm needs to backtrack on a partial match, but the stream may not support backtracking.
The actual behaviour is undefined - so the implementation is allowed to be helpful and make it seem to work, but doesn't have to.
I think you either need to copy the input, or use a smarter search algorithm (single-pass is possible) or a smarter iterator.
(In an ideal world at least one of the compilers would have warned you about this.)
Generally, with Microsoft's compiler, if your program compiles and links a main() function rather than a wmain() function, everything defaults to char. It would be wchar_t or WCHAR if you have a wmain(). If you have tmain() instead, then you are at the mercy of your compiler/make settings and it's the UNICODE macro that determines which flavor your program uses. But I doubt that char_t/wchar_t mismatch is actually the issue here because I think you would have got an warning or error if all four of the search parameters didn't use the same the same character width.
This is a bit of a guess, but try this:
if(eof == search(istreambuf_iterator<char>(fin.rdbuf()), eof, term.begin(), term.end())

redirecting input in c++

i was told that to redirect from standard input to file i need to do the following:
static std::ifstream inF("inpur.txt");
std::cin.rdbuf(inF.rdbuf());
and every call to std::cin will be redirected to input.txt.
but my question is: do i need to open inF? and if i do, where do i need to do this?
You opened it by calling it with the string constructor.
That's the beauty. You already did so while declaring the object and passing the string to the explicit constructor of ifstream.
The file is opened in TEXT mode.
Refer this
Your code as-is fine. Do make a backup though of the original cin.rdbuf -- you may need to reset it in case of an error.

How do you change the filename extension stored in a string in C++?

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!
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";
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.
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.
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.
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);
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)
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.
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");
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".
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.
How about using strstr:
char* lastSlash;
char* newExtension = ".code";
ChangeFileExtension(char* filename) {
lastSlash = strstr(filename, ".");
strcpy(lastSlash, newExtension);
}
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.
size_t pos = filename.rfind('.');
if(pos != string::npos)
filename.replace(pos, filename.length() - pos, ".code");
else
filename.append(".code");
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"