How to access the second last element of a string - c++

this is a function that checks if a person is a man or a woman by checking the second
last element of his social security number. If the number is even then the person is a
woman. If odd then a men. The code is working in a strange way. Sometimes it does the job
and sometimes not. this is the code:
char check_gender(string person_nummer){
int check_digit = (person_nummer.back() - 1) - '0';
char gender;
if(check_digit % 2 == 0){
gender = 'K'; // K for a women(kvinna in swedish)
}
else{
gender = 'M'; // M for man
}
return gender;
}
int main(){
string number;
cout << "enter number" << endl;
cin >> number;
cout << check_gender(number) << endl;
return 0;
}
input1: 8602024898
output1: M // correct output
input2: 8510309159
output1: K // wrong output
input3: 7102022980
output M // wrong output
input4: 4906147410
output M // correct output
weird!

This returns the last character in the string:
person_nummer.back()
you then subtract 1 from it. That means, if the last character is '9', you now have '8'.
To get the second last character, you need;
person_nummer[person_nummer.size() - 2]
This will give the correct output for your example numbers:
Demo
Getting the second last character using iterators:
*std::prev(person_nummer.cend(), 2)
Demo
or reverse iterators:
*std::next(person_nummer.rbegin())
The code is working in a strange way. Sometimes it does the job and sometimes not.
You will get a number by doing person_nummer.back() - 1 but it's a 50/50 chance that it'll be correct for the entered person_number. The last digit is a check digit and has nothing to do with the gender but you were using it to determine gender.

Related

Adding to very large numbers using stack

i am a novice to C++ , I was trying to write this program for adding two very large numbers using strings but the program is not working correctly and I can't get what's wrong with it , please help me with this.
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main() {
stack <char> a1;
stack<char> a2;
stack<int> result;
stack<int> temp;
int carry = 0;
string num1;
string num2;
cout << "Enter first number (both numbers should have equal digits)" << endl;
getline(cin, num1);
cout << "Enter second number" << endl;
getline(cin, num2);
for (int i = num1.size()-1; i >= 0; i--) {
a1.push(num1[i]);
a2.push(num2[i]);
}
while (!a1.empty() && !a2.empty()) {
int element = (int)a1.top() + (int)a2.top() + carry;
cout << element;
if (element > 10) {
element %= 10;
carry = 1;
}
result.push(element);
cout << result.top() << endl;
a1.pop();
a2.pop();
}
string abc;
while (!result.empty()) {
temp.push(result.top());
result.pop();
abc += temp.top();
}
cout << abc;
}
I know i have definitely made a logical mistake , but i can't get it , can anyone please guide me?
the following is the output am getting
I was thinking, why stacks should be used. My guess is that you did this, because the numbers must be processed from right to left.
Additionally, you have obiously a challenge with strings with a different length.
But both problems can be solved easily. Let us start with the different length strings.
If 2 strings have a different length, we can pad (fill in) the shorter string with leading `0's. How many leading '0s' do we need to add? Right, the delta of the lengths.
And for inserting characters in a string at a certain position, we have the function insert.
So, the code for that will look like this:
if (numberAsString1.length() < numberAsString2.length())
numberAsString1.insert(0, numberAsString2.length() - numberAsString2.length(), '0');
else
numberAsString2.insert(0, numberAsString1.length() - numberAsString2.length(), '0');
This is rather straightforward.
The result will always be 2 strings with equal length. With entering "1234" and "9", we will get: "1234" and "0009".
This makes the next task easier.
Now that we have 2 equal length strings, we can "add", like we learned in school.
We go from right to left, by starting with the highest possible index of a character in the string. This is always length-1.
For calculating the sum, we need first to subtract the ASCII code for '0' from the characters in the string, because the string contains not integer numbers, but characters. For example "123" consists of '1', '2', '3' and not of 1,2,3.
Suming up is then easy: digit + digit + carry.
The resulting digit is always the sum % 10. And the next carry is always sum / 10. Example 1: 3+5=8 8%10=8 8/10=0. Example 2: 9+8=17 17%10=7 17/10=1.
So, also this is rather simple.
After we worked on all digits of the strings, there maybe still a set carry. This we will then add to the string.
Adding digits will be done in any case using the instert function. Because we want to insert digits on the left side of the resulting string.
So, with working from right to left, using correct indices and the insert function, we do not have the need for a stack.
With a lot of input checking, the whole function would look like this:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
// Give instruction to user
std::cout << "\nPlease enter 2 positive interger numbers:\n";
// Here we will store the user input
std::string numberAsString1{}, numberAsString2{};
// Get strings from user and check, if that worked
if (std::cin >> numberAsString1 >> numberAsString2) {
// Check if all characters in string 1 are digits
if (std::all_of(numberAsString1.begin(), numberAsString1.end(), std::isdigit)) {
// Check if all characters in string 2 are digits
if (std::all_of(numberAsString2.begin(), numberAsString2.end(), std::isdigit)) {
// ---------------------------------------------------------------------------------
// Here we will store the calculated result
std::string result{};
// Temporary helpers
unsigned int carry{};
// ---------------------------------------------------------------------------------
// Make strings equal length. Pad with leading '0' s
if (numberAsString1.length() < numberAsString2.length())
numberAsString1.insert(0, numberAsString2.length() - numberAsString2.length(), '0');
else
numberAsString2.insert(0, numberAsString1.length() - numberAsString2.length(), '0');
// ---------------------------------------------------------------------------------
// Iterate over all digits from right to left
for (int i = numberAsString1.length()-1; i >= 0; --i) {
// Calculate the sum
const int sum = numberAsString1[i]-'0' + numberAsString2[i] - '0' + carry;
// Get the carry bit in case of overflow
carry = sum / 10;
// Save the resulting digit
result.insert(0, 1, sum % 10 + '0');
}
// handle last carry bit
if (carry) result.insert(0, 1, '1');
// ---------------------------------------------------------------------------------
// Show result
std::cout << "\n\nSum: " << result << '\n';
}
else std::cerr << "\n\nError: number 1 contains illegal characters\n";
}
else std::cerr << "\n\nError: number 2 contains illegal characters\n";
}
else std::cerr << "\n\nError: Problem with input\n";
return 0;
}

Taking user input of an integer that can only be limited 1 digit

i'm currently learning c++ and have a project that I'm currently working on. My program in its entirety is to randomize 3 numbers from values 0-9 or set them myself. I was able to get the randomize numbers to work but not the setting of numbers myself. The issue being that when i tried to have the numbers as the int data type it produced 3 numbers for one input. It should be that x = 1, y = 2, z =3.... vales are: 123. To counter this issue I made the data type a character instead but it bugs me that random numbers are int values and my set numbers are char values. This is my current code below:
if ( userInput == 's') {
cout << "Enter three distinct digits each in the range 0..9 (e.g. 354)";
char num1 = ' ';
char num2 = ' ';
char num3 = ' ';
cin >> num1 >> num2 >> num3;
cout << endl << "Values to guess are: " << num1 << num2 << num3;
This might help you understand better what you're looking for.
Consider for example using:
int x;
cin >> x; // read an integer from the standard input stream (ignoring initial white space)
This will read a single integer from standard in, while
char c;
cin >> c; // read a character from standard input stream (ignoring initial white space)
read a single character from standard in (generally an ASCII character value).
If you have the following in standard input:
354
the first will finish with x = 354 and the second with c = '3' // = 51.
From my understanding you want to read 3 digits from standard in and store them in 3 separate numeric data types. You can do this using the following code:
uint8_t get_digit() {
char c;
cin >> c; // read a single non-whitespace character
if (! is_digit(c) ) return -1; // Error did not read a digit return bogus number
return (uint8_t)(c - '0'); // convert ascii digit to number and return value
}
This code will read a single character and check if it was a digit, if not it returns a bogus result (-1) othewise it returns the numeric value of the digit.

How to make C++ program that is supposed to add up ages and separate it into categories?

I'm supposed to make a program that counts the number of people in each age group:
0-16 (including 16) is infant
16-29 is young
29-55 is middle
55-75 is old
75+ is really old
The intervals are closed to the left and open to the right.
I wrote a program that compiles, but does not give me the correct values. I'm new at coding so can anyone point me in the right direction? Here is what I have:
#include <iostream>
using namespace std;
main()
{
int countinfant, countyoung, countmiddle, countold, countreallyold;
char age;
countinfant=0;
countyoung=0;
countmiddle=0;
countold=0;
countreallyold=0;
cout<< "Please Enter Ages. To end, enter *\n";
cin.get(age);
while (age>0 && age != '*')
{
if (age>=0 && age<=16) countinfant = countinfant + 1;
if (age>16 && age<=29) countyoung = countyoung + 1;
if (age>29 && age<=55) countmiddle = countmiddle + 1;
if (age>55 && age<=75) countold = countold + 1;
if (age>75 && age>=76) countreallyold = countreallyold + 1;
cin.get(age);
}
cout<< "\n The Number of Infant's Are: " << countinfant;
cout<< "\n The Number of Young's Are: " << countyoung;
cout<< "\n The Number of Middle's Are: " <<countmiddle;
cout<< "\n The Number of old's Are: " <<countold;
cout<< "\n The Number of Really Old's Are: " <<countreallyold;
cout<<endl;
return 0;
}
Actually your problem is very easy to figure out once I looked closer at the code.
The get function of input streams read a single character and not numbers. So if you enter the character 5 as input it will be read and stored in age as a character, and if the encoding used on your system is ASCII encoding (which is the most common these days) then the value for the character '5' is the integer 53.
You then proceed to use the character you have read as an integer, which as it is encoded will give you the wrong results.
To get the correct values you need to read an integer, however since you want to check for the asterisk to end the input you can't use normal integer input with the >> operator, which is why you used get I guess. The solution is to use strings and check the string for the asterisk, and if not an asterisk convert the string to an integer.
Something like
std::string input;
while (std::cin >> input && input != "*")
{
int age = std::stoi(input);
...
}
It does not work because you declared age as a char. The program reads the input as a char, so if you enter 0, the value in age will be the ASCII code of the character 0, which is 48 (0x30). You need to declare it as int age; and for the exit condition simply enter a negative value, e.g. -1, don't use the '*'.

double value to int variable- unexpected output

Here is a simple piece of code. actually it is a "fill array" function code.
#include <iostream>
using namespace std;
int main(){
int size = 10; a[10]; numberUsed;
cout << "Enter up to " << size << " nonnegative whole numbers.\n"
<< "Mark the end of the list with a negative number.\n";
int next, index = 0;
cin >> next;
while ((next >= 0) && (index < size)){
a[index] = next;
index++;
cin >> next;
}
numberUsed = index;
for(int i = 0 ; i < numberUsed -1 ; i++){
cout << a[i] << endl;
}
}
it works fine when user enters integers. But when i enter double values it should trancate that particular value. and repeats that value for the next entered integers also.
so now for input 1 2 3 4 5 6.5 7 8 9 -1 .I get the following output
1
2
3
4
5
6
6
6
6
6
Any help will be appreciated.
You told cin to read an integer, so that's what it's going to do - it will stop as soon as it sees a character that isn't valid for an integer. In this case it's the '.'. Trying to read more integers will just continue to fail, in your case leaving next at its previous value.
If you want to truncate a floating point value, read into a floating point variable and then do the truncation yourself.
double next;
...
a[index] = (int) next;
When reading integer values (and your code is using int next;, anything that isn't an integer will "stop" the input from every reading anything else. Since next is 6 at the point when it hits a '.' in the input stream, it continues to fill the array with that value until it runs out of space.
If you check the status of the input, e.g. if(!cin >> next) ... error handling ...;, you can detect when things have gone wrong. As part of the error handling, you should then "ignore any input until a whitespace" - cin.ignore(1000, ' '); would be a good start. You will also need to reset the error flag on cin to not get an error next time, with cin.clear() will do that.
If you want to input floating point numbers, you need to use float or double type for next (and the array a).

Read input numbers separated by spaces

This may be a total beginner's question, but I have yet to find an answer that works for me.
Currently, I'm writing a program for a class that takes in a user's input (which can be one or more numbers separated by spaces), then determines whether the number is prime, perfect, or neither. If the number is perfect, then it will display the divisors.
Thus far, I've already written the code for the prime, perfect, and listing the divisors. I'm stuck on the input portion of my program. I don't know how to get the input that's separated by spaces to go through my loops one at a time.
This is my current program:
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin>>num;
while (divisor<=num)
if(num%divisor==0)
{
cout<<divisor<<endl;
total=total+divisor;
divisor++;
}
else divisor++;
if(total==num*2)
cout<<"The number you entered is perfect!"<<endl;
else cout<<"The number you entered is not perfect!"<<endl;
if(num==2||num==3||num==5||num==7)
cout<<"The number you entered is prime!"<<endl;
else if(num%2==0||num%3==0||num%5==0||num%7==0)
cout<<"The number you entered is not prime!"<<endl;
else cout<<"The number you entered is prime!"<<endl;
return 0;
It works, but only for a single number. If anyone could help me to get it to be able to read multiple inputs separated by spaces, it'd be greatly appreciated. Also, just a side note, I do not know how many numbers will be entered, so I can't just make a variable for each one. It will be a random amount of numbers.
Thanks!
By default, cin reads from the input discarding any spaces. So, all you have to do is to use a do while loop to read the input more than one time:
do {
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin >> num;
// reset your variables
// your function stuff (calculations)
}
while (true); // or some condition
I would recommend reading in the line into a string, then splitting it based on the spaces. For this, you can use the getline(...) function. The trick is having a dynamic sized data structure to hold the strings once it's split. Probably the easiest to use would be a vector.
#include <string>
#include <vector>
...
string rawInput;
vector<String> numbers;
while( getline( cin, rawInput, ' ' ) )
{
numbers.push_back(rawInput);
}
So say the input looks like this:
Enter a number, or numbers separated by a space, between 1 and 1000.
10 5 20 1 200 7
You will now have a vector, numbers, that contains the elements: {"10","5","20","1","200","7"}.
Note that these are still strings, so not useful in arithmetic. To convert them to integers, we use a combination of the STL function, atoi(...), and because atoi requires a c-string instead of a c++ style string, we use the string class' c_str() member function.
while(!numbers.empty())
{
string temp = numbers.pop_back();//removes the last element from the string
num = atoi( temp.c_str() ); //re-used your 'num' variable from your code
...//do stuff
}
Now there's some problems with this code. Yes, it runs, but it is kind of clunky, and it puts the numbers out in reverse order. Lets re-write it so that it is a little more compact:
#include <string>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
There's still lots of room for improvement with error handling (right now if you enter a non-number the program will crash), and there's infinitely more ways to actually handle the input to get it in a usable number form (the joys of programming!), but that should give you a comprehensive start. :)
Note: I had the reference pages as links, but I cannot post more than two since I have less than 15 posts :/
Edit:
I was a little bit wrong about the atoi behavior; I confused it with Java's string->Integer conversions which throw a Not-A-Number exception when given a string that isn't a number, and then crashes the program if the exception isn't handled. atoi(), on the other hand, returns 0, which is not as helpful because what if 0 is the number they entered? Let's make use of the isdigit(...) function. An important thing to note here is that c++ style strings can be accessed like an array, meaning rawInput[0] is the first character in the string all the way up to rawInput[length - 1].
#include <string>
#include <ctype.h>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
bool isNum = true;
for(int i = 0; i < rawInput.length() && isNum; ++i)
{
isNum = isdigit( rawInput[i]);
}
if(isNum)
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
else
cout << rawInput << " is not a number!" << endl;
}
The boolean (true/false or 1/0 respectively) is used as a flag for the for-loop, which steps through each character in the string and checks to see if it is a 0-9 digit. If any character in the string is not a digit, the loop will break during it's next execution when it gets to the condition "&& isNum" (assuming you've covered loops already). Then after the loop, isNum is used to determine whether to do your stuff, or to print the error message.
You'll want to:
Read in an entire line from the console
Tokenize the line, splitting along spaces.
Place those split pieces into an array or list
Step through that array/list, performing your prime/perfect/etc tests.
What has your class covered along these lines so far?
int main() {
int sum = 0;
cout << "enter number" << endl;
int i = 0;
while (true) {
cin >> i;
sum += i;
//cout << i << endl;
if (cin.peek() == '\n') {
break;
}
}
cout << "result: " << sum << endl;
return 0;
}
I think this code works, you may enter any int numbers and spaces, it will calculate the sum of input ints
std::vector<int> num{};
int buf;
do{
std::cin >> buf;
num.push_back(buf);
}while(std::cin.peek() == ' ');
In C language you can to it using scanf like this:
scanf('%d %d',&a,&b);