Improper use of system() call? - c++

I have a particle system program that generates a .dat file with particle coordinates in every iteration. The end goal is to run the program multiple times via a script with different parameters. So, I am trying to setup my program in a way that, for every run, all relevant data are going to be stored in a folder.
What I do is to generate PNGs from the .dat files with Gnuplot, call ffmpeg to create a video out of the PNGs, use WinRAR to compress the .dat files and finally clean up, by deleting all the intermediate files. This works, when I do it in the working directory.
Now I try to create a new directory and do the same stuff in there. My code:
// Load the proper library to use chdir() function
#ifdef _WIN32
#include <direct.h>
#elif defined __linux__ || defined __APPLE__&&__MACH__
#include <unistd.h>
#endif
// Make output directory and change working directory to new directory
ostringstream dirCommand;
dirCommand << "mkdir " << folderName_str;
system(dirCommand.str().c_str());
const char* test = folderName_str.c_str();
#ifdef _WIN32
if(_chdir(test))
{
printf( "Unable to locate the directory: %s\n",test);
return;
}
#elif defined __linux__ || defined __APPLE__&&__MACH__
if(chdir(test))
{
printf( "Unable to locate the directory: %s\n",test);
return;
}
#endif
else
printf("Created output directory...\n");
Already for this part, I know that there are going to be objections. I have looked extensively on SO and many people favor SetCurrentDirectory() for Windows, or they are skeptical about using system(). In my defense, I am a novice programmer and my knowledge is really limited...
Now, when I try to make the video with FFMpeg and then rar/tar my files:
// Make video
std::cout << "Generating Video..." << endl;
ostringstream command;
command << "ffmpeg -f image2 -r 1/0.1 -i output_%01d.png -vcodec mpeg4 " << videoName_str << ".avi -loglevel quiet";
std::system(command.str().c_str());
// Clean Up!
std::cout << "Cleaning up!" << endl;
ostringstream command2;
#ifdef _WIN32
command2 << "rar -inul a " << videoName_str << ".rar *.dat settings.gp loadfile.gp";
#elif defined __linux__ || defined __APPLE__&&__MACH__
command2 << "tar cf " << videoName_str << ".tar *.dat settings.gp loadfile.gp";
#endif
std::system(command2.str().c_str());
I get very different behaviors in Win/ Linux.
Win 7 x64, Visual Studio 2010/12
In windows, the folder is created. The .dat files are generated correctly and gnuplot plots the PNGs as well. When ffmpeg is called, nothing happens. No error message from FFMpeg or anything. The same goes for WinRAR. Maybe, for the last thing, I can use the command line utility of 7z which is free!
Linux Mint 14 x64, Qt 4.8.1
Strangely enough, the behavior is inverted from that of Windows. As soon as the dir is changed, only the first .dat file is generated. It is as if every subsequent call I make to fprintf() for my file generation does not work, or gets lost somewhere. Gnuplot works, as do ffmpeg and tar!!
I am really perplexed. Any help, would be really appreciated.

A few points that might be helpful:
Make sure to check the result of every system call, including system() and fprintf().
It's been a while since I last touched Windows; I remember that depending on how binaries were linked, they would not always print out to the same console. So ffmpeg/winrar could be throwing the error messages away, or just allocating a new, short-lived console to print.
I would use mkdir/_mkdir instead of calling system().
With popen()/_popen() you can get more control over the error output.
Consider using a shell script or bat file.

Related

Xcode App No Longer Reads Input From the Folder The App is Stored In

The title is a bit long-winded, but basically, I've written an app that reads and writes its input and output to text files. The entire time, it would read and write the files directly in the same directory as my Xcode derived data->project->build->products->debug folder. This was where everything was being written to and read from. I don't have a custom path set up for the application, so it just saves wherever the app is located. For the first time ever, I ran Apple's Instruments app, to try to learn how to use a profiler. Not long after selecting this app as the target in Instruments, I went back to the Xcode app to run the program some more. Everything works fine in Xcode. It reads from the files and prints to files in the same location as the folder, but if I try to run the actual program itself by clicking on the file and having it open terminal, it no longer reads or prints to the directory that app is in. Instead, its printing and reading from my home folder. I don't know what changed or what caused it to change, but I'm hoping its a simple fix. I'd like for the application to read from files and print files from the directory its located in again. I'm not sure if its an Xcode setting or a Terminal setting.
Any help would be greatly appreciated.
Update 1: Tried this with no luck:
how to change the working directory to the location of the program
The directory field was blank, so I thought this would the solution, but filling it in with the suggestion did nothing to alleviate the issue.
Update 2:
Just tried deleting the preference file, still no solution. I'm willing to give someone reputation. I don't have a whole lot because I'm a newer member, but I'll give what the person thinks is fair, to whoever solves it. I'm desperate and really don't want to wait 2 days to have this issue solved.
Update 3:
Tried changing the default path in the "Profile (release)->options area in the scheme section to the default variable suggested in update 1. No luck. I'm beginning to lose my mind.
Update 4:
I've tried deleting the scheme entirely and making a new one, in hopes that maybe there was something botched with the scheme, but this did not solve the issue. Input and output while running the app in Xcode is still using the working directory, while running the executable in the debug folder is using the home folder.
Update 5:
Just tested this on an older iMac and Xcode setup (OS 10.8.5 and Xcode 5.1.1) and it seems to be working correctly, reading and writing to the current working directory of the application in the debug folder.
For whatever reason, the solution suggested by https://stackoverflow.com/a/15537436/1035008 no longer works. Maybe broken in Xcode 8.1. But this seems to work:
#include <iostream>
#include <fstream>
#include <unistd.h>
using namespace std;
int main (int argc, const char * argv[])
{
// argv[0] returns the full path to the program, in my case "/Users/yuchen/Library/Developer/Xcode/DerivedData/../Debug/test
string directory(argv[0]);
// And we want to get rid of the program name `test`
directory = directory.substr(0, directory.find_last_of("/"));
// Point the directory to the program directory
chdir(directory.c_str());
cout << "Current directory is: " << getcwd(NULL, 0) << endl; // /Users/yuchen/Library/Developer/Xcode/DerivedData/../Debug/
ifstream fin("hi.txt");
if (fin.is_open()) cout << "File is Open" << endl;
else cout << "File is not open" << endl;
fin.close();
return 0;
}
Also see SO and SO. Hope this helps.

SDL_ttf "Couldn't load font file" with SDL2 in c++

I have the following code to draw some text in an SDL2 application. When I build and run, I'm consistently seeing an error of TTF_OpenFont() Failed: Couldn't load font file. I've tried the following:
Ensured the font file is in the current directory of running program. In fact, I've put the font in almost any directory the program could be running from and have tried with an absolute path.
Setting different permissions and owning the file
Opening the file separately with SDL_RWFromFile as described here: http://www.gamedev.net/topic/275525-sdl_ttf-weirdness/
Downloaded and recompiled a newer version of SDL_ttf (2.0.14)
Here's my code:
void SDLRenderer::drawText(
const Vector2d& pos,
string message,
const Color& color)
{
if(!TTF_WasInit()) {
cerr << "TTF_Init failed " << TTF_GetError() << endl;
exit(1);
}
TTF_Font* fixed = TTF_OpenFont("./DejaVuSansMono.ttf", 16);
if (fixed == NULL) {
cerr << "TTF_OpenFont() Failed: " << TTF_GetError() << endl;
TTF_Quit();
SDL_Quit();
exit(1);
}
...
I'm also calling TTF_Init() from the constructor of this code's class. I'm also a little unsure how to debug further because gdb doesn't even give a backtrace after the error and doesn't seem to let me step into the TTF_OpenFont function.
I ran into this issue and it was caused by linking against the incorrect version of the SDL_ttf library. I was using SDL 2.0, but I was linking against libSDL_ttf.so instead of libSDL2_ttf.so. libSDL_ttf.so is for SDL 1.2, and is not compatible with SDK 2.0.
My original command line was:
$ gcc -o showfont showfont.c `sdl2-config --cflags --libs` -lSDL_ttf
$ ./showfont /usr/share/fonts/truetype/freefont/FreeSans.ttf
Couldn't load 18 pt font from /usr/share/fonts/truetype/freefont/FreeSans.ttf: Couldn't load font file
I fixed it by linking against libSDL2_ttf.so instead:
$ gcc -o showfont showfont.c `sdl2-config --cflags --libs` -lSDL2_ttf
$ ./showfont /usr/share/fonts/truetype/freefont/FreeSans.ttf
Font is generally 21 big, and string is 21 big
The showfont.c program is an example included with SDL_ttf.
My thoughts probably belong in a comment but I don't have enough reputation. You can make sure you're in the right directory by explicitly setting the current working directory (chdir in unistd.h on Linux, or SetCurrentDirectory in windows.h on Windows). I don't think you need to include ./ in the file name.
I recall having problems with SDL_ttf when calling TTF_Init, TTF_Quit, and then TTF_Init again. This may not be causing your problem but I would recommend doing your TTF_Init just once at the beginning of the program and TTF_Quit once at the end, not every time your constructor runs.
If this doesn't work look into building a debug version of SDL_ttf that will play nicer with GDB.
I've had your same problem and managed to fix it by entering the full path to the font.
Instead of just passing the string "./font.ttf"
I used: "/User/MyUsername/Projects/MyProject/font.tff"
Hope this helps!

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

Like the questioner in "New to Xcode can't open files in c++?" I'm learning Xcode and OS X (I'm using Xcode 7 on a Yosemite mac).
I can get the code to work perfectly when I build and run it, but can't get the executable to work when I try to run it as a stand alone program.
I'm trying to translate some games I've written on a PC in C++ using SFML.
There has to be a way to save high scores and previous games within an app, but this has me stymied.
This is the sample code I used based on the previous question:
#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;
fin.close();
fout.open("outputFile.txt");
fout << input;
fout << "\n Data transferred \n";
fout.close();
}
This works perfectly when I build and run it, so I've got the proper path to the desktop folder set up. (I'm putting the data files in the same folder as the executable and specifying the path in Xcode.)
No problems when I run this within Xcode, but this is the message on the terminal console when I run the executable by itself:
"…/Desktop/datafiles/Build/Products/Debug/datafiles ; exit;
…/Desktop/datafiles/Build/Products/Debug/datafiles ; exit;
File failed to open.
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
[Process completed]"
Is there another flag or path that needs to be set within Xcode for this to work? Two other related questions: How do I access the terminal history to see what is going on? Finally, if I set up the project as an SFML app instead of a terminal project (command line tool app), why can't I see the files within the SFML app, even though I've set the command line flag to see hidden files, and I can see other hidden files on my hard drive? I can see the files if I open the SFML app folder in Windows, so I know they are there.
This is my first question on Stack Overflow, so apologies if this should be appended to the previous question, but this doesn't appear to be an answer to me, but is quite a different version of the original question that is not addressed in the answers.
Thanks!

How can I launch Mozilla Firefox using C++?

Compiled through compiler like Code::Blocks, I have tried the following, bit it does not work:
/*Running Firefox.exe*/
#include <stdio.h>
/*using c++*/
#include <iostream>
#include <stdlib.h>
using namespace std;
int main ()
{
int x;
cout << "Checking if processor is available..." << endl;
/*System used here*/
if (system(NULL)) puts ("Proceed");
else exit (1);
cout<< "Executing Firefox..." << endl;
/*Having some error here saying not recognized as internal or external command*/
x = system ("C:/Program Files (x86)/Mozilla Firefox/firefox.exe");
/*cout here*/
cout <<"The value returned was:" << x << endl;
return 0;
}
Is it because Firefox is not recognized as a system of windows? If so how can I run Firefox, or even Internet Explorer from code?
Run cmd.exe (Windows command shell) and enter the string C:/Program Files (x86)/Mozilla Firefox/firefox.exe at the command line, and you will see the same problem - i.e. the problem is with your command string rather than your C++ code.
The space in the path requires the command string to be quoted:
system ("\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\"") ;
or
system ("\"C:/Program Files (x86)/Mozilla Firefox/firefox.exe\"") ;
I believe you need to convert path to DOS format
Launch a command prompt cd into Mozilla Firefox folder
run this: for %I in (.) do echo %~sI
Copy the output to system command with \ replaced with \\ append firefox.exe at end
Is it because Firefox is not recognized as a system of windows?
If you open up cmd.exe and type in C:/Program Files... it won't work because spaces are used as a delimiter. Quote your path:
system("\"C:/Program Files (x86)/Mozilla Firefox/firefox.exe\"");
Although if you're targeting Windows you should consider using CreateProcess which saves you this trouble.
If so how can I run Firefox, or even Internet Explorer from code?
If you want to show a web page, use ShellExecute* and let the shell do the work. It will take care of launching Firefox, Internet Explorer, Chrome, or whatever browser the user has configured to view web pages.
*Read the Remarks section about initializing COM, first.
Try using windows API CreateProcess API

ofstream outputs in debug but not run

I have a very simple C++ program with a very simple project setup, but when I run the program I get no output. If I run the program in debug mode, it works perfectly. I am using Eclipse Kepler CDT 32 bit on windows with MinGW. I am somewhat new to eclipse, so it's probably something I did wrong.
The program is:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
ofstream outfile("testdata.txt");
int main()
{
outfile << "Program Start\n";
cout << "Program Start\n";
return 0;
}
Help!
If the problem is that the program quickly opens and then closes before you can see the output on the screen, then you can just run your program from any shell (CMD on Windows, bash on Linux, etc.). That way, it won't exit once your program ends and you can see the results.
Make sure also that you flush/close your ofstream before your program exits.
The problem is rather not releted to c++ itself. You should check if via "cmd" typying it in "launch menu" after you click start. Find the path of your program, then run it.
For the very beginning it is recommended to spend a few hours with terminal(cmd). To know how things works. After that you will be independent - you will be able to write the code in any IDE. Also simple trick to make it working is to use std::cin.get() . It is prefered to system("pause").
You open the testdata.txt file using the relative path.
And the created file may be created in the project binary output path, where the executable located in.
You can use everything software to check whether a file is created and its created path.
everything
For example, you can type your output file name testdata.txt into everything software to see where output file created.And check if the testdata.txt created in a wrong path or directory.