Ignoring invalid input from a count and average
The program requires the user to input numbers and when finished to exit the loop by entering a negative number. The program will then output the average of the numbers and the count of the numbers. The negative number should be removed from the series though. So if we have three numbers and exit on the (fourth) negative number, the average will only be of the three numbers and not include the negative number. Neat, I somehow made that work. Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100 also using a Boolean equation. It is at this point that I cannot determine how to exclude the erroneous input from the results.
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
float inScore= 1;
float sumScore= 0.0;
int scoreCount= 0;
float avgScore= 0.0;
bool moreNumbers = true;
bool notNumbers = true;
for ( inScore =1; inScore >=1; inScore++) //for loop some kind of blackmagic not really sure about this right now
{
cout << "Please enter grades (enter a negative integer to exit): ";
cin >> inScore;
if (!cin || inScore > 100)
{
notNumbers = false; //boolean to ignore non integers or numbers greater than 100
cin.clear();
cin.ignore(256, 'n');
scoreCount--;
cout << "Invalid number!" << endl;
} //something is wrong in this section and I can't get it to ignore the invalid inputs
else if (inScore < 0)
{
moreNumbers = false;
} //breaks the loop upon a negative number being entered
else
sumScore+=inScore;
scoreCount++;
}
avgScore = (sumScore+=inScore)/(scoreCount-1);
cout << "Number of Grades: " << scoreCount-1 << endl; //number of entries
cout << "Average: " << avgScore << endl; // average grade except I cannot figure out how to remove negative number from the array
return 0;
}
c++ loops boolean
add a comment |
The program requires the user to input numbers and when finished to exit the loop by entering a negative number. The program will then output the average of the numbers and the count of the numbers. The negative number should be removed from the series though. So if we have three numbers and exit on the (fourth) negative number, the average will only be of the three numbers and not include the negative number. Neat, I somehow made that work. Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100 also using a Boolean equation. It is at this point that I cannot determine how to exclude the erroneous input from the results.
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
float inScore= 1;
float sumScore= 0.0;
int scoreCount= 0;
float avgScore= 0.0;
bool moreNumbers = true;
bool notNumbers = true;
for ( inScore =1; inScore >=1; inScore++) //for loop some kind of blackmagic not really sure about this right now
{
cout << "Please enter grades (enter a negative integer to exit): ";
cin >> inScore;
if (!cin || inScore > 100)
{
notNumbers = false; //boolean to ignore non integers or numbers greater than 100
cin.clear();
cin.ignore(256, 'n');
scoreCount--;
cout << "Invalid number!" << endl;
} //something is wrong in this section and I can't get it to ignore the invalid inputs
else if (inScore < 0)
{
moreNumbers = false;
} //breaks the loop upon a negative number being entered
else
sumScore+=inScore;
scoreCount++;
}
avgScore = (sumScore+=inScore)/(scoreCount-1);
cout << "Number of Grades: " << scoreCount-1 << endl; //number of entries
cout << "Average: " << avgScore << endl; // average grade except I cannot figure out how to remove negative number from the array
return 0;
}
c++ loops boolean
Don't you need specify n?istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
I see the comment afterfor ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.
– user4581301
Nov 12 '18 at 4:16
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simplemain
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.
– user4581301
Nov 12 '18 at 4:17
Totally unrelated. But to get back on topic,cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll wantcin.ignore(numeric_limits<streamsize>::max(), 'n')
and#include <limits>
to getmax
.
– user4581301
Nov 12 '18 at 4:21
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39
add a comment |
The program requires the user to input numbers and when finished to exit the loop by entering a negative number. The program will then output the average of the numbers and the count of the numbers. The negative number should be removed from the series though. So if we have three numbers and exit on the (fourth) negative number, the average will only be of the three numbers and not include the negative number. Neat, I somehow made that work. Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100 also using a Boolean equation. It is at this point that I cannot determine how to exclude the erroneous input from the results.
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
float inScore= 1;
float sumScore= 0.0;
int scoreCount= 0;
float avgScore= 0.0;
bool moreNumbers = true;
bool notNumbers = true;
for ( inScore =1; inScore >=1; inScore++) //for loop some kind of blackmagic not really sure about this right now
{
cout << "Please enter grades (enter a negative integer to exit): ";
cin >> inScore;
if (!cin || inScore > 100)
{
notNumbers = false; //boolean to ignore non integers or numbers greater than 100
cin.clear();
cin.ignore(256, 'n');
scoreCount--;
cout << "Invalid number!" << endl;
} //something is wrong in this section and I can't get it to ignore the invalid inputs
else if (inScore < 0)
{
moreNumbers = false;
} //breaks the loop upon a negative number being entered
else
sumScore+=inScore;
scoreCount++;
}
avgScore = (sumScore+=inScore)/(scoreCount-1);
cout << "Number of Grades: " << scoreCount-1 << endl; //number of entries
cout << "Average: " << avgScore << endl; // average grade except I cannot figure out how to remove negative number from the array
return 0;
}
c++ loops boolean
The program requires the user to input numbers and when finished to exit the loop by entering a negative number. The program will then output the average of the numbers and the count of the numbers. The negative number should be removed from the series though. So if we have three numbers and exit on the (fourth) negative number, the average will only be of the three numbers and not include the negative number. Neat, I somehow made that work. Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100 also using a Boolean equation. It is at this point that I cannot determine how to exclude the erroneous input from the results.
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
float inScore= 1;
float sumScore= 0.0;
int scoreCount= 0;
float avgScore= 0.0;
bool moreNumbers = true;
bool notNumbers = true;
for ( inScore =1; inScore >=1; inScore++) //for loop some kind of blackmagic not really sure about this right now
{
cout << "Please enter grades (enter a negative integer to exit): ";
cin >> inScore;
if (!cin || inScore > 100)
{
notNumbers = false; //boolean to ignore non integers or numbers greater than 100
cin.clear();
cin.ignore(256, 'n');
scoreCount--;
cout << "Invalid number!" << endl;
} //something is wrong in this section and I can't get it to ignore the invalid inputs
else if (inScore < 0)
{
moreNumbers = false;
} //breaks the loop upon a negative number being entered
else
sumScore+=inScore;
scoreCount++;
}
avgScore = (sumScore+=inScore)/(scoreCount-1);
cout << "Number of Grades: " << scoreCount-1 << endl; //number of entries
cout << "Average: " << avgScore << endl; // average grade except I cannot figure out how to remove negative number from the array
return 0;
}
c++ loops boolean
c++ loops boolean
edited Nov 12 '18 at 4:37
asked Nov 12 '18 at 3:46
Chris Wagner
64
64
Don't you need specify n?istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
I see the comment afterfor ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.
– user4581301
Nov 12 '18 at 4:16
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simplemain
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.
– user4581301
Nov 12 '18 at 4:17
Totally unrelated. But to get back on topic,cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll wantcin.ignore(numeric_limits<streamsize>::max(), 'n')
and#include <limits>
to getmax
.
– user4581301
Nov 12 '18 at 4:21
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39
add a comment |
Don't you need specify n?istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
I see the comment afterfor ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.
– user4581301
Nov 12 '18 at 4:16
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simplemain
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.
– user4581301
Nov 12 '18 at 4:17
Totally unrelated. But to get back on topic,cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll wantcin.ignore(numeric_limits<streamsize>::max(), 'n')
and#include <limits>
to getmax
.
– user4581301
Nov 12 '18 at 4:21
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39
Don't you need specify n?
istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
Don't you need specify n?
istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
I see the comment after
for ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.– user4581301
Nov 12 '18 at 4:16
I see the comment after
for ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.– user4581301
Nov 12 '18 at 4:16
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simple
main
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.– user4581301
Nov 12 '18 at 4:17
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simple
main
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.– user4581301
Nov 12 '18 at 4:17
Totally unrelated. But to get back on topic,
cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll want cin.ignore(numeric_limits<streamsize>::max(), 'n')
and #include <limits>
to get max
.– user4581301
Nov 12 '18 at 4:21
Totally unrelated. But to get back on topic,
cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll want cin.ignore(numeric_limits<streamsize>::max(), 'n')
and #include <limits>
to get max
.– user4581301
Nov 12 '18 at 4:21
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39
add a comment |
1 Answer
1
active
oldest
votes
Remaining Problem
Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100
Since the above current code accepts floating point values as valid inputs, we must fix the code and exclude them as invalid inputs.
For instance, if we input 1.5
, 2.5
and -1
, then these values are accepted and output
Number of Grades: 2
Average: 2
is shown.
Also, the current code accepts two or more integers from just one input.
If we give an input 1.5 2.5 -1
, then the above output is again shown.
But we should judge 1.5
, 2.5
and 1.5 2.5 -1
as invalid inputs!
Definition of the Valid Input
Since I don't know your precise definition of valid input and I may be wrong, but here I assume that it is given by the following natural statements.
First of all, as you say,
- Each input represents an integer.
Therefore, I assume
Whitespace characters are allowed in the left and right side of input strings.
Whitespace characters between non-whitespace characters are not allowed.
In addition, I also assume
The first non-whitespace character must be
0
,1
, ...,9
,+
or-
.The second and the subsequent non-whitespace characters must be
0
,1
, ...,8
or9
.
Note that in my assumption the decimal-point character .
is not allowed.
For instance, " 123 "
, " +123 "
and " -123 "
are all valid inputs. But " 1 23"
, "+ 123"
, "- 123"
, "1.0"
and "123a"
are all invalid.
Validity Check Function
First, to check the validity of the input, using the following nice trimming function, we trim the input string and remove left and right whitespaces:
std::string_view trimLR(std::string_view str)
{
const auto strBegin = str.find_first_not_of(" fnrtv");
if (strBegin == std::string_view::npos){
return "";
}
const auto strEnd = str.find_last_not_of(" fnrtv");
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
Next, we define the following simple validity check function isInteger
which checks whether the passed string is an integer or not.
Here std::isdigit
is useful to check each character is one of the 10 decimal digits: 0
, 1
, ..., 9
.
My DEMO is here.
bool isInteger(std::string_view s)
{
s = trimLR(s);
if(s.empty()){
return false;
}
const std::size_t offset = ((s[0] == '-') || (s[0] == '+')) ? 1 : 0;
const auto begin = s.cbegin() + offset;
return (begin != s.cend()) // remove "+" and "-"
&& std::all_of(begin, s.cend(), (unsigned char c){
return std::isdigit(c);
});
}
In addition to this method, various interesting methods are proposed in past posts.
Main Function
Now it is easy and straightforward to implement the main for-loop.
The following code will work fine.
The input is verified to be an integer and less than 100.
int main()
{
double sumScore = 0;
int scoreCount = 0;
for(;;)
{
std::string s;
std::cout << "Please enter grades (enter a negative integer to exit): ";
std::getline(std::cin, s);
if(!isInteger(s)) {
std::cout << "Invalid number!" << std::endl;
continue;
}
const auto score = std::stoi(s);
if(score < 0) {
std::cout << "Negative number is input, Finished!" << std::endl;
break;
}
else if(score > 100) {
std::cout << "Input value is grater than 100, which is ignored." << std::endl;
continue;
}
sumScore += score;
++scoreCount;
}
const auto average = (scoreCount == 0) ? 0 : (sumScore/scoreCount);
std::cout
<< "Number of Grades: " << scoreCount << std::endl
<< "Average: " << average << std::endl;
return 0;
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255708%2fignoring-invalid-input-from-a-count-and-average%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Remaining Problem
Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100
Since the above current code accepts floating point values as valid inputs, we must fix the code and exclude them as invalid inputs.
For instance, if we input 1.5
, 2.5
and -1
, then these values are accepted and output
Number of Grades: 2
Average: 2
is shown.
Also, the current code accepts two or more integers from just one input.
If we give an input 1.5 2.5 -1
, then the above output is again shown.
But we should judge 1.5
, 2.5
and 1.5 2.5 -1
as invalid inputs!
Definition of the Valid Input
Since I don't know your precise definition of valid input and I may be wrong, but here I assume that it is given by the following natural statements.
First of all, as you say,
- Each input represents an integer.
Therefore, I assume
Whitespace characters are allowed in the left and right side of input strings.
Whitespace characters between non-whitespace characters are not allowed.
In addition, I also assume
The first non-whitespace character must be
0
,1
, ...,9
,+
or-
.The second and the subsequent non-whitespace characters must be
0
,1
, ...,8
or9
.
Note that in my assumption the decimal-point character .
is not allowed.
For instance, " 123 "
, " +123 "
and " -123 "
are all valid inputs. But " 1 23"
, "+ 123"
, "- 123"
, "1.0"
and "123a"
are all invalid.
Validity Check Function
First, to check the validity of the input, using the following nice trimming function, we trim the input string and remove left and right whitespaces:
std::string_view trimLR(std::string_view str)
{
const auto strBegin = str.find_first_not_of(" fnrtv");
if (strBegin == std::string_view::npos){
return "";
}
const auto strEnd = str.find_last_not_of(" fnrtv");
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
Next, we define the following simple validity check function isInteger
which checks whether the passed string is an integer or not.
Here std::isdigit
is useful to check each character is one of the 10 decimal digits: 0
, 1
, ..., 9
.
My DEMO is here.
bool isInteger(std::string_view s)
{
s = trimLR(s);
if(s.empty()){
return false;
}
const std::size_t offset = ((s[0] == '-') || (s[0] == '+')) ? 1 : 0;
const auto begin = s.cbegin() + offset;
return (begin != s.cend()) // remove "+" and "-"
&& std::all_of(begin, s.cend(), (unsigned char c){
return std::isdigit(c);
});
}
In addition to this method, various interesting methods are proposed in past posts.
Main Function
Now it is easy and straightforward to implement the main for-loop.
The following code will work fine.
The input is verified to be an integer and less than 100.
int main()
{
double sumScore = 0;
int scoreCount = 0;
for(;;)
{
std::string s;
std::cout << "Please enter grades (enter a negative integer to exit): ";
std::getline(std::cin, s);
if(!isInteger(s)) {
std::cout << "Invalid number!" << std::endl;
continue;
}
const auto score = std::stoi(s);
if(score < 0) {
std::cout << "Negative number is input, Finished!" << std::endl;
break;
}
else if(score > 100) {
std::cout << "Input value is grater than 100, which is ignored." << std::endl;
continue;
}
sumScore += score;
++scoreCount;
}
const auto average = (scoreCount == 0) ? 0 : (sumScore/scoreCount);
std::cout
<< "Number of Grades: " << scoreCount << std::endl
<< "Average: " << average << std::endl;
return 0;
}
add a comment |
Remaining Problem
Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100
Since the above current code accepts floating point values as valid inputs, we must fix the code and exclude them as invalid inputs.
For instance, if we input 1.5
, 2.5
and -1
, then these values are accepted and output
Number of Grades: 2
Average: 2
is shown.
Also, the current code accepts two or more integers from just one input.
If we give an input 1.5 2.5 -1
, then the above output is again shown.
But we should judge 1.5
, 2.5
and 1.5 2.5 -1
as invalid inputs!
Definition of the Valid Input
Since I don't know your precise definition of valid input and I may be wrong, but here I assume that it is given by the following natural statements.
First of all, as you say,
- Each input represents an integer.
Therefore, I assume
Whitespace characters are allowed in the left and right side of input strings.
Whitespace characters between non-whitespace characters are not allowed.
In addition, I also assume
The first non-whitespace character must be
0
,1
, ...,9
,+
or-
.The second and the subsequent non-whitespace characters must be
0
,1
, ...,8
or9
.
Note that in my assumption the decimal-point character .
is not allowed.
For instance, " 123 "
, " +123 "
and " -123 "
are all valid inputs. But " 1 23"
, "+ 123"
, "- 123"
, "1.0"
and "123a"
are all invalid.
Validity Check Function
First, to check the validity of the input, using the following nice trimming function, we trim the input string and remove left and right whitespaces:
std::string_view trimLR(std::string_view str)
{
const auto strBegin = str.find_first_not_of(" fnrtv");
if (strBegin == std::string_view::npos){
return "";
}
const auto strEnd = str.find_last_not_of(" fnrtv");
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
Next, we define the following simple validity check function isInteger
which checks whether the passed string is an integer or not.
Here std::isdigit
is useful to check each character is one of the 10 decimal digits: 0
, 1
, ..., 9
.
My DEMO is here.
bool isInteger(std::string_view s)
{
s = trimLR(s);
if(s.empty()){
return false;
}
const std::size_t offset = ((s[0] == '-') || (s[0] == '+')) ? 1 : 0;
const auto begin = s.cbegin() + offset;
return (begin != s.cend()) // remove "+" and "-"
&& std::all_of(begin, s.cend(), (unsigned char c){
return std::isdigit(c);
});
}
In addition to this method, various interesting methods are proposed in past posts.
Main Function
Now it is easy and straightforward to implement the main for-loop.
The following code will work fine.
The input is verified to be an integer and less than 100.
int main()
{
double sumScore = 0;
int scoreCount = 0;
for(;;)
{
std::string s;
std::cout << "Please enter grades (enter a negative integer to exit): ";
std::getline(std::cin, s);
if(!isInteger(s)) {
std::cout << "Invalid number!" << std::endl;
continue;
}
const auto score = std::stoi(s);
if(score < 0) {
std::cout << "Negative number is input, Finished!" << std::endl;
break;
}
else if(score > 100) {
std::cout << "Input value is grater than 100, which is ignored." << std::endl;
continue;
}
sumScore += score;
++scoreCount;
}
const auto average = (scoreCount == 0) ? 0 : (sumScore/scoreCount);
std::cout
<< "Number of Grades: " << scoreCount << std::endl
<< "Average: " << average << std::endl;
return 0;
}
add a comment |
Remaining Problem
Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100
Since the above current code accepts floating point values as valid inputs, we must fix the code and exclude them as invalid inputs.
For instance, if we input 1.5
, 2.5
and -1
, then these values are accepted and output
Number of Grades: 2
Average: 2
is shown.
Also, the current code accepts two or more integers from just one input.
If we give an input 1.5 2.5 -1
, then the above output is again shown.
But we should judge 1.5
, 2.5
and 1.5 2.5 -1
as invalid inputs!
Definition of the Valid Input
Since I don't know your precise definition of valid input and I may be wrong, but here I assume that it is given by the following natural statements.
First of all, as you say,
- Each input represents an integer.
Therefore, I assume
Whitespace characters are allowed in the left and right side of input strings.
Whitespace characters between non-whitespace characters are not allowed.
In addition, I also assume
The first non-whitespace character must be
0
,1
, ...,9
,+
or-
.The second and the subsequent non-whitespace characters must be
0
,1
, ...,8
or9
.
Note that in my assumption the decimal-point character .
is not allowed.
For instance, " 123 "
, " +123 "
and " -123 "
are all valid inputs. But " 1 23"
, "+ 123"
, "- 123"
, "1.0"
and "123a"
are all invalid.
Validity Check Function
First, to check the validity of the input, using the following nice trimming function, we trim the input string and remove left and right whitespaces:
std::string_view trimLR(std::string_view str)
{
const auto strBegin = str.find_first_not_of(" fnrtv");
if (strBegin == std::string_view::npos){
return "";
}
const auto strEnd = str.find_last_not_of(" fnrtv");
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
Next, we define the following simple validity check function isInteger
which checks whether the passed string is an integer or not.
Here std::isdigit
is useful to check each character is one of the 10 decimal digits: 0
, 1
, ..., 9
.
My DEMO is here.
bool isInteger(std::string_view s)
{
s = trimLR(s);
if(s.empty()){
return false;
}
const std::size_t offset = ((s[0] == '-') || (s[0] == '+')) ? 1 : 0;
const auto begin = s.cbegin() + offset;
return (begin != s.cend()) // remove "+" and "-"
&& std::all_of(begin, s.cend(), (unsigned char c){
return std::isdigit(c);
});
}
In addition to this method, various interesting methods are proposed in past posts.
Main Function
Now it is easy and straightforward to implement the main for-loop.
The following code will work fine.
The input is verified to be an integer and less than 100.
int main()
{
double sumScore = 0;
int scoreCount = 0;
for(;;)
{
std::string s;
std::cout << "Please enter grades (enter a negative integer to exit): ";
std::getline(std::cin, s);
if(!isInteger(s)) {
std::cout << "Invalid number!" << std::endl;
continue;
}
const auto score = std::stoi(s);
if(score < 0) {
std::cout << "Negative number is input, Finished!" << std::endl;
break;
}
else if(score > 100) {
std::cout << "Input value is grater than 100, which is ignored." << std::endl;
continue;
}
sumScore += score;
++scoreCount;
}
const auto average = (scoreCount == 0) ? 0 : (sumScore/scoreCount);
std::cout
<< "Number of Grades: " << scoreCount << std::endl
<< "Average: " << average << std::endl;
return 0;
}
Remaining Problem
Now, I need to expand upon this to make it so that the input is verified to be an integer and less than 100
Since the above current code accepts floating point values as valid inputs, we must fix the code and exclude them as invalid inputs.
For instance, if we input 1.5
, 2.5
and -1
, then these values are accepted and output
Number of Grades: 2
Average: 2
is shown.
Also, the current code accepts two or more integers from just one input.
If we give an input 1.5 2.5 -1
, then the above output is again shown.
But we should judge 1.5
, 2.5
and 1.5 2.5 -1
as invalid inputs!
Definition of the Valid Input
Since I don't know your precise definition of valid input and I may be wrong, but here I assume that it is given by the following natural statements.
First of all, as you say,
- Each input represents an integer.
Therefore, I assume
Whitespace characters are allowed in the left and right side of input strings.
Whitespace characters between non-whitespace characters are not allowed.
In addition, I also assume
The first non-whitespace character must be
0
,1
, ...,9
,+
or-
.The second and the subsequent non-whitespace characters must be
0
,1
, ...,8
or9
.
Note that in my assumption the decimal-point character .
is not allowed.
For instance, " 123 "
, " +123 "
and " -123 "
are all valid inputs. But " 1 23"
, "+ 123"
, "- 123"
, "1.0"
and "123a"
are all invalid.
Validity Check Function
First, to check the validity of the input, using the following nice trimming function, we trim the input string and remove left and right whitespaces:
std::string_view trimLR(std::string_view str)
{
const auto strBegin = str.find_first_not_of(" fnrtv");
if (strBegin == std::string_view::npos){
return "";
}
const auto strEnd = str.find_last_not_of(" fnrtv");
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
Next, we define the following simple validity check function isInteger
which checks whether the passed string is an integer or not.
Here std::isdigit
is useful to check each character is one of the 10 decimal digits: 0
, 1
, ..., 9
.
My DEMO is here.
bool isInteger(std::string_view s)
{
s = trimLR(s);
if(s.empty()){
return false;
}
const std::size_t offset = ((s[0] == '-') || (s[0] == '+')) ? 1 : 0;
const auto begin = s.cbegin() + offset;
return (begin != s.cend()) // remove "+" and "-"
&& std::all_of(begin, s.cend(), (unsigned char c){
return std::isdigit(c);
});
}
In addition to this method, various interesting methods are proposed in past posts.
Main Function
Now it is easy and straightforward to implement the main for-loop.
The following code will work fine.
The input is verified to be an integer and less than 100.
int main()
{
double sumScore = 0;
int scoreCount = 0;
for(;;)
{
std::string s;
std::cout << "Please enter grades (enter a negative integer to exit): ";
std::getline(std::cin, s);
if(!isInteger(s)) {
std::cout << "Invalid number!" << std::endl;
continue;
}
const auto score = std::stoi(s);
if(score < 0) {
std::cout << "Negative number is input, Finished!" << std::endl;
break;
}
else if(score > 100) {
std::cout << "Input value is grater than 100, which is ignored." << std::endl;
continue;
}
sumScore += score;
++scoreCount;
}
const auto average = (scoreCount == 0) ? 0 : (sumScore/scoreCount);
std::cout
<< "Number of Grades: " << scoreCount << std::endl
<< "Average: " << average << std::endl;
return 0;
}
edited Nov 23 '18 at 0:52
answered Nov 12 '18 at 17:32
Hiroki
1,0781314
1,0781314
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255708%2fignoring-invalid-input-from-a-count-and-average%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Don't you need specify n?
istream& ignore (streamsize n = 1, int delim = EOF);
– Soumya Kanti
Nov 12 '18 at 3:55
I see the comment after
for ( inScore =1; inScore >=1; inScore++)
, but if you're going to use junk code as a place holder, try to use something that makes sense. This only serves to obscure your problem.– user4581301
Nov 12 '18 at 4:16
Suggestion: Don't BS code, write less code. Right now what you want to figure out is how to get a valid number and only a valid number. To do that, write a function that does exactly that and nothing else. Then write a simple
main
function that tests the function every way you can think of. Once you have the function working, worry about looping calls to the function until you hit the exit condition. Think small and then bolt the small things together into something big.– user4581301
Nov 12 '18 at 4:17
Totally unrelated. But to get back on topic,
cin.ignore();
removes only one character. You need to remove the whole bad input and probably the whole line. To do that you'll wantcin.ignore(numeric_limits<streamsize>::max(), 'n')
and#include <limits>
to getmax
.– user4581301
Nov 12 '18 at 4:21
I changed the cin.ignore to reflect the size of the input and added "scoreCount--;" to remove the erroneous input. It seems to give the intended results at this point. Thanks @user4581301
– Chris Wagner
Nov 12 '18 at 4:39