I'm trying to capture a system command on Windows with the following code, to return the output as a string.
std::string exec(char* cmd) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
std::ifstream ifs(pipe);
std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
printf("%s", content);
return content;
}
When I call the function like this:
char *command = "set";
std::string results = exec(command);
printf("%s", results);
getchar();
The output is just a few random bytes.
╝÷:ö°:
I was trying to get all the results appended in 1 long string. Can anyone tell me what I'm doing wrong?
I tried redirecting the stderr to output with the command but it also gives some random bytes.
Since you're using printf() which knows nothing about C++ std::string values, you need to print the C string representation of the content:
printf("%s", content.c_str());
The printf() function was told to expect that, but it wasn't what you passed to it.
Or, as others pointed out, you should use the native C++ I/O:
std::cout << content;
Printf expects C string, char*.
Use
printf("%s",results.c_str());
Don't use printf, use the C++ standard output stream instead:
std::cout << content << '\n';
Related
I need to save a bunch of image files with numbered indices. I am trying to construct these filenames using a stringstream. However, stringstream.str() does not seem to return the filename, but rather returns some garbage.
Here is the code:
std::stringstream filename;
filename << filepath << fileindex << ".png";
bool ret = imwrite(filename.str(),frame, compression_params);
fileindex++;
printf("Wrote %s\n", filename.str());
Here is the output from one execution:
Wrote ╠±0
Wrote ╠±0
Wrote ╠±0
Wrote ╠±0
Here is the output from another execution:
Wrote ░‗V
Wrote ░‗V
Wrote ░‗V
Wrote ░‗V
Any suggestions? Is imwrite is an opencv function, and I have [code]using namespace cv;[/code] at the top of the file - is there some interference between opencv and std?
You can't pass a non-POD type like std::string to a C-style variadic function like printf.
You could use C++ output:
std::cout << "Wrote " << filename.str() << '\n';
or, if you like old-school weirdness, extract the C-style string for C-style output:
printf("Write %s\n", filename.str().c_str());
filename.str() returns a std::string object. You can't printf it directly. Format %s requires C-style string. This should work
printf("Wrote %s\n", filename.str().c_str());
In any case, using C-style functions with C++ objects is not always the best idea.
Okay Some may remember me from earlier, I am fairly new to programming so I may seem not up to par with many others. However at the moment, i am very much stuck.
int main(int argc, char* argv[]) {
string temp,input,output;//store input from file, and get which file//
ofstream out("output.txt");
if(argc == 3)
{
if(ifstream(argv[2]))
{
input = argv[2];
ifstream in(input);
while(in.good())
{
in >> temp;
ReverseWord(temp);
cout << temp << endl;
out << temp << endl;
}
out.close();
in.close();
}
}
}
This code right here is meant to reverse the letter order of words that it takes in from a file by typing "revstr < input.txt" with input.txt being the file name. however at the moment the program just opens and closes right away without anything happening and nothing being typed into the console. does anyone know how to fix this?
If you call your program as revstr < input.text your main() function will be called (on usual platforms) with:
argv = { "revstr", NULL }
argc = 1
In this case you get the contents of input.txt by reading from std::cin. That is what 'input readirection' means: your standard input stream is redirected to read from a file rather than the keyboard (aka terminal) device. No need to deal with the filename in that case.
To pass a filename as argument, use revstr input.txt. That should call main()with
argv = { "revstr", "input.txt", NULL }
argc = 2
so the filename will be available as argv[1].
The behavior in the former case is typically due to command shells, which treat '<' as a redirection directive (which ends the preceding command). You may have expected to get
argv = { "revstr", "<", "input.txt", NULL }
argc = 3
For that you would need to apply some form of quoting or escaping to disable the shell behavior, for example revstr "<" input.txtor revstr \< input.txt. But as far as I understand where you are coming from, you want the redirection. In that case forget about argc and argv and simply read your input from std::cin.
I am having an issue with printing a string which im using for debug purposes.
I create the string like so:
//checker is int
std::stringstream buttonx;
buttonx << "Button" << checker << "_x";
Now i try to print it to my error.txt file
FILE * p;
p = fopen ("error.txt","w");
fprintf(p, "%s" , buttonx.str());
fclose(p);
The output is:
,æ0
Its different every time. I'm not sure whats going on was hopeing some could explain the mistake?
fopen is plain C and cannot handle std::string. You need to input a char*, which you can access by calling .c_str() on the string, like this:
fprintf(p, "%s", buttonx.str().c_str());
the function fprintf wants a null terminated string (a C string); you need the c_str() instead of yours:
buttonx.c_str()
I'm trying to store strings directly into a file to be read later in C++ (basically for the full scope I'm trying to store an object array with string variables in a file, and those string variables will be read through something like object[0].string). However, everytime I try to read the string variables the system gives me a jumbled up error. The following codes are a basic part of what I'm trying.
#include <iostream>
#include <fstream>
using namespace std;
/*
//this is run first to create the file and store the string
int main(){
string reed;
reed = "sees";
ofstream ofs("filrsee.txt", ios::out|ios::binary);
ofs.write(reinterpret_cast<char*>(&reed), sizeof(reed));
ofs.close();
}*/
//this is run after that to open the file and read the string
int main(){
string ghhh;
ifstream ifs("filrsee.txt", ios::in|ios::binary);
ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));
cout<<ghhh;
ifs.close();
return 0;
}
The second part is where things go haywire when I try to read it.
Sorry if it's been asked before, I've taken a look around for similar questions but most of them are a bit different from what I'm trying to do or I don't really understand what they're trying to do (still quite new to this).
What am I doing wrong?
You are reading from a file and trying to put the data in the string structure itself, overwriting it, which is plain wrong.
As it can be verified at http://www.cplusplus.com/reference/iostream/istream/read/ , the types you used were wrong, and you know it because you had to force the std::string into a char * using a reinterpret_cast.
C++ Hint: using a reinterpret_cast in C++ is (almost) always a sign you did something wrong.
Why is it so complicated to read a file?
A long time ago, reading a file was easy. In some Basic-like language, you used the function LOAD, and voilà!, you had your file.
So why can't we do it now?
Because you don't know what's in a file.
It could be a string.
It could be a serialized array of structs with raw data dumped from memory.
It could even be a live stream, that is, a file which is appended continuously (a log file, the stdin, whatever).
You could want to read the data word by word
... or line by line...
Or the file is so large it doesn't fit in a string, so you want to read it by parts.
etc..
The more generic solution is to read the file (thus, in C++, a fstream), byte per byte using the function get (see http://www.cplusplus.com/reference/iostream/istream/get/), and do yourself the operation to transform it into the type you expect, and stopping at EOF.
The std::isteam interface have all the functions you need to read the file in different ways (see http://www.cplusplus.com/reference/iostream/istream/), and even then, there is an additional non-member function for the std::string to read a file until a delimiter is found (usually "\n", but it could be anything, see http://www.cplusplus.com/reference/string/getline/)
But I want a "load" function for a std::string!!!
Ok, I get it.
We assume that what you put in the file is the content of a std::string, but keeping it compatible with a C-style string, that is, the \0 character marks the end of the string (if not, we would need to load the file until reaching the EOF).
And we assume you want the whole file content fully loaded once the function loadFile returns.
So, here's the loadFile function:
#include <iostream>
#include <fstream>
#include <string>
bool loadFile(const std::string & p_name, std::string & p_content)
{
// We create the file object, saying I want to read it
std::fstream file(p_name.c_str(), std::fstream::in) ;
// We verify if the file was successfully opened
if(file.is_open())
{
// We use the standard getline function to read the file into
// a std::string, stoping only at "\0"
std::getline(file, p_content, '\0') ;
// We return the success of the operation
return ! file.bad() ;
}
// The file was not successfully opened, so returning false
return false ;
}
If you are using a C++11 enabled compiler, you can add this overloaded function, which will cost you nothing (while in C++03, baring optimizations, it could have cost you a temporary object):
std::string loadFile(const std::string & p_name)
{
std::string content ;
loadFile(p_name, content) ;
return content ;
}
Now, for completeness' sake, I wrote the corresponding saveFile function:
bool saveFile(const std::string & p_name, const std::string & p_content)
{
std::fstream file(p_name.c_str(), std::fstream::out) ;
if(file.is_open())
{
file.write(p_content.c_str(), p_content.length()) ;
return ! file.bad() ;
}
return false ;
}
And here, the "main" I used to test those functions:
int main()
{
const std::string name(".//myFile.txt") ;
const std::string content("AAA BBB CCC\nDDD EEE FFF\n\n") ;
{
const bool success = saveFile(name, content) ;
std::cout << "saveFile(\"" << name << "\", \"" << content << "\")\n\n"
<< "result is: " << success << "\n" ;
}
{
std::string myContent ;
const bool success = loadFile(name, myContent) ;
std::cout << "loadFile(\"" << name << "\", \"" << content << "\")\n\n"
<< "result is: " << success << "\n"
<< "content is: [" << myContent << "]\n"
<< "content ok is: " << (myContent == content)<< "\n" ;
}
}
More?
If you want to do more than that, then you will need to explore the C++ IOStreams library API, at http://www.cplusplus.com/reference/iostream/
You can't use std::istream::read() to read into a std::string object. What you could do is to determine the size of the file, create a string of suitable size, and read the data into the string's character array:
std::string str;
std::ifstream file("whatever");
std::string::size_type size = determine_size_of(file);
str.resize(size);
file.read(&str[0], size);
The tricky bit is determining the size the string should have. Given that the character sequence may get translated while reading, e.g., because line end sequences are transformed, this pretty much amounts to reading the string in the general case. Thus, I would recommend against doing it this way. Instead, I would read the string using something like this:
std::string str;
std::ifstream file("whatever");
if (std::getline(file, str, '\0')) {
...
}
This works OK for text strings and is about as fast as it gets on most systems. If the file can contain null characters, e.g., because it contains binary data, this doesn't quite work. If this is the case, I'd use an intermediate std::ostringstream:
std::ostringstream out;
std::ifstream file("whatever");
out << file.rdbuf();
std::string str = out.str();
A string object is not a mere char array, the line
ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));
is probably the root of your problems.
try applying the following changes:
char[BUFF_LEN] ghhh;
....
ifs.read(ghhh, BUFF_LEN);
So I have a .cpp file with a Function which recieves a filename, and should return a String with the contents of the file (actualy modified contents, I modified the code to make it more understandable, but that doesn't have any effect on my problem). The problem is that f.good() is returning false and the loop, which reads the file is not working.
CODE :
#include "StdAfx.h"
#include "Form21.h"
#include <string>
#include <fstream>
#include <iostream>
string ReadAndWrite(char* a){
char filename[8];
strcpy_s(filename,a);
string output;
char c;
ifstream f(filename,ios::in);
output+= "Example text"; // <-- this writes and returns just fine!
c = f.get();
while (f.good())
{
output+= c;
c= f.get();
}
return output;
}
Does anyone have an idea on why this is happening?
Does it have something to do with, that this is a seperate .cpp file( it doesnt even throw out an error when I remove #include <fstream>).
Maybe there is a different kind of method to make the loop?
I'll be very happy to hear any suggestions on how to fix this or maybe a different method on how to achieve my goal.
First, there's really no reason to copy the file name you receive -- you can just use it as-is. Second, almost any loop of the form while (stream.good()), while (!stream.bad()), while (stream), etc., is nearly certain to be buggy. What you normally want to do is check whether reading some data worked.
Alternatively, you can skip using a loop at all. There are a couple of ways to do this. One that works nicely for shorter files looks like this:
string readfile(std::string const &filename) {
std::ifstream f(filename.c_str());
std::string retval;
retval << f.rdbuf();
return retval;
}
That works nicely up to a few tens of kilobytes (or so) of data, but starts to slow down on larger files. In such a case, you usually want to use ifstream::read to get the data, something along this general line:
std::string readfile(std::string const &filename) {
std::ifstream f(filename.c_str());
f.seekg(0, std::ios_base::end);
size_t size = f.tellg();
std::string retval(size, ' ');
f.seekg(0);
f.read(&retval[0], size);
return retval;
}
Edit: If you need to process the individual characters (not just read them) you have a couple of choices. One is to separate it into phases, where you read all the data in one phase, and do the processing in a separate phase. Another possibility (if you just need to look at individual characters during processing) is to use something like std::transform to read data, do the processing, and put the output into a string:
struct character_processor {
char operator()(char input) {
// do some sort of processing on each character:
return ~input;
}
};
std::transform(std::istream_iterator<char>(f),
std::istream_iterator<char>(),
std::back_inserter(result),
character_processor());
I would check that strlen(a) is not greater than 7...
You might overrun filename and get a file name that doesn't exist.
Not relating the problem, I would re-write the function:
string ReadAndWrite(string a) { // string here, if you are into C++ already
string filename; // also here
filename = a; // simpler
string output;
char c;
ifstream f(filename.c_str()); // no need for ios::in (but needs a char *, not a string
output+= "Example text"; // <-- this writes and returns just fine!
f >> c; // instead c = f.get();
while (f) // no need for f.good())
{
output+= c;
f >> c; // again, instead c= f.get();
}
return output;
}
Might I suggest using fopen? http://www.cplusplus.com/reference/clibrary/cstdio/fopen/ It takes in a filename and returns a file pointer. With that you can use fgets to read the file line by line http://www.cplusplus.com/reference/clibrary/cstdio/fgets/