Length command and variable not declared in scope

May 8, 2019 at 8:43pm
I wrote a program to test my skills in using classes and now I'm stuck. I'm basically doing input validation right now. The third do while loop is giving me some problems. I want it to only accept 4 digits for the year. I am trying to use the length() command. This statement:
 
} while (yearString.length() != 4); 

It's giving me: "dateProg.cpp:83:11: error: ‘yearString’ was not declared in this scope"
But I did declare it here:
 
std::string yearString = std::to_string(inputYear);

The only thing I can think of is that my data members for "setYear/getYear" are set to int right now, this may be causing a problem. I'm trying to use to_string in there as well as I can't figurte out a way of using length without using a string.

Also, I would like to know if there is a more elegant way of doing my input validation. I am using a local variable (i) and incrementing it so the "invalid month!" "Invalid Day!" only comes up once. How else would I have the "input Day" prompt, for instance come up everytime, then the "Invalid Day" prompt come up only when invalid? I feel I'm using a workaround, but it works.
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
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <cstdlib>


class Date {
	private: 
	int month;
	int day;
	int year;
	public:
	void setMonth(int);
	void setDay(int);
	void setYear(int);
	int getMonth();
	int getDay();
	int getYear();
};

void Date::setMonth(int m)
{
	month = m;
}
void Date::setDay(int d)
{
	day = d;
}
void Date::setYear(int y)
{
	year = y;
}
int Date::getMonth()
{
	return month;
}
int Date::getDay()
{
	return day;
}
int Date::getYear()
{
	return year;
}


int main() {
	
	Date dateInput;
	int inputMonth;
	int inputDay;
	int inputYear;
	do{
	int i = 0;
	std::cout << "Input Month " << std::endl;
	std::cin >> inputMonth;
	
	if (i > 0) {
	std::cout << "Invalid month!" << std::endl;
}
	i++;
	} while (inputMonth < 1 || inputMonth > 12);

	do{
	int i = 0;
	std::cout << "Input Day " << std::endl;
	std::cin >> inputDay;
	
	if (i > 0) {
	std::cout << "Invalid day!" << std::endl;
}
	i++;
	} while (inputDay < 1 || inputDay > 31);
		
	do{
	int i = 0;
	std::cout << "Input year" << std::endl;
	std::cin >> inputYear;
	std::string yearString = std::to_string(inputYear);
	//std::string countString = yearString.length();
	
	if (i > 0) {
	std::cout << "Invalid Year" << std::endl;
	}	
	i++;
	} while (yearString.length() != 4); // THIS IS MY PROBLEM

	//std::cout << "Input Year " << std::endl;
	//std::cin >> inputYear;
	
	dateInput.setMonth(inputMonth);
	dateInput.setDay(inputDay);
	dateInput.setYear(inputYear);
	
	std::cout << "The date is: " << dateInput.getMonth() << "/" << dateInput.getDay() << "/" << dateInput.getYear() << std::endl;
	
	
	return EXIT_SUCCESS;
	
}



Thanks in advance!
May 8, 2019 at 8:51pm
Variables declared inside the do-while loop are unfortunately out of scope in the loop condition.

You have to declare yearString outside the loop.
1
2
3
4
5
6
std::string yearString;
do {
	...
	yearString = std::to_string(inputYear);
	...
} while (yearString.length() != 4);
Last edited on May 8, 2019 at 8:52pm
May 8, 2019 at 9:02pm
Ok, I did not know that, thanks! It is compiling now but the year validation is doing an infinite loop, even when I put in a 4 digit number. Could this be where me using int's for my classes, setters and getters might be causing the problem?
May 8, 2019 at 9:04pm
Oh wait. Would I have to put all this validation outside the loop since it doesnt have scope access to it? I guess I could create a function maybe?
May 9, 2019 at 8:05am
Inside the loop, make sure that you assign to the string that you created outside the loop.

 
std::string yearString = std::to_string(inputYear);
Last edited on May 9, 2019 at 8:06am
May 9, 2019 at 1:41pm
OMG! I never would have thought that putting std::string in front of it would make that big of a difference! Thank you! - If I could ask one more thing. Why? Why does that make such a big difference?
May 9, 2019 at 1:45pm
By C++ syntax,

(Type) (VariableName) = (Data); is declaring a new variable and initializing it with data

(VariableName) = (Data); is assigning data to a variable that ought to already exist.

When a declared parameter in an inner scope has the same name as the outer scope, it's called "shadowing" a variable -- a new variable is created, which has nothing to do with the former variable declared in an outer scope -- and it's best to avoid doing this.
https://en.wikipedia.org/wiki/Variable_shadowing
Last edited on May 9, 2019 at 1:48pm
May 9, 2019 at 9:03pm
Ok Ganado, thanks for the response. So that wikipedia article basically says it is just confusing and bad practice.

- In my code how else could I do what I'm trying to do without shadowing?

May 9, 2019 at 10:09pm
"shadowing" was how you had it before. The yearString variable inside the loop shadowed the yearString variable that was declared outside the loop. After you removed std::string inside the loop there is only one variable named "yearString" and hence no shadowing.
Last edited on May 10, 2019 at 8:07am
May 9, 2019 at 10:22pm
Oh ok. Thanks!!
May 9, 2019 at 10:33pm
Do you really need a string?
1
2
3
4
int year = 0;
while ( std::cin >> year && !(999 < year && year < 10000) ) {
  std::cout << "Invalid Year\n";
}
Topic archived. No new replies allowed.