How to insert multiple variables inside c++ std::system()? [closed] - c++

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 1 year ago.
Improve this question
I'm trying to add multiple variables inside the std::system function. By using .c_str on the end it only accepts one variable.
system(("riverctl map normal " + modkey + " " + i + " set-focused-tags " + decimal).c_str);

I recommend the format library:
C++20 format standard library
#include <cstdlib>
#include <format>
auto test(int modkey, int i, int decimal)
{
auto cmd = std::format("riverctl map normal {} {} set-focused-tags {}",
modkey, i, decimal);
system(cmd.c_str());
}
or
{fmt} library
#include <cstdlib>
#include <fmt/core.h>
auto test(int modkey, int i, int decimal)
{
auto cmd = fmt::format("riverctl map normal {} {} set-focused-tags {}",
modkey, i, decimal);
system(cmd.c_str());
}

This code
"riverctl map normal " + modkey
calls operator+ on two things: "riverctl map normal " and modkey. Which operator+ this is depends on the types of the two operands of +.
You want it to call operator+ which concatenates strings; if any of the two first operands is a string (std::string), the first + will do the right thing, and all the following + will do too (because the result of the first + would be std::string).
If modkey is an integer (any type of integer, including char), this + will do the wrong thing (unwanted pointer arithmetic). To fix, convert any of the first two operands to a string. If modkey is an integer, you have to use std::to_string on it anyway, so converting the first operand is not necessary. But for consistency (i.e. to stop worrying what would happen if you changed the format of your message), you might want to convert even the first one:
// minimal required change
system(("riverctl map normal " +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
// more robust code (C++14 and later)
system(("riverctl map normal "s +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
// more robust code (C++11)
system((std::string("riverctl map normal ") +
std::to_string(modkey) + " " +
std::to_string(i) + " set-focused-tags " +
std::to_string(decimal)).c_str());
If your command line is too complex, you might want to use a temporary stream for formatting; there are fewer surprises then:
std::ostringstream stream;
stream << "riverctl map normal " << modkey << " " << i << " set-focused-tags " << decimal;
system(stream.str().c_str());

In case all variables declared in the system block are primitives (I guess that 'modkey' is already std::string) - you need to cast everything to std::string and call c_str as a function.
system(("riverctl map normal " + modkey + " " + std::to_string(i) + " set-focused-tags " + std::to_string(decimal)).c_str());

Related

Removing trailing zeros - c++ [duplicate]

This question already has answers here:
C++11 std::to_string(double) - No trailing zeros
(10 answers)
Closed 2 years ago.
This code:
cout<< to_string(x) + "m ----> " + to_string(x *0.001)+ "km"<<endl;
with this outputting:
0.002000
However, I want to remove the trailing extra zeros, but it should be in a line of code as i have many lines like the above one.
try this snipet:
cout << "test zeros" << endl;
double x = 200;
cout << "before" << endl;
cout<< std::to_string(x) + "m ----> " + std::to_string(x *0.001)+ "km"<<endl;
std::string str = std::to_string(x * 0.001);
str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
cout << "after" << endl;
cout<< std::to_string(x) + "m ----> " + str + "km"<<endl;
with output:
test zeros
before
200.000000m ----> 0.200000km
after
200.000000m ----> 0.2km
it is better then std::setprecision cause you don't need to decide how many num after period you want to keep, but let the implementation find it for you.
Here the documentation for some extra information.
Try using std::setprecsion()
Set decimal precision
Sets the decimal precision to be used to format floating-point values on output operations.
So in your case, you can use :
std::cout << std::setprecision(3)
This will remove the trailing zeroes from 0.0020000 to 0.002
Edit
The below code works when you want to use to_string in your code :
#include <iostream>
using namespace std;
int main(){
int x=1;
string str2 = to_string(x *0.001);
str2.erase ( str2.find_last_not_of('0') + 1, std::string::npos );;
std::cout<<to_string(x)+ "m ----> " + str2+ "km";
}

Modifying strings in an Array of strings

I have an array of strings and I would like to modify its elements at will. This is the code:
char pieces[9][4] = { " ", " o ", " a ", " ", " ", " ", " b ", " ", " " };
pieces[2] = { " x " };
As I know, the elements in pieces[] are string literal, so they can't be changed (I'm not sure why this is like this). Maybe it could be solved using std::string or vectors. However, I would like to know if this kind of operation, or very similar operations, can be done using an array of strings. Can be done something like this using just an array of strings?
In your specific situation, it looks like you always have some character surrounded by spaces, so you could simply do pieces[2][1] = 'x'; to modify that one element. However...
You are correct to assume this can be made easier with std::string and std::vector, but since we already know the size, an std::array will probably be better here:
std::array<std::string, 9> pieces = { " ", " o ", " a ", " ", " ", " ", " b ", " ", " " };
pieces[2] = " x ";
You may notice that the subscript operator still works on std::array's. This means that even if you switch to std::array's, you probably won't even have to change too much in your other code (just the parts dealing with c-strings to be dealing with std::strings)
You can use strcpy();
See following example code. See working code here:
int main(void)
{
char pieces[9][4] = { " ", " o ", " a ", " ", " ", " ", " b ", " ", " " };
printf("At point 1: %s\n",pieces[2]);
strcpy(pieces[2]," x ");
printf("At point 2: %s",pieces[2]);
return 0;
}
Output:
At point 1: a
At point 2: x
Does
pieces[2][0] = ' ';
pieces[2][1] = 'x';
pieces[2][2] = ' ';
pieces[2][3] = '\0';
do what you want?
Firstly, using curly brackets like pieces[2] = { " x " }; is the way of initialization, so you can't do that.
Secondly, pieces[2] is an char array, so it is not modifiable l-value.
You can either change its content element by element or by using strcpy() function.
Just to sumarize the different solutions given by different users, the options are:
Modify one char element at a time. Example: pieces[2][1] = 'x'
Use strcpy(). Example: strcpy(pieces[2]," x ")
Another types: std::array, std::string, std::vector

C++ const casting

I am trying to print the value of a const but it is not working. I am making a return to C++ after years so I know casting is a possible solution but I can't get that working either.
The code is as follows:
//the number of blanks surrounding the greeting
const int pad = 0;
//the number of rows and columns to write
const int rows = pad * 2 + 3;
const string::size_type cols = greeting.size() + pad * 2 + 2;
cout << endl << "Rows : " + rows;
I am trying to print the value of 'rows' without success.
You want:
cout << endl << "Rows : " << rows;
Note this has nothing to do with const - C++ does not allow you to concatenate strings and numbers with the + operator. What you were actually doing was that mysterious thing called pointer arithmetic.
You're almost there:
cout << endl << "Rows : " << rows;
The error is because "Rows : " is a string literal, thus is a constant, and generally speaking is not modified as you may think.
Going slightly further, you likely used + (colloquially used as a concatenation operation) assuming you needed to build a string to give to the output stream. Instead operator << returns the output stream when it is done, allowing chaining.
// It is almost as if you did:
(((cout << endl) << "Rows : ") << rows)
I think you want:
std::cout << std::endl << "Rows : " << rows << std::endl;
I make this mistake all the time as I also work with java a lot.
As others have pointed out, you need
std::cout << std::endl << "Rows : " << rows << std::endl;
The reason (or one of the reasons) is that "Rows : " is a char* and the + operator for char*s doesn't concatenate strings, like the one for std::string and strings in languages like Java and Python.

Concatenation operator in C++?

I have an application in which I need to combine strings within a variable like so:
int int_arr[4];
int_arr[1] = 123;
int_arr[2] = 456;
int_arr[3] = 789;
int_arr[4] = 10;
std::string _string = "Text " + int_arr[1] + " Text " + int_arr[2] + " Text " + int_arr[3] + " Text " + int_arr[4];
It gives me the compile error
Error C2210: '+' Operator cannot add pointers" on the second string of the expression.
As far as I can tell I am combining string literals and integers, not pointers.
Is there another concatenation operator that I should be using? Or is the expression just completely wrong and should figure out another way to implement this?
BTW I am using Visual Studio 2010
Neither C nor C++ allow concatenation of const char * and int. Even C++'s std::string, doesn't concatenate integers. Use streams instead:
std::stringstream ss;
ss << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = ss.str();
You can do this in Java since it uses the toString() method automatically on each part.
If you want to do it the same way in C++, you'll have to explicitly convert those integer to strings in order for this to work.
Something like:
#include <iostream>
#include <sstream>
std::string intToStr (int i) {
std::ostringstream s;
s << i;
return s.str();
}
int main (void) {
int var = 7;
std::string s = "Var is '" + intToStr(var) + "'";
std::cout << s << std::endl;
return 0;
}
Of course, you can just use:
std::ostringstream os;
os << "Var is '" << var << "'";
std::string s = os.str();
which is a lot easier.
A string literal becomes a pointer in this context. Not a std::string. (Well, to be pedantically correct, string literals are character arrays, but the name of an array has an implicit conversion to a pointer. One predefined form of the + operator takes a pointer left-argument and an integral right argument, which is the best match, so the implicit conversion takes place here. No user-defined conversion can ever take precedence over this built-in conversion, according to the C++ overloading rules.).
You should study a good C++ book, we have a list here on SO.
A string literal is an expression returning a pointer const char*.
std::stringstream _string_stream;
_string_stream << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = _string_stream.str();

Convert double to string C++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I convert a double into a string in C++?
I want to combine a string and a double and g++ is throwing this error:
main.cpp: In function ‘int main()’:
main.cpp:40: error: invalid operands of types ‘const char [2]’ and ‘double’ to binary ‘operator+’
Here is the line of code which it is throwing the error on:
storedCorrect[count] = "("+c1+","+c2+")";
storedCorrect[] is a string array, and c1 and c2 are both doubles. Is there a way to convert c1 and c2 to strings to allow my program to compile correctly?
You can't do it directly. There are a number of ways to do it:
Use a std::stringstream:
std::ostringstream s;
s << "(" << c1 << ", " << c2 << ")";
storedCorrect[count] = s.str()
Use boost::lexical_cast:
storedCorrect[count] = "(" + boost::lexical_cast<std::string>(c1) + ", " + boost::lexical_cast<std::string>(c2) + ")";
Use std::snprintf:
char buffer[256]; // make sure this is big enough!!!
snprintf(buffer, sizeof(buffer), "(%g, %g)", c1, c2);
storedCorrect[count] = buffer;
There are a number of other ways, using various double-to-string conversion functions, but these are the main ways you'll see it done.
In C++11, use std::to_string if you can accept the default format (%f).
storedCorrect[count]= "(" + std::to_string(c1) + ", " + std::to_string(c2) + ")";
Use std::stringstream. Its operator << is overloaded for all built-in types.
#include <sstream>
std::stringstream s;
s << "(" << c1 << "," << c2 << ")";
storedCorrect[count] = s.str();
This works like you'd expect - the same way you print to the screen with std::cout. You're simply "printing" to a string instead. The internals of operator << take care of making sure there's enough space and doing any necessary conversions (e.g., double to string).
Also, if you have the Boost library available, you might consider looking into lexical_cast. The syntax looks much like the normal C++-style casts:
#include <string>
#include <boost/lexical_cast.hpp>
using namespace boost;
storedCorrect[count] = "(" + lexical_cast<std::string>(c1) +
"," + lexical_cast<std::string>(c2) + ")";
Under the hood, boost::lexical_cast is basically doing the same thing we did with std::stringstream. A key advantage to using the Boost library is you can go the other way (e.g., string to double) just as easily. No more messing with atof() or strtod() and raw C-style strings.
std::string stringify(double x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion("stringify(double)");
return o.str();
}
C++ FAQ:
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.1
I believe the sprintf is the right function for you. I's in the standard library, like printf. Follow the link below for more information:
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/