C++ converting character in vector to an integer...tough, need help? - c++

This is what I have:
char userInput;
int position;
vector<string> userVector(7);
vector<int> someVector(7,1);
cin >> userInput;
cin >> position;
if(userInput == 'X')
userVector[position] = '1';
if(userVector[position]-someVector[position] == 0)
cout << "Success"
My problem is that userVector[position] is actually a character, because userVector is a string vector. However, I need this calculation to take place (userVector[position] - someVector[position]) because I need to determine if the outcome is 0 or some other number. Any help?
In case it doesn't make sense here, userVector HAS to be a string vector, because it's part of the requirements for this program. Basically, a user is supposed to be allowed to enter an "X" anywhere in the userVector vector, and you have to tell them if it matches expected outputs.
So, in this case, the "expected output" would be someVector, which has a 1 in all of it's spaces. What I'm trying to do is subtract the two vectors so that if the user enters anything other than X, the vector subtraction will not equal 0, and consequently, result in the program doing something different.
Hope that clears things up!

If I understand correctly your code, you are trying to convert a string representing a decimal number into an integer. You have several ways of doing that; e.g., by using istringstream:
int num;
if (!(istringstream(userInput[position]) >> num))
num = 0;
if (n - someVector[position] == 0) {
...
or you could use good old atoi:
if (atoi(userInput[position].c_str()) - someVector[position] == 0) {
If I am wrong about what you are trying to do, please clarify what you are trying to do...

I can't figure out what you're trying to do from your statement of the
problem. The expression userInput[position] isn't legal, since
userInput isn't a pointer, nor anything that can be converted to a
pointer.
But your code doesn't seem to correspond to the textual description,
since you describe userInput as a string vector
(std::vector<std::string>?), but the code declares it as a char.

Related

Why does getline behave weirdly after 3 newlines?

I'll preface this by saying I'm relatively new to posting questions, as well as C++ in general, my title is a little lame as it doesn't really specifically address the problem I am dealing with, however I couldn't really think of another way to word it, so any suggestions on improving the title is appreciated.
I am working on a relatively simple function which is supposed to get a string using getline, and read the spaces and/or newlines in the string so that it can output how many words have been entered. After reaching the character 'q' it's basically supposed to stop reading in characters.
void ReadStdIn2() {
std::string userInput;
const char *inputArray = userInput.c_str();
int count = 0;
getline(std::cin, userInput, 'q');
for (int i = 0; i < strlen(inputArray); i++){
if ((inputArray[i] == ' ') || (inputArray[i] == '\n')){
count += 1;
}
}
std::cout << count << std::endl;
}
I want to be able to enter multiple words, followed by newlines, and have the function accurately display my number of words. I can't figure out why but for some reason after entering 3 newlines my count goes right back to 0.
For example, if I enter:
hello
jim
tim
q
the function works just fine, and returns 3 just like I expect it to. But if I enter
hello
jim
tim
bill
q
the count goes right to 0. I'm assuming this has something to do with my if statement but I'm really lost as to what is wrong, especially since it works fine up until the 3rd newline. Any help is appreciated
The behaviour of the program is undefined. Reading input into std::string potentially causes its capacity to increase. This causes pointers into the string to become invalid. Pointers such as inputArray. You then later attempt to read through the invalid pointer.
P.S. calculating the length of the string with std::strlen in every iteration of the loop is not a good idea. It is possible to get the size without calculation by using userInput.size().
To fix both issues, simply don't use inputArray. You don't need it:
for (int i = 0; i < userInput.size(); i++){
if ((userInput[i] == ' ') || (userInput[i] == '\n')){
...

How to stop an infinite loop due to invalid input C++

So I want to accept two inputs, a string and an int, and when the user enters "end" to exit out of the loop.
My problem is when "end" is entered that it gets stuck in a loop, since (I'm assuming) it is expecting two inputs when the user only types in one.
I've done some research and found stuff on discarding the input and resetting it with cin.ignore() and cin.clear(), however, these seem to only apply when accepting a single input, where as I'm asking for two separate inputs on one line, and it doesn't seem to work.
What my code is doing is basically asking for a list of things (name value), storing it in an array in a class, and is capped at 10 items. So, when "end" in entered, it only needs to exit the while loop. Everything else seems to work fine, i.e. when I enter 10 items it exits the loop and the rest of the code executes like it should. So there just seems to be a problem when typing in 'end'. (p.s. a is a string and b in an int type).
The section of code is:
do {
cout << "Enter the item and value (enter 'end' to stop): ";
cin >> a >> b;
items1.set_name(a, i);
items1.set_price(b, i);
i++;
} while ( i < 10 && a != "end" );
This seems like it should be very simple, and I'm sorry if its a stupid question, but I can't figure it out hahah.
Thanks in advance for helping me out.
You need to test the value of a BEFORE proceeding to read b; something like this:
cin >> a;
if(a == "end")
break;
cin >> b;
To get out of the loop, use
if (a == "end" || b == "end") break;

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)) {
...
}

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.

While loop doesn't end

I rewrote this loop in several ways, with nested Ifs and do whiles, yet behavior is the same. It behaves as expected as long as the user does not enter a character or a string. Once the user does it just goes on spinning the loop until I CTRL+C it.
From what I have researched, when a variable is a number and the user inputs a char or a string, they just get converted into their ASCII numbers, in which case the while check should work. The number should be larger than allowed and the user should be prompted for a new value right? Why does it keep looping infinitely?
Width is declared as a float.
void setWidth ()
{
std::cout << "\nPlease enter the width (use numbers greater than 0 and no greater than 20.0).\n";
std::cin >> width;
while (width <= 0 || width > 20)
{
std::cin.clear();
std::cin.ignore();
std::cout << "You have entered a number outside of the allowed range.\nPlease enter a number greater than 0 and no greater than 20.\n";
std::cin >> width;
}
}
Like I said, for numbers it works great, doubles, negatives, whatever. But something like "asdf" or "a" will put it in infinitely spinning loop.
It seems like I've tried everything. Why does this happen? I mean I know why it loops, it's because the number is not between 0 and 20, but why does it not ask user for input? I do clear the buffer.
The line std::cin >> width; fails because the input isn't a number. It also doesn't consume any of the input, so you are stuck in an infinite loop.
To avoid this, you should read the input using std::getline(), then try to convert it (std::ostringstream is one option), handling and reporting failures accordingly.
The default for cin.ignore() is to ignore just a single character.
If you want to ignore longer strings, you have to add extra parameters for that, perhaps cin.ignore(1000, '\n') which skips up to 1000 characters or the next newline (whichever comes first).
cin::clear() "Sets a new value for the error control state" 1, but the remaining input is still here and still read.
Then I guess the actual behavior depends on the compiler since when I compile it with g++ 4.6.3 and type the input "abc", it only loops three times and then wait for another input.
To empty the cin buffer you may rather see How do I flush the cin buffer?
Try checking the failbit on cin
Ok, thanks for all the help guys... I finally managed to get it to work with cin (not getline), by doing exactly what ive been doing, except I made a clearBuffer() function. So instead of clearing the buffer from within the getWidth function, the getWidth function calls another function.. thereby leaves the getWidth function to execute some code... then comes back to run the rest of it...
For some reason when it goes outside of the function it works fine and strings and chars trigger the error.. but if the cin.clear and cin.ignore are kept within the function then I have that problem.
So the final code looks like this.
void clearBuffer()
{
std::cin.clear();
std::cin.ignore(80, '\n'); //Ignore the first 80 characters up to an Enter character.
}
void setWidth ()
{
std::cout << "\n\t\tPlease enter the width.\n(use numbers greater than 0 and no greater than 20.0).\n";
float temp = NULL; //Using temp here so that we dont write invalid characters to an actual variable.
std::cin >> temp;
clearBuffer();
while (temp <= 0 || temp > 20)
{
std::cout << "\nERROR: You have entered width outside of the allowed range.\nPlease enter a number greater than 0 and no greater than 20.\n";
std::cin >> temp;
clearBuffer();
}
if(temp > 0 && temp <= 20)
width=temp;
}