4

I am programming a new server-client network for the game Crysis Wars. I have a function that centers a string to the amount of characters supported per-line in the console window. The window fits 113 characters, but I have set the maximum character width in my function to 111 as to fit text nicely.

This is my function:

string Main::CenterText(string s)
{
    return string((111 - s.length()) / 2, ' ') + s; 
}

This function is from a question I asked last year, but I however am not sure whether I ended up using it or not in past projects.

I am attempting to use this function in this context (the CryLogAlways function simply logs the string to the game/server logfile and prints it):

CryLogAlways(CenterText("   ____     ____      _ __      _  _  __").c_str());
CryLogAlways(CenterText("  /  _/__  / _(_)__  (_) /___ _( )| |/_/").c_str());
CryLogAlways(CenterText(" _/ // _ \\/ _/ / _ \\/ / __/ // //_>  <  ").c_str());
CryLogAlways(CenterText("/___/_//_/_//_/_//_/_/\\__/\\_, / /_/|_|  ").c_str());
CryLogAlways(CenterText("                         /___/          ").c_str());

However the output is:

enter image description here

Likewise as @deW1 requested, I have a similar output with CryLogAlways(CenterText("X").c_str());:

enter image description here

Why am I getting this output, and how can I fix this?

Community
  • 1
  • 1
AStopher
  • 4,207
  • 11
  • 50
  • 75
  • What is the output if you do `CryLogAlways(CenterText("X").c_str());` ? – deW1 Nov 21 '14 at 13:33
  • @deW1 http://puu.sh/cZEG8/7921d3bc39.png. It's a strange issue, I'll put that into the question. – AStopher Nov 21 '14 at 13:35
  • what do you mean by "I however am not sure whether I ended up using it or not" ? Are you sure that the `Main::CenterText` function that you showed is the actual one that you're using ? – Sander De Dycker Nov 21 '14 at 13:40
  • @SanderDeDycker I updated the sentence for clarity. I was referring to past projects, and not my current one. – AStopher Nov 21 '14 at 13:43
  • 4
    If that's a `CryString`, they've inverted the order of parameters for construction of a `string`: First the value, then the amount (as opposed to `std::string`). The character `' '` is 32 decimal, which corresponds to the amount of `'#'`characters in your output. – dyp Nov 21 '14 at 13:49
  • @dyp The `CryLogAlways` here takes a `const char *`, but it could very well be converted to `CryString` within its function. I'll check. – AStopher Nov 21 '14 at 13:59
  • 1
    @cybermonkey Well your function uses a type named `string` as both its parameter and return type, and within this function, you're constructing a `string` - here, the order of parameters matters. – dyp Nov 21 '14 at 14:00
  • 1
    Can you clarify what exactly `string` is? – Angew is no longer proud of SO Nov 21 '14 at 14:14
  • @Angew It's a standard C++ `string` type. The `CryString` type that @dyp refers to can be used as` `CryString` in place of `string`, but I've never actually used `CryString`. – AStopher Nov 21 '14 at 14:29
  • @cybermonkey: Apparently it's _not_ `std::string`... – Lightness Races in Orbit Nov 21 '14 at 14:32
  • @cybermonkey Does anything change if you explicitly qualify it as `std::string` in all occurences in the function? It's obviously interpreting `' '` (ASCII 32) as the number of characters, which `std::string` should most definitely not do. – Angew is no longer proud of SO Nov 21 '14 at 14:33
  • @LightnessRacesinOrbit It certainly *is* `std::string`, and it's definitely ***not*** `CryString`. – AStopher Nov 21 '14 at 14:33
  • @cybermonkey: Then what's all this about the arguments being switched? – Lightness Races in Orbit Nov 21 '14 at 14:34
  • @Angew Just tested that, and it's now outputting the desired text correctly. If you (or someone else) write out an answer detailing *why* simply using a normal `string` type won't work (and perhaps a revised function), I'll accept the answer. – AStopher Nov 21 '14 at 14:35
  • @LightnessRacesinOrbit I have no idea. I've done a few C++ Crysis DLL projects with the supplied SDK, and this is the first time I've heard anyone say that the arguments are switched. – AStopher Nov 21 '14 at 14:36
  • @cybermonkey: No one needs to "say" it; it's clear from both the documentation and [the source](http://www.gamedev.stjepan.net/ce3sdk/docs/CryEngine/html/_cry_string_8h_source.html). – Lightness Races in Orbit Nov 21 '14 at 14:41
  • @cybermonkey: The normal `[std::]string` type will work just fine; but currently you're _not_ using it. – Lightness Races in Orbit Nov 21 '14 at 14:43
  • @LightnessRacesinOrbit Surely to use that type I would have to use `CryString` (and `#include` its header), or am I missing something here? – AStopher Nov 21 '14 at 14:51
  • @cybermonkey: Sorry but I have no idea what you're talking about. No to use `std::string` you do not have to use `CryString`; that makes no sense! Write `std::string` in full to stop the compiler thinking that by `string` you instead mean `CryString`. Or simply reverse your arguments. – Lightness Races in Orbit Nov 21 '14 at 14:52
  • @LightnessRacesinOrbit I apologise; I looked into it further and it *is* using `CryString`. – AStopher Nov 21 '14 at 14:53
  • 1
    @cybermonkey Yes as we've all been saying all along :P – Lightness Races in Orbit Nov 21 '14 at 14:54
  • @LightnessRacesinOrbit Strange, I've worked on C++ projects for this game for a couple of years now, and never noticed that. I guess we all learn something new every day :-) – AStopher Nov 21 '14 at 14:55

2 Answers2

8

You're using the type string unqualified. I was assuming you have using namespace std somewhere (against best practice), which would make string refer to std::string. But apparently that is not the case, and you have the non-qualified name string defined to something (the question doesn't show what), which behaves similarly to a std::string (i.e. it has .length() and .c_str()). However, the constructor arguments of this something seem to be in reversed order to those of std::string.

If you want your function to work with standard library strings, say so eplicitly:

std::string Main::CenterText(std::string s)
{
    return std::string((111 - s.length()) / 2, ' ') + s; 
}

This is a prime example of why it's an extremely good idea to use explicit qualification for std types.

Community
  • 1
  • 1
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • *"This is a prime example of why it's an extremely good idea to use explicit qualification for std types."* I would rather assume CryTek used the `typedef CryString string` on purpose to exploit that bad practice: the interface of `CryString` looks very similar to `std::string`, I bet they tried to make it compatible. – dyp Nov 21 '14 at 17:39
  • I keep referring back to this, excellent answer so I'm awarding a bounty. Will award in 23 hours. – AStopher Mar 12 '15 at 09:02
  • 1
    @ʎǝʞuoɯɹǝqʎɔ Thanks; I'm happy it's been helpful. – Angew is no longer proud of SO Mar 12 '15 at 09:13
2

According to C++ Reference, you are right.

As pointed out in the comments, for the string implementation you use, the arguments are switched.

For the second example, you print the sign (111-1)/2 = 55 = '7' for ' ' = 32 times. Swap the arguments to

string(' ',(111 - s.length()) / 2)

and it should work better.

Martze
  • 921
  • 13
  • 32
  • This is on the right track, though. The compiler is clearly not matching this code to the std::string constructor for 'string (size_t n, char c);' But the OP tested using a string constant "X" and got the same result, so how can it not be std::string? – Richard Schwartz Nov 21 '14 at 14:01
  • 2
    @RichardSchwartz [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string/basic_string) has a constructor that takes the amount of repetition first, then the character to repeat. [CryString](https://github.com/adithedude007/alecmercer-origins/blob/master/Code/CryEngine/CryCommon/CryString.h) on the other hand first takes the character to repeat, then the amount of repetition. So Martze has it backwards. – dyp Nov 21 '14 at 14:04
  • So i made the same error as in the question but with the reference version. Wow. Fixed it though. – Martze Nov 21 '14 at 14:30