Fun with Structs

Hey guys it's me again, with another fun assignment from my instructor. Although this time, I can actually make my own functions. I can change the prototypes to whatever I need. Only other restriction is that he only wants one instance of the struct in memory.

Also, can't use std::string or std::stringstream

Anyway this program is supposed to take a date from the user as input, and turn it from m/d/yy (or yyyy) to Month, Day Year format (March 8, 2013 for example).

I'm having some trouble getting off the ground. He wants the user to enter the whole date at once, and put those elements directly into the Date struct (month, day, and year). In it's current form, it'll prompt the user and take the date, but it will just freeze up after that. Could you point out what I'm doing wrong?

Thanks in advance! :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// File: mjcdate.cpp
// Operating System: Linux
// Compiler: g++
// Written: 3/2013
// Purpose: 	This program will take a date as input from the user, and display it in a different format

#include <iostream>
#include <cstring>

struct Date 
{
	int month;
	int day;
	int year;
};

//prototypes
void input(struct Date &);
bool validate(const struct Date &);
void output(const struct Date &);

const char *MONTHS[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
const int DAYS[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

//initializes variables and calls the other functions
int main()
{
	//creating one Date object and a string to contain the user's response when prompted to continue
	std::cin >> std::dec;	
	Date test_date;
	int size = 256;
	char response_string[size];
	//main loop, will terminate when user enters "No"
	do
	{	//loops until user enters valid date
		do
		{
			test_date.month = test_date.day = test_date.year = 0;	
			input(test_date);
			if(!validate(test_date))
				std::cout << "The date you entered is invalid. Please try again" << std::endl;
		}while(!validate(test_date));

		//outputs the valid date, and prompts user to continue
		std::cout << std::endl;
		output(test_date);
		std::cout << std::endl;
		std::cout << "Would you like to continue? Please enter \"Yes\" or \"No\":  ";
		std::cin.getline(response_string, size);
	}while(strcmp(response_string, "No") != 0);
	return 0;
}

//takes input from user and puts it in the struct
void input(Date &test_date)
{

	std::cout << "Please enter a date in the format M/D/Y or M/D/YYYY:  " << std::flush;
	std::cin >> test_date.month;
	std::cin.ignore(50, '/');
	std::cin >> test_date.day;
	std::cin.ignore(50, '/');
	std::cin >> test_date.year;
	std::cin.clear();	//will clear any remaining garbage in the buffer
  	std::cin.ignore(50, '\n' );
}

//validates struct entered by user is a valid date
bool validate(const Date &test_date)
{
	bool flag = false;
	if(test_date.month >= 1 && test_date.month <= 12)
		if(test_date.day >= 1 && test_date.day <= DAYS[test_date.month-1])
			if(test_date.year >= 0 && test_date.year <= 99)
				flag = true;
			else if(test_date.year >= 1000 && test_date.year <= 9999)
				flag = true;
	return flag;

}

//outputs date structure in Month, Day Year format i.e. March 8, 2013
void output(const Date &test_date)
{
	std::cout << "The date you entered is:  " << MONTHS[test_date.month-1] << " " <<  test_date.day << ", ";
	if(test_date.year < 100)
		std::cout << test_date.year + 2000;
	else
		std::cout << test_date.year;
	std::cout << std::endl;
}
Last edited on
32
33
34
35
36
37
38
39
40
41
void input(Date &test_date)
{
	std::cout << "Please enter a date in the format M/D/Y or M/D/YYYY:  " << std::flush;
	std::cin >> test_date.month;
	std::cin.ignore(10, '/');
	std::cin >> test_date.day;
	std::cin.ignore(10, '/');
	std::cin >> test_date.year;
	std::cin.ignore(10, '/');
}
The problem here is that you have not told the user that they have to put spaces around each slash. When you use the >> function of std::cin, it reads until the next whitespace character and tries to interpret everything it read as the type you're inputting to. In this case, it fails, because "05/04/03" is not a number (but each of "05", "04", and "03" are).

I think in this case you need to use std::getline and stringstreams. Here is an example for the month:
1
2
3
4
string m;
std::getline(std::cin, m, '/');
std::istringstream ms (m);
ms >> test_date.month;
You can write a convenience function to do it for you, but be careful - remember there is no / after the year (there would be a new line instead)
Last edited on
My apologies, the other restriction is that we can't use std::string or std::stringstream. I also edited the main post to reflect this
I actually had one too many cin.ignore statements. The program was waiting on input that wasn't coming after it read in the year data member. It now reads as follows:

1
2
3
4
5
6
7
8
9
10
void input(Date &test_date)
{
	std::cout << "Please enter a date in the format M/D/Y or M/D/YYYY:  " << std::flush;
	std::cin >> test_date.month;
	std::cin.ignore(10, '/');
	std::cin >> test_date.day;
	std::cin.ignore(10, '/');
	std::cin >> test_date.year;
	std::cin.ignore(10, '/');
}


Stay tuned though. I got two more functions to go! >_<
Okay, the program is pretty much done. Except I'm having some issues in my main. The way it's supposed to work is that after outputting a valid date, the user has the choice of quitting by entering "No" (must be exactly that) or letting the program loop. For some reason it's skipping over my getline statement and looping the program without input from the user. I'm sure it's something obvious I'm forgetting about here

I've updated the full program in my original post as well

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
	std::cin >> std::dec;	
	Date test_date = {0, 0, 0};
	char response_string[3];
	do
	{
		do
		{
			input(test_date);
			if(!validate(test_date))
				std::cout << "The date you entered is invalid. Please try again" << std::endl;
		}while(!validate(test_date));
		std::cout << std::endl;
		output(test_date);
		std::cout << std::endl;
		std::cout << "Type anything other than \"No\" to continue:  ";
		std::cin.getline (response_string, 3);
	}while(strcmp(response_string, "No") != 0);
	return 0;
}
Add another cin ignore call at the end of the input function.
1
2
3
4
5
  . . .
  std::cin >> test_date.year;
  std::cin.clear();
  std::cin.ignore( 256, '\n' );
}
Last edited on
That seemed to have done the trick. Thank you much, and a big thanks to everyone else who helped me today with this. I've put the final code back in my original post
Topic archived. No new replies allowed.