c++ not able to find file (i think) - c++

I have the following code (simplified)
int main()
{
ifstream myFile("input.txt");
if(myFile.is_open())
cout<<"test";
}
However myFile.is_open() is returning false;
why?
I'm using eclipse and the input.txt file is right in the src folder with the .cpp file...
Thanks!

Every executable is - by default - ran from the directory of your project. So for a tree like this:
project
|- src
| |- a.cpp
| |- b.cpp
| |- foo.txt
|
|- Debug
| |- a.exe
|
|- foo2.txt
You shall use the paths like src/foo.txt or foo2.txt. Your exe is located in Debug directory, but it will be ran from your project's directory anyway. In this way, every build configuration's executables are ran in the same way (from the same place).
You can change your working directory and arguments under Run configurations (pull-down menu next to the "run" icon). Switch to tab "Arguments", uncheck "use default" and set whichever you'd like if the default's not OK for you.

You have the input.txt in your source folder but the application is executed from the Debug folder; from the 'source', it's located at ..\Debug. Just put your text file there and it should work fine.

If you do not specify a full path, the program will search in the current directory, that probably in your case is the directory where the executable is built edit: it turns out that by default it's the project directory (thanks #Kos).
You can move input.txt in that directory, specify a full path (or a correct relative one) or instruct your IDE to start the executable with a different current directory (I don't know if with Eclipse it's possible, I suggest this because with VS you can do that).
By the way, in general you should avoid to hardcode paths in your sources.

Check the working directory Eclipse sets for you. It might be that of the binary. Try placing the input.txt file in the same directory as that of the binary Eclipse compiles from your code, and then run the application.
To find the working directory setting of your project look in the project's settings dialog.
That said, it's probably a good idea to code in a manner independent from your working directory. You might set the binary's install directory in preprocessor constant string, and have your install script (or configuration script) set that #define to the proper directory. Or, if that's not an option, then you might fetch the directory value at runtime.

You probably have to set up eclipse's working directory to your src directory. I have no idea what the default is.

Related

File not being created in correct directory C++

I'm trying to use fstream to create a file, however the file i'm trying to create wont appear in the .exe directory or anywhere else in the file directory. After searching in my computer for the file, I found that was created in a different directory entirely even though i'm using a relative directory.
This is the code to create the file:
ofstream file;
file.open("something.jpg", ios::out|ios::binary|ios::beg);
Directory of created file: C:\Users\user-pc
Directory of project: D:\Users\user-pc\Documents\Visual Studio 2012\Projects\recvFile
by the way, using an absolute directory works perfectly fine. Could this be a problem with the projects working directory?
In your Visual Studio right-click on your project, click Properties, then go to Configuration Properties, then Debugging. There is a row "Working Directory". You can set the working directory there. If you need to do this programmatically, you can use SetCurrentDirectory .
If you need to create the file in the same directory as the .exe location, you can use this approach: https://stackoverflow.com/a/124901/1915854
Call GetModuleFileName() using 0 as a module handle...
If the .exe is installed in a shared directory like Program Files, then creation of the file in the same directory could require additional permissions and may be a bad idea. If the .exe is just cloned to the directory where it should create files, then there is no such problem.
Try adding "../" to the link:
file.open("../something.jpg", ios::out|ios::binary|ios::beg);
File will be created in Debug/Release folder of your project. try what Timo Rzipa suggested.

New to Xcode can't open files in c++?

I've been using windows in a class I've been taking but I am trying to run a basic code to figure out how to open/close/input/output from files on Xcode and the code I usually use on visual studios isn't working any idea why? thanks!
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream fin;
ofstream fout;
string input;
fin.open("inputFile.txt");
if(fin.fail())
cout << "File failed to open." << endl;
fin >> input;
fout.open("outputFile.txt");
fout << input;
}
Put your .txt files in the same directory where your main.cpp file is (or anywhere you like).
In Xcode go to Product > Scheme > Edit Scheme > Run (on the left) > Options (middle top)
Down under Options for "Working Directory" check “Use custom working directory” and set it to the directory where you .txt files are located.
To work with the files, you will have to specify just file names, e.g. in_file.open("inputFile.txt"); no path is necessary.
Here's a completely different approach: Have Xcode copy the input file for you.
Select your project in Xcode
Select Build Phases
Click the '+' button to create a new Build Phase
Select New Copy Files Build Phase
Select Products Directory
Click the '+' button to add your file
Click Add Other
Select your input file and click Open
Check the Copy items… checkbox and click Finish
Now every time you build your project, the input file will be copied to the same folder as the executable no matter where it is built. Of course, to see the output file, you'll still need to find the executable in Finder.
The answers don't really explain the problem so I thought I'd do that.
When you pass a relative path like "inputFile.txt" to file APIs, it's treated as relative to the working directory when the program is executed. This is the same as the 'working directory' when you use cmd.exe or Terminal.app or command lines in general. The Unix command pwd ("print working directory") displays the current working directory. On Windows running the command cd with no arguments performs the same function. (On Unix running cd with no arguments will change the working directory to the user's home directory.)
When you run a program from the command line, the command line shell sets the program's working directory. When you run a program from within an IDE, the IDE sets the working directory. Since, unlike on a command line, there's no obvious answer for what the IDE should set as the working directory, Visual Studio and Xcode set the working directory to different locations by default: Visual Studio sets the working directory to $(ProjectDir), the directory containing the Visual Studio project file; Xcode sets the working directory to the build products directory, i.e. the location the executable was written to.
Some possible solutions to your problem are:
Do not use a relative path, and therefore don't depend on the working directory. This isn't much help in making the program more portable, because the absolute paths will also differ between platforms, and so you will still have to 'configure' the program for each platform. In fact using an absolute path is worse, because it means your source code must differ, whereas it would be better to keep that difference confined to each platform's build configuration.
Configure the IDE to use your desired working directory. Visual Studio can be configured by right clicking the project, selecting Configuration Properties > Debugging > Working Directory, and setting the working directory to the desired path (potentially using Visual Studio build variables).
nepete's answer describes how to configure the working directly set by Xcode.
Configure the IDE's build process to copy your data files to an appropriate location. In Visual Studio you would do this in a C++ project by configuring the project's Properties > Configuration Properties > Build Events.
SSteve's answer covers how to configure additional build steps in Xcode.
I'm guessing you have inputFile.txt in the folder that contains your source code. That's not going to work. You need to put it in the folder that contains the generated executable. To find that folder, right-click on your app under Products and select Show In Finder.
This image shows what it looks like for a command line program. It also shows the Finder window that was opened. As you can see, it is a different folder than the one containing the source code.
As suggested by nepete, edit the scheme, but use $PROJECT_DIR as the custom working directory. Helps with moving the project around, or working in two different environments (e.g., home and office).
BTW. $PROJECT_DIR is one of the Xcode Environment Variables, and also helps with passing file names as command line arguments to programs (settable under "Arguments" in the scheme).
I've struggled with the same problem today. I wanted to add C code to my Swift project and my file pointer was always NULL.
Unfortunately, in XCode 9 for iOS app, I couldn't change the working directory. Changing Build phases didn't help me either. After 4+ hours of trial and error, that's what I've come up with finally and it works:
when copying files to XCode, I've chosen "Create groups", but I needed to choose "Create folder references":
I created a new objective-c file (.m) and copied all my C code there.
I left untouched .h files (XCode generated bridging header and my own .h file with public functions declaration). Now my project structure looked like this:
In my dict.m file in place of previous plain c fopen part:
FILE *dic = fopen("dictionary.txt", "r");
I added obj-C code:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"dictionary" ofType:#"txt"];
FILE *dic = fopen([filePath cStringUsingEncoding: NSUTF8StringEncoding], "r");
And it works now without any problem! It's just amazing!
ps I decided to write this answer in case it will help someone like me and will save them some time. If you know how to change working directory in XCode 9 for iOS, please, leave me a comment - now I am really curious why I can't find it.

Different paths used for #include and other files

I'm quite confused about this weird behaviour of my .cpp project. I've got the following folder structure:
include/mylib.h
myproject/src/eval.cpp
myproject/data/file.csv
myproject/Makefile
In eval.cpp I include mylib.h as follows:
#include "../../include/mylib.h"
and compile it through Makefile:
all:
g++ -I include ../include/mylib.h src/eval.cpp -o eval.out
Now in my eval.cpp I'm reading the file.csv from data directory and if I refer to it like this
../data/file.csv
it doesn't find it (gets empty lines all the time), but this
data/file.csv
works fine.
So, to include mylib.h it goes two directories up (from src folder) which seems right. But it doesn't make sense to me that to refer to another file from the same piece of code it assumes we are in project directory. I suppose it is connected with Makefile somehow, but I'm not sure.
Why is it so?
EDIT: After a few thing I tried it seems that the path which is used is not the path from binary location to the data location, but depends on where from I run the binary as well. I.e., if I have binary in bin directory and run it like:
./bin/eval.out
It works with data/file.csv.
This:
cd bin
./eval.out
works with ../data/file.csv.
Now it seems very confusing to me as depending on where I run the program from it will give different output. Can anyone please elaborate on the reasons for this behaviour and if it is normal or I'm making some mistake?
It is so because (as explained here ) the compiler will search for #included files with quotes (not with brackets) with the current working directory being the location of the source file.
Then, when you try to open your .csv file, it's now your program that looks for a file. But your program runs with the current working directory being myproject/ which explains why you must specify data/file.csv as your file path, and not ../data/file.csv. Your program does not run in your src folder, it will run in the directory the binary ends up being invoked from.
You could have noticed that in your Makefile, your -I options specify a different path for your header file than your .cpp file.
EDIT Answer: It's quite simple actually and completely normal. When you invoke your binary, the directory which you're in is the current working directory. That is, if you run it with the command ./myproject/bin/eval.out, the current working directory is . (e.g. /home/the_user/cpp_projects). My post was a bit misleading about that, I corrected it.
Note: You can use the command pwd in a command prompt to know which is the current working directory of this prompt (pwd stands for "print working directory").

Relative path problem - one dir up

This is workig:
I have my exe in the same directory as Images folder;
Main:
|-Images
|-cross_ball
|-frame.bmp
|-game.exe
I'm refering to frame.bmp in my game.exe.
This path is workig good: "Images\\cross_ball\\frame.bmp"
This is not working:
Exe is in bin folder. bin folder is in the same folder as Images folder;
Main:
|-Images
|-cross_ball
|-frame.bmp
|-bin
|-game.exe
This path is not working: "..\\Images\\cross_ball\\frame.bmp"
If "Images\cross_ball\frame.bmp" is working, then your app's current directory isn't the Images directory like you think it is. It must be one dir up for that to work. That would also explain why moving the exe to the bin directory fails.
Are you starting your app from a shortcut or in a debugger? Shortcuts and debuggers specify the app's current directory, which isn't necessarily the same directory the exe is in.
As an experiment, replace each \ by \\ and test again.
Back slash is generally used for escape sequences like '\n'.
By putting two of them together, the run time ought to change them into one.
"Images\\cross_ball\\frame.bmp"
It appears that your logic is fine. Are you sure your process hasn't changed the current working directory - i.e. Main/bin/ might not be your working directory when you go to make this change in the executable.

how to write path of external file in an included c++ source

Suppose I'm writing a library or a set of tools mytool where a class MyTool that other people can use is defined. Suppose I have a directory tree like this:
project
| - program1
| - main1.cpp
...
| - mytool
| - mytool.h
| - mytool.cpp
| - data.txt
in tool1.cpp I use the external binary huge file data.dat:
ifsteam f("data.txt");
the main1.cpp use mytool, but if mytool.(s)o is linked with main1.o the program can't find data.dat, for this case I need to change the previous line to:
ifstream f("../mytool/data.txt");
but I can't know where other people put mytool for example they can have a different directory tree:
project
| - program1
| - main1.cpp
| - mytool
| - tool1.h
| - tool2.cpp
| - data.dat
In addition (am I right?) the path depend on where the program is executed.
The only solution I can imagine is to pass to the class contructor MyTool the path of data.dat but I want to keep hidden this file for the user.
You need to know the absolute path of the file, or else the path of the file relative to your working directory. One approach is to have a configuration script which the user runs before compiling your program. The script then hardcodes into your program the relevant path, so the program has the path hardwired in a manner customized for the user.
Sometimes that's not an option because you don't want to distribute the source code, or because you wish to allow the path to change at runtime. Then you can read a configuration file at runtime which says where the file is. But this is just a layer of abstraction: you still need to know where that configuration file is. You might, for example, ask the system where the user's personal directory is, and then find the file there at that directory. This is a sort of mix between compile-time and runtime computation of the path.
One option would be to use an environment variable for the location of your tools. For instance, name it MYTOOLDIR. You can set the path on installation of MyTool. A call to getenv("MYTOOLDIR"); can resolve the path.
On windows, within the mytool dir, run SETX PATH=%PATH%;./, or on Linux, just PATH=$PATH:./. (Provide a set_env.bat or whatnot to do it.)
You'll need to make the location of the binary file a configuration value that the user defines on a particular installation of the program. Or, more easily, just always put the binary file in the same place as the final executable and use "data.dat" as the path.