Receiving a string, checking for a Capital Letter - c++

What Im trying to do is check if the user-supplied string has a capital letter or not.
The first part of the code with the enumerated constant, is just there for another method,
which I got to work using numbers assigned to the words Sunday = 7, Monday=1, Tuesday=2, etc. I'm trying have the user not supply numbers, but the actual word (Sunday, Monday, Tuesday), but I want them to specify the day of the week with a capital letter.
Problem I get: compiles fine, but anything you type in is somehow redirected along an execution path that always returns "Retype w/ a capital letter." This happens if I type in fjdkalfda or sunday or Sunday or whatever. Here is the code. Sorry if its not in code format, first time user of Stack Overflow.
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main(){
/*enum DaysOfWeek {
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};*/ //I'm not using this, but I can get my code to work with this
//enumerated constant by asking the user to input a number corresponding
//to the day of the week and then using if-else statements to check, say,
// int Day;
// cin >> Day
// then use if statements to check if Day = a certain number, to give output
cout << "Enter the day of week with a capital letter: ";
string Day;
getline(cin, Day);
if (Day == ("monday") || ("tuesday"))
cout << "Retype w/ a capital letter" << endl;
else if (Day == ("wednesday") || ("thursday"))
cout << "Retype w/ a capital letter" << endl;
else if (Day == ("friday") || ("saturday"))
cout << "Retype w/ a capital letter" << endl;
else if (Day == ("sunday"))
cout << "Retype w/ a capital letter" << endl;
else
{
if (Day == "Monday")
cout << "Moon" << endl;
else if (Day == "Tuesday")
cout << "Mars" << endl; //continue with the days etc...
}
return 0;
}

One would observe that there is a function called toupper which can turn a lower case letter into upper case, and leave an upper case letter alone. Perhaps you can reuse this function to help solve your problem with less code.
I am inferring from your code that you are only interested in verifying that the first letter is a capital letter. Is that correct?

There is an isupper function in ctype.h that returns true if a char is upper case:
#include <ctype.h>
...
isCapitalized = isupper(str[0]);
...

I'm assuming you're actually not bothered about capitol letters if we can somehow organize the input choice in an enum type. Instead of this enum classes would be a better choice if you have C++11. If not, it would be quite easy to change this code for normal enums
If you're using gcc/g++, you may need to include prefix -std=c++11
Note: you may want to add another enum element to enum class Days such as null_day. Or even better, Make sure user inputs the correct day, until he/she does, don't carry on with program (hint: use while loop when using getline)
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using std::string;
using std::transform;
using std::cout;
using std::cin;
using std::endl;
// only in C++ 11
enum class Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
int main () {
cout << "Enter the day of week: ";
// store day from user input, transform all to lower case so
// we don't bother with user input type (only error in spelling will be the problem now)
string get_day;
getline(cin, get_day);
transform(get_day.begin(), get_day.end(), get_day.begin(), tolower);
// define instance of enum class Day, and sort out what day user has input
// note that if you do not initialize myDay object, it will set to the first
// element in the enum class Day above (which is Monday). This will happen
// if user input is not allowed to initialize it. See the << >> section below
Day myDay;
if (get_day == "monday")
myDay = Day::Monday;
else if (get_day == "tuesday")
myDay = Day::Tuesday;
else if (get_day == "wednesday")
myDay = Day::Wednesday;
else if (get_day == "thursday")
myDay = Day::Thursday;
else if (get_day == "friday")
myDay = Day::Friday;
else if (get_day == "saturday")
myDay = Day::Saturday;
else if (get_day == "sunday")
myDay = Day::Sunday;
else
<< ERROR CODE HERE >>
<< MAYBE A WHILE LOOP UNTIL USER INPUTS CORRECT DATA >>
// perform your calculations/operations/etc separate from above
if (myDay == Day::Monday)
cout << "Moon" << endl;
else if (myDay == Day::Tuesday)
cout << "Mars" << endl; //continue with the days etc...
return 0;
}

Related

How can I get an if-statement that takes multiple cin inputs to recognize an error if only the first cin input is incorrect?

I am building a program that is meant to store values from day-of-week/value pairs into a vector, and then display and sum the values for each day of the week. Therefore, I am asking the user to enter both a string (day of the week, which can be in 4 different forms for each day of the week) and an integer (a corresponding value) for each cin input. (The program only shows Monday and an exit condition so far; I will later build it out to include Tuesday through Sunday as well.)
The program is also meant to identify incorrect input (and allow the user to retry their input). However, I am having trouble getting the program to recognize erroneous input if only the day of week is entered incorrectly. For instance, the program will successfully announce "Incorrect day of week detected" if I enter "test test" as the input. It will also announce this message (even though the wording needs to be tweaked) if I enter "Monday x." However, if I enter "Test 5," the program accepts this without displaying the "Incorrect day of week" message.
How would it be possible to change my program so that, using the pre-existing else statement, it displays "Incorrect day of week" when I enter something like "Test 5"?
One solution would be to create a very long if statement that displays this message if the day of week entered does not match any of the 29 valid day-of-week entries (e.g. "Monday," "monday," "Mon," "mon," "Tuesday," "tuesday" . . . ). However, I would like to find a simpler approach.
Thank you for your help!
#include "../std_lib_facilities.h"
#include <iostream>
//Program in progress. Completing as part of my independent study of Programming: Principles and Practice by Bjarne Stroustrup.
int main()
{
string dayofweek;
int value;
vector<int> mondayvalues;
vector<int> tuesdayvalues;
vector<int> wednesdayvalues;
vector<int> thursdayvalues;
vector<int> fridayvalues;
vector<int> saturdayvalues;
vector<int> sundayvalues;
int incorrectentrycounter = 0;
int mondaysum = 0;
cout << "Please enter days of the week followed by values in integer form. When you are finished, please enter Done 0.\n";
string incorrectnumdump;
while (cin) {
if (cin >> dayofweek >> value) {
if (dayofweek == "Monday" || dayofweek == "monday" || dayofweek == "Mon" || dayofweek == "mon") {
mondayvalues.push_back(value);
}
if ((dayofweek == "Done") && (value == 0)) {
break;
}
}
else {
cin.clear();
cin >> incorrectnumdump;
cout << "Incorrect day of week detected; please try again.\n";
incorrectentrycounter++;
continue;
}
}
cout << "Here are the values you entered for each day of the week, along with their sums:\n";
cout << "Monday: ";
for (int x : mondayvalues)
cout << x << " ";
for (int i = 0; i < mondayvalues.size(); i++) {
mondaysum += mondayvalues[i];
}
cout << "\nSum of Monday values: " << mondaysum;
cout << "\nThere were " << incorrectentrycounter << "entries that displayed non-valid days of the week.";
}
Hmm.. Maybe you can use an ASCII technique to internally flip all inputs to either all caps or all small letters so that you won't have to look for both cases in your if statements as long as caps or small letters doesn't matter.
Make a function that takes the inputs and converts them to all caps or all small. Use this function before assigning the inputs to your variables. This will make checking them easier.
After that, you could create a const array[7] of std::string that will include all days. You can check your inputs by a method of elimination. You will be comparing input and array days letter by later and eliminating the days that don't match each time. If all days are eliminated then wrong input. If 2 or more days remain - input not sufficient. If 1 day remains that's the correct input!
Lemme know if you need help
After playing around with the code, I settled on this solution, which I think will meet my needs. The code now has two invalid entry statement blocks instead of one. The first ("Incorrect day of week detected") is within the if (cin >> dayofweek >> value) condition, and will identify dayofweek entries that don't match one of the Monday strings or Done.
The second ("Invalid entry") is outside the if (cin >> dayofweek >> value) condition but within the while (cin) condition. I added this second one so that if someone enters something like "test test," they will be notified of the error but the while loop will still continue.
So it seems as though when the user needs to enter multiple values via cin >>, one approach to input validation can be to enter multiple error messages at different levels of the code.
This solution is still a little clunky, but allows me to capture invalid entry with just "else" {} rather than "else" followed by a long set of conditions.
#include "../std_lib_facilities.h"
#include <iostream>
//Program in progress. Completing as part of my independent study of Programming: Principles and Practice by Bjarne Stroustrup.
int main()
{
string dayofweek;
int value;
vector<int> mondayvalues;
vector<int> tuesdayvalues;
vector<int> wednesdayvalues;
vector<int> thursdayvalues;
vector<int> fridayvalues;
vector<int> saturdayvalues;
vector<int> sundayvalues;
int incorrectentrycounter = 0;
int mondaysum = 0;
cout << "Please enter days of the week followed by values in integer form. When you are finished, please enter Done 0.\n";
string incorrectnumdump;
while (cin)
{
if (cin >> dayofweek >> value)
{
if (dayofweek == "Monday" || dayofweek == "monday" || dayofweek == "Mon" || dayofweek == "mon")
{
mondayvalues.push_back(value);
}
else if ((dayofweek == "Done") && (value == 0))
{
break;
}
else
{
cin.clear();
cin.ignore(10000, '\n');
cout << "Incorrect day of week detected; please try again.\n";
incorrectentrycounter++;
continue;
}
}
else
{
cin.clear();
cin.ignore(10000, '\n');
cout << "Invalid entry; please try again.\n";
incorrectentrycounter++;
continue;
}
}
cout << "Here are the values you entered for each day of the week, along with their sums:\n";
cout << "Monday: ";
for (int x : mondayvalues)
cout << x << " ";
for (int i = 0; i < mondayvalues.size(); i++)
{
mondaysum += mondayvalues[i];
}
cout << "\nSum of Monday values: " << mondaysum << "\n";
cout << "\nThere were " << incorrectentrycounter << " invalid entries.";
}

How to compare day from the ctime lib with a day string?

does anyone know how to compare the day with day string.. It might sound confusing but I had this thing in mind.. Hope the code clears everything out
#include <iostream>
#include <ctime>
int main()
{
/// current date/time based on current system
time_t now = time(0);
/// convert now to string form
tm *ltm = localtime(&now);
cout << "The local date and time is: " << ltm << endl;
if(*ltm == "Mon") Monday();
else if(*ltm == "Tue") Tuesday();
else if(*ltm == "Wed") Wednesday();
else if(*ltm == "Thu") Thursday();
else if(*ltm == "Fri") Friday();
else if(*ltm == "Sat" || *ltm == "Sun") Monday();
return 0;
}
and that's the one of the huge error message board,I'm giving just that one line because the rest of the errors are the same but for different lines.
/home/shadowdragon/Documents/uktc_schdule/UKTC_schedule/main.cpp|90|error: no match for ‘operator==’ (operand types are ‘tm’ and ‘const char [4]’)|
You don't even need to compare it with a string (viz. const char*)... <ctime> provides its own method to compare all that...
First, make an enumerator that keeps track of all days of the week (0-6),
enum
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
Now check it like this:
if (*ltm.tm_wday == Sunday)
std::cout << "Its Sunday!" << std::endl;
Do the same for the other days as well...
If you look closely, you can see that the struct member tm_wday returns a number between the range 0-6 (Sunday to Monday) and the enumerator is just to clarify it... (So that you don't get confused with if (*ltm.tm_wday == 0 /*Sunday*/) or something like that...)
See more about the tm structure here...
There is even a C++ alternative here...
Note: std::tm gives you the accurate UTC time, so it is recommended to check it out, and use this function instead of localtime() as pointed out in the comments section...
Edit: If you have to compare it with a string... then maybe a function can be of help...
const char * GetDay(struct tm * tm)
{
switch (tm->tm_wday)
{
case 0:
return "Sun";
case 1:
return "Mon";
case 2:
return "Tue";
case 3:
return "Wed";
case 4:
return "Thu";
case 5:
return "Fri";
case 6:
return "Sat";
default: return "";
}
}
Then do something like:
if (GetDay(ltm) == "Sun")
std::cout << "Its Sunday again!" << std::endl;
Kind regards,
Ruks.

Syntax of a string function definition [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Can someone explain to me what I'm doing wrong with the syntax below? My textbook doesn't have any examples of user-defined string functions and I can't figure out what I should be doing. Thanks in advance!
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <string>
string dayOfWeek(int day);
using namespace std;
int main()
{
cout << "Please enter a day of week (0 for Sunday, 1 for Monday, etc): ";
cin >> day;
cout << "The name of the day of the week is: " dayOfWeek(day) << endl;
}
string dayOfWeek(int day)
{
if (day == 0)
return "SUNDAY";
else if (day == 1)
return "MONDAY";
else if (day == 2)
return "TUESDAY";
else if (day == 3)
return "WEDNESDAY";
else if (day == 4)
return "THURSDAY";
else if (day == 5)
return "FRIDAY";
else if (day == 6)
return "SATURDAY";
}
#include <string>
#include <iostream>
std::string dayOfWeek(int day)
{
if (day == 0)
return "SUNDAY";
else if (day == 1)
return "MONDAY";
else if (day == 2)
return "TUESDAY";
else if (day == 3)
return "WEDNESDAY";
else if (day == 4)
return "THURSDAY";
else if (day == 5)
return "FRIDAY";
else if (day == 6)
return "SATURDAY";
return "Invalid input!"; // May be you should guarantee a return value.
}
int main() {
std::cout << dayOfWeek(5) << std::endl;
}
should work as expected.
The crux of the problem is here:
string dayOfWeek(int day);
using namespace std;
The using is after code that depends on it, so the compiler goes looking for string and can't find it. It doesn't go looking for std::string because it hasn't been told to yet.
You could move using up a few lines, but for the many reasons covered in the answers to Why is "using namespace std" considered bad practice? and a few not covered, you're probably better off not putting
using namespace std;
in your code at all. Prefix the std:: explicitly and you can avoid a litany of nasty surprises.
I also recommend following #πάνταῥεῖ example with where the function was placed. Forward declaring and then declaring gives you two places to have to change code and one more place to have a bug. Declaring the function ahead where it will be used mean you only ever have to change one declaration.
Putting it all together with a few other small tweaks:
#include <string>
#include <iostream>
std::string dayOfWeek(int day)
{
switch (day) // for stuff like this, I like a switch. I find it looks nicer.
{
case 0:
return "SUNDAY";
case 1:
return "MONDAY";
case 2:
return "TUESDAY";
case 3:
return "WEDNESDAY";
case 4:
return "THURSDAY";
case 5:
return "FRIDAY";
case 6:
return "SATURDAY";
default:
return "No such day"; // functions must always return something.
// in this case what will cout print if you
// don't return a string? Don't know?
// Don't feel bad. Neither do I.
// Welcome to Undefined Behaviour
}
}
int main()
{
int day; //this was missing
std::cout << "Please enter a day of week (0 for Sunday, 1 for Monday, etc): ";
std::cin >> day;
std::cout << "The name of the day of the week is: " << dayOfWeek(day) << std::endl;
}
There's one other trick you can use to get rid of the if or switch entirely
#include <string>
#include <iostream>
// define an array of days of the week to print. const means dayOfWeek cannot be changed
const std::string dayOfWeek[] =
{
"SUNDAY",
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY"
};
int main()
{
unsigned int day;
//Note unsigned int. Negative numbers are now disallowed
std::cout << "Please enter a day of week (0 for Sunday, 1 for Monday, etc): ";
// keep looping until user provides a good number
while (!(std::cin >> day) // user MUST input a number
|| day > 6) // number is a usable number
{
std::cin.clear(); // clean up bad input
std::cout << "Please enter a day of week (0 for Sunday, 1 for Monday, etc): ";
}
// since we know day is a usable (0..6) number we can read the day out of the array
std::cout << "The name of the day of the week is: " << dayOfWeek[day] << std::endl;
}

How do I display the output of my C++ class

Hello guys I am trying to create a date class in C++ where it display the default date, displays a short set date, displays a long set date, just display a set year. However, I am trying this display the contents of the class when I input the data but I am getting an error "Use of undeclared identifier 'setDate'
Here is the header file code:
#ifndef dateClass_h
#define dateClass_h
using namespace std;
class DateObj
{
public:
int setDate(int month, int day, int year);
void shortDate(int month, int day, int year);
void longDate(string month, int day, int year);
//return the year
int getYear(int year){
return year;
}
private:
int month;
int day;
int year;
};
#endif /* dateClass_h */
Here is my implementation file code:
#include <stdio.h>
#include <iostream>
#include <string>
#include "dateClass.h"
using namespace std;
//setDate Method
int DateObj::setDate(int month, int day, int year){
//setMonth = month;
//day = setDay;
//year = setYear;
//check to make sure month is between 1 - 12.
if(month < 1 || month > 12){
cout << "This is an invalid Month. Please enter a month that is between 1 and 12: " << endl;
}
//check to make sure day is between 1 -31.
if(day < 1 || day > 31){
cout << "This is an invalid Day. Please enter a day that is between 1 and 31: " << endl;
}
//check to make sure year is greater than zero.
if(year < 0){
cout << "This is an invalid Year. Please enter a year that is greater than Zero" << endl;
}
return setDate(month,day,year);
}
And here is my main program code:
#include <iostream>
#include <string>
#include "dateClass.h"
using namespace std;
int main() {
DateObj myDate;
myDate.setDate(12, 25, 2016); //set the date to Dec 25, 2016.
cout << "The current date is: " << setDate() << endl;
return 0;
}
I will just like to know why I am getting this error and what I will need to fix in my class or main program.
Edit
I got the program to compile butI got the following error "EXC_BAD_ACCESS (code=2, address=0x7fff5f3fffe8) at the return setDate(month, day, year) break point.
#include <iostream>
#include <string>
#include "dateClass.h"
using namespace std;
int main() {
DateObj myDate;
myDate.setDate(12,25,2016); //set the date to Dec 25, 2016.
cout << "The current date is: " << myDate.setDate(12, 25, 2016) << endl;
return 0;
}
There appears to be no implementation for your shortDate function.
You have it in your header file, but you don't appear to have it in your dateClass.cpp file. You need to implement it in your dateClass.cpp file similar to how you did for setDate.
You're getting the error because it can't find any implementation.
The reason you are getting an error is because setDate() is a void function. When you try to use setDate() in the line:
cout << "The current date is: " << setDate() << endl;
you get an error because setDate() needs to return an std::ostream & object or some other data that is convertible. I recommend using setDate(int month, int day, int year) purely to set the data members of your class and create a separate function to actually print out the values.
As an alternative, you could overload setDate() so that it returns an acceptable data type, like so:
#include <iomanip>
//the parameter 'right' is required for chaining together different << when forming output
std::ostream & DateObj::setDate(std::ostream & right) {
//displays the date in mm/dd/yyyy format
//setfill defines a character to fill empty spaces created by setw
right << std::setfill('0') << std::setw(2) << month
<< '/' << std::setfill('0') << std::setw(2) << day
<< '/' << std::setfill('0') << std::setw(4) << year;
return right;
}
Well, for one thing you're calling setDate() inside setDate() in such a way that it will infinitely just call itself. You'll call setDate(), which will call setDate(), which will call setDate() and so on. I'm kind of a noob too, but I'm pretty sure what you're getting is a stack overflow error (Hey, title drop! :D). A stack overflow happens when you allocate too many variables and run out of memory. So because you're calling setDate() infinitely, you are also making infinite versions of the variables in it, and filling up all your memory.
For another, set date doesn't currently actually do anything. It checks to see if you have valid input, then calls itself again. From the name, I assume it's meant to populate your member variables? If that's what it's supposed to do, it should probably look more like this:
int DateObj::setDate(int month, int day, int year){
//check to make sure month is between 1 - 12.
if(month < 1 || month > 12){
cout << "This is an invalid Month. Please enter a month that is between 1 and 12: " << endl;
}
//check to make sure day is between 1 -31.
if(day < 1 || day > 31){
cout << "This is an invalid Day. Please enter a day that is between 1 and 31: " << endl;
}
//check to make sure year is greater than zero.
if(year < 0){
cout << "This is an invalid Year. Please enter a year that is greater than Zero" << endl;
}
//the part that actually sets the variables. Aka, the important bit.
month_ = month;
day_ = day;
year_ = year
}
The trailing underscores on month, day and year are just style things, I like to use them for member data so that I can use those names again as local variables in my functions, which was useful here if you noticed. Once you've put the data into your variables, it should be pretty easy to display everything. Just do something like:
cout << month_ << "/" << day_ << "/" << year_ << endl;
That will output your date to the console in a format something like this: 3/12/2016.

comparing strings c++ with wildcard values

I've been lurking around here for a long time, thank you for all your help in the past, even if this is the first question I've had to ask.
I'm trying to make a simple database program, and I am stuck the search requirement for it.
When searching, the user needs to be able to enter a question mark if they don't know a value. If you knew a movie was from the 90's you could enter 199? and it would find all the movies that matched 199_. I keep getting errors when I compile, "cannot convert 'char*' to 'char ()[5] for argument '2' to 'bool compareYears(const char, char (*)[5]"
I am trying to figure most of it out on my own, and I like to separate the functions and make them work in a separate .cpp file before adding them to the main file, just to make debugging easier.
#include <iostream>
#include <cstring>
#include <fstream>
#include <cctype>
using namespace std;
const int yearLength = 4;
typedef char year[yearLength + 1];
bool compareYears(const year year1, year year2[]);
int main()
{
year year1 = "1992"; //year from database, will be assigned the
// variable when implemented in main program.
year year2; //year entered by user, it will be compared to year1.
cout << "Enter a year to search for: ";
cin >> year2;
cout << endl;
if((compareYears(year1, year2)) == true)
cout << "they match\n";
if((compareYears(year1, year2)) == true)
cout << "they do not match\n";
return 0;
}
bool compareYears(const year year1, year year2[])
{
for(int i = 0; i < 4; i++)
{
if (strncom(year1, year2[i], 4) ==0)
return true;
else if (strncmp(year1, "????", 4) == 0)
return true;
else
return false;
}
}
Thanks for helping me out with this, usually the most help I get from others is useless or insulting. What I need help with most is getting rid of that compiler error. I cannot figure it out for the life of me.
First of all read this: typedef fixed length array
Then, use this typedef:
typedef struct year { char characters[4]; } year;
and change the code this way:
int main()
{
year year1;
year1.characters= "1992"; //year from database, will be assigned the variable when implemented in main program.
year year2; //year entered by user, it will be compared to year1.
cout << "Enter a year to search for: ";
cin >> year2.characters;
cout << endl;
if((compareYears(year1, year2)) == true)
cout << "they match\n";
else
cout << "they do not match\n";
return 0;
}
bool compareYears(year year1, year year2)
{
if (strncom(year1.characters, year2.characters, 4) ==0)
return true;
else if (strncmp(year1, "????", 4) == 0)
return true;
return false;
}
I also fixed some logical bugs
Just change these lines and it will work...the function declaration needs an array of year and you are trying to pass a variable..
if((compareYears(year1, &year2)) == true) //this changed from year2 to &year2
cout << "they match\n";
if((compareYears(year1, &year2)) == true) //this changed from year2 to &year2
cout << "they do not match\n";
The type of the year2 argument for compareYears looks strange. It looks like this argument is the mask to test against, i.e. a literal year like 1992 or something using wildcards. Hence, how about making it a char array of yearLength bytes?
It might be even easier to write just a generic function which is given two strings or arbitrary length (the second of which may use wildcards) and sees whether they are equal. The quality test could first see whether both strings are the same length and if so, whether the character at every position in both strings is either equal or the character at the given position in the second string is a '?'. You could use a single loop to walk over both strings in parallel to do this.