Let's say I have a variable:
int fish5 = 7;
Can I access fish5 by concatenation of the term "fish" and "5" somehow?
An ideal solution would look something like this:
printf("I am displaying the number seven: %i", fish + 5);
No, not exactly what you want. But in your example, you can use an Array (only works if you want to concatenate an variablename with an number):
int fish[6] = {0};
fish[5] = 7;
printf("I am displaying the number seven: %i", fish[5]);
See also here for an reference to Arrays in C++.
Another solution would be using a std::map instead, like pointed out by Thrustmaster in the comments.
Then you could write something like:
#include <map>
#include <string>
int main(int argc, char* argv[]){
std::map<std::string, int> map;
map.insert(std::make_pair("fish5", 7));
printf("I am displaying the number seven: %d", map[std::string("fish") + std::to_string(5)]);
return 0;
}
For more Information about std::map, see here.
It is impossible to transition the solution from the compile time to run time, because c++ is a compiled language, not interpreted one. The variable names "lose their meaning" after compilation. They are just a set of symbols with addresses. This means, that after compilation asking for something like fish5 makes no sense.
To achieve what you want, you need to bind the name to the object somehow programmatically for example by using a map, that stores names as keys, and object references as values. This is how python does it, and why in python you can actually access the object via its name from the code.
In case anyone would wonder why for example gdb or crash dumps are meaningful, it is for pretty much the same reason. The symbol names must be saved at the compilation time (either embedded in the executable or an external file), then an external tool can figure out what is the name of a variable under a certain address. But a compiled executable can work just fine with out this information.
Alternatively, you need to remember the reference itself in some more convenient way, that allows it to be computable. E.g. store it in an array and access as fish[5]; although in this example it can be evaluated at the compile time, you can use the same method at run-time using a variable in place of 5.
The distinction between compile-time and run-time is very important, because you can actually do what you want at the compile-time with preprocessor, but only because it is compile time.
You could use operating system specific things, like (on Posix e.g. Linux) dlsym(3) to access variables thru the symbol table inside the (unstripped) ELF executable at runtime.
So, preferably declare the variables you want to access by their name as extern "C" e.g.
extern "C" int fish17;
(otherwise, take into account compiler specific name mangling)
Declare also a program handle:
void *progdlh;
initialize it early in main
progdlh = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
if (!progdlh) { fprintf(stderr, "dlopen failure %s\n", dlerror());
exit(EXIT_FAILURE); }
then, to retrieve your variable by a computed name you might try:
char nambuf[32];
snprintf (nambuf, sizeof(nambuf), "%s%d", "fish", 17);
int *pvar = dlsym(progdlh, nambuf);
if (!pvar) { fprintf(stderr, "dlsym %s failure %s\n", nambuf, dlerror());
exit(EXIT_FAILURE); }
printf ("variable %s is %d\n", nambuf, *pvar);
You'll probably should link your program with -rdynamic flag (and with the -ldl library)
My answer should work on Linux.
You can only do this at compile time, using preprocessor. Complete example:
#include <cstdio>
#define JOIN(a,b) a##b
int main(void) {
int fish5 = 5;
std::printf("I am displaying the number five: %i", JOIN(fish, 5));
return 0;
}
However, this is strictly compile time. If you try JOIN(fish, fish) you get error: ‘fishfish’ undeclared and if you try JOIN("fish", fish) you get error: pasting ""fish"" and "fish" does not give a valid preprocessing token.
In C++, variable names do not exist at runtime, so the operation can't be done at runtime, except though some deep debug info hackary to find variables by their name string (like a debugges does). If using strings is valid approach for you, then it's better to just have a map from string to variable address explicitly. Other answers show how to do this already, by using std::map.
Related
I am using libfmt to build a code generator that generates a sort of adapter layer around an existing library. So I have a dataset of parameter descriptions that include format strings describing the conversion from the data type in the outer layer to the data type in the inner layer. In the most simple case, this might look like
"{type_out} {var_out} = {var_in};\n"
in a more complex case, the conversion might depend on another parameter:
"int {var_out} = function_call({var_in}, {dependent_param__var_out});\n"
The name dependent_param (and as such any name that refers to one of its attributes, such as dependent_param__var_out) is not known to the code generator at compile time; it's constructed at runtime from the parameter dataset.
This means that I need to build a fmt::dynamic_format_arg_store some of whose named arguments are constructed at runtime. In essence, what I would like is along the lines of
#include <fmt/args.h>
#include <fmt/format.h>
#include <string>
fmt::dynamic_format_arg_store<fmt::format_context>
construct_arg_store(std::string const ¶mname) {
fmt::dynamic_format_arg_store<fmt::format_context> fmt_args;
// so far, so good.
fmt_args.push_back(fmt::arg("var_in", paramname));
fmt_args.push_back(fmt::arg("var_out", paramname + "_out"));
// imagine this were constructed by iterating over runtime-available data.
std::string argname = "dependent_param__var_out";
std::string argvalue = "dependent_param_out";
// Does not compile; fmt::arg expects char const *
fmt_args.push_back(fmt::arg(argname, argvalue));
return fmt_args;
}
int main() {
std::string fmtstring = "int {var_out} = function_call({var_in}, {dependent_param__var_out});\n";
auto args = construct_arg_store("foo");
fmt::vprint(fmtstring, args);
}
Right now, I build a symbol table from the dataset that contains std::string objects for all possible format arg names and use their .c_str() to build the fmt::arg objects (so that the generated C strings have a long enough lifetime). This works, but it seems like a bit of a dirty hack.
So I'm wondering, is there a better way to do it than that?
In general, it's better to use a template system like Mustache for this. That said, storing argument names as std::strings on the side and use them to construct dynamic_format_arg_store is OK. There is nothing hacky about it.
I'm working on an old network engine and the type of package sent over the network is made up of 2 bytes.
This is more or less human readable form, for example "LO" stands for Login.
In the part that reads the data there is an enormous switch, like this:
short sh=(((int)ad.cData[p])<<8)+((int)ad.cData[p+1]);
switch(sh)
{
case CMD('M','D'):
..some code here
break
where CMD is a define:
#define CMD(a,b) ((a<<8)+b)
I know there are better ways but just to clean up a bit and also to be able to search for the tag (say "LO") more easily (and not search for different types of "'L','O'" or "'L' , 'O'" or the occasional "'L', 'O'" <- spaces make it hard to search) I tried to make a MACRO for the switch so I could use "LO" instead of the define but I just can't get it to compile.
So here is the question: how do you change the #define to a macro that I can use like this instead:
case CMD("MD"):
..some code here
break
It started out as a little subtask to make life a little bit easier but now I can't get it out of my head, thanks for any help!
Cheers!
[edit] The code works, it the world that's wrong! ie. Visual Studio 2010 has a bug concerning this. No wonder I cut my teeth on it.
Macro-based solution
A string-literal is really an instance of char const[N] where N is the length of the string, including the terminating null-byte. With this in mind you can easily access any character within the string-literal by using string-literal[idx] to specify that you'd like to read the character stored at offset idx.
#define CMD(str) ((str[0]<<8)+str[1])
CMD("LO") => (("LO"[0]<<8)+"LO"[1]) => (('L'<<8)+'0')
You should however keep in mind that there's nothing preventing your from using the above macro with a string which is shorter than that of length 2, meaning that you can run into undefined-behavior if you try to read an offset which is not actually valid.
RECOMMENDED: C++11, use a constexpr function
You could create a function usable in constant-expressions (and with that, in case-labels), with a parameter of reference to const char[3], which is the "real" type of your string-literal "FO".
constexpr short cmd (char const(&ref)[3]) {
return (ref[0]<<8) + ref[1];
}
int main () {
short data = ...;
switch (data) {
case cmd("LO"):
...
}
}
C++11 and user-defined literals
In C++11 we were granted the possibility to define user-defined literals. This will make your code far easier to maintain and interpret, as well as having it be safer to use:
#include <stdexcept>
constexpr short operator"" _cmd (char const * s, unsigned long len) {
return len != 2 ? throw std::invalid_argument ("") : ((s[0]<<8)+s[1]);
}
int main () {
short data = ...;
switch (data) {
case "LO"_cmd:
...
}
}
The value associated with a case-label must be yield through a constant-expression. It might look like the above might throw an exception during runtime, but since a case-label is constant-expression the compiler must be able to evaluate "LO"_cmd during translation.
If this is not possible, as in "FOO"_cmd, the compiler will issue a diagnostic saying that the code is ill-formed.
#include <stdio.h>
#include <string.h>
int foo(char* a)
{ char str[10];
if (strlen(a)<10)
{
sprintf(str,"Yes");
puts(str);
return 0;
}
else
{
sprintf(str,"No");
puts(str);
return 1;
}
}
Now, lets say while writing a LLVM pass, I want to ensure that instead of calling sprintf, printf is called instead (with the same arguments). How could I go about doing that?
In a nutshell,
Go over all instructions in the function.
If the instruction is a CallInst, check if it's a call to sprintf (you can just check its name).
Create a new CallInst (via CallInst::Create) that calls printf instead of sprintf. I think the easiest way to get the Value of the printf declaration is to use one of the Module::getOrCreate methods. The type of printf should be the same as the one for sprintf minus the first parameter.
Set the operands of the new call instructions to be the same as for sprintf, minus the first parameter.
Replace the old call with the new call - replaceInstWithInst (in BasicBlockUtils.h) is probably the most convenient way.
Finally, you might want to track the usages of the old first parameter, remove them all and then remove it - so you'd get rid of that puts call.
#ifdef USE_BUFFER
#define my_printf(...) sprintf(buffer, __VA_ARGS__)
#else
#define my_printf(...) printf(__VA_ARGS__)
#endif
Now you can use for instance my_printf("My name is %s.", "Bozo"); and it will compile as if it was printf("My name is %s.", "Bozo") by default.
If you include #define USE_BUFFER before the headers, it will instead convert those lines to sprintf(buffer, "My name is %s.", "Bozo") at compile time. Of course the variable buffer must exist in the context.
I had learned that
inline ostream & _Cdecl ostream::operator<< (const signed char * _s) {
outstr(_s, (const signed char *)0);
return *this;
}
is how the insertion operator (<<) is declared(overloaded) in the iostream.h header file. Can I possibly use the same function to print a string value on screen?
I tried
#include<iostream.h>
int main() {
outstr("Hello world!", (const signed char *)0);
return 0;
}
it ended up in error. I would like to use something like this in order to see if there is some possible way to answer this query of printing something on screen without using printf, cout or puts().
Update: I would welcome if you have any suggestions other than
#include<stdlib.h>
void main() {
system("echo /"Hello world!/"");
}
NB: I have no restrictions if you can provide the C equivalent code that can print without a printf(), cout or puts()
Yes you could call the function directly, however your reasoning to do so is flawed. The time you save by eliminating the subroutine call to the operator is negligible when compared to the time taken to perform the actual function; this would be like closing the windows of your car while the convertible roof is down in order to reduce the rain.
If you want portability across all standards compliant C++ implementations, you can print a string to standard output in the following ways
const char * str = "Hello World\n";
fprintf(stdout, str);
fputs(str, stdout);
for (int i=0; str[i]!=0; ++i)
putchar(str[i]);
for (int i=0; str[i]!=0; ++i)
putc(str[i], stdout);
for (int i=0; str[i]!=0; ++i)
fputc(str[i], stdout);
fwrite(str, sizeof(*str), strlen(str), stdout);
Additionally, you can use std::cerr and std::clog. They write to stderr instead of stdout, but from the user's perspective, that's often the same place:
std::cerr << str;
std::clog << str;
From an efficiency perspective, I doubt any of these are going to help you. For that purpose, you might want to look at something a bit more platform specific. For POSIX systems, see the answer given by Dave S. For Windows, see this link.
What you shouldn't do, is open up your header files and imitate what they use. At least, not at the middle levels, where they are using different various obscure functions within their own implementation. Those functions might not exist upon the next release. However, if you go to the deepest levels, you will find OS specific calls like the ones in the link I provided above. Those should be safe to use as long as you stay on the same OS, or even between OS versions.
On a UNIX type system, you can do the following.
#include <unistd.h>
#include <stdio.h>
int main()
{
const char x[] = "Hello World!";
write(STDOUT_FILENO, x, strlen(x)); // Feel free to check the return value.
return 0;
}
I'm curious what your motivation for doing this would be. Outside of signal handlers, I'm reluctant to go to the lower level calls like this. The performance of the I/O will be the primary driver of time, not the intermediate function calls which are usually fairly heavily optimized / inlined.
The time required to make a function call is much, much smaller than the amount of time it takes to print your string. The amount of time you might save with your approach can (and usually should) be ignored.
You can directly use system calls.
http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html
This page, for example, explains linux system calls. You can start from the link I copied, and use many methods using assembly, or to say it in the other way, do something without calling the function of it.
But I'm guessing that was a trick question and if I had a company, I would never hire a person that uses system calls instead of functions.
This is an example of using sys_write(4) with standart output(1). You can inline assembly codes into your C/C++ code.
http://docs.cs.up.ac.za/programming/asm/derick_tut/#helloworld
The extraction operator is overloaded in the ostream class. So you cannot actually use it without having an object of that class with it.
It is implemented in the following manner:
cout<<"Hii";
is equivalent to:
cout.operator<<("Hii")
My understanding is that string is a member of the std namespace, so why does the following occur?
#include <iostream>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString);
cin.get();
return 0;
}
Each time the program runs, myString prints a seemingly random string of 3 characters, such as in the output above.
C++23 Update
We now finally have std::print as a way to use std::format for output directly:
#include <print>
#include <string>
int main() {
// ...
std::print("Follow this command: {}", myString);
// ...
}
This combines the best of both approaches.
Original Answer
It's compiling because printf isn't type safe, since it uses variable arguments in the C sense1. printf has no option for std::string, only a C-style string. Using something else in place of what it expects definitely won't give you the results you want. It's actually undefined behaviour, so anything at all could happen.
The easiest way to fix this, since you're using C++, is printing it normally with std::cout, since std::string supports that through operator overloading:
std::cout << "Follow this command: " << myString;
If, for some reason, you need to extract the C-style string, you can use the c_str() method of std::string to get a const char * that is null-terminated. Using your example:
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString.c_str()); //note the use of c_str
cin.get();
return 0;
}
If you want a function that is like printf, but type safe, look into variadic templates (C++11, supported on all major compilers as of MSVC12). You can find an example of one here. There's nothing I know of implemented like that in the standard library, but there might be in Boost, specifically boost::format.
[1]: This means that you can pass any number of arguments, but the function relies on you to tell it the number and types of those arguments. In the case of printf, that means a string with encoded type information like %d meaning int. If you lie about the type or number, the function has no standard way of knowing, although some compilers have the ability to check and give warnings when you lie.
Please don't use printf("%s", your_string.c_str());
Use cout << your_string; instead. Short, simple and typesafe. In fact, when you're writing C++, you generally want to avoid printf entirely -- it's a leftover from C that's rarely needed or useful in C++.
As to why you should use cout instead of printf, the reasons are numerous. Here's a sampling of a few of the most obvious:
As the question shows, printf isn't type-safe. If the type you pass differs from that given in the conversion specifier, printf will try to use whatever it finds on the stack as if it were the specified type, giving undefined behavior. Some compilers can warn about this under some circumstances, but some compilers can't/won't at all, and none can under all circumstances.
printf isn't extensible. You can only pass primitive types to it. The set of conversion specifiers it understands is hard-coded in its implementation, and there's no way for you to add more/others. Most well-written C++ should use these types primarily to implement types oriented toward the problem being solved.
It makes decent formatting much more difficult. For an obvious example, when you're printing numbers for people to read, you typically want to insert thousands separators every few digits. The exact number of digits and the characters used as separators varies, but cout has that covered as well. For example:
std::locale loc("");
std::cout.imbue(loc);
std::cout << 123456.78;
The nameless locale (the "") picks a locale based on the user's configuration. Therefore, on my machine (configured for US English) this prints out as 123,456.78. For somebody who has their computer configured for (say) Germany, it would print out something like 123.456,78. For somebody with it configured for India, it would print out as 1,23,456.78 (and of course there are many others). With printf I get exactly one result: 123456.78. It is consistent, but it's consistently wrong for everybody everywhere. Essentially the only way to work around it is to do the formatting separately, then pass the result as a string to printf, because printf itself simply will not do the job correctly.
Although they're quite compact, printf format strings can be quite unreadable. Even among C programmers who use printf virtually every day, I'd guess at least 99% would need to look things up to be sure what the # in %#x means, and how that differs from what the # in %#f means (and yes, they mean entirely different things).
use myString.c_str() if you want a c-like string (const char*) to use with printf
thanks
Use std::printf and c_str()
example:
std::printf("Follow this command: %s", myString.c_str());
You can use snprinft to determine the number of characters needed and allocate a buffer of the right size.
int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;
This is a minor adaption of an example on cppreference.com
printf accepts a variable number of arguments. Those can only have Plain Old Data (POD) types. Code that passes anything other than POD to printf only compiles because the compiler assumes you got your format right. %s means that the respective argument is supposed to be a pointer to a char. In your case it is an std::string not const char*. printf does not know it because the argument type goes lost and is supposed to be restored from the format parameter. When turning that std::string argument into const char* the resulting pointer will point to some irrelevant region of memory instead of your desired C string. For that reason your code prints out gibberish.
While printf is an excellent choice for printing out formatted text, (especially if you intend to have padding), it can be dangerous if you haven't enabled compiler warnings. Always enable warnings because then mistakes like this are easily avoidable. There is no reason to use the clumsy std::cout mechanism if the printf family can do the same task in a much faster and prettier way. Just make sure you have enabled all warnings (-Wall -Wextra) and you will be good. In case you use your own custom printf implementation you should declare it with the __attribute__ mechanism that enables the compiler to check the format string against the parameters provided.
The main reason is probably that a C++ string is a struct that includes a current-length value, not just the address of a sequence of chars terminated by a 0 byte. Printf and its relatives expect to find such a sequence, not a struct, and therefore get confused by C++ strings.
Speaking for myself, I believe that printf has a place that can't easily be filled by C++ syntactic features, just as table structures in html have a place that can't easily be filled by divs. As Dykstra wrote later about the goto, he didn't intend to start a religion and was really only arguing against using it as a kludge to make up for poorly-designed code.
It would be quite nice if the GNU project would add the printf family to their g++ extensions.
Printf is actually pretty good to use if size matters. Meaning if you are running a program where memory is an issue, then printf is actually a very good and under rater solution. Cout essentially shifts bits over to make room for the string, while printf just takes in some sort of parameters and prints it to the screen. If you were to compile a simple hello world program, printf would be able to compile it in less than 60, 000 bits as opposed to cout, it would take over 1 million bits to compile.
For your situation, id suggest using cout simply because it is much more convenient to use. Although, I would argue that printf is something good to know.
Here’s a generic way of doing it.
#include <string>
#include <stdio.h>
auto print_helper(auto const & t){
return t;
}
auto print_helper(std::string const & s){
return s.c_str();
}
std::string four(){
return "four";
}
template<class ... Args>
void print(char const * fmt, Args&& ...args){
printf(fmt, print_helper(args) ...);
}
int main(){
std::string one {"one"};
char const * three = "three";
print("%c %d %s %s, %s five", 'c', 3+4, one + " two", three, four());
}