• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
BrandonSnider

(C++ Beginner) I hate to post here, but... why won't my "if" statement evaluate a string?

35 posts in this topic

I've worked with other languages in the past including basic and a lot of scripting languages, and I have worked a decent bit on C++ too. I haven't worked on C++ in quite a while now, and last night I was trying to refresh myself on the basics... so--and this is a little embarrassing--I wrote this small piece of code for a console program to send my girlfriend:

[CODE]
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//Vars
string username = "";

//Execute
cout << "Hello \n";
cin.get();
cout << "What is your name? ";
getline (cin, username);
cout << "Your name is: " << username;
cin.get();
if (username == "Tiffany" || "tiffany" || "Tiffany McClure" || "tiffany McClure" || "Tiffany Mcclure" || "tiffany mcclue")
{
cout << "Your name is Tiffany... \n The Creator has a message for you: \n I love you Cupcake";
cin.get();
}
else
{
cout << "Your name is not Tiffany.";
cin.get();
}
return 0;
}
[/CODE]

The problem is... it doesn't appear that the "if (username == "Tiffany" || "tiffany" || "Tiffany McClure" || "tiffany McClure" || "Tiffany Mcclure" || "tiffany mcclue")" statement evaluates correctly, as the program always displays the cout message in the "if" block, even if the if statement should be false.


I know these are beginner C++ concepts that have nothing to do with game development, but... this is like the only forum acct. I have for anything like this, and I hate to create another just to ask this somewhat stupid question.

I appreciate any help with this, I'm trying to pick up C++ again so that maybe I can do something useful with it.


EDIT: Oops. I haven't been on this site in a while. Forgot there was a "For Beginners" Section. This probably belongs there. Sorry about that. Edited by bls61793
-1

Share this post


Link to post
Share on other sites
Thanks... XD I knew I would feel dumb at the end of this one... always the little things.

Appreciate it. Sometimes it's just helpful to have someone else look at it.
1

Share this post


Link to post
Share on other sites
The || && and ! operators operate on entire logical expressions. username == "Tiffany" is an entire expression, but "tiffany" is just a string literal.I made that mistake too when I first started out.
1

Share this post


Link to post
Share on other sites
I don't know how std::string handles this, but you should be able to do [font=courier new,courier,monospace]if(stricmp(username.c_str(), "Tiffany McClure")==0) [/font]to do a case insensitive comparison.
(stricmp measures some kind of "difference" between the strings, so you have to check for == 0)
0

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1342385514' post='4959358'][...] convert [...] strings to all lowercase...[/quote]

I was going to suggest this. This is a great technique. Saves space and it means you catch strange possibilities like "TiffAnY MCClurE"; which would otherwise take up huge amounts of space if you tried to catch every single version. Edited by BinaryPhysics
0

Share this post


Link to post
Share on other sites
[quote name='Krohm' timestamp='1342422636' post='4959485']
[quote name='BinaryPhysics' timestamp='1342395942' post='4959383']
Saves space
[/quote]How?
[/quote]


Stops the exe having to have all the different supported permutations of the string stored in its data section.

"Saves space" is pushing it though, overhead of calling method is likely to outweight space saving but of course this is irrelevant and space saving is hardly the reason to use this approach.
0

Share this post


Link to post
Share on other sites
I seriously hope you're jocking.
Using this to [i]not [/i]store the permutations is [i]not [/i]saving [i]space[/i].
Rather, doing the permutation thing is [i]brain damaged[/i]. And don't even get me started on checking the match. I'm sure I've seen it on the daily WTF.
Thus, not storing them is not about saving space but rather doing things right.
0

Share this post


Link to post
Share on other sites
[quote name='Krohm' timestamp='1342444871' post='4959585']
Using this to [i]not [/i]store the permutations is [i]not [/i]saving [i]space[/i].
[/quote]

Actually, it saves a quarter of a meg ;-)

Which is eight times as much memory as my first computer had! Edited by mark ds
0

Share this post


Link to post
Share on other sites
[size=2][b][Edit:][/b] Double-posted for some reason. Can't seem to find the 'delete post' button.[/size]
0

Share this post


Link to post
Share on other sites
[quote name='Krohm' timestamp='1342444871' post='4959585']
I seriously hope you're jocking.
Using this to [i]not [/i]store the permutations is [i]not [/i]saving [i]space[/i].
Rather, doing the permutation thing is [i]brain damaged[/i]. And don't even get me started on checking the match. I'm sure I've seen it on the daily WTF.
Thus, not storing them is not about saving space but rather doing things right.
[/quote]
I'm confused about what you are disagreeing with.

Are you saying that this...
[code]
if(name == "person mcperson" || name == "Person Mcperson" || name == "Person McPerson"
|| name == "PERSON MCPERSON" || name == "person MCPERSON" || name == "PERSON mcperson" || ...etc... )
{
//...
}[/code]

...is better than this:
[code]std::string name = "Person McPerson";
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(name == "person mcperson")
{
//...
}[/code]

Or are you just saying to cache the lowercase name when possible, so you don't have to convert it every function call?

As for 'saving space', I fully agree that any 'space' you save is absurdly small and unimportant if developing for a modern PC. For me, the benefit of the second one is about writing cleaner and easier-to-maintain code, and also ensuring you catch [i]all[/i] the valid possibilities and not just some of them.

[quote name='mark ds' timestamp='1342452766' post='4959616']
Actually, it saves a quarter of a meg ;-)
Which is eight times as much memory as my first computer had!
[/quote]
How does it save a quarter of a megabyte? Worst case scenario, with the example I gave ("Person McPerson"), it'd save 32 kilabytes I think - and only if someone bothered to type out every possible lowercase vs uppercase version of "Person McPerson", starting with "person mcperson", "Person mcperson", "PErson mcperson", "PERson mcperson", and so on, which is unlikely.
0

Share this post


Link to post
Share on other sites
[quote name='bls61793' timestamp='1342363560' post='4959267']
[CODE]
if (username == "Tiffany" || "tiffany" || "Tiffany McClure" || "tiffany McClure" || "Tiffany Mcclure" || "tiffany mcclue")

[/CODE]

[/quote]

Am I the only one thinking that looks pretty elegant? Is there any language that implements this way of checking the same variable for different boolean cases?

It looks to me like "Tiffany" is the real string to look for here, so I would convert to lowercase and check for "tiffany".. what if she wrotes "Tiffany Cupcake" ? :P You'll miss that.
0

Share this post


Link to post
Share on other sites
[quote name='kunos' timestamp='1342466480' post='4959691']
[quote name='bls61793' timestamp='1342363560' post='4959267']
[CODE]
if (username == "Tiffany" || "tiffany" || "Tiffany McClure" || "tiffany McClure" || "Tiffany Mcclure" || "tiffany mcclue")

[/CODE]

[/quote]

Am I the only one thinking that looks pretty elegant? Is there any language that implements this way of checking the same variable for different boolean cases?

It looks to me like "Tiffany" is the real string to look for here, so I would convert to lowercase and check for "tiffany".. what if she wrotes "Tiffany Cupcake" ? [img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img] You'll miss that.
[/quote]Some languages allow this:
[code]switch(name){
case "Tiffany":
case "tiffany":
case "Tiffany McClure":
...
break;
default:
...
}[/code]Close enough?
0

Share this post


Link to post
Share on other sites
[quote name='King Mir' timestamp='1342470870' post='4959728']
Some languages allow this:
[code]switch(name){
case "Tiffany":
case "tiffany":
case "Tiffany McClure":
...
break;
default:
...
}[/code]Close enough?
[/quote]
C++ switch statements only work with some data types (mostly ints) - not with std::strings. Even so, that's pretty ugly syntax. [img]http://public.gamedev.net//public/style_emoticons/default/happy.png[/img] Edited by Servant of the Lord
2

Share this post


Link to post
Share on other sites
Am I the only one who noticed the typo ([font=courier new,courier,monospace]... "tiffany McClure" || "Tiffany Mcclure" || "tiffany [u][b]mcclue[/b][/u]"[/font])? One big reason checking each permutation sucks is because it's too easy to introduce human error.

I'd say convert to lower (or upper) case and check the string. I love regular expressions, but I probably wouldn't use them here.
1

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1342471896' post='4959736']
[quote name='King Mir' timestamp='1342470870' post='4959728']
Some languages allow this:
[code]switch(name){
case "Tiffany":
case "tiffany":
case "Tiffany McClure":
...
break;
default:
...
}[/code]Close enough?
[/quote]
C++ switch statements only work with some data types (mostly ints) - not with std::strings. Even so, that's pretty ugly syntax. [img]http://public.gamedev.net//public/style_emoticons/default/happy.png[/img]
[/quote]Which is why I said "some languages" and not "c++ and some languages". Why do you think switches are ugly?
0

Share this post


Link to post
Share on other sites
[quote name='King Mir' timestamp='1342474441' post='4959760']
[quote name='Servant of the Lord' timestamp='1342471896' post='4959736']
C++ switch statements only work with some data types (mostly ints) - not with std::strings. Even so, that's pretty ugly syntax. [img]http://public.gamedev.net//public/style_emoticons/default/happy.png[/img]
[/quote]Which is why I said "some languages" and not "c++ and some languages"[/quote]Ah, I thought your "some languages" was a not-so-subtle "hint hint", referring to C++ itself (What with the topic being about C++, and the "Close enough?" comment).

[quote]Why do you think switches are ugly?[/quote]
Not switches, per se, but using switches (which are typically meant to branch logic) to imitate the use of AND logic (which is what && is for).
In some situations it may be the best solution, but in general I prefer to use if() when I mean logical IF, and && when I mean logical AND. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1342478231' post='4959787']
[quote name='King Mir' timestamp='1342474441' post='4959760']
[quote name='Servant of the Lord' timestamp='1342471896' post='4959736']
C++ switch statements only work with some data types (mostly ints) - not with std::strings. Even so, that's pretty ugly syntax. [img]http://public.gamedev.net//public/style_emoticons/default/happy.png[/img]
[/quote]Which is why I said "some languages" and not "c++ and some languages"[/quote]Ah, I thought your "some languages" was a not-so-subtle "hint hint", referring to C++ itself (What with the topic being about C++, and the "Close enough?" comment).[/quote]I was responding to kunos's question if any languages allowed the syntax he quoted.

[quote][quote]Why do you think switches are ugly?[/quote]
Not switches, per se, but using switches (which are typically meant to branch logic) to imitate the use of AND logic (which is what && is for).
In some situations it may be the best solution, but in general I prefer to use if() when I mean logical IF, and && when I mean logical AND. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]Totally don't agree here. Switching on a variable is what switches are for.
0

Share this post


Link to post
Share on other sites
Switching, yes, but you aren't switching (the code execution path isn't really changing much), you're faking multiple logical ANDs, and using more lines to do so, with - in my opinion - slightly less code clarity.

[quote name='King Mir' timestamp='1342485609' post='4959819']
[quote name='Servant of the Lord' timestamp='1342478231' post='4959787']
Ah, I thought your "some languages" was a not-so-subtle "hint hint", referring to C++ itself (What with the topic being about C++, and the "Close enough?" comment).[/quote]I was responding to kunos's question if any languages allowed the syntax he quoted.[/quote]

Ah, my mistake then. Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
*snip*
[...] AND logic (which is what && is for).
[...] and && when I mean logical logical AND. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]
[quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
[...] you're faking multiple logical ANDs
[/quote]
I presume you mean logical OR ([font=courier new,courier,monospace]operator ||[/font]), correct?

[quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
and using more lines to do so
[/quote]
Depends on how you format your code. I'd probably break the [font=courier new,courier,monospace]if[/font] condition into multiple lines if it was that long anyway. But that's me.

I don't think I'd use a switch for only two code paths (like in this example), but I might use it if there are more (or if I was switching on strings and the switch was done by hashes and [font=courier new,courier,monospace]operator ==[/font] was not, and I cared about that).
1

Share this post


Link to post
Share on other sites
[quote name='Cornstalks' timestamp='1342487648' post='4959826']
[quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
*snip*
[...] AND logic (which is what && is for).
[...] and && when I mean logical logical AND. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]
[quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
[...] you're faking multiple logical ANDs
[/quote]
I presume you mean logical OR ([font=courier new,courier,monospace]operator ||[/font]), correct?[/quote]

[b]</facepalm>[/b] Yes, logical OR. [img]http://public.gamedev.net//public/style_emoticons/default/wacko.png[/img]

[quote][quote name='Servant of the Lord' timestamp='1342486937' post='4959823']
and using more lines to do so
[/quote]
Depends on how you format your code. I'd probably break the [font=courier new,courier,monospace]if[/font] condition into multiple lines if it was that long anyway. But that's me.[/quote]

Certainly, I typically write longer comparisons like this:
[code]if(blah || blah || blah
|| blah || blah)
{
//...
}[/code]

...and, depending on the logic of the function, may even group the options into boolean variables.
[code]bool logicalEvaluationA = (blah || blah || blah);
bool logicalEvaluationB (blah || blah);
if(logicalEvaluationA || logicalEvaluationB)
{

}[/code]

...but switch statements just have more visible clutter (to me). Furthermore, the name 'switch()' implies switching, and past usage and experience teaches your mind that that is what those kinds of statements do.

When you read code, you have certain expectations from blocks of code before you even read it. while() implies a loop, as does for(). for() usually implies an iteration or a fixed number of loops, whereas while() usually implies a continuous loop until some condition is meant. if() usually implies conditional logic, if-else() multiple branches, and switch() usually implies a large number of branches.
When these "first glance" expectations are then turned on their head following a closer inspection, my mind has to do a double take, and reevaluate the whole block of code.

Doing things like:
[code]do
{

}
while(false); //Hahah, not actually a loop![/code]

Or:
[code]switch(option)
{
case :
case :
case :
case :
case :
{

} break;
default: //Jokes on you, I'm actually a if-else() statement in disguise!
{

} break;
}[/code]

...increase the time it takes (at least for me) to understand code, because my mind has to then backpedal and throw out some previously made common assumptions about the code that is [i]usually[/i] true, but in this case is not.

Often times when reading through code, you don't actually have to read the fine details of the code, you can just look at the general picture and understand what it's doing. This is really useful. If the code does what it is expected to do, and looks like it should do, that's good. If you have to manually mentally walk through a piece of code to find out what it actually does, because it breaks expectations, that's not good (but is acceptable if that's what is required - for example, a heavily optimized algorithm).

Reading code (from top of the page downward), you start to build an idea of what the code does.
[code]for(int i = 0; i < myVector.size(); i++)[/code]

"[i]...looking at the lady in the red dress? Look again, Neo.[/i]"
[CODE]for(int i = 0; i < myVector.size(); i++)
{
//...code...
if((myVector % 2) == 1)
{
i++;
}
//...code...
}[/CODE]

Additional logic that controls the flow of the entire loop is buried in the body of the loop?!

A 'break', 'return', or even 'continue' is fine, because your mind easily parses those keywords and can argument it's understanding of the code very rapidly. It'll take a few moments longer for your mind to recognize the 'i++' alters the flow of the code (and even longer if it's hidden away admist other code), and it may even have to throw out parts of its previous understanding that your mind has already built up, causing even more mentally delay and extra mental, "Let me double check this" processing as it encounters unexpected deviations from the norm.

[quote]I don't think I'd use a switch for only two code paths (like in this example), but I might use it if there are more (or if I was switching on strings and the switch was done by hashes and operator == was not, and I cared about that).
[/quote]
Well sure, I'm not at all saying switch()s are bad. I'm not even saying case fall-through is bad. When asked about it originally, I was trying to explain that using a switch() when you really want a single if() or if-else() is undesirable as a default thing to go to, because it makes your code less understandable at-a-glance, and departs from the norm of what is expected that a switch() statement does.

For multiple branches of logic, switch() statements are excellent. For other situations, switch() statements are less desirable. 'Less desirable' may be a fine tradeoff if something else is needed in its place, like speed or memory optimization, but if you are decreasing readability and not gaining anything at all, that's not a good tradeoff - so as a default (but I'm not saying "never" or "always" - there are exceptions), one should go for the most commonly expected solution, so code does what one expects it to do.

An extreme example of such a valid [i]optimization vs code expectation tradeoff[/i] would be [url="http://en.wikipedia.org/wiki/Duff"]Duff's Device[/url].
Do you understand that code? Being honest with yourself, how many times did you have to read through it carefully (the first time you ever saw it) before you understood it?

Now this, on the other hand:
[code]int sum = 0;
for(iterator = numbers.begin(); iterator != numbers.end(); iterator++)
{
sum += *iterator;
}[/code]

...you barely even had to read. You already knew, in general, what it did before you even read the fine details of it... and even reading the fine details, you understood it without any mental hiccups or backpedalling, and so having understood it, you continued onward to reading this paragraph of my post - if you were reading real code, you would have continued on reading code further down the page, and the above for() loop wouldn't have interrupted your reading in the least, and certainly wouldn't have caused your understanding of the inner workings of the function to come to a crashing halt like a more extreme example of code-convolution might have.

Using a switch() to choose between multiple hashes of a string? Certainly, because you're [u]switch[/u]ing between multiple code branches. When you see a switch() statement, this is your instant expectation from your prior experience with switch statements.
Using a switch() to imitate "if(optionA OR optionB OR optionC)" won't cause too much mental backpedaling, but it will take a bit longer to process because you are failing to take advantage of the instant mental expectation of if()s which are normally used for that purpose... so by default, one should prefer the more common "if( OR OR )" with its built-in mental benefits and syntactical simplicity. Edited by Servant of the Lord
1

Share this post


Link to post
Share on other sites
I agree with you in general, but not concerning switch. There's not much cognitive difference between this:
[code]switch(myString){
case "--option1":
case "-o1":
case "o1":

...
break;
default:
...
}[/code]
And this:
[code]switch(hash(myString)){
case hash("--option1"):
case hash("-o1"):
case hash("o1"):
...
break;
default:
...
}[/code]

Or doing the same thing with a single character. Not having to write myString== a bunch of times reduces code size, and so clarifies what's going on; it's only comparing values to a single variable. To each his own I guess.
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0