This question already has answers here:
How to change a digit in string to integer rather than its ASCII code?
(2 answers)
Closed last month.
So I was on Edabit chillin doing so fun little exercises before I went to bed, having a blast then I stated a blackjack challenge. Thinking it would be a fun one to end the night with. That was until i made this monstrosity.
The prompt was:
Create a function that takes an array of card numbers and checks if the sum of their value exceeds 21. If the sum exceeds 21, return true and if the sum is under or equal to 21, return false. Values of the cards are as follows:
2-10 are their value.
J-K (face cards) count as 10.
Aces count either as 1 or 11 - play conservatively, so that if giving an ace a value of 11 causes you to lose and 1 allows you to win, then go with 1.
The code would be tested with these inputs:
That(overTwentyOne({'A', '2', '3'})
That(overTwentyOne({'A', 'J', 'K'})
That(overTwentyOne({'A', 'J', 'K', 'Q'})
That(overTwentyOne({'5', '3', '6', '6', '7', '9'})
simple enough right??
#include <iostream>
#include <vector>
using namespace std;
bool overTwentyOne(std::vector<char> cards);
int main()
{
int player_1 = 10;
int player_2 = 10;
int player_3 = 10;
int player_4 = 10;
std::vector<char> player1 = {'A', '2', '3'};
std::vector<char> player2 = {'A', 'J', 'K'};
std::vector<char> player3 = {'A', 'J', 'K', 'Q'};
std::vector<char> player4 = {'5', '3', '6', '6', '7', '9'};
cout << "Player 1\n";
player_1 = overTwentyOne(player1);
cout << player_1;
cout << "Player 2\n";
player_2 = overTwentyOne(player2);
cout << player_2;
cout << "Player 3\n";
player_3 = overTwentyOne(player3);
cout << player_3;
cout << "Player 4\n";
player_4 = overTwentyOne(player4);
cout << player_4;
}
bool overTwentyOne(std::vector<char> cards) {
int player_total = 0;
bool ace_in_play = false;
// iterate thru vector
for (int i = 0; i < cards.size(); i++) {
//check for face card
if (cards[i] == 'J'|| cards[i] == 'Q' || cards[i] == 'K') {
player_total = player_total + 10;
}
//check for ace
else if (cards[i] == 'A') {
player_total = player_total + 11;
ace_in_play = true;
}
//add number cards
else
{
player_total = player_total + cards[i];
}
}
//verifies that the player hand is NOT over 21
if (player_total <= 21) {
return false;
}
//verifies that playe hand is over 21
else if (player_total > 21) {
//makes sure that player doesnt have a ace and if not the player will be over 21
if (ace_in_play == false) {
return true;
}
//checks to see if the ace is worth 1, whether or not the player is still over 21
else if (ace_in_play == true) {
player_total -= 10;
if (player_total <= 21) {
return false;
}
else{
return true;
}
}
}
return NULL;
}
So everything inside main doesn't matter and is used for troubleshooting, when I was messing around with inputs player2 and player3 were adding up correctly. but player1 and player4 were adding up completely wrong. The function was identifying cards correctly but during the addition the numbers were getting crazy...
player1:
identifies card 1 as 11
players total now 11
identifies card 2 as 2
now players total is 61
identifies card 3 as 3
now players total is 112
player4:
identifies card 1 as 5
player total is now 53
identifies card 2 as 3
player total is now 104
identifies card 3 as 6
player total is now 158
identifies card 4 as 6
player total is now 212
identifies card 5 as 7
player total is now 267
identifies card 6 as 9
player total is now 324
it is now 3am and I can't figure this out please help lol!
also this is my first post on here so idk if I did everything correctly.
The cards are chars, not ints. You're summing the codepage of the characters '0' - '9' instead of the digits they represent. I.e.:
player_total = player_total + cards[i] - '0';
// This was missing -------------------^
Besides the error pointed out in Mureinik's answer, you may have missed a key point in the problem statement:
Create a function that takes an array of card numbers and checks if the sum of their value exceeds 21. If the sum exceeds 21, return true and if the sum is under or equal to 21, return false.
That's the only thing that function has to do, so you don't really need to try all the possible values an ace (or more than one) can have, just use 1.
You aren't asked to check if the maximum value of the cards is less than or equal to 21.
#include <numeric>
bool over_twenty_one(std::vector<char> const& cards)
{
constexpr auto sum_min_value = [](int sum, char card) -> int
{
if ( card == 'J' or card == 'Q' or card == 'K' )
{
return sum + 10;
}
if ( '1' < card and card <= '9' )
{
return sum + card - '0';
}
if ( card == 'A' )
{
return sum + 1;
}
return sum;
};
return 21 < std::accumulate(cards.cbegin(), cards.cend(), 0, sum_min_value);
}
Related
After resolving the CS50 credit problem set, my only problem is that card number 4062901840, does not pass the test. Running check50 says that after enter this number, it should print "Invalid" (which is correct, is a 10 digit number) but instead prints " ".
Already ran 20 tests using 10 digit numbers and all 20 passed the test correctly, the code is pretty simple since i tried to use only what we´ve been taught so far and don´t use arrays or other libraries. Can you point me in the right direction to know why this is happening?
The program should ask for a number, and evaluates if it meets the luhn algorithm, which is:
Multiply every other digit by 2, starting with the number’s
second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total
modulo 10 is congruent to 0), the number is valid!
After that, the program should check if the card number is amex, visa, mastercard or invalid
The conditions for every card type are:
-American Express (15 digits)
Start with 34 or 37
-Mastercard (16 digits)
Start with 51, 52, 53, 53 OR 55
Visa(13 or 16 digits)
Startt with 4
Here is my code
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long cnum, cnumClone;
int count, first, tempo, sum = 0;
do{
printf("Enter card number\n");
scanf("%ld", &cnum);
} while(cnum == 0);
// Clones card number to manipulate it through the iteration
cnumClone = cnum;
//Count every digit of the entered card number
for(count = 1; cnumClone != 0; count++)
{
//Get the last digit
tempo = cnumClone % 10;
//Remove last digit
cnumClone /= 10;
//Select digits to be multiplied
if(count % 2 == 0)
{
tempo *= 2;
//In case the product is a 2 digit number
if (tempo >=10)
{
tempo = tempo % 10;
tempo += 1;
sum += tempo;
}else{
//Add to the sum
sum += tempo;
}
}else{
//Add to the sum directly if it wasn´t a every other digit
sum += tempo;
}
}
//Last step of Luhn´s algorithm
if (sum % 10 == 0)
{
//Since count initiates on 1 for iteration purposes, take away 1
count -= 1;
// If card number length is 16 checks if it´s a mastercard or visa
if(count == 16)
{
first = cnum / 100000000000000;
if(first == 51 || first== 52 || first == 53 || first == 54 || first == 55)
{
printf("MASTERCARD\n");
}else{
first = first /10;
if(first == 4)
{
printf("VISA\n");
}else{
printf("INVALID\n");
}
}
}
// If card number length is 15 checks if it´s an amex
if(count == 15)
{
first = cnum / 10000000000000;
if(first == 34 || first == 37)
{
printf("AMEX\n");
}else{
printf("INVALID\n");
}
}
// If card number length is 15 checks if it´s a visa
if (count == 13)
{
first = cnum / 1000000000000;
if(first == 4)
{
printf("VISA\n");
}
}
}else{
//If card number has a length different than 13, 15 or 16
printf("INVALID\n");
}
}
Thanks in advance, hope i use this forum the right way.
The problem is here
}else{
//If card number has a length different than 13, 15 or 16
printf("INVALID\n");
}
What does the first } in the phrase close? Hint: it has nothing to do with the length. Suggest the length tests be if...else if...else if...else; the (new) final else outputs the INVALID message.
Before this line
}else{
//If card number has a length different than 13, 15 or 16
printf("INVALID\n");
}
Consider adding another else block, that takes care of less than 13, it works for me: like so
if (count < 13)
{
printf("INVALID\n");
}
Hope that helps
Task: This cipher shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet.
For example:
string = "Abc Def Ghi 999 -*%/&()[]"
shift(number that you entered) = 1(Can be any integer)
Program should print like this: Bcd Efg Hij -*%/&()[]
I did this with a void function but once I tried to do same thing with string function it didn't work. It just process first element of string then returns the value. For this particular situation
my program prints like "Bbc Def Ghi 999 -*%/&()[]"
Any idea to solve this problem?
#include <iostream>
#include <cmath>
using namespace std;
string Cipher(string password, int shift) {
char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };
for (int i = 0; i < password.length(); i++) {
for (int k = 0; k < 26; k++) {
int add = shift + k;
if (password[i] == Uppercase[k]) {
for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25
add -= 25;
}
password[i] = Uppercase[add]; // converting each letter
}
else if (password[i] == Lowercase[k]) {
for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25
add -= 25;
}
password[i] = Lowercase[add]; //converting each letter
}
else {
k = 25; // if element of string is different from letters, program goes to next element
}
}
}
return password;
}
int main() {
cout << "Please enter an integer different from 0 and multiples of 25: ";
string password = "Abc def ghi 999 -*%/&()[]";
int shift;
cin >> shift;
cout<< Cipher(password, shift);
system("pause>0");
}
Your encryption problem can be solved with one statement by using modern C++.
But because this is somehow advanced, I will give a detailed explanation.
Let us first think, what to do and then, how to implement.
The what:
Only alpha characters shall be converted
None alpha characters shall be output unencrypted (same as input)
In case of encryption, the case of the original letter shall be preserved for the encrypted letter. Meaning, if at position 5 was an uppcase letter, also in the encrypted string the letter in position 5 shall be uppercase
Letters shall be shifted by a specified amount.
The how:
We will first check, it the original letter is an alpha-letter by using the isalpha-function.
So, for the case that it is an alpha letter, we will check, if the letter is in uppercase or in lowercase. Actually, we check only, if it is a uppercase letter.
Because if it is not, then it must be a lowercase letter (because it was definitely a letter, what we did check before, and, if it is not upper, then it is lower case). For this check, we use the isupper-function.
We will then do the shift action. And convert back to a letter, taken the case into account.
We assume ASCII. If we to convert an ASCII letter/character into a 0 based index, we need to do the following:
If we look in the ASCII table, then we see, that and 'A' is equivalent to 65 and so forth. So, to get the 0-based index, we subtract 65 from the letter. Then we have an index value between 0 and 25.
Then we add the shift value. There could of course be an overflow. But, this can be simply corrected by a modulo 26 division.
So: 26->0, 27->1, 28->2 and so on. Rather simple. But, because we want to have later a letter again, we will add 65 to this result.
For lowercase letters, we will do nearly the same, but use 97 for the offset to letter 'a'.
Then, we can put verything in one expresion by using the ternary or conditional-operator.
std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c
This is a short for
// Check if letter/character is alpha
if (std::isalpha(c)) {
// Now check for upper or lower case
if (std::isupper(c)) {
// The character is uppercase
c = (c - 65 + shift) % 26 + 65;
}
else {
// The character is lower case
c = (c - 97 + shift) % 26 + 97;
}
}
else {
// The character is not alpha
}
Same as the one liner, no difference
So, first, check for alpha. If true, check for uppercase, if true, do the conversion for uppcase letter, else for lower case letters. If it was no alpha letter, then leave it unchanged.
All this we will then embed as a Lambda-expresion in a std::transform-statement. Please see here for a description.
The result will be one statement only, for the whole conversion process:
std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
{return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });
At the end, we build a small driver program for demo purposes:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
// Our password
std::string password = "Abc def ghi 999 -*%/&()[]";
// Give instruction to the user
std::cout << "\nPlease enter a postive integer: ";
// Get number of shifts from user and check, if the value could be read
if (int shift{}; std::cin >> shift && shift > 0) {
// Now do the encryption
std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
{return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });
// Show the result to the user
std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
}
else std::cerr << "\n\n*** Error: Problem with input!\n\n";
return 0;
}
And, since the one liner is maybe too advanced, let's use the explicit and more verbose code. Just to be complete:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
// Our password
std::string password = "Abc def ghi 999 -*%/&()[]";
// Give instruction to the user
std::cout << "\nPlease enter a postive integer: ";
// Get number of shifts from user and check, if the value could be read
if (int shift{}; std::cin >> shift && shift > 0) {
// --------------Can be written in one statement -----------------------
for (char& c : password) {
// Check if letter/character is alpha
if (std::isalpha(c)) {
// Now check for upper or lower case
if (std::isupper(c)) {
// The character is uppercase
c = (c - 65 + shift) % 26 + 65;
}
else {
// The character is lower case
c = (c - 97 + shift) % 26 + 97;
}
}
else {
// The character is not alpha
}
// ------------------------------------------------------------------
}
// Show the result to the user
std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
}
else std::cerr << "\n\n*** Error: Problem with input!\n\n";
return 0;
}
Within your k loop you determine the index of the letter in the alphabet. However, when e.g. i=1 then password[1] represents the letter 'b'. Now, starting the k-loop from k==0 where Uppercase[0] and Lowercase[0] represent 'A' and 'a', respectively, you directly end up in the else condition and your k-loop terminates without doing anything (you set k=25 and increment it). Here is a fixed version (note that I also use the modulo operator % to make sure that 0 < add < 26:
#include <iostream>
#include <cmath>
using namespace std;
string Cipher(string password, int shift) {
char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };
for (int i = 0; i < password.length(); i++) {
for (int k = 0; k < 26; k++) {
int add = (shift + k)%26;
if (password[i] == Uppercase[k]) {
password[i] = Uppercase[add]; // converting each letter
break;
}
else if (password[i] == Lowercase[k]) {
password[i] = Lowercase[add]; //converting each letter
break;
}
}
}
return password;
}
int main() {
cout << "Please enter an integer different from 0 and multiples of 25: ";
string password = "Abc def ghi 999 -*%/&()[]";
int shift;
cin >> shift;
cout<< Cipher(password, shift);
system("pause>0");
}
I am trying to solve a problem here. I have two arrays which needs to be added and produce a desired output. {'A','A','A','B','A','X','M'} and {'A', 'B', 'A', 'A', 'B', 'A', 'B', 'B'}. Value of A is 10 and B is 20.
If A or B are repeated consecutively then the bonus numbers are added which is 10. I need to get an output of total score of 90 for first and 140 for second. How Can I write the perfect code.
My Code here is as below: The output should be 90 for the first array and 140 for a second. X and M have 0 value. SO don't mind them.
Here First character in array is A so score is 10
Second is also A so now 10 for A and as the previous was A so 10+10 = 20
Now as third one is also A add another 10 to previous score as 10 + 20(as last two were two as well ) ie. 30
Now fourth element in array is B so its not A and Streak is Broken so add Score For B which is set as 20
For Fifth Element we have A but as previous was Blue so no streak bonus and score of A was reset so add 10 now
Add 0 for X and M element
hence total score is 10+20+30+20+10 = 90
#include <iostream>
int main()
{
int currentEScore = 0;
int TotalScore = 0;
char Box[] = { 'A', 'A', 'A', 'B', 'A', 'X', 'M' };
// A B A R A R A A
for (int i = 0; i < Box[i]; i++) {
if (Box[i] == 'A') {
currentEScore = 10;
if (Box[i - 1] == Box[i]) {
currentEScore += 10;
TotalScore = TotalScore + currentEScore;
}
else {
TotalScore = TotalScore + currentEScore;
}
}
else if (Box[i] == 'B') {
currentEScore = 20;
if (Box[i - 1] == Box[i]) {
currentEScore += 10;
TotalScore = TotalScore + currentEScore;
}
else {
TotalScore = TotalScore + currentEScore;
}
}
else {
currentEScore = 0;
}
}
std::cout << TotalScore;
}
First things first: You are accessing the array out-of-bounds in the first iteration (if (Box[i - 1] == Box[i])). That is undefined behavior and strictly speaking all your code is meaningless, because a compiler is not mandated to do anything meaningful with invalid code. It just happens that this does not affect the outcome of your code. This is the worst incarnation of undefined behavior: It appears to work. You need to fix that.
Next, your loop reads for (int i = 0; i < Box[i]; i++) { and the condition cannot be correct. Again this makes your loop access the array out-of-bounds. I am a bit puzzled how this worked (I didnt realize it myself first). This also has to be fixed! I suggest to use a std::string for character arrays. It is much less error prone and it has a size() method to get its size.
The above issues didn't affect the output (nevertheless they have to be fixed!), so now lets look at the logic of your code. But first a disclaimer: Really the best advice I can give you is to not continue reading this answer. The problem you are facing is a good opportunity to learn how to use a debugger. That is a skill you will need always. If you still decide to read the following, then at least you should try to forget everything this answers says and go trough the same process on your own, by either using a debugger or a piece of paper and a pen.
Lets go step by step in your first example { 'A', 'A', 'A', 'B', 'A', 'X', 'M' }
first character is A
if (Box[i] == 'A') -> condition is true
currentEScore = 10; -> currentEScoe == 10
(we ignore the out-of-bounds for a moment)
TotalScore = TotalScore + currentEScore; -> TotalScore == 10
next character is A
if (Box[i] == 'A') -> condition is true
currentEScore = 10; -> currentEScore == 10
if (Box[i - 1] == Box[i]) -> yes
currentEScore += 10; -> currentEScore == 20
TotalScore = TotalScore + currentEScore; -> TotalScore == 10+20 == 30
next character is A
if (Box[i] == 'A') -> condition is true
currentEScore = 10; -> currentEScore == 10 -> stop... this is wrong !
You are resetting the bonus score on each character and then only check for the previous one. The effect is that you never give bonus more than 20.
Solution: Fix the out-of-bounds access and only reset the bonus when the character is different from the last. Also the code can be simplified a bit, by realizing that the bonus is indepenent from whether the character is A or B. You only have to check if it is the same as the last, hence calculating the bonus and adding points for A and B can be done seperately:
#include <iostream>
#include <string>
int main()
{
int bonus_increment = 10;
int bonus = 0;
int score_A = 10;
int score_B = 20;
int TotalScore = 0;
std::string Box{"AAABAXM"};
for (size_t i = 0; i < Box.size(); i++) {
// determine bonus
if ( i > 0 && Box[i] == Box[i-1] ) {
bonus += bonus_increment;
} else {
bonus = 0;
}
// accumulate score
if (Box[i] == 'A') {
TotalScore += score_A + bonus;
} else if (Box[i] == 'B') {
TotalScore += score_B + bonus;
}
}
std::cout << TotalScore;
}
Don't forget what I said above. You waste this exercise if you simply copy this code and assume that you completed the exercise by doing so.
Here's I have made some changes with your code with minimal optimization.
It'll work for you. Please check it and let me know it's working or not.
#include <iostream>
int main()
{
int currentEScore = 0;
int TotalScore = 0;
char Box[] = {'A','A','A','B','A','X','M'};
// A B A R A R A A
for (int i = 0; i < Box[i]; i++) {
if (Box[i] == 'A') {
if (Box[i - 1] == Box[i]) {
currentEScore += 10;
}
else {
currentEScore = 10;
}
}
else if (Box[i] == 'B') {
if (Box[i - 1] == Box[i]) {
currentEScore += 10;
}
else {
currentEScore = 20;
}
}
else {
currentEScore = 0;
}
TotalScore = TotalScore + currentEScore;
}
std::cout << TotalScore;
}
So let's say we have the following case: for ”12323465723” possible answers would be ”abcbcdfegbc” (1 2 3 2 3 4 6 5 7 2 3), ”awwdfegw” (1 23 23 4 6 5 7 23), ”lcwdefgw” (12 3 23 4 6 5 7 23), in this case, the user will input numbers from 1 to 26, not divided by any space and the program itself will suggest 3 ways of interpreting the numbers, getting the most of the combinations from 1 to 26 these being the values from a to z
As you can see this is edited, as this is the last part of the problem, Thank you all who have helped me this far, I've managed to solve half of my problem, only the above mentioned one is left.
SOLVED -> Thank you
This involves a decision between 0 to 2 outcomes at each step. The base cases are there are no more characters or none of them can be used. In the latter case, we backtrack to output the entire tree. We store the word in memory like dynamic programming. This naturally leads to a recursive algorithm.
#include <stdlib.h> /* EXIT */
#include <stdio.h> /* (f)printf */
#include <errno.h> /* errno */
#include <string.h> /* strlen */
static char word[2000];
static size_t count;
static void recurse(const char *const str) {
/* Base case when it hits the end of the string. */
if(*str == '\0') { printf("%.*s\n", (int)count, word); return; }
/* Bad input. */
if(*str < '0' || *str > '9') { errno = ERANGE; return; }
/* Zero is not a valid start; backtrack without output. */
if(*str == '0') return;
/* Recurse with one digit. */
word[count++] = *str - '0' + 'a' - 1;
recurse(str + 1);
count--;
/* Maybe recurse with two digits. */
if((*str != '1' && *str != '2')
|| (*str == '1' && (str[1] < '0' || str[1] > '9'))
|| (*str == '2' && (str[1] < '0' || str[1] > '6'))) return;
word[count++] = (str[0] - '0') * 10 + str[1] - '0' + 'a' - 1;
recurse(str + 2);
count--;
}
int main(int argc, char **argv) {
if(argc != 2)
return fprintf(stderr, "Usage: a.out <number>\n"), EXIT_FAILURE;
if(strlen(argv[1]) > sizeof word)
return fprintf(stderr, "Too long.\n"), EXIT_FAILURE;
recurse(argv[1]);
return errno ? (perror("numbers"), EXIT_FAILURE) : EXIT_SUCCESS;
}
When run on your original input, ./a.out 12323465723, it gives,
abcbcdfegbc
abcbcdfegw
abcwdfegbc
abcwdfegw
awbcdfegbc
awbcdfegw
awwdfegbc
awwdfegw
lcbcdfegbc
lcbcdfegw
lcwdfegbc
lcwdfegw
(I think you have made a transposition in lcwdefgw.)
According to ASCII table we know that from 65 to 90 it A to Z.
so below is the simple logic to achieve what you're trying.
int main(){
int n;
cin>>n;
n=n+64;
char a=(char) n;
if (a>=64 && a<=90)
cout<<a;
else cout<<"Error";
return 0;
}
If you want to count the occurencs of "ab" then this will do it:
int main()
{
char line[150];
int grup = 0;
cout << "Enter a line of string: ";
cin.getline(line, 150);
for (int i = 0; line[i] != '\0'; ++i)
{
if (line[i] == 'a' && line[i+1] == 'b')
{
++grup;
}
}
cout << "Occurences of ab: " << grup << endl;
return 0;
}
If you want to convert an int to an ASCII-value you can do that using this code:
// Output ASCII-values
int nr;
do {
cout << "\nEnter a number: ";
cin >> nr;
nr += 96; // + 96 because the ASCII-values of lower case letters start after 96
cout << (char) nr;
} while (nr > 96 && nr < 123);
Here I use the C style of casting values to keep things simple.
Also bear in mind ASCII-values: ASCII Table
Hope this helps.
This could be an interesting problem and you probably tagged it wrong, There's nothing specific to C++ here, but more on algorithm.
First of all the "decode" method that you described from numerical to alphabetical strings is ambiguious. Eg., 135 could be interpreted as either "ace" or "me". Is this simply an oversight or the intended question?
Suppose the ambiguity is just an oversight, and the user will enter numbers properly separated by say a white space (eg., either "1 3 5" or "13 5"). Let nstr be the numerical string, astr be the alphabetical string to count, then you would
Set i=0, cnt=0.
Read the next integer k from nstr (like in this answer).
Decode k into character ch
If ch == astr[i], increment i
If i == astr.length(), set i=0 and increment cnt
Repeat from 2 until reaching the end of nstr.
On the other hand, suppose the ambiguous decode is intended (the numerical string is supposed to have multiple ways to be decoded), further clarification is needed in order to write a solution. For example, how many k's are there in "1111"? Is it 1 or 2, given "1111" can be decoded either as aka or kk, or maybe even 3, if the counting of k doesn't care about how the entire "1111" is decoded?
I'm trying to write a c++ program that reads input from a text file and assigns grades using a ten point grading scale then prints the results onscreen.
I think my issue may be with the if else statements in the function deriveGrade, rather than incrementing the enum, they seem to be suming up the increments. Any help would be appreciated, thanks.
#include <iostream>
#include <string>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
int deriveGrade(double avarage);
enum letter_grade { A, B, C, D, F };
namespace tenPoint
{
letter_grade deriveGrade(double avarage);
char grade;
}
using namespace tenPoint;
int main()
{
string name;
double average;
ifstream inData; // Is the variable for input data from the file.
inData.open("student_status.txt", ios::in);
while (!inData.eof())
{
getline(inData, name);
inData >> average;
inData.ignore();
grade = ::deriveGrade(average);
cout << name << " " << average << " " << char(grade) << endl;
}
inData.close();
return 0;
}
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70 && average < 80)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60 && average < 70)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else
{
cout << "Invalid entry." << endl;
}
return grade;
}
Input from file:
Doe, John K.
93.2
Andrews, Susan S.
84.7
Monroe, Marylin
75.1
Gaston, Arthur C.
62.8
Harpo, Joanie Y.
42.7
Ginger, Fred T.
95.8
Program output:
Doe, John K. 93.2 A
Andrews, Susan S. 84.7 B
Monroe, Marylin 75.1 D
Gaston, Arthur C. 62.8 G
Harpo, Joanie Y. 42.7 K
Ginger, Fred T. 95.8 î
Press any key to continue . . .
Logic of your program is quite strange, but some common remarks can be given without deepening into your task.
Pay attention, that while you use if... else statements one by one like
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80 && average < 90)
{
grade = static_cast<letter_grade>(grade + 1);
}
...
there is no need to check average < 90 in the else branch after average >= 90 found false. So at least code can be shorter:
int deriveGrade(double average)
{
if (average >= 90)
{
grade = static_cast<letter_grade>(grade + 65);
}
else if (average >= 80)
{
grade = static_cast<letter_grade>(grade + 1);
}
else if (average >= 70)
{
grade = static_cast<letter_grade>(grade + 2);
}
else if (average >= 60)
{
grade = static_cast<letter_grade>(grade + 3);
}
else if (average <= 50)
{
grade = static_cast<letter_grade>(grade + 4);
}
else // check here! Invalid interval is for values between 50 and 60?
{
cout << "Invalid entry." << endl;
}
return grade;
}
But this is not significant improvement.... much better to make a formula and use single statement with assignment to grade = ...
UPDATE:
And one more comment. If you know the interval of unacceptable values, check it first (before all other calculations):
int deriveGrade(double average)
{
// check the correctness of argument first
if (average > 50 && average < 60)
{
cout << "Invalid entry." << endl; // notification
return grade; // previous value
// also consider returning special value for error case
}
// calculate value for grade
grade = ...
// return updated value
return grade;
}
section "calculate value for grade" is for you, and while writing this part of code keep in mind that:
ternary operation operation is useful for one special case, e.g. grade = (average >= 90)? 65 : floor(100 - average) / 10;
using global values (like grade) in a function is bad practice as well as making logic based on the assumption that initial value of global variable is correct
The reason is because you are adding to your grade variable without clearing it, so the result of previous operations are carried over in deriveGrade.
My advice is to remove the global char grade; in your namespace, use a local variable in your deriveGrade, and a different local variable in your main.
If you look at your function code, grade will only have 65 added to it (to make an ASCII 'A') if your grade is above 90. Every subsequent addition however, pretends that this addition has happened. If you instead make sure that each else if does not rely on previous if or else if code, then your code should be more correct.
char deriveGrade( double average )
if( average > 90.0 )
{
return 'A';
}
else if( average > 80.0 )
{
return 'B';
}
...
This solution removes even the need to use a grade variable in your deriveGrade
An even better alternative that uses the enum you so nicely created is:
enum letter_grade : char
{
A = 'A', B = 'B', C = 'C', D = 'D', F = 'F'
};
Which allows you through a (char)letter_grade to swap between the enum representation and a char (your deriveGrade would then return a letter_grade instead).