In this rather simple exercise I have to receive an user input, store said input into a string, pass the string to a function by reference and finally modify the string so that every character is "parsed" by the toupper() function.
However, should the user insert 'q' as input, the program stops saying "Bye" OR if he just presses the Enter Key, the program is supposed to say something like "Hey, this string is empty".
Now the real problem here is in the last part since my code won't manage the case where the user inputs only the Enter Key value (to be honest, even if I just text a bunch of spaces followed by the Enter Key, nothing happens)
void uppercase(std::string &);
int main(){
using namespace std;
string ex2;
cout << "Exercise 2" <<endl;
while(ex2!="Bye"){
cout << "Enter a string(q to quit): ";
cin >> ex2;
cout << "Was: " << ex2 << endl << "Now is: ";
uppercase(ex2);
}
return 0;
}
void uppercase(std::string &str){
using namespace std;
if(str[0]=='\n')
cout <<"Empty string dude!" << endl;
else{
if(str.length()==1 && str[0]=='q'){ //press 'q' to exit program
str="Bye";
cout << str;
}
else{ //uppercase
for(int i=0;i<str.length();i++){
str[i]=(toupper(str[i]));
}
cout << str <<endl;
}
}
}
I also tried the compare() function and even to compare the whole string to null (pointless, but still worth a shot) and to the string "";
Sorry for the bad interpretation of your problem, trying
if( (str.length()==1 && str[0]=='q') || str.length() == 0)
{}
May help you out of the problem
Related
here is some fragment of my code. Can anyone help me? On how to make so the mask of the password is delayed by a second or two before it replaces the password with '*'?
struct adminInfo
{
string adminID;
string adminName;
string adminPassword;
};
void create_admin (adminInfo ad [], int &count)
{
char pass = 0;
const char BACKSPACE = 127;
const char RETURN = 10;
cout << " **************************************" << endl;
cout << " REGISTER ADMINISTRATOR" << endl;
cout << " **************************************" << endl;
cout << " Enter admin registration number (ID) : "; cin >> ws;
getline (cin, ad[count].adminID);
cout << " Enter admin full name : "; cin >> ws;
getline (cin, ad[count].adminName);
cout << " Please create your password : ";// cin >> ws;
//getline (cin, ad[count].adminPassword)
while ((pass=getch(void)) != RETURN)
{
if (pass == BACKSPACE)
{
if (ad[count].adminPassword.length() != 0)
{
cout << "\b \b";
ad[count].adminPassword.resize(ad[count].adminPassword.length() - 1);
}
}
else
{
ad[count].adminPassword += pass;
cout << "*";
}
}
count++;
}
Side note: Should std::endl always be used?
Also it might be easier for me to answer if I knew what libraries you were using. For the sake of simplicity I will presume you use the standard C++ library iostream for cout etc conio.h for getch() string for string and namespace std.
If you don't mind the last character being seen, you could literally just wait for the user input like this:
while ((pass = getch()) != RETURN) {
/* Making length variable so I don't have to call length() function multiple times and it looks cleaner */
int length = ad[count].adminPassword.length()
/* Using bigger than zero just to make it more explicit */
if (length > 0) {
/* Change last character to asterisk */
cout << "\b \b*";
}
if (pass == BACKSPACE) {
if (length > 0) {
cout << "\b \b";
ad[count].adminPassword.resize(length - 1);
}
} else {
ad[count].adminPassword += pass;
/* Instead of asterisk as that is now changed at every keypress after first input */
cout << pass;
}
}
If you wish to actually wait you could just include <windows.h> (or unix equivalent) and use Sleep(milliseconds) function like this in the else statement:
cout << pass;
ad[count].adminPassword += pass;
Sleep(Time in milliseconds)
cout << "\b \b*";
But this will wait the time in milliseconds to print out the next value and will give a pretty confusing and questionable output if you type above 3 wpm.
This is the best that I could think of, I'm not that knoweledgeable about C++ so sorry if I could not answer your question well enough.
I'm presuming you could do something with multithreading to make it wait while taking input. But as I said I do not know much about C++ so I will leave that to someone smarter than me ;D.
Please note that I am a complete beginner at C++. I'm trying to write a simple program for an ATM and I have to account for all errors. User may use only integers for input so I need to check if input value is indeed an integer, and my program (this one is shortened) works for the most part.
The problem arises when I try to input a string value instead of an integer while choosing an operation. It works with invalid value integers, but with strings it creates an infinite loop until it eventually stops (unless I add system("cls"), then it doesn't even stop), when it should output the same result as it does for invalid integers:
Invalid choice of operation.
Please select an operation:
1 - Balance inquiry
7 - Return card
Enter your choice and press return:
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool isNumber(string s) //function to determine if input value is int
{
for (int i = 0; i < s.length(); i++)
if (isdigit(s[i]) == false)
return false;
return true;
}
int ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
else if (rtrn == "2" and isNumber(rtrn)) { return true; }
else {cout << "Invalid choice." << endl; ReturnCard(); };
return 0;
}
int menu() //function for operation choice and execution
{
int choice;
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == 1 and isNumber(to_string(choice))) { cout << "Your balance is $" << balance; "\n\n"; }
else if (choice == 7 and isNumber(to_string(choice))) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; menu(); }
} while (ReturnCard()==false);
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
I've tried every possible solution I know, but nothing seems to work.
***There is a different bug, which is that when I get to the "Do you wish to continue?" part and input any invalid value and follow it up with 2 (which is supposed to end the program) after it asks again, it outputs the result for 1 (continue running - menu etc.). I have already emailed my teacher about this and this is not my main question, but I would appreciate any help.
Thank you!
There are a few things mixed up in your code. Always try to compile your code with maximum warnings turned on, e.g., for GCC add at least the -Wall flag.
Then your compiler would warn you of some of the mistakes you made.
First, it seems like you are confusing string choice and int choice. Two different variables in different scopes. The string one is unused and completely redundant. You can delete it and nothing will change.
In menu, you say cin >> choice;, where choice is of type int. The stream operator >> works like this: It will try to read as many characters as it can, such that the characters match the requested type. So this will only read ints.
Then you convert your valid int into a string and call isNumber() - which will alway return true.
So if you wish to read any line of text and handle it, you can use getline():
string inp;
std::getline(std::cin, inp);
if (!isNumber(inp)) {
std::cout << "ERROR\n";
return 1;
}
int choice = std::stoi(inp); // May throw an exception if invalid range
See stoi
Your isNumber() implementation could look like this:
#include <algorithm>
bool is_number(const string &inp) {
return std::all_of(inp.cbegin(), inp.cend(),
[](unsigned char c){ return std::isdigit(c); });
}
If you are into that functional style, like I am ;)
EDIT:
Btw., another bug which the compiler warns about: cout << "Your balance is $" << balance; "\n\n"; - the newlines are separated by ;, so it's a new statement and this does nothing. You probably wanted the << operator instead.
Recursive call bug:
In { cout << "Invalid choice of operation."; menu(); } and same for ReturnCard(), the function calls itself (recursion).
This is not at all what you want! This will start the function over, but once that call has ended, you continue where that call happened.
What you want in menu() is to start the loop over. You can do that with the continue keyword.
You want the same for ReturnCard(). But you need a loop there.
And now, that I read that code, you don't even need to convert the input to an integer. All you do is compare it. So you can simply do:
string inp;
std::getline(std::cin, inp);
if (inp == "1" || inp == "2") {
// good
} else {
// Invalid
}
Unless that is part of your task.
It is always good to save console input in a string variable instead of another
type, e.g. int or double. This avoids trouble with input errors, e.g. if
characters instead of numbers are given by the program user. Afterwards the
string variable could by analyzed for further actions.
Therefore I changed the type of choice from int to string and adopted the
downstream code to it.
Please try the following program and consider my adaptations which are
written as comments starting with tag //CKE:. Thanks.
#include <iostream>
#include <string>
using namespace std;
bool isNumber(const string& s) //function to determine if input value is int
{
for (size_t i = 0; i < s.length(); i++) //CKE: keep same variable type, e.g. unsigned
if (isdigit(s[i]) == false)
return false;
return true;
}
bool ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
if (rtrn == "2" and isNumber(rtrn)) { return true; } //CKE: remove redundant else
cout << "Invalid choice." << endl; ReturnCard(); //CKE: remove redundant else + semicolon
return false;
}
int menu() //function for operation choice and execution
{
string choice; //CKE: change variable type here from int to string
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == "1" and isNumber(choice)) { cout << "Your balance is $" << balance << "\n\n"; } //CKE: semicolon replaced by output stream operator
else if (choice == "7" and isNumber(choice)) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; } //CKE: remove recursion here as it isn't required
} while (!ReturnCard()); //CKE: negate result of ReturnCard function
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
NOTE: SOLVED, problem was not getline() but find function with an
Improperly filled array!
I've looked up several questions before posting my own, but I could not find an answer for my problem. This is my first question posted, but I did do some research and tried other solutions from other questions before posting my own. So I am not entirely sure this isn't a duplicate. My apologies! Thank you for understanding in advance!
I am trying to use getline() (c++) to get user input. It works fine in my main, but does not in my user defined function. I thought it might have to do with the buffer, so i used cin.ignore() as suggested in:
C++ getline method not working
and i checked:
How does getline work with cin?
to make sure I properly understood getline(). However my program still does not work correctly.
My program takes English Text as a string from user input (console input) and converts it into Morse Code and outputs result as a string (console output).
basically my problem is this:
getline works in my main function for both strings and strings with spaces ex: "This" and "This Code".
However, in my user defined function, it ONLY works for strings without spaces ex: "This".
Thanks for the help! Code snippets below!
#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;
string textToMorse(const string alphabet, const string morseAlphabet[]);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;
cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
resultString = textToMorse(alphabet, morseAlphabet); // function where I use
// getline() but does not work
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
// does not work
string textToMorse(const string alphabet, const string morseAlphabet[])
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with strings without spaces,
//but breaks with others. ex: "This" works as input
//but "This code" breaks and the console seems to freeze
// then crashes out
cin.clear();
// rest of code, but program breaks before this.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += " "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}
However if I edit my code and get the input from my main and pass it in as a parameter, it works.
#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;
string textToMorse(const string alphabet, const string morseAlphabet[], string userInput);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;
cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with both "This" and "This code"
cin.clear();
resultString = textToMorse(alphabet, morseAlphabet, userInput); //function modified
//to take one more
//parameter
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
string textToMorse(const string alphabet, const string morseAlphabet[], string userInput)
{
//code, but program works.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += " "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}
I didn't include all of the code, just the parts I felt were relevant to the question.
by works I mean:
getline successfully takes input. getline successfully assigns a string such as "this" and "this code" to the variable userInput when used in main function.
it only successfully assigns strings without spaces such as "this" when used in my user defined function. In that function, for some reason it does not work when I enter a string like "this code" or any string with a space inbetween.
note: program is not finished, as I plan to add other methods to do the reverse (as seen in code with
extra user options, but these are not yet implemented or defined, code still runs and compiles for problem I am facing.
The problem is that there is no morse code for a space.
Make a verification:
int n = alphabet.find(userInput[i]);
encodedEnglishText += (n == string::npos) ? " ": morseAlphabet[n];
Then it will work.
When you are looking for your input character in the alphabet string you won't find ' ' and std::string::find() return std::string::npos (normally -1 converted to the type std::string::size_type but the value isn't guaranteed). Using this value to index morseAlphabet won't do you much good: it is undefined behavior. This problem does not arise when you enter just one string as all characters are found in alphabet.
The proper way to deal with the situation is to look for the character and capture the result. Before using the result, you'd test the input, e.g.:
std::string::size_type pos(alphabet.find(userInput[i]));
if (pos == std::string::npos) {
// deal with the character not being part of the alphabet
}
else {
encodedEnglishText += morseAlphabet[pos];
}
Note that there are a few other things wrong with your program:
The selection of options should be inside the loop! The way it is implemented entering, e.g. 2 results in an infinite loop.
Using std::toupper() with a char can also result in undefined behavior! The problem is that std::toupper() expects a non-negative value of the value EOF but char may be signed. To avoid this problem you should use any of the functions from <cctype> or <ctype.h> with unsigned char:
userInput[i] = toupper[static_cast<unsigned char>(userInput[i]));
If the user doesn't enter an integer but, e.g., foo reading userSelection will fail and stream will get into failure state where it won't do anything until std::cin.clear() is entered. The best approach to deal with this situation is to test the result of reading the value before doing anything. If the input failed you can recover from the situation by clearing the status and skipping the offending character, e.g.:
if (std::cin >> userSelection) {
// use the selection
}
else {
std::cout << "ignoring invalid input\n";
std::cin.clear();
std::cin.ignore();
}
Note that your use of std::cin.clear() should be needed. Also, you should verify that the input you read with std::getline() is successful: in general, all user inputs should be tested for success.
If you enter a space character after the integer when reading userSelection, your call to std::cin.ignore() will ignore this space not the newline! To avoid this problem you could either read all charactors up to the first newline or skip all whitespace prior to the non-whitespace character:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // all till newline
std::cin >> std::ws; // skip all whitespace to first non-whitespace character
Do not use std::endl! It does not only create a newline but it also flushes the stream. This can easily create a performance problem.
You should probably pass std::string arguments by reference rather than by value. Passing the argument alphabet by value creates a copy with is inefficient (the morseAlphabet argument is passed by pointer although it looks like an array).
Some string literals seem to be split across multiple lines. Doing so is illegal (I guess, however, that this problem was introduced when pasting the code to the question above at some point).
I have a txt file which contains the name and roll number of students. I want to read and display a particular roll number from his file. It shows only the first roll number, but I want to read the roll number of the 2nd person.
That is, if I want to read the roll number of "ss", it shows the roll number of the first person
The program is
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
void student_read()
{
clrscr();
char name[30], n[30], temp[30];
int i, roll_no, code, count=0;
ifstream fin("tt.txt",ios::in|ios::beg);
if(!fin)
{
cout << "cannot open for read ";
return;
}
cout << "Enter the name of student" << "\n";
cin >> n;
while(fin >> name >> roll_no)
{
cout << roll_no << endl;
}
if(string[name] == string[n])
{
cout << "roll no" << "\n" << roll_no;
}
else
cout << "Not found";
}
void main()
{
clrscr();
cout << "Students details is" << "\n";
student_read();
getch();
}
The txt file contains this data:
sourav
123
ss
33
Does you have end of each line in your text file? Does you have sourav 123 ss 33 or sourav 123\nss 33?And this if(n[30]==name[30]) compare only 1 character in string.
You're doing the output of what is in the file already before you even input the name to search for.
Reorder your statements, like this:
cout<<"Enter the name of student"<<"\n";
cin>>n;
while(fin>>name>>roll_no)
{
//...
Also, if you only want to output one name and roll_no, in your loop, you have to check some kind of condition whether to print or not. At the moment, your code should actually print the roll_no of all rows in the file, and possibly sometimes the last one twice.
So the condition you have after the input belongs into the loop.
Additionally, however, you're only comparing the 31st character of the char array (which is actually already out of the bounds of your array variables! Their indices go from 0..29, i.e. even if you allocated a 30 characters array, the ). That means, your condition will be true if the next to last character matches. This place will most likely not be initialized yet, so you compare basically gargabe values and will get unexpected/random results.
If you want to, as the description suggests, want to compare the whole char array, that works differently by the way (not with the == operator, that would only compare pointer addresses), you'd need to use the strcmp function. But even better would be to use std::string instead of char *.
void student_read()
{
clrscr();
std::string name, n, temp;
int i, roll_no, code, count = 0;
std::ifstream fin("tt.txt", ios::in | ios::beg);
if (!fin)
{
std::cout << "cannot open for read ";
return;
}
std::cout << "Enter the name of student" << "\n";
std::cin >> n;
while (fin >> name >> roll_no)
{
std::cout << roll_no << std::endl;
}
if (name == n)
{
std::cout << "roll no" << "\n" << roll_no;
}
else
std::cout << "Not found";
}
int main()
{
clrscr();
std::cout << "Students details is\n";
student_read();
getch();
}
I'm new to C++. I decided to not watch the next tutorial and put my skills to use, by making a funny Mind Reader application. I'm pleased with myself, however, even though I've ironed out most bugs, I still have one concerning the exit function. I read the C++ documentation for it, and I'm not sure what I did wrong. I did exit(0);. I have a very weird error, which is:
no match for call to '(std::string {aka std::basic_string<char>}) (int)
I have searched online, however I am still unaware of what the problem is. My error is on line 59 (marked in the code):
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
//declaring variables to be used later
string name;
string country;
int age;
//header goes below
cout << "#######################################";
" ############ MIND READER ############"
"#######################################\n\n";
//asks if the user would like to continue and in not, terminates
cout << "Would like you to have your mind read? Enter y for yes and n for no." << endl;
cout << "If you do not choose to proceed, this program will terminate." << endl;
string exitOrNot;
//receives user's input
cin >> exitOrNot;
//deals with input if it is 'y'
if (exitOrNot == "y"){
cout << "Okay, first you will need to sync your mind with this program. You will have to answer the following questions to synchronise.\n\n";
//asks questions
cout << "Firstly, please enter your full name, with correct capitalisation:\n\n";
cin >> name;
cout << "Now please enter the country you are in at the moment:\n\n";
cin >> country;
cout << "This will be the final question; please provide your age:\n\n";
cin >> age;
//asks the user to start the sync
cout << "There is enough information to start synchronisation. Enter p to start the sync...\n\n";
string proceed;
cin >> proceed;
//checks to see if to proceed and does so
if (proceed == "p"){
//provides results of mind read
cout << "Sync complete." << endl;
cout << "Your mind has been synced and read.\n\n";
cout << "However, due to too much interference, only limited data was aquired from your mind." << endl;
cout << "Here is what was read from your mind:\n\n";
//puts variables in sentence
cout << "Your name is " << name << " and you are " << age << " years old. You are based in " << country << "." << endl << "\n\n";
cout << "Thanks for using Mind Reader, have a nice day. Enter e to exit." << endl;
//terminates the program the program
string exit;
cin >> exit;
if (exit == "e"){
exit(0); // <------------- LINE 59
}
}
}
//terminates the program if the input is 'n'
if (exitOrNot == "n"){
exit(0);
}
return 0;
}
Thanks
The local variable exit shadows other identifiers from outer scopes with the same name.
To illustrate with a smaller example:
int main()
{
int i;
{
int i;
i = 0; // assign to the "nearest" i
// the other i cannot be reached from this scope
}
}
Since the only exit visible is an object of type std::string, the compiler sees exit(0) as a call to operator()(int) and throws a hissy fit when it doesn't find one among std::string members.
You can either qualify the name (std::exit(0);) or rename the variable. And since all of your code is in main you can simply say return 0; instead.
Try using return 0; or return EXIT_SUCCESS;. It's the exact same thing. Also, you can only input one word into a cin. Instead, use getline(cin, string name); If it still doesn't work, add a cin.ignore(); before your getline(cin, string name);, like this:
//stuff
string country;
cout << "Now please enter the country you are in at the moment:\n\n";
cin.ignore();
getline(cin, country);
//stuff
return 0;
The problem is arrising because you declared a standard keyword as the name of a local variable.
Now as the local variable is of type sting it is not able to take it as its value.