3

I need to read input from standard input until a space or a TAB is pressed.

Eventually, I need to hold the input in a std::string object.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
AAaa
  • 3,659
  • 7
  • 35
  • 40
  • Since input is usually line-buffered, I don't think it's easy to do. – Xeo Jan 29 '12 at 15:44
  • 1
    If the input is interactive, the terminal usually doesn't send content until a full line is typed (input is sent after the user enters the "return" key). If you are expecting to type away and have your program react at each space or tab character, you'll be in for a little surprise. – André Caron Jan 29 '12 at 16:03
  • 1
    C++ has no notion of "pressing a key". You will require a platform-specific terminal handling library. Try `ncurses`. – Kerrek SB Jan 29 '12 at 16:23
  • @Kerrek SB - I didnt explain myself correctly. I ment before a TAB or space is spotted, not typed. if I read from a file, I want the string the hold only the first word until the tab/space – AAaa Jan 29 '12 at 18:26

8 Answers8

4
#include <iostream>
#include <string>

int main()
{
    std::string result;
    std::cin >> std::noskipws; //don't skip whitespaces
    char c;
    while (std::cin >> c)
    {
        if(c == '\t' || c == ' ')
             break;
        result.push_back(c);
    }

}
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • I try to run it and it keeps getting input after spave and TAB. eventually onlt the chars before the space are stored in result (and this is good), but for some reason only when I press enter the input window is closed. – AAaa Jan 29 '12 at 16:02
  • 2
    @AAaa: In order for the input to work, you must eventually press ENTER. In this case your string will contain only the characters before the first TAB or SPACE. There is no standard C++ way to actually detect keypress – Armen Tsirunyan Jan 29 '12 at 16:05
  • 4
    @AAaa: the program does not receive the input until the user presses enter because the terminal program does not send it until the enter key is pressed. This "feature" allows the terminal to implement editing (e.g. pressing backspace and changing the input) before sending it to the program). – André Caron Jan 29 '12 at 16:07
3

Since a tab counts as whitespace, you are asking to extract the first token from the stream. This is very easy in C++, as token extraction is already the default behaviour of the >> operator:

#include <iostream>
#include <string>

int main()
{
    std::string token;

    if (!(std::cin >> token)) { /* error */ return 1; }

    // now you have the first token in "token".
}

(The error can only occur in arcane circumstances, e.g. when the input file descriptor is already closed when the program starts.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

You can use getch() or getchar() to read each character separately, and then process the input manually so that when a space or a tab is pressed, you end the input.

Ilya Kogan
  • 21,995
  • 15
  • 85
  • 141
  • 2
    `getch` is platform specific; it doesn't exits on most platforms. `getchar` is the equivalant of `std::cin.get()`, and as some of the comments to the original posting have pointed out, most systems won't return anything until the enter key has been pressed. – James Kanze Jan 29 '12 at 16:38
1

You can have std::cin to stop reading at any designated character using

char temp[100];
std::cin.getline(temp, 100, '\t');

I don't know if you can easily get it to work with two characters though.

nikolas
  • 8,707
  • 9
  • 50
  • 70
  • You can't, but if you really need such functionality, you can write your own version of `std::getline()` that accepts a predicate as third parameter have test agains that rather than the newline character. – André Caron Jan 29 '12 at 16:05
1

This should do the job:

#include <stdio.h>

int main ()
{
  char c;
  do {
    c=getchar();
    /** Your code here **/
  } while ((c != ' ') && (c != '\t'));
  return 0;
}
Dr G
  • 3,987
  • 2
  • 19
  • 25
  • I need to get an std::string eventually. can I do it with your example? – AAaa Jan 29 '12 at 15:50
  • Create an empty `std::string` before the loop and append each character (you can use the overloaded `+=` operator) – nikolas Jan 29 '12 at 15:53
  • Just add the characters to a string, e.g. `str.push_back(c)` – Dr G Jan 29 '12 at 15:54
  • Thanks. But same thing as i commented to Armen's answer - for some reason the input window is not closed after the space or TAB. I know that what I enter afterwards is not being read because I check the result and it has what I need, but the input window itself doesn't close. It only closes after an ENTER. – AAaa Jan 29 '12 at 16:04
1

It seems that the solution to this is, indeed, a lot easier using scanf("%[^\t ]", buffer). If you want to do it using C++ IOStreams I think the nicest to use option is to install a std::locale with a modified std::ctype<char> facet which uses a modified interpretation of what is considered to be a space and then read a std::string (see e.g. this answer I gave for a similar problem). Independent of whether you are using a C or a C++ approach you probably need to turn off line buffering on the standard input if you want to find out about the space or the tab when it entered rather than when the entire line is given to your program.

Community
  • 1
  • 1
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

use scanf for this:

A simple code:

#include<iostream>
#include<stdio.h>
int main()
{
        char t[1000]={'\0'};
        scanf("%[^\t ]",t);
        printf("%s",t);
        std::string mains(t);
        return 1;

}
Global Warrior
  • 5,050
  • 9
  • 45
  • 75
0

The simple answer is that you can't. In fact, the way you've formulated the question shows that you don't understand istream input: there's no such thing as “pressed” in istream, because there's no guarantee that the input is coming from a keyboard.

What you probably need is curses or ncurses, which does understand keyboard input; console output and the rest.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Come on, James! We all know that you can turn off line buffering (at least on POSIX systems) and go from there, even with `std::cin`. Sure, we wouldn't know if it is attached to a keyboard but we might not care: just call the system calls and don't be to picky about their result. – Dietmar Kühl Jan 29 '12 at 17:03
  • @DietmarKühl There are certainly system dependent solutions, as well as `curses`. The problem is that they're just that---system dependent. And as far as I know, under Windows, the only way to circumvent line buffering is by using a different set of system calls. (But then, I don't know Windows that well, so there could easily be something I'm missing.) – James Kanze Jan 30 '12 at 08:27