Comparing a string of quiz answers to questions - c++

I have a C++ test question that asks us to write a program that:
1) asks the user to input a string of answers a,b,c, and d: (Example: ACDBDA)
2) asks he user to input a string that is the answer key: (example DBADCD) (we also need to put in something to make sure the length of the answer key is the same as the answers, but that is no biggie)
3) prints the percentage of input answers that were correct, ie match up with the answer key.
Most of this isn't too bad, but I'm not sure how to go about comparing the two strings to see how they differ. Is there any way to get a variable equal to one of the characters in the string which could then be compared with a variable representing the character in the same place as the other string? That's the only way that comes to mind for me. I'm not really looking for a specific code or someone to do it for me, just need some pointers in the right direction.
Thanks!
Ok, so I've made some progress on this and I think I am close. The problem now is that I'm getting "Expression must be of class type" error on the commented lines. I think the issue is in the way I am passing my parameters but I can't seem to figure out how to fix it :(. I've google'd several parameter passing articles but none seem to speak to passing a parameter then getting it's length or comparing it as I do in the program. Any help would be greatly appreciated. Here is the code:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
string getAnswers(string answers)
{
cout << "What are your answers to this questionless quiz? BE WARY OF CHOOSING INCORRECTLY\n:";
cin >> answers;
return answers;
}
string getKey(string key)
{
cout << "Just kidding. What are the answers? \n:";
cin >> key;
return key;
}
double getPercentage(double percentage)
{
int total;
int correct;
getAnswers();
getKey();
total = getAnswers.size(); // "error: expression must have class type"
for (i=0; i>total; i++)
{
int j = 0;
if (getAnswers.at(j) = getKey.at(j)) // "error: expression must have class type" (for both getAnswers and getKey)
correct++;
j++;
}
percentage = (correct/total) * 100;
}
int main()
{
getAnswers();
getKey();
cout << getPercentage(answers, key); //Also I'm really not sure how to get the parameters from previous functions into this one here. Maybe I shoudln't even add parameters and just show the function?
return 0;
}

Related

Code for decrypting simple sentences made with CodeBlocks crashes without outputting a single character [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am making a program that inputs the alphabetical order for encrypting a sentence to decrypt it (just replacing characters). I am required to input the number of words it has, but the method I'm using doesn't need that so I just input it and do nothing with it (it doesn't matter because an AI will be verifying only the output of the program). I think I came up with a decent algorithm, but the program keeps crashing after I enter the encrypted sentence. I tried changing a lot of things but nothing seems to solve the issue. Also, I'm sorry for any things that don't make sense in the code, I'm just a beginner. Please help me stop the program from crashing so I can submit it before the end of tomorrow.
This is my code
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n, i, j;
string key, encrypted;
cin >> key;
char alphabet[]={'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'};
cin >> n;
getline(cin>>ws, encrypted);
for (i=0;i<=encrypted.size();i++)
{
for (j=0;j<encrypted.size();j++)
{
if (encrypted[i]==key[j])
{
cout << alphabet[j];
}
else if (encrypted[i]==key[j]+32)
{
cout << alphabet[j]+32;
}
else if (encrypted[i]==' ')
{
cout << " ";
}
}
}
}
Your program has the following bugs:
First bug:
As already pointed out in the comments section, you should change the line
for (j=0;j<encrypted.size();j++)
to
for (j=0;j<key.size();j++)
Second bug:
Due to integer promotion, the expression alphabet[j]+32; will evaluate to a value of type int, not char. This means that
cout << alphabet[j]+32;
will print a number, not a character. Therefore, you must cast the result of the expression back to the data type char, like this:
cout << static_cast<char>( alphabet[j]+32 );
Third bug:
The line
cout << " ";
should only be called once per outer loop iteration, i.e. once per character in the string encrypted. However, you are calling it once per inner loop iteration, which means you are calling it several times per character. Therefore, you should remove that statement from the inner loop and put it into the outer loop.
Fourth bug:
The line
for (i=0;i<=encrypted.size();i++)
is wrong. It should be < instead of <=. Otherwise, you will also process the terminating null character of the string, which is not meaningful.

Trying to ignore all whitespace up to the first character (desperately needing a simple nudge)

I'll be flat out honest, this is a small snippet of code I need to finish my homework assignment. I know the community is very suspicious of helping students, but I've been racking my head against the wall for the past 5 hours and literally have accomplished nothing on this assignment. I've never asked for help on any assignments, but none have given me this much trouble.
All I'm having trouble with is getting the program to strip the leading whitespace out. I think I can handle the rest. I'm not asking for a solution to my overall assignment, just a nudge on this one particular section.
I'll post the full assignment text here, but I am NOT posting it to try to get a full solution, I'm only posting it so others can see the conditions I have to work with.
"This homework will give you more practice in writing functions and also how numbers are read into a variable. You need to write a function that will read an unsigned integer into a variable of type unsigned short int. This will have a maximum value of 65535, and the function needs to take care of illegal numbers. You can not use "cin >>", inside the function.
The rules for numeric input are basically as follows:
1) skip all leading white spaces
2) first character found must be numeric else an error will occur
3) numeric characters are then processed one at a time and combine with number
4) processing stops when non-numeric found
We will follow these rules and also add error handling and overflow. If an illegal entry is made before a numeric than an error code of "1" will be sent back, if overflow occurs, that is number bigger then 65535, then error code of "2" will be sent back. If no error then "0" is sent back.
Make sure the main function will continue to loop until the user enters a “n” or “N” for NO, the main should test the error code returned from the function called “ReadInt” and display appropriate error messages or display the number if there is no error. Take care in designing the “ReadInt” function, it should be value returning and have a reference parameter. The function needs to process one character at a time from the input buffer and deal with it in a correct fashion. Once the number has been read in, then make sure the input buffer is empty, otherwise the loop in main may not work correct. I know this is not how the extraction works, but lets do it this way.
You do not need to turn in an algorithm with this assignment, but I would advise you to write one. And the debugger may prove helpful as well. You are basically rewriting the extraction operator as it works on integers."
A majority of my code won't make sense as I've been deleting things and adding things like crazy to try everything I can think of.
#include <iostream>
#include <CTYPE.h>
using namespace std;
int ReadInt (unsigned short int &UserIn);
int main()
{
int Error;
unsigned short int UserInput;
char RepeatProgram;
do
{
Error=ReadInt(UserInput);
if (Error==0)
cout << "Number is " << UserInput << endl;
else if (Error==1)
cout << "Illegal Data Entry\n";
else if (Error==2)
cout << "Numerical overflow, number too big\n";
cout << "Continue? n/N to quit: ";
cin >> RepeatProgram;
cout << endl;
} while (RepeatProgram!='N' && RepeatProgram!='n');
}
int ReadInt (unsigned short int &UserIn)
{
int Err=0;
char TemporaryStorage;
long int FinalNumber=0;
cout << "Enter a number: ";
//cin.ignore(1000, !' '); this didn't work
cin.get(TemporaryStorage);
cout << TemporaryStorage;//I'm only displaying this while I test my ideas to see if they are working or not, before I move onto the the next step
cout << endl;
return Err;
}
I really appreciate any help I may get and hope I don't give the impression that I'm looking for a full free solution to the whole problem. I want to do this on my own, I'm just lot on this beginning.
As a preface, I want to state that this is a question made by a student, but unlike most of their type, it is a quality question that merits a quality answer, so I'll try to do it ;). I won't try to just answer your concrete question, but also to show you other slight problems in your code.
First of all, let's analyze your code step by step. More or less like what a debugger would do. Take your time to read this carefully ;)...
#include <iostream>
#include <CTYPE.h>
Includes headers <iostream> and <ctype.h> (the uppercase works because of some flaws/design-decisions of NTFS in Windows). I'ld recommend you to change the second line to #include <cctype> instead.
using namespace std;
This is okay for any beginner/student, but don't get an habit of it! For the purposes of "purity", I would explicitly use std:: along this answer, as if this line didn't existed.
int ReadInt (unsigned short int &UserIn);
Declares a function ReadInt that takes a reference UserIn to type unsigned short int and returns an object of type int.
int main()
{
Special function main; no parameters, returns int. Begin function.
int Error;
unsigned short int UserInput;
char RepeatProgram;
Declares variables Error, UserInput, and RepeatProgram with respective types int, unsigned short int, and char.
do
{
Do-while block. Begin.
Error=ReadInt(UserInput);
Assign return value of ReadInt of type int called with argument UserInput of type int& to variable Error of type unsigned short int.
if (Error==0)
std::cout << "Number is " << UserInput << endl;
If Error is zero, then print out UserInput to standard output.
else if (Error==1)
std::cout << "Illegal Data Entry\n";
else if (Error==2)
std::cout << "Numerical overflow, number too big\n";
Otherwise, if an error occurs, report it to the user by means of std::cout.
std::cout << "Continue? n/N to quit: ";
std::cin >> RepeatProgram;
Query the user if he/she wants to continue or quit. Store the input character in RepeatProgram of type char.
std::cout << std::endl;
Redundant, unless you want to add padding, which is probably your purpose. Actually, you're better off doing std::cout << '\n', but that doesn't matters too much.
} while (RepeatProgram!='N' && RepeatProgram!='n');
Matching expression for the do-while block above. Repeat execution of the given block if RepeatProgram is neither lower- or uppercase- letter N.
}
End function main. Implicit return value is zero.
int ReadInt (unsigned short int &UserIn)
{
Function ReadInt takes a reference UserIn to unsigned short int and returns an object of type int. Begin function.
int Err=0;
char TemporaryStorage;
long int FinalNumber=0;
Declares variables Err, TemporaryStorage, and FinalNumber of respective types int, char, and long int. Variables Err and FinalNumber are initialized to 0 and 0, respectively. But, just a single thing. Didn't the assignment said that the output number be stored in a unsigned short int? So, better of this...
unsigned short int FinalNumber = 0;
Now...
std::cout << "Enter a number: ";
//std::cin.ignore(1000, !' '); this didn't work
Eh? What's this supposed to be? (Error: Aborting debugger because this makes no logic!**). I'm expecting that you just forgot the // before the comment, right? Now, what do you expect !' ' to evaluate to other than '\0'? istream::ignore(n, ch)will discard characters from the input stream until either n characters have been discarded, ch is found, or the End-Of-File is reached.
A better approach would be...
do
std::cin.get(TemporaryStorage);
while(std::isspace(TemporyStorage));
Now...
std::cin.get(TemporaryStorage);
This line can be discarded with the above approach ;).
Right. Now, where getting into the part where you obviously banged your head against all solid objects known to mankind. Let me help you a bit there. We have this situation. With the above code, TemporaryStorage will hold the first character that is not whitespace after the do-while loop. So, we have three things left. First of all, check that at least one digit is in the input, otherwise return an error. Now, while the input is made up of digits, translate characters into integers, and multiply then add to get the actual integer. Finally, and this is the most... ahem... strange part, we need to avoid any overflows.
if (!std::isdigit(TemporaryStorage)) {
Err = 1;
return Err;
}
while (std::isdigit(TemporaryStorage)) {
unsigned short int OverflowChecker = FinalNumber;
FinalNumber *= 10; // Make slot for another digit
FinalNumber += TemporaryStorage - '0'; '0' - '0' = 0, '1' - '0' = 1...
// If an unsigned overflows, it'll "wrap-around" to zero. We exploit that to detect any possible overflow
if (FinalNumber > 65535 || OverflowChecker > FinalNumber) {
Err = 2;
return Err;
}
std::cin.get(TemporaryStorage);
}
// We've got the number, yay!
UserIn = FinalNumber;
The code is self-explanatory. Please comment if you have any doubts with it.
std::cout << TemporaryStorage;//I'm only displaying this while I test my ideas to see if they are working or not, before I move onto the the next step
cout << endl;
return Err;
Should I say something here? Anyway, I already did. Just remember to take that std::couts out before showing your work ;).
}
End function ReadInt.
You can skip leading whitespace from a stream using std::ws. For example:
std::cin >> std::ws;
This use of >> just invokes the manipulator std::ws on the stream. To meet the teacher's requirements you can invoke it directly:
std::ws(std::cin);
Formatted input automatically skips whitespace. Note that should also always check whether input was successful:
if (std::cin.get(TemporaryStorage)) {
...
}

Read from file up to another point C++

So I have a list
{"ID":"55e5f0c8ace3e","nombre":"Jacqueline ","apellido":"Charlet ","sobrenombre":"","edad":"30","caracteristicas":"","comentario":"",
I need to change that list and put it in a correct way like:
ID: 55e5f0c8ace3e
Nombre: Jacqueline
Apellido: ...
etc..
Tried this:
#include <iostream>
#include <fstream>
using namespace std;
ifstream datos("datos.txt");
ofstream final("final.txt");
int main(){
char valor;
if(!datos)
{
cout << "error";
}
else
{
while(!datos.eof())
{
datos.get(valor);
if(valor == 'I' && datos.peek() == 'D')
{
cout << "I can read" << endl;
}
}
}
}
I´m trying to do this with C++, which is the correct way to do it? I´ve tried some ways, but i dont know how to read from one point to another, by this i mean read from the double comas the ID and finish on the other double comas.
Thanks in advance
Introduce a integer state variable that describes what part of file you're in. Then interpret every character in accordance with that. For example, initially it's 0. Once you encounter a ", it becomes 1 - that means you're reading a name. If state is 1, and a character is not a "", you accumulate characters in some string variable. Once you encounter a quote character and state is 1, that means the name is over. And so on.
If this is not homework, Google for a C++ JSON parser. This is a stock problem, solved a thousand times already.
Also, please don't edit the answer - place a comment instead.

how to insert a word and use it to make comparison in if condition in c++

i want to use the word i insert to use it to make comparison in if condition to show some word it the comparison is true.
here is my code
#include <iostream>
using namespace std;
int main()
{
char u[5];
cout<<" p " <<" c "<<" U "<<endl;
cout<<" pepsi=5"<<" coca=3"<<" 7-UP=2"<<endl;
cout<<"CHOOSE your drink"<<endl;
cin>>u;
if (u=="pepsi")
cout<<"your choice is pepsi and ur bill is 5 ";
}
First in the future I would suggest trying to be more specific on what your problem is and what you don't understand. Just saying I want to do X and here is my code is giving us very little to work with and we are basically just guessing on what you are having problems with.
Now on to what I believe you are having problems with (I am assuming since you didn't tell us what is going wrong).
In this case you are using a character array with a length of 5. Now when you use character arrays you need to take into account that all the reasonable inputs that that variable might store will actually fit into that character array.
Let's look at pepsi. You might think it would fit but in fact it doesn't because you are forgetting about the null character that is added on the end. This is what it looks like.
u[0] = 'p'
u[1] = 'e'
u[2] = 'p'
u[3] = 's'
u[4] = 'i'
u[5] = '\0'
So as you can see there is actually 6 characters in this word which will cause a overflow. I am assuming this is your problem.
Now how do we fix this? As others have said in the comments if you are using C++ it is probably better for you to use std::string for this problem since it will hide from you most of the problems you have to do deal with when using C style string (What you are using now). Then once you feel more comfortable with the language you can come back and revisit C style strings.
With std::string it would look something like this. Remember that when testing strings case matters (IE "string" is not the same as "String").
std::string choice;
std::cin >> choice;
if (choice == "pepsi")
{
std::cout << "You selected pepsi!" << std::endl;
}
Hope that helps a little and fixes your problems.

Validating a string to be all digits

Hi I'm having trouble validating this string to be all decimals, even if I type in 9999 it still tell me my if statement comes out false. I think it's a typo but I don't know where.
cout<<"Enter a very large number"<<endl;
cin>>In1; //inputs a string
for(int i=0; 0<In1.length();i++){ //the loop that goes thru each index
if (!(isdigit(In1[i]))){ //validates each index
//tells the user to try again
cout<<"You did not enter a valid input, please try again"<<endl;
In1="";
cin>>In1;
i=0;//starts the loop over if reached
}
}
I keep receiving the "You did not enter a valid input, please try again" regardless of whether I type it right or wrong.
for(int i=0; 0<In1.length();i++){
See what you did? Change to
for(int i=0; i<In1.length();i++)
In your loop condition you need to compare i with In1.length().
You might want to change
0<In1.length()
to
i<In1.length()
Using
#include<algorithm>
if ( std::find_not_if( in1.begin(), in1.end(), isdigit ) != in1.end() ){ ...
might have prevented this unfortunate incident, and is also quite clear on the intent. The dual _not/!= muddles it slightly but still.
There are quite a few convenience algorithms, replacing common uses for simple for- statements. Most of them are on the form
do_this( where_to_start, where_to_end, do_this_operation )
There is usually nothing special or dramatic with these function, they apply the operation to each element in the start-end sequence.
You have find, count, copy, and generate to mention a few. Their purpose is to clarify the intent of your for-statement. You can find a complete list at http://en.cppreference.com/w/cpp/algorithm
You will almost certainly find that, over time, you become more adept at seperating different parts of code into the functionality that they each provide. Making debugging and later modification considerably easier.
It also makes, as Captain Giraffe points out, the intent of the code considerably more clear - something that can only make reading the code easier & quicker.
I've not used std::find_not_if, opting instead to use the method that you've chosen (based on the assumption that the important thing is knowing how to get the right answer, as opposed to simply supplying the right answer - well, that and me not knowing of find_not_if's existence :grin:) You'll see that I've chucked it into it's own function, which I call from main. The function also only performs a single task - that of checking the validity of the string. Any attempt to prompt the user for this text, re-prompt in the case of error and finally, take action on the correct input is the sole responsibility of the code that calls isValidNumericalString - there's no reason you couldn't throw those functions into their own functions, as opposed to having a single, large body of main.
#include <iostream>
using namespace std;
// returns true if all characters in string are numerical (0-9)
bool isValidNumericalString(string inputString)
{
int i, n = inputString.length();
for (i=0; i<n; i++)
if ( !isdigit(inputString[i]) )
return false;
return true;
}
int main()
{
string In1;
cout << "Enter a very large number (digits 0-9 only. 10e1 is unacceptable): ";
cin >> In1;
while (!isValidNumericalString(In1))
{
cout << "You did not enter a valid input, please try again :p" << endl;
cout << "Enter a very large number (digits 0-9 only. 10e1 is unacceptable): ";
cin >> In1;
}
cout << "Congratulations - '" << In1 << "' is a valid string representation of a number" << endl;
return 0;
}