Program about Average age - c++

i wrote this code about a program that should print males and females's average age but it doesn't work and I don't know why. Could anyone help me?
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int CountM,CountF,TotM,TotF,i,QP,Age;
float MediaM;
float MediaF;
char Sex[100];
CountM=0;
CountF=0;
TotF=0;
TotM=0;
QP=0;
cout<<"How many people do you want to analyze?"<<endl;
cin>>QP;
for(i=0;QP<i;i++)
{
cout<<"Enter Person sex "<<i+1<<endl;
cin>>Sex[i];
while((Sex[i] != 'M' || Sex[i] != 'm') && (Sex[i] != 'F' || Sex[i] != 'f')){
cout<<"The entered sex is invalid,enter M o F"<<endl;
cin>>Sex[i];}
cout<<"How many years?"<<endl;
cin>>Age;
if(Sex[i] == 'M' || Sex[i] == 'm'){
CountM++;
TotM=TotM+Age;}
else {
CountF++;
TotF=TotF+Age; }
}
MediaM=TotM/CountM;
MediaF=TotF/CountF;
cout<<"The average age of males is"<<MediaM<<endl;
cout<<"The average age of females is"<<MediaF<<endl;
return 0;
}
Thanks for help.

for (i = 0; QP < i; i++)
This line has a logic error; you want your for-loop to run QP Number of times. Hence, you should change the for-loop header to:
for (i = 0; i < QP; i++)
Another thing: your while loop condition logic is incorrect:
while((Sex[i] != 'M' || Sex[i] != 'm') && (Sex[i] != 'F' || Sex[i] != 'f'))
Here, if we see the Sex[i] != 'M' || Sex[i] != 'm', this will always be true, because even if Sex[i] is 'M', it cannot be 'm' at the same thie, hence you will have false OR true, which will lead to the while-loop condition being true, and not falsified, as you would want with the correct input being entered.
Hence change your for-loop condition to:
Sex[i] != 'M' && Sex[i] != 'm'
This error is replicated in other parts of your while loop condition. Fix that so that it works as expected.

Related

Recursive function that counts vowels

I have an assignment that asks me to "Write a recursive function vowels(s,low,high) that returns the number of vowels in an input string s[]." We are also limited by "Do not use the C++ string type. Read the characters into an array one at a time using cin.get()." I think I solved the task at hand, but it doesnt compile so I am unsure. If anyone could assist me and show how to fix my error and any errors I've made towards my solution that would be great.
Here is my error message.
***main.cpp:24:37: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
vowelCount = vowels(s, low, high);**
Here is my code:
#include <iostream>
#include <cstring>
using namespace std;
int vowels(char, int, int);
int main()
{
char s[500];
int high,
vowelCount,
low = 0;
cout << "Enter a string of characters: ";
cin.get(s, 500);
high = strlen(s);
vowelCount = vowels(s, low, high);
cout << "The string contains " << vowelCount << " vowels." << endl;
return 0;
}
int vowels(char s[], int low, int high)
{
if (s[low] == 'a' || 'A' || 'e' || 'E' || 'i' || 'I' || 'o' || 'O' || 'u' || 'U') {
return 1 + vowels(s, low + 1, high - 1);
} else {
return vowels(s, low + 1, high - 1);
}
}
We are talking about a so called XY-Problem here.
The teacher wants to cover recursive functions. The vowel counting is just some noise. Unfortunately the given example is a bad one, because it could be implemented by far better with an iterative approach.
The recursion is just adding unnecessary time and space complexity. So, the performance is worse compared to a simple loop in all cases.
If the teacher wants that you learn about recursion, you may want to first look at this description or that more practical example.
After having read this, you will understand that a loop can be simply converted into a recursive function.
I am not sure, why there is a "low" and a "high" parameter. Maybe because of the usage of C-strings stored in a char array (what is nonsense in C++). I doubt that 2 self calls should be established and the function should walk from the begin and the end of the string to the middle. That would even further reduce the performance. So, let us assume the standard case.
Next to your problem with the comparison. What you have written is wrong. The correct comparison in C++ would be:
if ((s[low] == 'a') || (s[low] == 'A') || (s[low] == 'e') ||
(s[low] == 'E') || (s[low] == 'i') || (s[low] == 'I') ||
(s[low] == 'o') || (s[low] == 'O') || (s[low] == 'u') ||
(s[low] == 'U'))
Of course, nobody would write such a long statement, because you can simply calculate, without any comparison, if an ASCII character is a vowel. You could simply write:
if (std::isalpha(s[low]) && ((0x208222 >> (s[low] & 0x1f)) & 1))
and thats it. If you are interested, I can explain the theory later, but not needed for this example.
Then, next, your recursive function is dangerously wrong, because it does not have an end condition. it will run forever or until the stack overflows.
So, you need to rework that, It could be done like this:
#include <iostream>
#include <cstring>
using namespace std;
int vowels(char[], int, int);
int main()
{
char s[500];
int high,
vowelCount,
low = 0;
cout << "Enter a string of characters: ";
cin.get(s, 500);
high = strlen(s);
vowelCount = vowels(s, low, high);
cout << "The string contains " << vowelCount << " vowels." << endl;
return 0;
}
int vowels(char s[], int low, int high)
{
int sum = 0;
if (low != high) {
if ((s[low] == 'a') || (s[low] == 'A') || (s[low] == 'e') ||
(s[low] == 'E') || (s[low] == 'i') || (s[low] == 'I') ||
(s[low] == 'o') || (s[low] == 'O') || (s[low] == 'u') ||
(s[low] == 'U'))
{
++sum;
}
sum += vowels(s,low+1,high);
}
return sum;
}
If we go a little bit more into the direction of C++ and use meaningful variable names and comments, then we could come up with that:
#include <iostream>
#include <cstring>
// A recursive function to count the vowels in a rang of a text
int countVowelsRecursive(char textToEvaluate[], unsigned int startPositionForEvaluation, unsigned int endPositionOfText)
{
// Here we will store the number of vowels. We will use tail recursion
// So, the overall calculation will be done at the end
unsigned int numberOfVowelsInThisRecursion = 0u;
// Now we are evaluating this character from the text
const char currentChar = textToEvaluate[startPositionForEvaluation];
// Check, for the end of recursion condition
if (startPositionForEvaluation != endPositionOfText) {
// Check, if it is a vowel
if ((currentChar == 'a') || (currentChar == 'A') || (currentChar == 'e') ||
(currentChar == 'E') || (currentChar == 'i') || (currentChar == 'I') ||
(currentChar == 'o') || (currentChar == 'O') || (currentChar == 'u') ||
(currentChar == 'U'))
{
// Vowel found. Increase counter by one
++numberOfVowelsInThisRecursion;
}
// Tail recursion. Self call, starting at next position of the string
numberOfVowelsInThisRecursion +=
countVowelsRecursive(textToEvaluate,startPositionForEvaluation + 1, endPositionOfText);
}
// This will be the final result
return numberOfVowelsInThisRecursion;
}
// We will allow a maximal input text length like this
constexpr unsigned int MaxTextLength = 500u;
// Driver code / test function
int main()
{
// Here we will store the text from the user
char text[MaxTextLength]{};
// Give instructions and get the text
std::cout << "Enter a string of characters: ";
std::cin.get(text, MaxTextLength);
// Set text parameters for the evaluation
unsigned int startOfText = 0u;
unsigned int endOfText = static_cast<unsigned int>(strlen(text));
// Calculate the vowels
unsigned int vowelCount = countVowelsRecursive(text, startOfText, endOfText);
// Show result to user
std::cout << "The string contains " << vowelCount << " vowels." << std::endl;
return 0;
}
And if we would be allowed to use C++ then we would write:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
// Give instructions and get the text
std::cout << "\nEnter a text:\n";
if (std::string text{}; std::getline(std::cin, text))
// Show result to user
std::cout << "\n\nThe string contains "
<< std::count_if(text.begin(), text.end(), [](const char c){ return std::isalpha(c) && ((0x208222 >> (c & 0x1f)) & 1);})
<< " vowels.\n";
return 0;
}
Have fun . . .

Trying to make a conditional forloop when reading from a file

I am trying to create a for loop that has a conditional statement which reads until an operation is found, ex. (+,-,/,*), but every time I try I get an error:
Unhandled exception at 0x7936F2F6 (ucrtbased.dll) in CIS310 Project 44.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
while (getline(infile, hex))
{
n = hex.length();//find the length of the line
for (i = 0; hex[i] != '/'||'+'||'-'||'*'; i++,++k) //loop to split the first hexadecimal number
h1 = h1 + hex[i];
for (i++; i < n - 1; i++) //loop to get the second hexadecimal number
h2 = h2 + hex[i];
n1 = convertDecimal(h1); //convert the first hexadecimal number to decimal
n2 = convertDecimal(h2);
Your condition hex[i] != '/'||'+'||'-'||'*' is malformed. C++ requires that you specify both sides of the operator each time, so you will need something more similar to hex[i] != '/' || hex[i] != '+' || ....
You have to check after every ' | | '(OR), like:
hex[i] != '/' || hex[i] != '+' || hex[i] != '-' || hex[i] != '*'
This is a similar code to what you wrote:
while(getline(file,line))
{
string firstPart = "";
unsigned int i;
//We can use the algorithm library to search for them but its ok
for(i=0;(line[i] != '+') || (line[i] != '-') || (line[i] != '*') || (line[i] != '/') || (line[i] != '\0');i++ );
firstPart = line.substr(0,i);
}
now if you tried this, it will cause the same error (or atleast similar to it), if we even try to print every character in the loop
for(/*stuff*/)
cout << line[i];
Then notice this will become an infinite loop, the problem is that you're checking the character line[i] if it wasn't a + or - or * or / all at the same time, fix this by changing the || to &&.
I'll suppose that your file (named testfile.txt) has the content below:
0xAB+0xCD
0x11-0x03
Sample working code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream file("testfile.txt");
///Don't forget to check if file has opened
if(!file.is_open())
{
cout << "File didn\'t open :(";
return 0;
}
string line;
while(getline(file,line))
{
string firstPart = "",secondPart = "";
char operation;
unsigned int i;
//We can use the algorithm library to search for them but its ok
for(i=0;(line[i] != '+') && (line[i] != '-') && (line[i] != '*') && (line[i] != '/') && (line[i] != '\0');i++ );
firstPart = line.substr(0,i);
operation = line[i];
secondPart = line.substr(i+1,firstPart.size());
}
file.close();
return 0;
}

How can a char value be converted to a specific int value

I have an assignment where I have to make a program that allows a person to input a seven letter word and converts it to a telephone number (1-800-PAINTER to 1-800-724-6837 for example). I'm trying to make each letter convert to a specific number to be outputted to the user, with each letter corresponding to its number on a telephone keypad (so a, A, b, B or c, C equals 1, i.e, more info: https://en.wikipedia.org/wiki/Telephone_keypad).
Currently I have it set up so that each letter of the input word represents a char variable of one, two, three, four, five, six, or seven respectively. Then, using switch and if statements, the idea was to convert a char to an int variable of xtwo = 2, xthree = 3, etc. This isn't working however. Is there a better way to do this?
Example of code (up to first switch, though mostly it's a repeating pattern like so):
int main()
{
char one, two, three, four, five, six, seven;
cout << "Enter seven letter word (1-800-***-****): " << "\n";
cin >> one >> two >> three >> four >> five >> six >> seven;
int xtwo = 2; int xthree = 3; int xfour = 4; int xfive = 5; int xsix = 6; int xseven = 7; int xeight = 8;
int xnine = 9;
switch (one)
{
case 1:
if (one == 'a' || one == 'b' || one == 'c' || one == 'A' || one == 'B' || one == 'C')
{
one = xtwo;
}
break;
case 2:
if (one == 'd' || one == 'e' || one == 'f' || one == 'D' || one == 'E' || one == 'F')
{
one = xthree;
}
break;
case 3:
if (one == 'g' || one == 'h' || one == 'l' || one == 'G' || one == 'H' || one == 'L')
{
one = xfour;
}
break;
case 4:
if (one == 'j' || one == 'k' || one == 'l' || one == 'J' || one == 'K' || one == 'L')
{
one = xfive;
}
break;
case 5:
if (one == 'm' || one == 'n' || one == 'o' || one == 'M' || one == 'N' || one == 'O')
{
one = xsix;
}
break;
case 6:
if (one == 'p' || one == 'q' || one == 'r' || one == 's' || one == 'P' || one == 'Q' || one == 'R' || one == 'S')
{
one = xseven;
}
break;
case 7:
if (one == 't' || one == 'u' || one == 'v' || one == 'T' || one == 'U' || one == 'V')
{
one = xeight;
}
break;
case 8:
if (one == 'w' || one == 'x' || one == 'y' || one == 'z' || one == 'W' || one == 'X' || one == 'Y' || one == 'Z')
{
one = xnine;
}
break;
}
So, in essence, how can a char variable of a letter be converted to a specific int variable?
You could use a std::map.
For example, you could have
std::map<char,int> char_to_dig {
{'a',1}, {'b',1}, {'c',1},
{'d',2}, {'e',2}, {'f',2}
};
Then
char_to_dig['a']
will give you 1.
Alternatively, you could write a function that does the mapping. Something along the lines of this:
int char_to_dig(char c) {
static const char _c[] = "abcdefghi";
static const int _i[] = { 1,1,1,2,2,2,3,3,3 };
for (unsigned i=0; i<9; ++i) {
if (_c[i]==c) return _i[i];
}
return -1; // some value to signal error
}
Or, instead of using arrays, you could perform arithmetic on the chars (since they are just small integers).
int char_to_dig(char c) {
c = std::toupper(c);
if (c < 'A' || c > 'Z') return -1;
if (c == 'Z') return 9;
if (c > 'R') --c;
return ((c-'A')/3)+2;
}
This will give you numbers like on this pad:
Apparently, there's been a similar code golf question.
It has been years since I wrote any c/c++ code and I don't even have a compiler installed to test with .. but this should get you started on the right track
Check functions and syntax...all out of my head. Needs checking.
//
int numArray[7];
char inputStr[10];
cout << " give me 7 characters";
cin >> input;
/*
use a for loop to read the string letter by letter (a string in c is an
array of characters)
convert the characters to uppercase
fall through case statements for each group of letters
assing value to output array to do wiht as you like.
*/
for(i=0; i < 7; i++){
inputStr[i] = toupper(inputStr[i]);
switch(input[i]){
case 'A':
case 'B':
case 'C':
numArray[i] = 2;
break;
case 'D':
case 'E':
case 'F':
numArray[i] = 3;
break;
and so on and so foth....
}
}

Why does each single character of the string not equal to the character equivalent?

I am trying to check if each character of a string in a string array is equal to any of the five vowels. However, when I test it to see when a vowel character in a string is equal to 'vowel', I get that they are not equal. The problem with the code is the bolded part below. Also, when I try to do "a" || "e" || "i" || "o" || "u", I get the error that ISO C++ forbids comparison between pointer and integer. How can I be able to check if they are equal? Thank you for your time.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <cstdlib>
using namespace std;
int l, c; //l is amount of letters in password, c is amount of letters being inputted
char letters[1000000]; //the letters being inputted
vector <string> pass; //string vector of the stored passwords
void rec(string current, int index, int x){ //determining all possible passwords
if (index >= 4){
pass.push_back(current);
}
else{
for (int i=0; i<c; i++){
if (x<i){
int old;
old = x;
x = i;
rec(current + letters[i], index+1, x);
x = old;
}
}
}
}
int main (int argc, char ** argv)
{
cin >> l >> c;
int x = -1;
for (int i=0; i<c ;i++){
cin >> letters[i];
}
sort(letters, letters + c); //sorted from least to greatest
rec("", 0, x);
for (int i=0; i<pass.size(); i++){
int vl=0; //number of vowels
int nvl=0; //number of non-vowels (consonants)
for (int j=0; j<l; j++){
**if (pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u'){**
vl++;
}
else{
nvl++;
}
if (j == l-1){
if (vl >= 1 && nvl >= 2){
cout << pass.at(0) << endl;
}
}
}
}
return 0;
}
In C++, X || Y means:
Test if X is true. If so, result of whole expression is true
Otherwise, test if Y is true. Result of Y is result of expression.
So your code:
pass.at(0)[j] == 'a' || 'e'
(omitting for now the i etc. as they don't change anything).
We tested pass.at(0)[j] == 'a' . That was false, so now we test 'e'. Not that you did NOT test pass.at(0)[j] == 'e'. You just tested 'e'. This is the same as testing 'e' != 0, which is true. So your expression evaluates to true at this point (and does not go onto check 'i' etc.)
You probably intended to test whether pass.at(0)[j] held any of the values 'a', 'e', etc. If so then one way to encode that is:
if ( std::strchr("aeiou", pass.at(0)[j]) )
You should make sure j < strlen(pass.at(0)) before doing this though; using [] to generate an out of bounds index causes undefined behaviour.
Because you are using the || wrong. The part either side of || is a "true or false" expressin in itself, so you need something like:
if (pass.at(0)[j] == 'a' || pass.at(0)[j] == 'e' ... )
Otherwise, the expression is always true, since || is true if the expression on left or right is true, and 'e' is true by not being zero.
This does not do what you think...
(pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u')
You need to explicitly compare,
char t = pass.at(0)[j];
if (t == 'a' || t == 'e' || t == 'i' || t == 'o' || t == 'u') {

Why does it give the same output for every value?

int main (void)
{
char n;
label0:
cout<<"Please enter a character value(C/S)\n";
cin>>n;
n = toupper(n);
if ( n!= 'C' || n!= 'S' )
{
cout<<"Please enter proper value\n";
cin.clear();
cin.ignore();
goto label0;
}
else
{
cout<<"You entered"<<n<<"\n";
}
return 0;
}
In this code, even when I enter c C s S , it gives the same output as Please enter the proper value. Why is it not comparing?
if ( n!= 'C' || n!= 'S' )
This is true for every n in the world. You probably meant to use &&.
Think about it:
if n == 'C', then the condition is satisfied since n != 'S',
if n == 'S', then the condition is satisfied since n != 'C',
if n == 'X', then the condition is satisfied since n != 'C',
...
Read more about short circuit evaluation.
In general, you are having trouble by understanding the way in that logical operators are used.
The condition n != 'C' is equivalent to !(n == 'C').
Thus, the if() condition in your code can be rewritten in this way:
if ( !(n == 'C') || !(n == 'S') )
However, the condition you need in your code is another one:
if ( ! (n == 'C' || n == 'S') )
I suggest to do the job in reverse order:
if ( n== 'C' || n== 'S' )
{
cout<<"You entered"<<n<<"\n";
}
else
{
cout<<"Please enter proper value\n";
cin.clear();
cin.ignore();
goto label0;
}
In this way, if the entered character is c C s S, then the character is correct, and in any other case, a new character must be entered.
On the other hand, the goto statements must be used only in excepcional cases, when the flow of the program becomes very intrincated, and one really need "to jump out of the mess".
However, your program is very simple, and can be achieved with normal loop control sentences, such as do {} while():
int main (void)
{
char n;
do {
cout<<"Please enter a (proper) character value(C/S)\n";
cin>>n;
n = toupper(n);
cin.clear();
cin.ignore();
} while ( ! (n == 'C' || n == 'S') );
cout<<"You entered"<<n<<"\n";
return 0;
}
Now, the user is enforced to enter one of the desired characters: c C s S, until the entered character is correct.