I'm writing a simple, universal function that shows a dialog. I intend to call it from different places in my code. The problem is that I need to clear the input buffer at the beginning of the function so lingering data from previous input is not interpreted as an answer.
This has to be a pretty common think to do, so I believe that C++ standard library provide some function that does that. However, I haven't any luck in finding it.
Here is a practical example of what I want to accomplish:
#include <iostream>
#include <string>
unsigned dialog(const char question[], const char answers[])
{
//TODO reset std::cin
while (true)
{
std::cout << question << " [";
for (unsigned i = 0; answers[i] != '\0'; ++i)
{
if (i != 0)
std::cout << '/';
std::cout << answers[i];
}
std::cout << ']' << std::endl;
std::string line;
std::getline(std::cin, line);
if (line.empty())
{
for (unsigned i = 0; answers[i] != '\0'; ++i)
if (answers[i] >= 'A' && answers[i] <= 'Z')
return i;
} else if (line.length() == 1)
{
const char answer = toupper(line[0]);
for (unsigned i = 0; answers[i] != '\0'; ++i)
if (answer == toupper(answers[i]))
return i;
}
}
}
int main()
{
// --- optional part ---
std::cout << "Write something to clutter the input buffer..." << std::endl;
std::string foo;
std::cin >> foo; //User enters "aaa bbb ccc"
// --- optional part end ---
return dialog("Do you like this question?", "Yn");
}
interactive version
Unlike this other similar question, I'm looking for some portable solution. It should be supported in at least Windows and any Linux system.
There is also this question that is very similar to mine. However, all the answers seems to assume that input buffer is not empty at the moment. If I put it before my dialog and the input is empty at the moment (e.g. directly after start of the program), it leads to a situation when user needs to press Enter to even display my dialog on screen. A few answer from that question that don't assume that buffer is not empty, base on functions that depend on implementation of the standard library.
Related
The program works fine, although the fist printed number is always "3452816845". I have tried initializing "str[i]" by adding curly brackets when defining the array, or by giving it NULL value, but then the first printed number is always "zero", and only then it prints what I entered. Please take a look below:
#include <iostream>
using namespace std;
int main() {
unsigned* str = new unsigned[1000];
int cnt = 0;
char ch;
int a;
cout << "Please enter text: ";
do {
cin.get(ch);
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
} while (ch != '\n');
cout << "The entered numbers are: ";
for (int i = 0; i <= cnt; i++) {
cout << str[i] << " "; // here is where the error appears
}
delete[] str;
return 0;
}
Do not using namespace std;. Especially not in headers, but try to not use it in plain .cpp files either. It's more convenient to debug code that unambiguously tells you which namespace an identifier came from right where that identifier is being used.
unsigned* str = new unsigned[1000];
Since the advent of C++11, "naked" memory allocation like that is frowned upon, and is definitely not necessary here.
You could just use a static array (unsigned str[1000];).
You could use smart pointers (auto str = std::make_unique<char[]>(1000);).
Best choice, use C++ containers, like <vector>, <string>, or (if overhead really bothers you) <array>.
if (ch <=57 && ch >=48) {
int a = ch - '0';
Do not use "magic numbers" in your code. If you want to know if the character entered is a digit, use isdigit, which is more expressive and works even for non-ASCII encodings that might have their digits at a different location in the code table.
int a = ch - '0';
This isn't wrong, as the standard guarantees this to work for digits. Note that similar arithmetic on characters (the infamous ... - 'a') is frowned upon though, and will break as soon as you leave the realm of strict ASCII-7 encoding.
cnt++;
str[cnt] = a;
C/C++ start counting at zero. You just left the first item in the array uninitialized. The beauty of the post-increment is that you can do it right there where you use the index, i.e. str[cnt++] = a;.
for (int i = 0; i <= cnt; i++)
cout << str[i] << " "; // here is where the error appears
}
Very C, and also wrong. You didn't initialize str[0], so the first round through that loop accesses uninitialized memory. If you had initialized str[0] (by incrementing cnt only after using it as an index), i <= cnt would go one item beyond what you wrote into str[], again accessing uninitialized memory. A loop should run from 0 to < cnt (not <=).
If you took my earlier advice to use <vector> or <string>, there's a much better way to loop through the items stored in it, the range-for.
#include <iostream>
#include <vector>
int main()
{
char ch;
std::vector< int > digits;
std::cout << "Please enter text: ";
do
{
std::cin.get( ch );
if ( std::isdigit( ch ) )
{
digits.push_back( ch - '0' );
}
} while (ch != '\n');
std::cout << "The entered numbers are: ";
for ( auto & i : digits )
{
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
You never initialize str[0], but you output it.
The problem is here:
...
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
...
You are incrementing cnt too early, leaving str[0] uninitialized. You should do:
if (ch <=57 && ch >=48) {
int a = ch - '0';
str[cnt++] = a;
}
Also you do have a problem in your for loop; You should start from 0 till the last initialized element in the string which is at index cnt - 1. It should be like this:
for (int i = 0; i < cnt; i++) {
cout << str[i] << " ";
}
or
for (int i = 0; i <= cnt - 1; i++) {
cout << str[i] << " ";
}
I'm looking for a method to limit the visible user input using std::cin.
#include <iostream>
int main()
{
std::cout << "Enter your planet:\n";
string planet;
std::cin >> planet; // During the prompt, only "accept" x characters
}
What the user sees if they enter earth or any other word exceeding 4 characters before pressing enter:
Enter your planet:
eart
This is assuming the character limit is 4, note that the 'h' is missing. The console does not display any other character once it has exceeded the character limit. and this is before you press the enter key.
Kinda like typing in an input box like password fields, but it only allows 5 characters, so typing any other character goes unnoticed
A better analogy would be the maxlength attribute for text input in HTML.
That can't be achieved portably, because OS consoles aren't part of C++ standard. In windows, you could use <windows.h> header - it provides console handles etc., but since you didn't specify OS you are using, the is no point in posting windows-only code here (since it might not meet your needs).
EDIT:
Here is (not perfect) code that will limit visible input of the user:
#include <iostream>
#include <windows.h>
#include <conio.h>
int main()
{
COORD last_pos;
CONSOLE_SCREEN_BUFFER_INFO info;
std::string input;
int keystroke;
int max_input = 10;
int input_len = 0;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
std::cout << "Input (max 10) characters, press ENTER to prompt:" << std::endl;
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
while(true)
{
if(kbhit())
{
keystroke = _getch();
//declare what characters you allow in input (here: a-z, A-Z, 0-9, space)
if(std::isalnum(keystroke) || keystroke == ' ')
{
if(input_len + 1 > max_input)
continue;
++input_len;
std::cout << char(keystroke);
input += char(keystroke);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
else if(keystroke == 8) //backspace
{
if(input_len - 1 >= 0)
{
--input_len;
input.pop_back();
COORD back_pos {short(last_pos.X-1), last_pos.Y};
SetConsoleCursorPosition(handle, back_pos);
std::cout << ' ';
SetConsoleCursorPosition(handle, back_pos);
GetConsoleScreenBufferInfo(handle, &info);
last_pos = info.dwCursorPosition;
}
}
else if(keystroke == 13) //enter
{
std::cout << std::endl;
break;
}
}
}
std::cout << "You entered: " << std::endl
<< input << std::endl;
}
After a few days of experimenting, I found another solution that seems to be quite easy to grasp as it is somewhat beginner level and without requiring any knowledge of windows programming.
NOTE:
The conio.h library function _getch() could easily be replaced with the getchar() function;
I'm not saying the previous answer was not okay, but this solution is sort of aimed towards beginners with only basic knowledge of c++
char ch;
string temp;
ch = _getch();
while(ch != 13)// Character representing enter
{
if(ch == '\b'){ //check for backspace character
if(temp.size() > 0) // check if string can still be reduced with pop_back() to avoid errors
{
cout << "\b \b"; //
temp.pop_back(); // remove last character
}
}
else if((temp.size() > 0) || !isalpha(ch))// checks for limit, in this case limit is one
{ //character and also optional checks if it is an alphabet
cout << '\a'; // for a really annoying sound that tells you know this is wrong
}else {
temp.push_back(ch); // pushing ch into temp
cout << ch; // display entered character on screen
}
ch = _getch();
}
This could probably use some tweaks, because it's definitely not perfect, but I think it is easy enough to understand, at least I hope so
The following program should read some integer values from input and store them into an array until the user presses "Esc" key, but i cannot figure out how to do that. I have tried to use it's ASCII value as a condition but it doesn't work, or I'm doing something wrong.Could somebody please help me? Here is the code :
void main(){
int i=0, a[MAX];
cout <<"Please enter several integer numbers and press Esc when you want to finish" << endl;
while ((i != char(27)) && (i < MAX)) {
cin >> a[i];
i++;
}
There are several problems here. The first, and most important,
is that most systems will do line oriented input, which means
that they will pick up a lot of control characters (including,
probably, ESC) and do something with them internally, rather
than returning them to you; it might not even be possible to
ever see an ESC in the input.
For the rest, there are several problems with your code. The
first is that you're testing against the index into the array
(where you'll put the next character), not against anything
you've read. The second is that you're inputting int, so you
won't see any individual characters; just the results of the
conversion of your input. (In fact, if an ESC character does
get through, you'll end up with std::cin in a error state.)
The third is that you never test whether the input has
succeeded.
A better solution would be to adopt some other convention for
the input: say one number per line, with an empty line signaling
the end. In that case, you could write something like:
std::vector<int> a;
std::string line;
std::cout << "..." << std::endl;
while ( std::getline( std::cin, line ) && !line.empty() ) {
std::istringstream parse( line );
int value;
parse >> value >> std::ws;
if ( !parse ) {
std::cout << "That wasn't an integer, try again" << std::endl;
} else if ( parse.get() != EOF ) {
std::cout << "Extra garbage at end of line, ignoring it" << std::endl;
} else {
a.push_back( value );
}
}
(You'll note that I've used std::vector, since you don't know
up front how many inputs you'll get.)
If you really want to use ESC, you'll probably need a third
party library, along the lines of curses, to do raw input,
reading one character at a time, and collecting the digits into
a string, for conversion using std::istringstream.
Do not do this use James method its much better and will run on evrything but just for the sake of answering a question you can do this. This will not work on all platforms It works on visual c++ compiler.
# include <iostream>
# include <conio.h>
# include <vector>
using namespace std;
int main()
{
char key;
vector<int> a;
int temp = 0;
while ((key = getch()) != 27)
{
cin >> temp;
a.push_back(temp);
}
for (int i = 0 ; i < a.size() ; i++)
{
cout << a.at(i) << endl;
}
printf("Exit");
cout << endl;
system("Pause");
return 0;
}
Edit: Programs clearer now. Note this program should not be used it is very platform and compiler dependant.
I am writing a program right now that alters a C_String using pointers to the string. I have an implementation that works fine. The only problem I am running into is that when I reach the end of my program, if I try to delete the pointers I get an error.
My code:
void CStringSwitcher()
{
string input = "";
char* cStringArray = new char[ASIZE];
char* reversed = new char[ASIZE];
const char* originalReversed = reversed;
char* pointers[POINTER_SIZE];
memset(reversed, '\0', ASIZE);
memset(cStringArray, '\0', ASIZE);
memset(pointers, '\0', POINTER_SIZE);
char* current = cStringArray;
cout << "Enter a sentence on each line. Input a 0 to stop." << endl;
// Receives input from the user and stores it into cStringArray
int i = 0;
do
{
cout << ">";
cin.clear();
fflush(stdin);
input = "";
getline(cin, input);
if (input == "0")
break;
else
{
input.append("\n");
pointers[i] = current;
_CRT_SECURE_STRCPY(pointers[i], ASIZE - 1, input.c_str());
current += input.length();
i++;
}
} while(i < POINTER_SIZE);
char* end = current;
--i;
do
{
/// Check if done
if(i < 0)
break;
/// Copy from current to end
current = pointers[i];
do
{
*reversed++ = *current++;
}while(current < end);
/// Update end
end = pointers[i];
/// Update i
--i;
}while(true);
*reversed = '\0';
cout << endl << originalReversed << endl;
system("PAUSE");
//delete[] originalReversed;
//delete[] cStringArray;
return;
}
As it is written above the code works fine, however if I uncomment the two delete lines just before the return I was getting an error:
Project_06.exe has initiated a breakpoint
and the program crashes. Weird thing is I just ran the program again to get the exact wording of the error message and it runs with no error? Any ideas on why that is?
I'm guessing that this code is an educational/practice piece to try and solidify your knowledge of pointers, but to be frank with you: it's an absolute horror to read.
This answer is in the spirit of "teach a man to fish".
Start by removing all of the allocations and instead use fixed-sized arrays.
char cStringArray[ASIZE] = "";
char reversed[ASIZE] = "";
This eliminates the need for the memsets for now, this assignment actually sets the entire array to 0s (see http://ideone.com/WmLtQp).
Doing it this way makes it much easier to catch corruption while running it thru the debugger.
Then switch the arrays over to dynamic allocations.
Lastly, don't mix stdin and cin, doing so can invoke undefined behavior.
---- Edit ----
Here is a C++-refactoring of your code. This particular piece shows both how to do it by hand (manually copying the bytes) and using C++ features to reduce the amount of work we have to do ourselves.
ideone live demo: http://ideone.com/0KuGiB
#include <iostream>
#include <string>
#include <vector>
void CStringSwitcher()
{
std::vector<std::string> inputs;
size_t totalLength = 0;
std::cout << "Enter a sentence on each line. Input a 0 to stop." << std::endl;
inputs.reserve(16);
for ( ; /* until break */ ; ) {
std::cout << ">";
std::string input;
getline(std::cin, input);
if (input == "0")
break;
inputs.push_back(input);
totalLength += input.length() + 1; // for the '\n'
}
std::string reversed = "";
reversed.reserve(totalLength); // eliminate allocations
// walk backwards thru the list of strings.
for (auto inputsIt = inputs.rbegin(); inputsIt != inputs.rend(); ++inputsIt) {
const std::string& input = *(inputsIt);
#ifndef REAL_CODE
// educational, Do-It-Yourself way
const size_t length = input.length();
// walk backwards thru the characters
for (size_t i = 0; i < length; ++i) {
reversed += input[length - 1 - i];
}
#else
// call append with reversed iterators to do it for us.
reversed.append(input.rbegin(), input.rend());
#endif
// add the trailing '\n'
reversed += '\n';
}
std::cout << std::endl << reversed << std::endl;
// don't pause, set a break point at the end of the function
// or run without debugging.
return;
}
int main(int argc, const char* argv[])
{
CStringSwitcher();
return 0;
}
_CRT_SECURE_STRCPY(pointers[i], ASIZE - 1, input.c_str());
current += input.length();
ASIZE-=input.length();
ASIZE-=input.length();
Don't know why it helps to get rid of error. This should only prevent from overflow if size of new string > size of the remaining bytes. Looks like some Microsoft-Specific magic.
Also there are many errors in you code, but this is another story. Just consider using vector, unique_ptr.
---EDIT---
I came with some weird things.
_CRT_SECURE_STRCPY is define to strcpy_s
#include <iostream>
#include <numeric>
using namespace std;
int main()
{
char arr[10];
iota(arr, end(arr), 'A');
for (auto i : arr) cout << i << '\t'; cout << '\n';
strcpy_s(arr, "");
for (auto i : arr) cout << i << '\t'; cout << '\n';
}
My output is:
A B C D E F G H I J
(nonpritable characters)
It means that strcpy_s rewrites WHOLE destination buffer. Even if you pass one char.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
For example : how are you? ----> woh era uoy?
This is my code, i got it worked but the question mark is besing reversed too.
How can i make it remained intact?
#include <iostream>
using namespace std;
int main()
{
string ch;
while(cin >> ch)
{
for(int i = ch.length() - 1; i >= 0; i--)
{
cout << ch[i];
}
cout << " ";
}
return 0;
}
Your chosen input method (cin >> ch) automatically splits the input into separate words.
Like Jerry Coffin said in his answer, you have to skip over punctuation etc to find to alpha characters to swap. Roughly like this:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string ch;
while (cout << "String? " && cin >> ch)
{
cout << "Input: <<" << ch << ">>\n";
const char *bp = ch.c_str();
const char *ep = ch.c_str() + ch.length() - 1;
const char *sp = ch.c_str();
while (sp < ep)
{
while (sp < ep && (*sp != ' ' && !isalpha(*sp)))
sp++;
while (sp < ep && (*ep != ' ' && !isalpha(*ep)))
ep--;
char c = *sp;
ch[sp-bp] = *ep;
ch[ep-bp] = c;
sp++;
ep--;
}
cout << "Output: <<" << ch << ">>\n";
}
cout << endl;
return 0;
}
Sample dialogue
String? How are you?
Input: <<How>>
Output: <<woH>>
String? Input: <<are>>
Output: <<era>>
String? Input: <<you?>>
Output: <<uoy?>>
String? Pug!natious=punctuation.
Input: <<Pug!natious=punctuation.>>
Output: <<noi!tautcnu=psuoitanguP.>>
String?
You can tweak it from here. I'm far from claiming this is idiomatic C++; the use of const char * in the middle shows my C background.
Start from the beginning of the string, and scan forward until you find a letter. The scan backwards from the end until you find a letter. Swap them. Continue until the two positions meet.
Note: above I've used "letter", but all I really mean is "one of the characters that should be reversed." You haven't defined very precisely which characters should be swapped and which shouldn't, but I'm assuming you (or your teacher) has a reasonably specific definition in mind.
Try using array and scanning each letter to see if there is a question mark. If there is, move it to the last place of the array.
simple solution or hack to solve this case alone. if there are more cases comment it lets solve it together.
#include <iostream>
using namespace std;
int main()
{
string ch;
while(cin >> ch)
{
int flag = 0;
for(int i = ch.length() - 1; i >= 0; i--)
{
if(ch[i] != '?')
cout << ch[i];
else
flag = 1;
}
if(flag)
cout << "?";
else
cout << " ";
}
return 0;
}