File Path Name and User Input - c++

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

Related

std::fstream different behavior on msvc and g++ with utf-8

std::string path("path.txt");
std::fstream f(path);
f.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::string lcpath;
f >> lcpath;
Reading a utf-8 text from path.txt on windows fails with MSVC compiler on windows in the sense lcpath does not understand the path as utf-8.
The below code works correctly on linux when compiled with g++.
std::string path("path.txt");
std::fstream ff;
ff.open(path.c_str());
std::string lcpath;
ff>>lcpath;
Is fstream on windows(MSVC) by default assume ascii only?
In the first snippet if I change string with wstring and fstream with wfstream, lcpath gets correct value on windows as well.
EDIT: If I convert the read lcpath using MultiByteToWideChar(), I get the correct representation. But why can't I directly read a UTF-8 string into std::string on windows?
Imbuing an opened file can be problamatic:
http://www.cplusplus.com/reference/fstream/filebuf/imbue/
If loc is not the same locale as currently used by the file stream buffer, either the internal position pointer points to the beginning of the file, or its encoding is not state-dependent. Otherwise, it causes undefined behavior.
The problem here is that when a file is opened and the file has a BOM marker in it this will usually be read from the file by the currently installed local. Thus the position pointer is no longer at the beginning of the file and we have undefined behavior.
To make sure your local is set correctly you must do it before opening the file.
std::fstream f;
f.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::string path("path.txt");
f.open(path);
std::string lcpath;
f >> lcpath;

Implicit file extension using fopen in C++

I'm working on a project where I'm required to take input from a file with an extension ".input". when run, the user gives the filename without the file extension as a command line argument. I then take that argument, argv[1] and open the file specified but I can't get it to work without the user typing in the entire filename
for example:
user enters> run file.input
//"run" is the executable, "file.input" is the filename
user is supposed to enter> run file
how do I get this file extension implied when using this code:
fopen(argv[1],"r");
I tried using a string, setting it to argv[1] and then appending ".input" to it but fopen won't accept that string.
Without seeing your code, I can't say for certain what went wrong, but I suspect you did something like this:
string filename = argv[1];
filename += ".input";
FILE* f = fopen(filename, "r"); // <--- Error here
The issue here is that the C++ std::string type is not a char *, which is what's expected by fopen. To fix this, you can use the .c_str() member function of the std::string type, which gives back a null-terminated C-style string:
FILE* f = fopen(filename.c_str(), "r"); // No more errors!
As I mentioned in my comment, though, I think you'd be better off just using ifstream:
string filename = argv[1];
filename += ".input";
ifstream input(filename);
There's no longer a need for .c_str(), and you don't need to worry about leaking resources. Everything's managed for you. Plus, it's type-safe!

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

open file by its full path

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

need help to getin ifstream::open to open a file and getline from it

I am just trying to open this file and use the getline function to read from the file but I cant seem to figure out why it is not working. I have stepped through it many times and the fileOpen variable is being loaded correctly with the file im trying to open, so Im unsure on why it wont open, to use getline with it. I would just like to be able to read through the file with getline, all of this is done in a recursive function to eventually read through all the files in directories. Let me know if you need more information on what exactly im doing.
string line;
ifstream file;
string fileOpen;
bf::directory_iterator dirIter ( fullPath ); //fullPath is type bf::path, passed into the function
fileOpen = (dirIter->path().filename());
file.open(fileOpen);
getline(file, line);
The path::filename function returns the base filename. If you have a path of "foo\bar.txt", path::filename will return "bar.txt". So unless "foo\" is in the current directory, the file probably doesn't exist.
What you're more likely looking for is this:
file.open(dirIter->path().native());
Or, you can use the boost::filesystem iostream types:
#include <boost/filesystem/fstream>
bf::ifstream file;
bf::directory_iterator dirIter ( fullPath ); //fullPath is type bf::path, passed into the function
file.open(dirIter->path());