This question already has answers here:
Get path of executable
(25 answers)
Get a file name from a path
(24 answers)
Closed 2 years ago.
hey so i wanted to get name of the exe that is currently running
here is what ive tried doing
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char filename[ MAX_PATH ];
DWORD size = GetModuleFileNameA( NULL, filename);
if (size)
cout << "EXE file name is: " << filename << "\n";
else
cout << "Could not fine EXE file name.\n";
return 0;
}
but it gets the path of the exe too but i only need the exe name any help?
The first command line argument is the name of the current program
#include <iostream>
#include <string>
#include <windows.h>
#include <algorithm>
int main(int argc, char** argv)
{
if (argc > 0)
std::cout << argv[0] << std::endl;
else {
//some other method has to be used, use OP's suggestion
char filename[ MAX_PATH ];
DWORD size = GetModuleFileNameA( NULL, filename, MAX_PATH);
if (!size) {
std::cout << "Could not fine EXE file name.\n";
return -1;
}
//Remove everything before the last "\"
std::string name = filename;
auto it = std::find(name.rbegin(), name.rend(), '\\'); //escape the escape character
if (it != name.rend()) {
name.erase(name.begin(), it.base());
}
std::cout << filename << std::endl;
}
}
Related
I've written this code, which it get the repository and look for the files within. it aims to create binary files for each file found so as to write some data inside it later. However, the code is not running as expected. and the binary file are not created this the issue.
the directory has two images, and the output I get is as follows :
Creating bin files
C:\repo\1.bin
Error: failed to create file
Press <RETURN> to close this window...
I really do not know where I miss it. Any advice I'd be glad.
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}
First I have to say, if you directory you are looking for doesn't exists or is empty, the program gets locked, it would be nice to have that fixed if making a bigger program.
Then, for your case, I don't see whars the point of that stringstream, so I tried removing that, and changing it by a normal string, removing the last \n character you get from reading the filenames:
cout << fileName << '\n';
string ss = fileName.substr(0, fileName.size() - 1);
myOfstream.open(ss.c_str(), fstream::binary);
if (!myOfstream)
{
hope it helps
I found the issue bro, after debugging ;D
the problem is in the "newline", the string fileName has a "\n" at the end that's whats rise your error. Thus you have to erase it, I ve used this statement fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
and I included algorithm lib.
the working code is as follows :
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
#include <algorithm>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a text file that consists of "funny" non-ASCII characters such as NUL, RS, CAN all in a black square. When I read the file line by line, it just stops each line where one of these appear.
All I want to do is to copy the same file only without these characters.
How to do that?
Let's say you are reading the file line by line and write the output to a different file like this:
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
string inPath("a.txt");
string outPath("b.txt");
string line;
ifstream in(inPath.c_str(), ifstream::in | ifstream::binary);
if ( ! in.is_open() ) {
cerr << "Error: Failed to read file \"" << inPath << "\"." << endl;
return EXIT_FAILURE;
}
ofstream out(outPath.c_str(), ofstream::out | ofstream::binary);
if ( ! out.is_open() ) {
cerr << "Error: Failed to write file \"" << outPath << "\"." << endl;
return EXIT_FAILURE;
}
while ( getline(in, line) ) {
out << line;
}
cout << "Done." << endl;
return EXIT_SUCCESS;
}
The problem is that the input stream gets interpreted if not opened in binary mode. That means all control characters (the ones you see in Notepad++ for example in black boxes) are not handled as ordinary characters but in a special way.Depending on the library implementation the read operation may just stop, ignore those characters, convert them into different character sequences or tread them in their special way (like as end of text mark for example).You can check if a characters is a control character with iscntrl() for example.To remove these characters in every line you can use the following code:
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main() {
string inPath("a.txt");
string outPath("b.txt");
string line;
ifstream in(inPath.c_str(), ifstream::in | ifstream::binary);
if ( ! in.is_open() ) {
cerr << "Error: Failed to read file \"" << inPath << "\"." << endl;
return EXIT_FAILURE;
}
ofstream out(outPath.c_str(), ofstream::out | ofstream::binary);
if ( ! out.is_open() ) {
cerr << "Error: Failed to write file \"" << outPath << "\"." << endl;
return EXIT_FAILURE;
}
while ( getline(in, line) ) {
/* this also removes line-feed and carrier-return */
line.erase(remove_if(line.begin(), line.end(), ::iscntrl), line.end());
out << line << '\n';
}
cout << "Done." << endl;
return EXIT_SUCCESS;
}
you can loop through each char in the file and use utility functions like isalpha(), isalnum() and isdigit() to make sure each char is is ascii, and skip out the others.
see http://www.cplusplus.com/reference/cctype/isalpha/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string>
using std::string;
int die(string &msg) {
fprintf(stderr, "%s\n", msg.c_str());
exit(-1);
return -1; // Not really.
}
int
main(int argc, char **argv) {
string msg;
string inpt;
FILE *INPT;
string oupt;
FILE *OUPT;
int c;
(argc > 1) ||
(die(msg += "Missing filename arg."));
inpt += argv[1];
(oupt += inpt) += ".nxt";
(INPT = fopen(inpt.c_str(), "r")) ||
(die(((msg += "Can't open \"") += inpt) += "\" for input."));
(OUPT = fopen(oupt.c_str(), "w")) ||
(die(((msg += "Can't open \"") += oupt) += "\" for output."));
for (;(c = fgetc(INPT)) != EOF;) {
((unsigned)c < 0x80u) &&
(
(isprint(c)) ||
((iscntrl(c)) && (isspace(c)))
) &&
(fputc(c, OUPT));
}
fclose(OUPT);
fclose(INPT);
return 0;
}
This is what I tried:
#include <iostream>
#include <string>
int main(int argc, char const *argv[]) {
using namespace std;
for (string cin_line; getline(cin, cin_line);) {
cout << cin_line << endl;
}
FILE* pipe = popen("app.exe", "r");
for (string result_line; getline(pipe, result_line);) {
cout << result_line << endl;
}
pclose(pipe);
return 0;
}
It doesn't compile, the result is:
no matching function for call to 'getline(FILE*&, std::__cxx11::string&)'
Second example I've found here: https://stackoverflow.com/a/10702464/393087
But it seems mingw doesn't have pstream included: fatal error: pstream.h: No such file or directory - edit: ok I know, I missed that this is not a GCC library, it is named like it was but this is separate download: http://pstreams.sourceforge.net/
I know how to do it using buffer and get whole output on single line (like here: https://stackoverflow.com/a/478960/393087 ) then explode the line by \n and get my array, but the point here is that I must provide the output as soon as the input comes in.
Also I tried example from here: https://stackoverflow.com/a/313382/393087 - I've added main function to that:
#include <cstdio>
#include <iostream>
#include <string>
int main(int argc, char const *argv[]) {
using namespace std;
FILE * fp ;
if((fp= popen("/bin/df","r")) == NULL) {
// error processing and exit
}
ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor
string s;
while (! ins.eof()){
getline(ins,s);
// do something
}
return 0;
}
This also doesn't compile:
error: variable 'std::ifstream ins' has initializer but incomplete type
ifstream ins(fileno(fp)); // ifstream ctor using a file descriptor
You can't do this:
FILE* pipe = popen("app.exe", "r");
for (string result_line; getline(pipe, result_line);) {
cout << result_line << endl;
}
pclose(pipe);
You need to do this:
#include <boost/noncopyable.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
FILE* pipe = popen("app.exe", "r");
boost::iostreams::file_descriptor_source
source(fileno(pipe), boost::iostreams::never_close_handle);
boost::iostreams::stream<boost::iostreams::file_descriptor_source>
stream(source, 0x1000, 0x1000);
string result_line;
while (getline(stream, result_line)) {
cout << result_line << endl;
}
:)
I am writing a simple program to take in two files. The terminal command line looks like this.
./fileIO foo.code foo.encode
When it runs, the second file is not read in. When I enter
./fileIO foo.code foo.code
it works. I can't seem to figure out why the second one is not opening. Any ideas? Thanks!
#include <fstream>
#include <iostream>
#include <queue>
#include <iomanip>
#include <map>
#include <string>
#include <cassert>
using namespace std;
int main( int argc, char *argv[] )
{
// convert the C-style command line parameter to a C++-style string,
// so that we can do concatenation on it
assert( argc == 3 );
const string code = argv[1];
const string encode = argv[2];
string firstTextFile = code;
string secondTextFile = encode;
//manipulate the first infile
ifstream firstFile( firstTextFile.c_str(), ios::in );
if( !firstFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
string lineIn;
string codeSubstring;
string hexSubstring;
while( getline( firstFile, lineIn ) )
{
hexSubstring = lineIn.substr(0, 2);
codeSubstring = lineIn.substr(4, lineIn.length() );
cout << hexSubstring << ", " << codeSubstring << endl;
}
//manipulate the second infile
ifstream secondFile( secondTextFile.c_str(), ios::in );
if( !secondFile )
{
cerr << "Cannot open text file for input" << endl;
return 1;
}
char characterIn;
while( secondFile.get( characterIn ) )
{
cout << characterIn << endl;
}
return 0;
}
One thing you might want to try is adding the close() call as is standard procedure after you're done using files. Sometimes issues arise with re-opening files if they were not closed properly in a previous run.
firstFile.close();
secondFile.close();
Also, you may try restarting the computer if there is some lingering file handle that hasn't been released.
Hey everyone. I need to write a POSIX program to search through an entire file system for a specified file starting at the top directory. I've got some code which isn't done at all, but when I run it, and check to see if a particular file is a directory, it's saying this file which is not at all a directory is a directory and is trying to move into it, causing an error. I'm not sure how I can tell it that this type of file isn't a directory.
Here's my code. I know it's not perfect and I could probably do some things differently in the way of getting the directory names and passing them into the function. Either way, I'm pretty sure I have to do this recursively.
The file in question is /dev/dri/card0 and I'm running this from a Debian virtual machine.
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>
#include <locale.h>
#include <langinfo.h>
#include <fcntl.h>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
void SearchDirectory(string file_Name, string directory){
string new_Directory = directory;
DIR *dirp;
dirp = opendir(directory.c_str());
struct dirent *dptr;
struct stat statStruct;
while(dptr = readdir(dirp)){
stat(dptr->d_name, &statStruct);
if( S_ISDIR(statStruct.st_mode) ){
string check = dptr->d_name;
if ( check.compare(".") == 0 || check.compare("..") == 0 ){
continue;
}
else{
cout << dptr->d_name << " is is a directory" << endl;
new_Directory.append("/");
new_Directory.append(dptr->d_name);
SearchDirectory(file_Name, new_Directory);
}
}
else if( S_ISREG(statStruct.st_mode)){
string check = dptr->d_name;
if( check.compare(file_Name) == 0){
cout << "Found " << file_Name << " in " << directory << "/" << endl;
}
}
}
}
int main(int argc, char *argv[]){
if(argc < 2 || argc > 2){
cerr << "This program will find the specified file." << endl;
cerr << "Usage: mysearch <filename>" << endl;
return 1;
}
string file_Name = argv[1];
SearchDirectory(file_Name, "/");
return 0;
}
POSIX.2 requires a working "find" command.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>", argv[0]);
}
execlp("find", "find", "/", "-name", argv[1], "-print", (char *)NULL);
exit(EXIT_FAILURE);
}
->d_name returns just the name of the file, not the path to the file. You need to stat (not yet constructed) new_Directory instead of dptr->d_name.
You also have a problem if a directory contains more than one subdirectories. Your construction of new_Directory is incorrect for each subdirectory after the first.
You never closedir your directory handle, so you run out of resources. You should also consider loading the entire directory into an array before recursing to avoid running out of handles.
void SearchDirectory(string directory, string target_File_Name){
DIR *dirp = opendir(directory.c_str());
if (!dirp) {
perror(("opendir " + directory).c_str());
return;
}
struct dirent *dptr;
while(dptr = readdir(dirp)){
string file_Name = dptr->d_name;
string file_Path = directory + "/" + file_Name;
struct stat statStruct;
stat(file_Path.c_str(), &statStruct);
if( S_ISDIR(statStruct.st_mode) ){
if ( file_Name.compare(".") == 0 || file_Name.compare("..") == 0 ){
continue;
}
SearchDirectory(file_Path, target_File_Name);
}
else if( S_ISREG(statStruct.st_mode)){
if( file_Name.compare(target_File_Name) == 0){
cout << file_Path << endl;
}
}
}
closedir(dirp);
}
Update: Added second problem.
Update: Added third problem.
Update: Added code.
Not for the benefit of the OP, who writes "The point is to come up with a way to do it myself," but rather for the benefit of posterity, here is a way to use Boost.Filesystem:
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
// sample usage: find_file("/home", ".profile");
void find_file( const fs::path& dirPath, const std::string& fileName) {
fs::recursive_directory_iterator end;
for(fs::recursive_directory_iterator it(dirPath); it != end; ++it) {
if(it->leaf() == fileName)
std::cout << it->path() << "\n";
if(fs::is_symlink(it->symlink_status()))
it.no_push();
}
}
Use fork, execv and the Unix implemented /usr/bin/find process and redirect its output for your result area?
I'm not sure if it's POSIX or not but the nftw library function is widely available on UNIX (HP-UX, AIX, Linux).
Your problem is "search a tree for a match"
BFS and DFS are the canonical basic algorithms. Give them a start node and go.
You will get into trouble if you follow symlinks; so test for them and don't follow them.
You should be able to map each point in the *FS algorithms to a directory operation.
Since C++ is an option, why not use something like Boost.Filesystem? The Boost.Filesystem two-minute tutorial gives an example of how to implement your search using directory iterators.