c++: concat constant string with macro-defined string - c++

I want to concat the constant string and the macro defined string.
#define DEEP_DRIVE_NET "C:/Users/tumh/hookv/deep_drive_model.prototxt"
#define DEEP_DRIVE_WEIGHT "C:/Users/tumh/hookv/caffe_deep_drive_train_iter_35352.caffemodel"
CHECK(file_exist(DEEP_DRIVE_WEIGHT)) << "Net Weight " + DEEP_DRIVE_WEIGHT + " Not Found";
CHECK(file_exist(DEEP_DRIVE_NET)) << "Net definition " + DEEP_DRIVE_NET + " Not Found";
the compile error from msvc 2013 compiler is
C:\Users\tumh\hookv\samples\Test\Inference.cpp(28): error C2110: '+' : cannot add two pointers [C:\Users\tumh\hookv\build\NativeTrainer.vcxproj]
C:\Users\tumh\hookv\samples\Test\Inference.cpp(29): error C2110: '+' : cannot add two pointers [C:\Users\tumh\hookv\build\NativeTrainer.vcxproj]
How can I concatenate such strings?
Thanks.

Just omit the + operations to concatenate c-style string literals:
CHECK(file_exist(DEEP_DRIVE_WEIGHT)) << "Net Weight " DEEP_DRIVE_WEIGHT " Not Found";
CHECK(file_exist(DEEP_DRIVE_NET)) << "Net definition " DEEP_DRIVE_NET " Not Found";

Related

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++ single quotes syntax

I am learning C++ and just started reading "Programming Principles and Practice" by Bjarne Stroustrup and he uses this code to illustrate a point:
#include "std_lib_facilities.h"
using namespace std;
int main() // C++ programs start by executing the function main
{
char c = 'x';
int i1 = c;
int i2 = 'x';
char c2 = i1;
cout << c << ' << i1 << ' << c2 << '\n';
return 0;
}
I am familiar in general with the difference between double and single quotes in the C++ world, but would someone kindly explain the construction and purpose of the section ' << i1 << '
Thanks
cout << c << ' << i1 << ' << c2 << '\n';
appears to be a typo in the book. I see it in Programming Principles and Practice Using C++ (Second Edition) Second printing. I do not see it listed in the errata.
According to the book, the intended output is
x 120 x
But what happens here is ' << i1 << ' attempts to compress the << i1 << to a multi-byte character and prints out an integer (most likely 540818464-> 0x203C3C20 -> ASCII values of ' ', '<', '<', ' ') because cout doesn't know wide characters. You'd need wcout for that. End result is output something like
x540818464x
and a warning or two from the compiler because while it's valid C++ code, it's almost certainly not what you want to be doing.
The line should most likely read
cout << c << ' ' << i1 << ' ' << c2 << '\n';
which will output the expected x 120 x
In other words, Linker3000, you are not crazy and not misunderstanding the example code.
Anyone know who I should contact to log errata or get a clarification on the off chance there is some top secret sneakiness going way over my head?
Before answering your question, here is a little background on what that is actually doing. Also note that there is a typo in the example, the string constant should have been double quoted:
cout << c << " << i1 << " << c2 << "\n";
In C++, operators can be overloaded so that they mean different things with different functions. In the case of cout, the << operator is overloaded as the "Insertion Operator". Think of it as taking the operand on the right, and inserting it (or sending it) into the operator on the left.
For example,
cout << "Hello World";
This takes the string "Hello World", and sends it to cout for processing.
So what beginners do not get is what something like this means:
cout << "Hello" << " World";
This is doing the same thing, but the operator precedence says to perform the injections from left to right. To make this work, the cout object returns itself as a function return value. Why is this important? Because the above statement is actually two separate operator evaluations:
(cout << "Hello") << " World";
This first injects "Hello" to cout, which outputs it, then continues to evaluate the next inject operator. Because cout returns itself, after the (cout << "Hello") is executed you have the following still to be evaluated:
cout << " World";
This expression injects " World" into the cout object, which then outputs " World", with the net effect being that you see "Hello World" just like the first time.
So in your example, what is it doing?
cout << c << " << i1 << " << c2 << "\n";
This is evaluated left to right as follows:
((((cout << c) << " << i1 << ") << c2) << "\n"); => Outputs value of c
((((cout ) << " << i1 << ") << c2) << "\n"); => Outputs string " << i1 << "
((( cout ) << c2) << "\n"); => Outputs value of c2
(( cout ) << "\n"); => Outputs newline character
( cout ); => No more output
Expression completes and returns the cout object as the expression value.
Assuming c='x' and c2='x', the final output from this expression is the following character string output on a single line:
x << i1 << x
For beginners, all those insertion operators << look a little strange. It is because you are dealing with objects. You could build the string up as a complete formatted object before injecting it into cout, and while that make the cout expression look simpler, we do not do that in C++ because it makes your code more complex and error prone. Note also, there is nothing special about the cout object. If you wanted to output to the standard error stream, you would use cerr instead. If you wanted to output to a file, your would instantiate a stream object that outputs to the desired file. That rest of the code in your example would be the same.
In C, the same thing would be done procedurally using a format string:
printf("%d << i1 << %d\n", i1, c2);
This is allowed in C++ too, because C++ is a superset of C. Many C++ programmers still use this output method, but that is because those programmers learned C first, and may not have fully embraced the object oriented nature of C++
Note that you may also have seen the << operator in the context of mathematical expressions like:
A = A << 8;
In this case, the << operator is the bitwise rotate operation. It has nothing to do with output to cout. It will rotate the bits in A to the left by eight bits.

Macros argument order matters?

When i compile the below program following error is generated by the compiler.
example.cpp:12:13: error: invalid operands to binary expression ('const char *' and 'const char *')
cout << JMP(to_string(10)) << endl;
^~~~~~~~~~~~~~~~~~
example.cpp:6:34: note: expanded from macro 'JMP'
#define JMP(add) "DEFAULT is : " + DEFAULT + " JMP is : " + add
~~~~~~~~~~~~~~~ ^ ~~~~~~~
#include <iostream>
#include <string>
#define DEFAULT "00000"
#define JMP(add) "DEFAULT is : " + DEFAULT + " JMP is : " + add
using namespace std;
int main()
{
cout << JMP(to_string(10)) << endl;
return 0;
}
Whereas the below program compiles properly
#include <iostream>
#include <string>
#define DEFAULT "00000"
#define JMP(add) "JMP is : " + add + "DEFAULT is : " + DEFAULT
using namespace std;
int main()
{
cout << JMP(to_string(10)) << endl;
return 0;
}
Why the order of argument present in the macro body matters ?
Try to get rid of the + to concatenate char array literals:
#define JMP(add) "DEFAULT is : " DEFAULT " JMP is : " add
NOTE:
Since add will expand to a std::string value (to_string(10)) from your sample, this won't work either. You'll need to call the macro like this:
cout << JMP("10") << endl;
An alternate solution would be making the parts std::string instances:
#define JMP(add) std::string("DEFAULT is : " DEFAULT " JMP is : ") + add
The error is telling you that the operands given to the binary expression (i.e. + operator) are not of expected types. This operator is expecting a const string & (or a string & using C++ 11) for at least one of its operands. That plus left to right evaluation is why it works when you switch the order.
cout << to_string(10) + " is the JUMP" << endl; // having valid operands, + operator returns a string object
cout << "JUMP is : " + to_string(10) << endl; // same here
cout << "DEFAULT is : " + "00000" << endl; // no bueno: both operands are const char pointers
Provided that you have a const string & as a starter*, you can keep concatenating const char *s all day long:
cout << "JUMP is : " + to_string(10) + " DEFAULT is : " + "00000" + "game is " + "concentration, " + "category is " + "..." << endl;
So, this actually is not about order of macro arguments but about strings, char pointers, concatenation, associativity, and operators.
*as in a sports game.

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();