0

Hello there I have a little problem with cin. How can I do cin while != '.' and '\n' ? Below is my code

#include <stdio.h> #include <iostream> using namespace std; void reverse(char x[]) { if(*x=='\0') { return; } else { reverse(x+1); cout<<*x; } } int main(){ char a[]=""; while (cin.get()!='\n'&&cin.get()!='.') { cin>>a; } reverse(a); } 

Input: foo. Output: .o It cut me 2 last words

3
  • 1
    cin >> a is undefined behaviour unless the user never inputs strings larger than 1 character in length. Did you mean for a to be a std::string? Commented Dec 10, 2015 at 22:06
  • a should be declared as char Commented Dec 10, 2015 at 22:12
  • Okay, well it's up to you. Just telling you what will happen if you declare it as a char[2] as is currently the case. Commented Dec 10, 2015 at 22:13

3 Answers 3

1

You shouldn't include both "stdio.h" (or better <cstdio>) and <iostream>. The former lets you use C standard IO functions, while the latter is the standard for C++. Pick one, for example as in your code you are actually using some <iostrem> facilities, include that.

The problem you are facing basically requieres 3 steps:

  • read standard input untill a '.' or a '\n' is entered.
  • store each character except '.' or '\n'.
  • send the character read to standard output in reverse order.

I think that second point is the key point. Where do you store the character you read? In your code you seem to use c-style null terminated char arrays, but you are not allocating the necessary memory for doing that.

Then, when you use cin.get() you are actually removing a character from to input stream and you do that 2 times before reading a.

I also don't think that using recursion for the last step is a good idea. Maybe it's mandatory in your assigned task, but use of recursion like this (and the tipical factorial example) better stay in books. If you want to use a stack to accomplish the task, it's better to do so explicitly, like here:

#include <iostream> #include <stack> int main() { char c; std::stack<char> sc; while ( std::cin.get(c) && c!='\n' && c!='.' ) sc.push(c); std::cout << std::endl; while ( !sc.empty() ) { std::cout << sc.top(); sc.pop(); } std::cout << std::endl; return 0; } 

A more "natural" way of doing this task is to store the chars in a std::string and show them in reverse order:

#include <iostream> #include <string> int main() { std::string a; char c; while ( std::cin.get(c) && c != '.' && c != '\n' ) a += c; std::cout << std::endl; // you can print what you read with: std::cout << a; for ( std::string::reverse_iterator rit = a.rbegin(); rit != a.rend(); ++rit ) std::cout << *rit; std::cout << std::endl; return 0; } 

If you want to use an array of char to store the input, you have to preallocate enough memory for your needs.

#include <iostream> #define MAX_CHARS 128 int main() { char a[MAX_CHARS + 1]; // enough to store 128 char and the '\0' char c; int counter = 0; // better knowing how many char you read for ( counter = 0; counter < MAX_CHARS && std::cin.get(c) && c!='.' && c!='\n'; counter++ ) a[counter] = c; a[counter] = '\0'; std::cout << std::endl; // you can print what you have read with: std::cout << a; while( counter > 0 ) { --counter; std::cout << a[counter]; } std::cout << std::endl; return 0; } 

If you are reading input from terminal you have to enter a whole line followed by newline in any case, because you are reading a buffered input. If you need unbuffered input and to stop reading characters right when a . or enter is pressed then there isn't a standard C++ solution, it depends on your environment. For sake of semplicity you can use the c-style (and deprecated) getch():

#include <cstdio> #include "conio.h" #define MAX_CHARS 128 int main() { char a[MAX_CHARS + 1]; // enough to store 128 char and the '\0' char c; int counter = 0; // better know how many char you read while ( counter < MAX_CHARS && (c=getch()) && c!='.' && c!='\n' && c!='\r' ) { putchar(c); a[counter] = c; counter++ } a[counter] = '\0'; printf("\n"); // you can print what you read with: printf("%s\n",a); while( counter > 0 ) { --counter; putchar(a[counter]); } printf("\n"); return 0; } 
Sign up to request clarification or add additional context in comments.

Comments

0

You can replace the first get with peek:

while (cin.peek() != '\n' && cin.get() != '.') 

std::basic_istream::peek keeps the character in the buffer, so std::basic_istream::get reads the same, but compares it to other.

- wrong. That would keep \n in the buffer, but . not.

Right: Use a char variable into which you extract only once and compare it twice:

char c; while (cin.get(c) && c != '\n' && c != '.') ... 

2 Comments

If i use while (cin.peek() != '\n' && cin.peek() != '.') { cin >> a; } the output is: .oof now i need to cut this "."
Then no extraction will happen. You'll be getting the same character again and again.
0

Doing a get removes the character from the input stream, so the first two characters are removed in the while loop condition before you've even entered the loop. cin >> a; reads in the next word (space separated) and puts it into a. It does not read character by character. This puts "o." into a, as 'f'and 'o' have been removed from the input stream. You then read the newline in the condition check and you exit out of the loop.

Instead, you should call cin.get() once and store the return value as an int ready for using it ie.

int ch = cin.get(); while(ch!='\n' && ch != '.') { // Do something with ch //get the next character ready for the next iteration ch = cin.get(); } 

I should also mention that a only has enough space for one character. You should make a bigger, doing something like char a[200]; which creates space for 200 characters. You should also check you don't try to access anything past a[199].

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.