Is it possible to stringify a character in a preprocessor macro without it including the (')s
example:
#define S(name, chr) const char * name = #name chr
usage:
S(hello, 'W'); //should expand to 'const char * hello = "helloW"
Thanks a bunch!,
Andrew
You don't need to, because in C adjacent string constants are merged.
ie.
const char *hello = "hello" "W";
is equivalent to
const char *hello = "helloW";
so your current macro is fine - just call it like so:
S(hello, "W");
Here are three ways. None use a single-quoted char, though:
#include <iostream>
#define S1(x, y) (#x #y)
#define S2(x, y) (#x y)
#define S3(x, y) (x y)
int main(void)
{
std::cout << S1(hello, W) << std::endl;
std::cout << S2(hello, "W") << std::endl;
std::cout << S3("hello", "W") << std::endl;
};
All output:
helloW
Related
I have a preprocessor define that should determine the size of an array.
This constant should also be passed to a HLSL shader.
For this I need to pass it around as a string.
Is there a way to embed preprocessor defines as a string?
#include <iostream>
#ifndef SIZE
#define SIZE 16
#endif
int main() {
const int arr[SIZE] = {}; // array size is 16 :)
const char* str = "SIZE"; // literal is "SIZE" and not "16" :(
std::cout << str << std::endl; // should print "16"
std::cout << SIZE << std::endl; // prints 16, but is not a string
}
You can use a stringifying macro, eg:
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
const char* str = STRINGIFY(SIZE);
std::cout << str << std::endl;
Alternatively, use a runtime format via snprintf() or equivalent, eg:
char str[12];
snprintf(str, "%d", SIZE);
std::cout << str << std::endl;
However, you really should be using std::string in C++ instead of char*, eg:
#include <string>
std::string str = std::to_string(SIZE);
std::cout << str << std::endl;
Or:
#include <string>
#include <sstream>
std::ostringstream oss;
oss << SIZE;
std::cout << oss.str() << std::endl;
How can i get/print variable name from this? I am using arduino Stream to print to console.
#ifndef any_h
#define any_h
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
struct any {
any(Stream& s):serial(s){}
template <class T>
void print(const T& msg)
{
getName(class T);
serial.print(msg);
}
template <class A, class... B>
void print(A head, B... tail)
{
print('{');
print(head);
print(tail...);
}
private:
Stream& serial;
};
#endif
Usage:
any A(Serial);
int myInt =34;
float myFloat = 944.5555f;
String myString = " this string";
A.print(myInt,myFloat,myString);
current output
34944.555 this string
I am trying to get something like with the same usage/access or like in this: Demo.
{"variableName":value,"variableName":value}
// That is in this case:
{myInt:34,myFloat:944.55,myString: this string}
What i have already tried:
#define getName(x) serial.print(#x)
void print(const T& msg)
{
getName(msg);
//getName(class T);
serial.print(msg);
}
output : msg34msg944.555msg this string
You can use macro to do that combined with stringify preprocessor:
Code:
#include <stdio.h>
#define PRINT_NAME(name) print_name(#name, (name))
void print_name(char *name, char* value) {
printf("name: %s ---> value: %s\n", name, value);
}
int main (int argc, char* argv[]) {
char* var1 = 'my var 1';
char* var2 = 'my new var 2';
PRINT_NAME(var1);
PRINT_NAME(var2);
return 0;
}
Output:
name: var1 --> value: my var 1
name: var2 --> value: my new var 2
I hope this helps :)
C++ doesn't have reflection, so you're limited to using macros, such as:
#include <iostream>
#define STRINGIFY_IMPL(X) #X
#define STRINGIFY(X) STRINGIFY_IMPL(X)
#define VARIABLE_NAME(X) STRINGIFY(X)
#define VARIABLE_VALUE(X) X
int main()
{
double d = 3.141;
std::cout << VARIABLE_NAME(d) << ": " << VARIABLE_VALUE(d) << '\n';
return 0;
}
(VARIABLE_NAME and VARIABLE_VALUE aren't truly needed, you could also use std::cout << STRINGIFY(d) << ": " << d << '\n';).
You can, of course, combine this all into a super macro (with macros from above):
#include <iostream>
#include <string>
#define STREAM_NAME_VALUE(str, X) str << '{' << STRINGIFY(X) << ':' << X << '}'
int main()
{
int myInt =34;
float myFloat = 944.5555f;
std::string myString = " this string";
STREAM_NAME_VALUE(std::cout, myInt);
std::cout << '\n';
STREAM_NAME_VALUE(std::cout, myFloat);
std::cout << '\n';
STREAM_NAME_VALUE(std::cout, myString);
std::cout << '\n';
return 0;
}
I'm trying to code a macro called EMPTY_OR, which will return the first argument, but if it's empty, it will return the second one.
Here's what I have so far:
#include <iostream>
#define EMPTY_OR(x, y) ( (sizeof(#x) > sizeof("")) ? (x) : (y) )
#define TEST(x, y) EMPTY_OR(y, x)
using namespace std;
int main()
{
int four = TEST(4, );
int eight = TEST(4, 8);
cout << "four: " << four << endl;
cout << "eight: " << eight << endl;
return 0;
}
It's close, but it doesn't work because the first line of the main function expands to the following:
( (sizeof("") > sizeof("")) ? () : (4) )
The condition is never true, so () is never evaluated. I shouldn't care about it, but the compiler does, and it shows an error.
How can I solve it with the most straightforward and standard-compliant (or at least MSVC-compliant) way?
If I'm understanding what you're trying to do correctly, I'd remove the sizeof and just check if the first character in the string is \0;
#define EMPTY_OR(x, y) ( #x[0] ? (x+0) : (y) )
Here's a solution adapted from this article and without Boost that works on anything that I can think of that you can pass:
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a##b
#define IF(cond, t, f) CAT(IF_, cond)(t, f)
#define IF_1(t, f) t
#define IF_0(t, f) f
#define COMMA(x) ,
#define ARG3(a, b, c, ...) c
#define HAS_COMMA(x) ARG3(x, 1, 0,)
#define EMPTY(x) EMPTY_(HAS_COMMA(COMMA x ()))
#define EMPTY_(x) HAS_COMMA(CAT(EMPTY_, x))
#define EMPTY_1 ,
#define EMPTY_OR(x, y) IF(EMPTY(x), y, x)
#define TEST(x, y) EMPTY_OR(y, x)
#include <iostream>
using namespace std;
int main()
{
int t = TEST(1==, ) 1;
int f = TEST(1==, 0==) 1;
cout << "t: " << t << endl;
cout << "f: " << f << endl;
return 0;
}
In Pascal Lazarus/Delphi, we have a function QuotedStr() that wraps any string within single quotes.
Here's an example of my current C++ code:
//I need to quote tblCustomers
pqxx::result r = txn.exec( "Select * from \"tblCustomers\" ");
Another one:
//I need to quote cCustomerName
std::cout << "Name: " << r[a]["\"cCustomerName\""];
Similar to the above, I have to frequently double-quote strings. Typing this in is kind of slowing me down. Is there a standard function I can use for this?
BTW, I develop using Ubuntu/Windows with Code::Blocks. The technique used must be compatible across both platforms. If there's no function, this means that I must write one.
C++14 added std::quoted which does exactly that, and more actually: it takes care of escaping quotes and backslashes in output streams, and of unescaping them in input streams. It is efficient, in that it does not create a new string, it's really a IO manipulator. (So you don't get a string, as you'd like.)
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::string in = "\\Hello \"Wörld\"\\\n";
std::stringstream ss;
ss << std::quoted(in);
std::string out;
ss >> std::quoted(out);
std::cout << '{' << in << "}\n"
<< '{' << ss.str() << "}\n"
<< '{' << out << "}\n";
}
gives
{\Hello "Wörld"\
}
{"\\Hello \"Wörld\"\\
"}
{\Hello "Wörld"\
}
As described in its proposal, it was really designed for round-tripping of strings.
Using C++11 you can create user defined literals like this:
#include <iostream>
#include <string>
#include <cstddef>
// Define user defined literal "_quoted" operator.
std::string operator"" _quoted(const char* text, std::size_t len) {
return "\"" + std::string(text, len) + "\"";
}
int main() {
std::cout << "tblCustomers"_quoted << std::endl;
std::cout << "cCustomerName"_quoted << std::endl;
}
Output:
"tblCustomers"
"cCustomerName"
You can even define the operator with a shorter name if you want, e.g.:
std::string operator"" _q(const char* text, std::size_t len) { /* ... */ }
// ...
std::cout << "tblCustomers"_q << std::endl;
More info on user-defined literals
String str = "tblCustomers";
str = "'" + str + "'";
See more options here
No standard function, unless you count std::basic_string::operator+(), but writing it is trivial.
I'm somewhat confused by what's slowing you down - quoted( "cCustomerName" ) is more characters, no? :>
You could use your own placeholder character to stand for the quote, some ASCII symbol that will never be used, and replace it with " just before you output the strings.
#include <iostream>
#include <string>
struct quoted
{
const char * _text;
quoted( const char * text ) : _text(text) {}
operator std::string () const
{
std::string quotedStr = "\"";
quotedStr += _text;
quotedStr += "\"";
return quotedStr;
}
};
std::ostream & operator<< ( std::ostream & ostr, const quoted & q )
{
ostr << "\"" << q._text << "\"";
return ostr;
}
int main ( int argc, char * argv[] )
{
std::string strq = quoted( "tblCustomers" );
std::cout << strq << std::endl;
std::cout << quoted( "cCustomerName" ) << std::endl;
return 0;
}
With this you get what you want.
What about using some C function and backslash to escape the quotes?
Like sprintf_s:
#define BUF_SIZE 100
void execute_prog() {
//Strings that will be predicted by quotes
string param1 = "C:\\users\\foo\\input file.txt", string param2 = "output.txt";
//Char array with any buffer size
char command[BUF_SIZE];
//Concating my prog call in the C string.
//sprintf_s requires a buffer size for security reasons
sprintf_s(command, BUF_SIZE, "program.exe \"%s\" \"%s\"", param1.c_str(),
param2.c_str());
system(command);
}
Resulting string is:
program.exe "C:\users\foo\input file.txt" "output.txt"
Here is the documentation.
So, when I pass a const char * to a function once, can I use it again? It appears to end up spitting out crap to me.
const char *config_file = "file.txt";
function(int x, config_file);
cout << "Number" << x;
secondfunction(int y, config_file);
Do I need to make another pointer to config_file?
If so, how do I do that?
Thanks!
No, your can use it just fine. Despite the fact that the code you gave is uncompilable, I think I understand what you're asking.
A code segment like:
const char *x = "Hello";
fnA (x);
fnB (x);
should be just fine.
If you find that fnB is not getting what it expects then either:
fnA is changing what x points to (normally not possible since it's a const char *); or
some unshown piece of code is changing the pointer itself; or
something is corrupting the memory.
Try this code as an example:
#include <iostream>
#include <iomanip>
static void fnA (const char *a) {
std::cout << "fnA: [" << a << "]" << std::endl;
}
static void fnB (const char *b) {
std::cout << "fnB: [" << b << "]" << std::endl;
}
int main (void) {
const char *x = "Hello";
fnA (x);
fnB (x);
return 0;
}
It outputs, as expected:
fnA: [Hello]
fnB: [Hello]