So my program is coming along, but now I am writing in the range checking to ensure that the inputs are actually what they should be. My code works fine for time, except for the fact that white space gets ignored. I need to ensure that a user cannot input "10: 09 AM". It must be in the format hh:mm

My code:

void Time::makeAppt()
{
  Time startTime, endTime;

  cout << "Start time >>";
  cin >> startTime;
  cout << "End time >> ";
  cin >> endTime;
}

istream &operator>>( istream &input, Time &time)
{
  input >> time.hour;
  input.ignore();
  input >> time.minute;
  input.ignore();
  input >> time.period;

  return input;
}

Thank you for any suggestions you might have. =]

Recommended Answers

All 8 Replies

How about using cin.get() to get one character at a time, verifying that the order is digit, digit [convert to int and check range], colon, digit, digit [convert to int and check range], end-of-line. Maybe ignore leading or trailing white space to be nice. Not sure how you're going to indicate an error -- throw an exception maybe, or just exit() after an error message?

How would I use the cin.get() within my overloaded operator? As for the errors, well, I have to build certain messages into it and loop it back around to handle asking for the input again. I'm not worried about that part.

How would I use the cin.get() within my overloaded operator? As for the errors, well, I have to build certain messages into it and loop it back around to handle asking for the input again. I'm not worried about that part.

If you read it in as a c-style string, you can use getline and specify 6 characters (5 + 1) maximum. Or use get () five times.

http://www.cplusplus.com/reference/iostream/istream/getline/

isdigit could come in handy from cctype.

http://www.cplusplus.com/reference/clibrary/cctype/isdigit/

To use get or getline using a c-string, declare a C-string of size 6. If you want to use get, loop through, specifying the character with the loop control variables.

char c[6];
for (int i = 0; i < 5; i++)
{
   cin.get (c[i]);
}
c[5] = 0;

Don't have a compiler handy , but I think this should work. One potential problem is if the user doesn't type in at least 5 characters. That's why getline may be superior here.

http://www.cplusplus.com/reference/iostream/istream/get/

[edit]
Replace "cin" with "input" above. I didn't pay attention to the fact that you had an istream, not necessarily cin.
[/edit]

getline() seems to be doing the trick, but for some reason, it will only process once, not twice.

istream &operator>>( istream &input, Time &time)
{
  char charHour[60], charMinute[60];
  input.getline(charHour, 3, ':');
  input.getline(charMinute, 3, ' ');
  input.getline(time.period, 3, ' ');
  time.hour = atoi(charHour);
  time.minute = atoi(charMinute);
}

From my original code, it should run through it once, store it in startTime, then run through it again (when I call the operator once more) and store it in endTime. Instead, it just runs through it for startTime, then leaves, but the data is correctly stored in startTime.

So I ended up figuring out how to do it to allow for white space and get the information as needed. Problem is, I cannot seem to store the AM/PM portion.

istream &operator>>( istream &input, Time &time)
{
  char s[256];
  time.period = new char[3];
  input.getline(s, 256);
  time.hour = atoi(strtok(s,":"));
  time.minute = atoi(strtok(NULL," "));
  time.period = strtok(NULL, " ");
}

When I output time.hour and time.minute, they work just fine, but time.period doesn't seem to store anything.

Edit: Take that back. It still has a problem with white space (It's part of the assignment that people can't follow instructions to input a time...) as well.

Without seeing the function calls and the class and the exact assumptions regarding what you can assume as far as data, plus whatever else may be going on with the stream, I'm not 100% sure what the problem is. Note that "time" is highlighted. It's a C++ keyword. I doubt that's the problem, but possibly consider renaming the variable just in case.

I assume this is the criteria, in order:

  1. Any amount of white space.
  2. 0-5 (index 0)
  3. 0-9 (index 1)
  4. : (index 2)
  5. 0-5 (index 3)
  6. 0-9 (index 4)
  7. Exactly one blank space (index 5)
  8. "AM", "PM", "am" or "pm" (indexes 6 and 7)

If this is it, you can use getline to get a maximum of 8 characters, then just go character by character. Use no character delimiter.

// read in and throw away all white-space, character by character, till you get to first non-white space.  "Put back" into the stream any non-white-space character if you have read it in.

char s[9];
getline (s, 9);
// check length of s using strlen.  If it isn't 8, flag as invalid input.

// Go through s[] character by character, testing using the criteria above.  If any test fails, flag as invalid input.

isspace and isdigit from cctype could come in handy. strlen and strcmp from cstring could also come in handy. peek, get, getline, ignore, unget, and putback from the istream library could be useful.

http://www.cplusplus.com/reference/iostream/istream/

What are you supposed to do if the person enters bad data and what data do you need to be able to handle? Depending on that, you may need to do a variety of things to the stream, including setting or clearing failure bits, or clearing the stream. I'm not trying to over-complicate things, so if I am, I'm sorry. It's just good to know as much as possible what data might be thrown at you, what you need to be able to handle and recover from, and what you don't. If it's simply a cin stream where you ask people to enter times and press enter, then say "Sorry, try again" if it's bad, that's less complicated than if you have to set failure bits at the exact point of failure and allow the stream to be cleared and used again, stuff like that.

This page, as well as the next several pages in the link, might be useful.

http://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_074.html

... Note that "time" is highlighted. It's a C++ keyword.

Sorry for the tangent, but "time" is not a C++ keyword. The fact that it's highlighted is maybe because the syntax highlighter handles multiple languages, and "time" is a keyword in some of them (for instance, in the bash shell); or maybe because there is a Unix/POSIX/C standard function called time() from time.h . But "time" is not a C or C++ keyword, and the global function time() wouldn't conflict with a member variable called "time."

Sorry for the tangent, but "time" is not a C++ keyword. The fact that it's highlighted is maybe because the syntax highlighter handles multiple languages, and "time" is a keyword in some of them (for instance, in the bash shell); or maybe because there is a Unix/POSIX/C standard function called time() from time.h . But "time" is not a C or C++ keyword, and the global function time() wouldn't conflict with a member variable called "time."

Yes, you are correct. Thanks for pointing that out. I was thinking of the time(time_t*) function. I was pretty sure it would not be a problem, but should not have called it a keyword. Here is a list of keywords.

http://www.cppreference.com/wiki/keywords/start

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.