Hello, I am making a menu program with 4 options. The user will enter a (string) sentence of any length, then make a selection 1 -4. Options 2 and 3 will change the users input all to UPPERCASE or all to LOWERCASE.
The problem I'm facing: "This IS a TEST !@#" this is my test input.
When converting "This IS a TEST 1@#" to UPPER, my output is: "HIS A"
When converting "This IS a TEST !@#" to LOWER, my output is: "t is test"
neither will read the char if it is already upper/lower, and also will not display the symbols. I will post my full code for better reading. Any help would be appreciated as I am stuck on this and cannot figure it out.
@furry guy, Im not sure we are allowed to do it that way as we have never used "transform" or anything like that. The way he showed us looked just like the code I have, but I'm not sure how to just allow it to read whitespace and symbols, and ignore the case of the test string.
Also my headers:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
Using the brute-force method for transforming a string to lower or upper case, transforming only the letters which need to be changed while ignoring all the other characters:
#include <iostream>
#include <string>
#include <cctype> // ::isupper // ::islower
// https://en.cppreference.com/w/cpp/string/byte/islowerint main()
{
// create a string
std::string str { "This IS a TEST !@#" };
// display it
std::cout << str << '\n';
// transform the string to lower case
for (unsigned i { }; i < str.size(); ++i)
{
// is the element an upper case letter?
if (::isupper(str[i]))
{
str[i] += 32;
}
}
// display the transformed string
std::cout << str << '\n';
// transform the string to upper case
for (unsigned i { }; i < str.size(); ++i)
{
// is the element an lower case letter?
if (::islower(str[i]))
{
str[i] -= 32;
}
}
// display the transformed string
std::cout << str << '\n';
}
This IS a TEST !@#
this is a test !@#
THIS IS A TEST !@#
#include <iostream>
#include <string>
int main()
{
// create a string
std::string str { "This IS a TEST !@#" };
// display it
std::cout << str << '\n';
// transform the string to lower case
for (unsigned i { }; i < str.size(); ++i)
{
// is the element an upper case letter?
if (str[i] >= 'A' && str[i] <= 'Z')
{
str[i] += 32;
}
}
// display the transformed string
std::cout << str << '\n';
// transform the string to upper case
for (unsigned i { }; i < str.size(); ++i)
{
// is the element an lower case letter?
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] -= 32;
}
}
// display the transformed string
std::cout << str << '\n';
}
#include <iostream>
#include <string>
#include <ranges> // std::views::reverse
int main()
{
// create a string
std::string str { "This IS a TEST !@#" };
// display it reversed, simple for loop
for (unsigned i { str.size() }; i > 0; --i)
{
std::cout << str[i - 1];
}
std::cout << "\n\n";
// display it reversed, using string iterators
for (auto i { str.cend() }; i != str.cbegin(); --i)
{
std::cout << *i;
}
std::cout << "\n\n";
// display it reversed, range-based for loop
// C++20 feature for the reversal!
// range-based for loops were added in C++11
for (constauto& itr : str | std::views::reverse)
{
std::cout << itr;
}
std::cout << '\n';
}
If'n you don't understand loops 2 or 3 don't worry, hopefully you will be exposed to them in time.
One thing to note, your string transformation to either upper or lower case operates directly on the original string. If you need to retain the original copy it to a temp string and transform the copy.
@Furry Guy, option 4 "Backwards" i got it working, that was the first one I did. It works perfect.
1 is middle character but I haven't gotten to that yet because if the user can input a sentence of any length, I would have to figure out if it is odd or even I suppose, so I'm waiting to do that one.
2 and 3 have me stumped, but I think he used the "temp" string. Would you mind elaborating a bit more on how to use a temp string?
#include <iostream>
#include <string>
int main()
{
// create a string
std::string str { "This IS a TEST !@#" };
// display it
std::cout << str << '\n';
// create a temp string for the transformations
std::string temp { str };
// display the temp string
std::cout << temp << "\n\n";
// transform the temp string to lower case
for (unsigned i { }; i < temp.size(); ++i)
{
// is the element an upper case letter?
if (temp[i] >= 'A' && temp[i] <= 'Z')
{
temp[i] += 32;
}
}
// display the strings
std::cout << str << '\n' << temp << "\n\n";
// restore the temp to the original
temp = str;
// transform the temp string to upper case
for (unsigned i { }; i < temp.size(); ++i)
{
// is the element an lower case letter?
if (temp[i] >= 'a' && temp[i] <= 'z')
{
temp[i] -= 32;
}
}
// display the strings
std::cout << str << '\n' << temp << '\n';
}
This IS a TEST !@#
This IS a TEST !@#
This IS a TEST !@#
this is a test !@#
This IS a TEST !@#
THIS IS A TEST !@#
that makes so much sense. Thank you for all of your help, truly i appreciate it. I need to study a bit more, but I'm not entirely sure where i can find info on all of these different functions. But again, thank you, you're very thorough with your explanations.
Another potential issue that can cause problems, mixing std::cin and std::getline.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <string>
int main()
{
std::string name { };
int age { };
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "Enter your name: ";
std::getline(std::cin, name);
std::cout << "\nHello, " << name << ", you are " << age << " years old.\n";
}
Enter your age: 20
Enter your name:
Hello, , you are 20 years old.
Ooops!
std::cin leaves the carriage return ('\n') in the input stream, std::getline sees the carriage return and acts as if the user entered something. The string gets no data!
You need to IGNORE any superfluous data in the input stream, including the carriage return.
Another way is to use std::ws to remove the not-needed data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <string>
int main()
{
std::string name { };
int age { };
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "Enter your name: ";
std::getline(std::cin >> std::ws, name);
std::cout << "\nHello, " << name << ", you are " << age << " years old.\n";
}
Enter your age: 20
Enter your name: John Doe
Hello, John Doe, you are 20 years old.
Personally I haven't been able to evaluate whether list-initialization prevents more runtime errors than it causes.
My intuition is that it might come out ahead, but not by much, because I believe it's easier to avoid runtime errors involving {} than with =.
We'd need data to call it, and even then the answer could vary depending on the code you write.
This is exactly the problem with C++ — users of the language spend as much time programming the language as they do programming other stuff.
And now we have this really stupid syntax to “fix” problems by offloading them onto the programmer.
int y = x is considered compliant because it does not invoke any narrowing conversions (both x and y are ints).
The (narrowing) conversion issue is one caused by allowing operator overloading. There are multiple ways to automagically transform one type to another type — not necessarily obvious ways — during assignment.
Rather than fix the problem some reasonable way (IMNSHO) the committee chose to introduce a new syntax which is non-obvious and just looks wrong. Like, how the quiznak are you supposed to get “assignment/initialization” out of int x {12};?
You can’t. It’s stupid, and requires you to learn more and think harder to use.