As noted in the comments, you are confusing characters and strings. This can be a pain point when C++ is your first language. A char
is a single character, and is surrounded by single quotes, like
char letter = 'a';
.
A string can consist of zero to many characters and is surrounded by double quotes.
std::string str = "Hello";
An animal name would definitely be a string and not a character. This is usually further confused by the fact that a C-string is a special array of characters. char str[] = "Hello";
is valid code and the elements of the character array are 'H'
, 'e'
, 'l'
, 'l'
, 'o'
, '\0'
.
The code 'cat'
is just going to end in a bad time. The single quotes imply a character, but you've stuffed multiple characters in there. Compiling with warnings enabled would have likely caught this, use -Wall -Wextra
at a minimum.
Below is an example of the favorite animal portion using std::string
:
#include <cctype>
#include <iostream>
#include <string>
void string_to_lower(std::string& str) {
for (auto& l : str) {
l = std::tolower(static_cast<unsigned char>(l));
}
}
int main() {
std::string input;
std::cout << "What's your favorite animal? ";
std::getline(std::cin, input);
string_to_lower(input);
if (input == "cat" || input == "dog") {
std::cout << "Cool.\n";
} else {
std::cout << "That's unfortunate.\n";
}
}
Some output:
~/tmp
❯ ./a.out
What's your favorite animal? CAT
Cool.
~/tmp
❯ ./a.out
What's your favorite animal? cAt
Cool.
~/tmp took 4s
❯ ./a.out
What's your favorite animal? axolotl
That's unfortunate.
Note that by lower-casing the input after getting it, I only have to check against "cat"
and "dog"
, and I catch all possible ways of writing them. Your code misses both of the inputs I used, and a lot of others.
If you cannot use std::string
(which I think is silly), your comparison using C-strings is a bit weirder and the code is generally a bit clunkier.
#include <cctype>
#include <cstring>
#include <iostream>
void string_to_lower(char str[], int sz) {
for (int i = 0; i < sz; ++i) {
str[i] = std::tolower(static_cast<unsigned char>(str[i]));
}
}
int main() {
constexpr int strsz = 256;
char input[strsz] = {0};
std::cout << "What's your favorite animal? ";
std::cin.getline(input, strsz - 1);
// Unnecessary ternary, but it can catch issues and shorten the execution time
// of the function
string_to_lower(input, strlen(input) < strsz ? strlen(input) : strsz);
if (!std::strcmp(input, "cat") || !strcmp(input, "dog")) {
std::cout << "Cool.\n";
} else {
std::cout << "That's unfortunate.\n";
}
}
Some outputs:
~/tmp
❯ ./a.out
What's your favorite animal? CAT
Cool.
~/tmp
❯ ./a.out
What's your favorite animal? doG
Cool.
~/tmp took 6s
❯ ./a.out
What's your favorite animal? axolotl
That's unfortunate.
In both code examples, I use a getline
method instead of a direct std::cin
. By doing this, I can capture multi-word inputs without the program getting weird. Note that I have to use a different method to grab a line for std::string
and C-strings.
I have also recently edited in some static_cast
s to the string_to_lower()
functions. They are needed to avoid undefined behavior if, for example, someone attempts to type in an accented character or a letter that is not found in the English alphabet. One takeaway from the comments to this answer should be that validating input is hard, moreso in C++ due to the lack of built-in support that exists.