Thank you! Actuallymar wrote:Shouldn't that be it->second = value instead?
Code: Select all
it->second.value = value;Moderator: Ras
Thank you! Actuallymar wrote:Shouldn't that be it->second = value instead?
Code: Select all
it->second.value = value;Exactly:Sven Schüle wrote:I'd assume that typically you only change option values at runtime while the set of supported options itself stays constant. Your "struct Option" data structure combines a static, descriptive part specifying what your program supports, and a dynamic part containing a value per option, initially set to some default.lucasart wrote:I typically have to change engine options at runtime
Sven
Code: Select all
struct Option
{
enum Type { Boolean, Integer };
Type type;
std::string name;
int value, min, max;
typedef std::pair<Type, std::string> Key;
};
Code: Select all
struct Option
{
enum Type { Boolean, Integer };
Type type;
std::string name;
int min, max;
typedef std::pair<Type, std::string> Key;
};
struct OptionValue {
int value;
};
Code: Select all
std::string s;
int time = 60000, inc = 1000;
s += "go wtime " + time + " winc " + inc;
Code: Select all
...("go wtime %d winc %d", wtime, winc)OK I managed to get the stringstream version working:lucasart wrote:Another noob question on C++. I can't figure out how to use std::string. Here's is the code that I'm trying to do:I can do this with a stringstream, but it's so convoluted and ugly. Then I'd have to "paste" my stringstream into the original string.Code: Select all
std::string s; int time = 60000, inc = 1000; s += "go wtime " + time + " winc " + inc;
Ideally I want to use a function like printf() where I can define a format:How does one do that in C++ ?Code: Select all
...("go wtime %d winc %d", wtime, winc)
Code: Select all
std::ostringstream ostrm;
int time = 60000, inc = 1000;
ostrm << "go wtime " << time << " winc " << inc;
std::string s = ostrm.str();
Don't worry, std::string and streams are quite fast, and definitely fast enough for your application of a tournament CLI. Things like I/O, network communication, or inter-process communcation typically take much more time than some string or stream operations. Building large tables of data will require attention, but fiddling with some strings should not cause any performance trouble for your application.lucasart wrote:OK I managed to get the stringstream version working:But I'm a little worried about the performance of such a code. If I understand correctly:Code: Select all
std::ostringstream ostrm; int time = 60000, inc = 1000; ostrm << "go wtime " << time << " winc " << inc; std::string s = ostrm.str();
* ostrm is created and initialized with an empty string (and possibly some prealloc of some size I don't know)
* every single << is really a function call, which would do two things: (1) handle the resizing of the string (2) some kind of strcat()
* a new string s is created (allocation and initialization) and it's "buffer" is copied from the one of ostrm. The allocation is optimized because it knows how many bytes to allocate.
* the temporary ostrm still lives (with memory allocated on free store), and will die when gets out of scope and gets destructed.
Isn't there a more efficient way of doing this ?
I'm just worried that all this C++ syntactic sugar can make some code "look nice" (though a sprintf() is far more straightforward and more readable) but actually hide some terrible inefficience if one doesn't know what is behind it (ie. how string and ostrm are implemented and exactly what all these operators do).
ok, thank you.mar wrote: I'm not sure (never used std::string/streams) but I bet it does the same as std::vector, i.e. it grows capacity 2x when needed and subsequent additions should be fast (i.e. no reallocation) until it needs more space again.
sprintf() is really doing things the C-way, and I want to learn the C++-way, so I force myself not to hack around C++ with C code (otherwise I'll never learn).mar wrote: If you are used to sprintf then I see no problem doing sprintf to a buffer then assign it to a string, but maybe that would be considered ugly by some.
Code: Select all
char s[0x100];
sprintf(s, "go wtime %d wind %d", time, inc);
Code: Select all
int time = 60000, inc = 1000;
string s = "go wtime " + time + " inc " + inc;
The reason is simply that the operator + is defined for std::string, not string literal. So if you wrote string("go wtime") + ..., it should work fine.lucasart wrote:But I'm a bit disappointed about C++ here. The whole STL thing is about allowing programmers to write high-level code, right ? So why didn't the C++ standard define operators that allow people to simply write:I think this would be even more efficient than going through a stringstream. There would be no need to allocate a second string (the one contained by the stringstream). And the code would be much more natural and familiar to people with a background in true high-level languages, where a string is a native type.Code: Select all
int time = 60000, inc = 1000; string s = "go wtime " + time + " inc " + inc;
Is there any reason why they didn't want to, or couldn't do it ?
Well the problem is that STL is only optional, for convenience, so I would learn the language itself first, then libraries. STL isn't bad but IMHO it could have been much better, hard to say. The reason I stick with STL is that it's well tested (therefore there should be no surprises like bugs) and that some debuggers support it natively, i.e. you see containers in human-readable form, which is of course convenient. STL also demonstrates the power of the language, namely templates.lucasart wrote: sprintf() is really doing things the C-way, and I want to learn the C++-way, so I force myself not to hack around C++ with C code (otherwise I'll never learn).
I absolutely agree. A very thorough reasoning.I would say there are pros and cons of doing an sprintf() here:
1/ pros
- is far more concise and readable than a spaghetti code with a bunch of <<Code: Select all
char s[0x100]; sprintf(s, "go wtime %d wind %d", time, inc);
- the allocation is uber-fast: it is allocated on the stack by moving the stack pointer (a single assembly op code)
2/ cons
- 0x100 is a magic number that comes out of nowhere
- 0x100 is assumed by the programmer to be large enough to avoid overflow (risky if you screw up, and painful to debug some segfaulty code afterwards)
- if you make the number too large to be on the safe side every time, you'll end up wasting a lot of memory, and more importantly stack memory, which you can easily run out of (perhaps not on a modern PC, but on mobile devices or whatever)
=> Anyway, it's good to have both at your disposal, so you can make the correct decision when a trade-off needs to be made. I'll try to do things the C++ way first, and only when I have some performance issue, and after profiling the code, I might do some low-level optimization.