Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

C++ problem

  • 09-10-2010 2:04pm
    #1
    Registered Users, Registered Users 2 Posts: 7,893 ✭✭✭


    Hey folks.

    I'm writing a console app and I am taking in some characters from standard input and putting them in an array. What I want is to stop the input when the user presses a certain character (Not Enter), for example when they press "x" the program will stop taking input and move on.

    The array is a character array and has a set limit, and will stop once either that limit is reached, or the user presses the certain character above to stop.

    I've tried cin.get(), cin.getline, getline() but cant figure this out. I'm thinking I have to read 1 char in at a time, process it and then put it in the array if its not the terminating character. What I have already is a non-working version that will pick up the terminating character, but only after enter is pressed!!

    Is there a way I can get C++ to process each character as they come in, and not after ENTER is pressed?

    In short, what i want is:

    char array[someNum]
    if input == X, then quit
    //read input -> array[a,b,c,d,e,X] // quit after X is pressed

    cheers.


Comments

  • Registered Users, Registered Users 2 Posts: 2,763 ✭✭✭Sheeps


    int index = 0;
    char array[];
    while(cin>>array[index] != 'x')
    {
        index++;
    }
    

    Would something like that work?


  • Registered Users, Registered Users 2 Posts: 2,763 ✭✭✭Sheeps


    if you are looking to take a string in from the command line you could pass it through as a parameter to the program in the argv array or else
    char array[];
    getline(cin, array);
    

    then iterate the c-string to look for x and quit if its there or what ever you want

    sorry its been a while since ive touched on C++


  • Registered Users, Registered Users 2 Posts: 7,893 ✭✭✭The_B_Man


    Hi sheeps,
    I wont be taking input from command line, only from when the program is run.

    I'll test out the first one, but i suspect it wont work, as "cin" will take input until ENTER is pressed (I think), which leaves me back at square one.

    I remember when I was learning C, I used the getch() command. Might look into a C++ equivalent.


  • Registered Users, Registered Users 2 Posts: 40,038 ✭✭✭✭Sparks


    What you're doing is getting down close to the terminal layer. There aren't any nice portable solutions when you get down that low, but you're possibly just above the point where it gets messy and you start to need curses or other terminal libraries. You could try using
    char c = ' ';
    string userinput;
    
    cin.get(c);
    while (c != 'x') {
       userinput += c;
       cin.get(c);
    }
    

    But really, you should be looking to something like curses if you're doing this stuff, unless you know it's not going to get more complex than this and you don't mind things not being all that portable or tidy or capable (things like backspace can tend to cause hassle with simple i/o that wants to look at individual characters like that).


  • Registered Users, Registered Users 2 Posts: 40,038 ✭✭✭✭Sparks


    The_B_Man wrote: »
    I remember when I was learning C, I used the getch() command. Might look into a C++ equivalent.
    Avoid getch().
    It's not standard C or standard C++, it's a holdover from the old Borland <conio.h> library and it's a really bad idea to be using it because it's not even close to being portable. If you're doing stuff that <conio.h> seems useful for, you should be using curses.


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2,426 ✭✭✭ressem


    I think that PDCurses is about the most straightforward version of curses to install. http://gnuwin32.sourceforge.net/packages/pdcurses.htm

    Failing that you'll just have to annoy future code readers and use _getch() or _getche (there's wide char versions also) from the windows C library conio.h to interact with the keyboard device and document this windows dependency.
    The starting underscores indicate implementation dependent functions.

    Document the dependency and get on with the rest. Or perhaps look at the QT suite of C++ libraries if portability and futureproofing is important. Great but pricy if you're not allowed open source your code when distributing the end result.


  • Closed Accounts Posts: 4,564 ✭✭✭Naikon


    This is how I would go about it. I suggest you forget messing around with curses and other terminal handling libraries as this is a steam oriented issue. This is all ANSI C, so at least in theory, it should work on any OS that has access to a ANSI stepped C compiler. Sorry, I don't know much about C++, but there should be a similar function included with the C++ standard libraries. Remember that fgetc casts each return char to a symbolic integer value just to note. You will still need to press enter to read the next char, but the input following an x won't be read into the array. Such is the nature of these functions.
    #include <stdio.h>
    #define LENGTH 20
    
    /*This code will print the chars as is(newlines too)to stdout*/
    int main(int argc, char *argv[])
    {
        /*Index counter and int to hold return value of fgetc*/
        int i, cur_char;
        char string[LENGTH + 1]; /*Store stdin input here*/
    
        /*Essentially, keep storing the current char at the i'th array postion
        until user does not indicate 'x'. Each char has */
        for(i=0; i <= LENGTH - 1 && (cur_char = fgetc(stdin) != 0x78); i++)
        {
            string[i] = cur_char;
        }
    
        string[i] = '\0'; /*Don't forget to null terminate our string, LOL*/
        fprintf(stdout, "\nArray holds: %s\n", string); /*Print string to stdout*/
        return(0);
    }
    


  • Registered Users, Registered Users 2 Posts: 40,038 ✭✭✭✭Sparks


    Naikon, you're just doing in that code exactly what the code I posted above does; you use the C stdio library and I'm using the C++ one, but that's the sole difference; and yours is based on static arrays because of that difference.

    As to messing around with curses, it might be better to start using it now rather than trying to engineer it in later on; if the OP's trying to do character-level stuff like this, he's within a smidge of doing terminal level stuff anyway.

    edit: btw, why do you call sizeof(string) in the for loop condition when the string array is staticly defined anyway? Just do i<=LENGTH and it's both more efficient and easier to read.


  • Closed Accounts Posts: 4,564 ✭✭✭Naikon


    Sparks wrote: »
    Naikon, you're just doing in that code exactly what the code I posted above does; you use the C stdio library and I'm using the C++ one, but that's the sole difference; and yours is based on static arrays because of that difference.

    As to messing around with curses, it might be better to start using it now rather than trying to engineer it in later on; if the OP's trying to do character-level stuff like this, he's within a smidge of doing terminal level stuff anyway.

    edit: btw, why do you call sizeof(string) in the for loop condition when the string array is staticly defined anyway? Just do i<=LENGTH and it's both more efficient and easier to read.

    True. I guess op will have toi use curses/terminal handling routines. This is beyond the scope of stream oriented functions. I should try learn curses soon. @mistake - duh, should of thought of that:pac:

    @Sparks - I take it your solution uses a vector? Didn't know dynamic arrays are used by default in C++ :(
    EDIT - When in doubt - reference.


  • Registered Users, Registered Users 2 Posts: 7,893 ✭✭✭The_B_Man


    thanks for the help lads. Still working through all the samples you posted up.

    so is it impossible in C++ without these "curses" (which I've never heard of :() to process each keystroke in real time? I've been trying cin.get(char), but like I said, it relies on ENTER being pressed before the char is processed.


  • Advertisement
  • Closed Accounts Posts: 4,564 ✭✭✭Naikon


    The_B_Man wrote: »
    thanks for the help lads. Still working through all the samples you posted up.

    so is it impossible in C++ without these "curses" (which I've never heard of :() to process each keystroke in real time? I've been trying cin.get(char), but like I said, it relies on ENTER being pressed before the char is processed.

    I would not say it is impossible, but it's alot more hassle than using ncurses or pdcurses. Ncurses is the GNU library for Text gui's in Linux. Pdcurses might fit the bill as is works on Windows too which is a bonus. These libraries are just a way of providing a higher level of abstraction to tty/terminal devices beyond line oriented terminal codes, where you have access to a an API for creating text based windows(text based GUI's)without X11.

    I would go with pdcurses if you are using windows, otherwise GNU ncurses if you are on Linux. I am sure there is a way of getting ncurses compiled for use under Windows though. Mind you, in the code I gave above, if you change the 0x78(HEX 'x') to EOF, once you press CTRL+D on the keyboard, the program will stop without enter. You will still have to flush the input stream though, as it can take two presses to register. Don't use fflush(stdin) is the only advice I can give you. It's basically undefined for most purposes from what I have read. I will try to find a better solution OP.


  • Users Awaiting Email Confirmation Posts: 351 ✭✭ron_darrell


    Have to disagree with the portability of the conio library as it's supported not only by Borland but also by Microsoft Visual studio and as far as I know by the g++ compiler on Linux.
    #include <conio.h>
    
    void main() {
    char input = '';
    int index = 0;
    char myarray[1000];
    while(input!='x')
    input = _getch();
    myarray[index] = input;
    index++;
    }
    }
    


  • Registered Users, Registered Users 2 Posts: 40,038 ✭✭✭✭Sparks


    ...but not identically. What works on one platform won't work on another, and since it's not standard, it's not guaranteed to be maintained. If none of that's an issue, have at it. But if any of it is, avoid <conio.h> like the plague of locusts it is.


  • Closed Accounts Posts: 4,564 ✭✭✭Naikon


    Ok, I really don't think there is a standard way of handling the issue you have without using ncurses and the like OP. I did rewrite my trivial example above to be less verbose though. strchr() is a pretty handy function if I must say so myself. This is basically the same as the code above though : \ Does anybody here know of a way to achieve what the op has requested in standard ANSI C/C++? I doubt it's possible without non standard libs. I can understand why the standards don't assume low level details like if you are emulating a vt100 like terminal emulator for example. Details like that are not platform agnostic.

    Again, sorry this is not in C++:( Gotta start learning me some C++.
    #include <stdio.h>
    #include <string.h>
    #define LENGTH 20
    
    /*Bog standard example to record some values into a static stack array*/
    int main(int argc, char *argv[])
    {
        /*Index counter and int to hold return value of fgetc*/
        char string[LENGTH + 1], *sp; /*Store stdin input here. sp for traversal*/
    
        /*Write out input line to our string of len LENGTH with stdin as source*/
        if((fgets(string, LENGTH, stdin)) != NULL) {
        /*We have encountered our termination char if sp points to non null val*/
            if((sp = strchr(string, 'x')) != NULL) {
                *sp = '\0'; 
            }
        }
        fprintf(stdout, "\nArray holds: %s\n", string); /*Print string to stdout*/
        return(0);
    }
    


  • Registered Users, Registered Users 2 Posts: 7,893 ✭✭✭The_B_Man


    This is just for some college homework so I'm thinking that I read a lot more into it. Maybe I can get away with typing the string and using ENTER to process it. I might just give that a go and see what they say.

    Its weird though, that theres no standard way of doing it in C++. I wasnt aware of getch() had so much "controversy" surrounding it, as when I used it in C previously, it was taken for granted that this was how it was done!


  • Registered Users, Registered Users 2 Posts: 40,038 ✭✭✭✭Sparks


    Well, it's not *that* wierd; what you're doing is basicly a low-level, platform-dependant user interface function, which on UNIX has to take into account direct user access at a terminal, or remote access over the net, or indirect access via pipes, and which on other platforms is often equally complicated.
    It only sounds easy :D
    It's why the whole cin/cout/iostream abstraction model was thought up in the first place.


Advertisement