Thread: Capturing keyboard input, one character at a time

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    42

    Capturing keyboard input, one character at a time

    How would I go about creating a function where when the user hits one key on their keyboard (except for the enter key) and the function adds that character to an array, then preps the user for another character (and so on and so forth until the user hits enter)?

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    You can't do that with any portable means. What is your operating system and your compiler?
    Devoted my life to programming...

  3. #3

  4. #4
    Registered User
    Join Date
    Oct 2012
    Posts
    42
    I'm using GCC on Redhat 6.3, it doesn't seem to include conio.h.

    Here's the assignment, it's pretty basic:
    Write a program that prompts the user for characters (not strings!). As the user enters characters your program must call the "vector function" (that you must write) to automatically adjust the character array size to hold the input. The function must use malloc/calloc to create/adjust the array size. You CANNOT use realloc! The function must return a pointer (to the array) to the main routine (you will probably want to pass in the array also). You can adjust the array in chunks of 5 or 10 characters (vs 1 character) if you want. When the user enters "return" (in place of a character) your program must append the '\0' character to the end (making it a string). Your program must then append the new string to the text/string "HW 3 input: " (be carefull here). Your program must then print out the resulting string.
    I'm pretty sure I understand the logic behind this, I made up this pseudocode

    Code:
    function1
    {
      //is called when the user hits a key that isn't the enter key
      //throws the passed in character into an array of characters
      //if needed assigns the old array into a new, larger array using memcpy
    }
    
    main
    {
       //initialize some pointers and an array
       //use malloc to assign pointers
       //ask for keyboard input 
       //something (loop maybe?) to grab each key as the user presses it and passes it as a character into the above function (quits loop when enter key is presssed)
       //takes entire character array and converts it into a string and prints it
    }

  5. #5
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Paul Omans View Post
    I'm using GCC on Redhat 6.3, it doesn't seem to include conio.h.
    No, conio.h is a Windows/DOS interface.

    In Linux and Unix land (including Mac OS and *BSDs, basically everywhere except in Windows), this requires terminal control. The most common and recommended way is to use a Curses library -- at least one is available for Windows, too; they're all inter-compatible -- but you can also use the basic termios interface. When using stdio.h, you also need to tell the C library not to buffer inputs, using setvbuf().

    Terminals have two basic states: canonical, and raw. Canonical mode is the one where you can edit each line, and only when you press Enter, it is supplied to the program (shell or your own program). These editing facilities are provided by the kernel itself; it's not just some program that is helping you.

    Raw mode, as you can probably guess, is the raw mode, where the kernel does not interfere; it lets the data flow through. (The kernel can still do a lot of interesting stuff to the data, like converting newline conventions on the fly -- but all that is another topic, for another time.)

    When you change the terminal to raw mode, you also need to make sure you restore it back to the original mode before your program exits, because most shells and terminal emulators do not automatically reset back to canonical mode! In fact, if you've ever had your terminal window go wonky, producing strange output, and not responding correctly to your keypresses, it is because it's in raw mode. Fortunately, there is a command called reset, which resets the terminal back to normal mode. If your terminal window goes wonky, just type "reset"+enter a couple of times, and it should recover.

    Here is an example implementation with lots of comments, on how to modify the state of a terminal (where the terminal is related to the FILE stream specified as a parameter). The first one sets the terminal to raw state, and the second one restores the original state.
    Code:
    #include <stdlib.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    #include <stdio.h>
    #include <errno.h>
    #include <ctype.h>
    
    /* Call this to change the terminal related to the stream to "raw" state.
     * (Usually you call this with stdin).
     * This means you get all keystrokes, and special keypresses like CTRL-C
     * no longer generate interrupts.
     *
     * You must restore the state before your program exits, or your user will
     * frantically have to figure out how to type 'reset' blind, to get their terminal
     * back to a sane state.
     *
     * The function returns 0 if success, errno error code otherwise.
    */
    static int stream_makeraw(FILE *const stream, struct termios *const state)
    {
        struct termios  old, raw, actual;
        int             fd;
    
        if (!stream)
            return errno = EINVAL;
    
        /* Tell the C library not to buffer any data from/to the stream. */
        if (setvbuf(stream, NULL, _IONBF, 0))
            return errno = EIO;
    
        /* Write/discard already buffered data in the stream. */
        fflush(stream);
    
        /* Termios functions use the file descriptor. */
        fd = fileno(stream);
        if (fd == -1)
            return errno = EINVAL;
    
        /* Discard all unread input and untransmitted output. */
        tcflush(fd, TCIOFLUSH);
    
        /* Get current terminal settings. */
        if (tcgetattr(fd, &old))
            return errno;
    
        /* Store state, if requested. */
        if (state)
            *state = old; /* Structures can be assigned! */
    
        /* New terminal settings are based on current ones. */
        raw = old;
    
        /* Because the terminal needs to be restored to the original state,
         * you want to ignore CTRL-C (break). */
        raw.c_iflag |= IGNBRK;  /* do ignore break, */
        raw.c_iflag &= ~BRKINT; /* do not generate INT signal at break. */
    
        /* Make sure we are enabled to receive data. */
        raw.c_cflag |= CREAD;
    
        /* Do not generate signals from special keypresses. */
        raw.c_lflag &= ~ISIG;
    
        /* Do not echo characters. */
        raw.c_lflag &= ~ECHO;
    
        /* Most importantly, disable "canonical" mode. */
        raw.c_lflag &= ~ICANON;
    
        /* In non-canonical mode, we can set whether getc() returns immediately
         * when there is no data, or whether it waits until there is data.
         * You can even set the wait timeout in tenths of a second.
         * This sets indefinite wait mode. */
        raw.c_cc[VMIN] = 1;  /* Wait until at least one character available, */
        raw.c_cc[VTIME] = 0; /* Wait indefinitely. */
    
        /* Set the new terminal settings. */
        if (tcsetattr(fd, TCSAFLUSH, &raw))
            return errno;
    
        /* tcsetattr() is happy even if it did not set *all* settings.
         * We need to verify. */
        if (tcgetattr(fd, &actual)) {
            const int saved_errno = errno;
            /* Try restoring the old settings! */
            tcsetattr(fd, TCSANOW, &old);
            return errno = saved_errno;
        }
    
        if (actual.c_iflag != raw.c_iflag ||
            actual.c_oflag != raw.c_oflag ||
            actual.c_cflag != raw.c_cflag ||
            actual.c_lflag != raw.c_lflag) {
            /* Try restoring the old settings! */
            tcsetattr(fd, TCSANOW, &old);
            return errno = EIO;
        }
    
        /* Success! */
        return 0;
    }
    
    /* Call this to restore the saved state.
     *
     * The function returns 0 if success, errno error code otherwise.
    */
    static int stream_restore(FILE *const stream, const struct termios *const state)
    {
        int fd, result;
    
        if (!stream || !state)
            return errno = EINVAL;
    
        /* Write/discard all buffered data in the stream. Ignores errors. */
        fflush(stream);
    
        /* Termios functions use the file descriptor. */
        fd = fileno(stream);
        if (fd == -1)
            return errno = EINVAL;
    
        /* Discard all unread input and untransmitted output. */
        do {
            result = tcflush(fd, TCIOFLUSH);
        } while (result == -1 && errno == EINTR);
    
        /* Restore terminal state. */
        do {
            result = tcsetattr(fd, TCSAFLUSH, state);
        } while (result == -1 && errno == EINTR);
        if (result == -1)
            return errno;
    
        /* Success. */
        return 0;
    }
    The ctype.h is used for the example main() below; it's not needed by the two above functions.

    The first function changes the terminal related to the file descriptor, and the second function restores the original state. You normally use standard input, stdin.

    Here is an example program using the above. You need to type Q (uppercase Q, not lowercase q) to exit from the program:
    Code:
    int main(void)
    {
        struct termios  saved;
        int             c;
    
        /* Make terminal at standard input unbuffered and raw. */
        if (stream_makeraw(stdin, &saved)) {
            fprintf(stderr, "Cannot make standard input raw: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        fprintf(stdout, "Press Q to quit.\n");
        fflush(stdout);
    
        do {
    
            c = getchar(); /* Or c = getc(stdin); */
    
            if (isprint(c))
                fprintf(stdout, "Received character '%c', code %d = 0%03o = 0x%02x\n", c, c, c, c);
            else
                fprintf(stdout, "Received code %d = 0%03o = 0x%02x\n", c, c, c);
            fflush(stdout);
    
        } while (c != 'Q');
    
        /* Restore terminal to original state. */
        if (stream_restore(stdin, &saved)) {
            fprintf(stderr, "Cannot restore standard input state: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
    
        fprintf(stdout, "All done.\n");
        return EXIT_SUCCESS;
    }
    If you experiment with special keys, like function keys and arrow keys, you'll see they produce a sequence of input characters, all beginning with code 27 and '['.

    These are standard CSI sequences ("ANSI escape sequences", standardized in ECMA-48 and ISO/IEC 6429). For example, the ANSI escape code Wikipedia page lists some of them in a table under the "Some ANSI escape sequences" heading.

    For example, the "Up" cursor key produces 27 91 65 = \033[A, which is the CSI sequence for cursor up.
    Last edited by Nominal Animal; 05-29-2013 at 01:28 PM. Reason: Forgot to emphasise Curses first.

  6. #6
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    And here is the recommended approach, using a curses library:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <curses.h>
    #include <locale.h>
    #include <ctype.h>
    
    int main(void)
    {
        WINDOW *w;
        int     c;
    
        /* This is optional. This tells the C libraries to use user's locale settings. */
        setlocale(LC_ALL, "");
    
        /* Initialize curses. */
        w = initscr();
        if (w == NULL) {
            fprintf(stderr, "Error initializing curses library.\n");
            return EXIT_FAILURE;
        }
        raw();              /* Terminal in raw mode, no buffering */
        noecho();           /* Disable echoing */
        nonl();             /* Disable newline/return mapping */
        keypad(w, FALSE);   /* FALSE: CSI codes, TRUE: curses codes for keys */
    
        printw("Press Q to quit.\n");
     
        do {
    
            c = getch();
    
            if (isprint(c))
                printw("Received character '%c', code %d = 0%03o = 0x%02x\n", c, c, c, c);
            else
                printw("Received code %d = 0%03o = 0x%02x\n", c, c, c);
    
        } while (c != 'Q');
    
        /* Done. */
        endwin();
    
        return EXIT_SUCCESS;
    }
    In Linux, make sure you have a curses development package installed (ncurses-devel or libncurses5-dev or similar). For Windows, you can use PDcurses, or, if using MingW, ncurses (there are some binaries linked at the end of the page).

    ncurses is very common on non-Windows systems; it is practically always available.

    The development libraries, however, are not always installed; you may have to the admin to install them. In other words, compiled programs work, but to compile new programs, you need the development libraries. In Red Hat and similar distributions, it is usually called ncurses-devel, in Debian/Ubuntu it is libncurses5-dev, I believe.

    In most operating systems you can compile the above (ctest.c) using
    Code:
    cc ctest.c -lcurses -o ctest
    but in Linux, I recommend
    Code:
    gcc -W -Wall ctest.c -lncurses -o ctest
    Finally, note the keypad(w,FALSE); line. If you change it to TRUE, curses will interpret CSI/ANSI escape sequences internally, and provide you with single-character constants listed for example here (man 3 curs_getch).

  7. #7
    Registered User
    Join Date
    Oct 2012
    Posts
    42
    Thanks for the info, I was able to find an example that accomplishes it with standard C libraries. Now the only problem is when it gets to the printf statements in lines 59-69, it prints NULLs instead of the actual values. What am I missing?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    
    int getch(void) //Dynamic String Input function from Daniweb.com
    { 
        int ch;
        struct termios oldt;
        struct termios newt;
        tcgetattr(STDIN_FILENO, &oldt); /*store old settings */
        newt = oldt; /* copy old settings to new settings */
        newt.c_lflag &= ~(ICANON | ECHO); /* make one change to old settings in new settings */
        tcsetattr(STDIN_FILENO, TCSANOW, &newt); /*apply the new settings immediatly */
        ch = getchar(); /* standard getchar call */
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt); /*reapply the old settings */
        return ch; /*return received char */
    }
    
    int main(void)
    {
        char *x;
        x = malloc(sizeof(int));
        if (x == NULL) exit(1);
        int *temp, *temp2;
        *x = ' ';
        printf("Enter characters: ");
        int arraySize = 0;
        temp=calloc(1, sizeof(int));
        if (temp == NULL) exit(1); 
        temp2=calloc(1, sizeof(int));
        if (temp2 == NULL) exit(1); 
        int c, i;
        while (*x != '\n')
        { 
            *x = getch();
            printf("%c", *x);
            if (arraySize % 2) //if arraySize is odd
            {
                temp[arraySize]=*x;
                //printf("%s", &temp[arraySize]);
                arraySize++;
                temp2=calloc(arraySize, sizeof(int));
                memcpy(temp2, temp, sizeof(temp2));
                printf("%s", &temp2[arraySize]);
            }
            else //if arraySize is even
            {
                temp2[arraySize]=*x;
                //printf("%s", &temp2[arraySize]);
                arraySize++;
                temp=calloc(arraySize, sizeof(int));
                memcpy(temp, temp2, sizeof(temp));
                printf("%s", &temp[arraySize]);
            }
        }
        //printf("%d\n", arraySize);
        if (arraySize % 2)
        {
            for (i=1; i < arraySize; i++) {
                printf("%s", temp[i]);
            }
        }
        else
        {
            for (i=1; i < arraySize; i++) {
                printf("%s", temp2[i]);
            }
        }
    }

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >>c = getchar(); /* Or c = getc(stdin); */
    >>ch = getchar(); /* standard getchar call */
    You shouldn't be using stdlib functions on a stream that you've manipulate "behind its back". There are implementations that are known to crash when you do this. Use read() on the descriptor instead, like in this simple example: while getch question

    >>Here's the assignment, it's pretty basic:
    So they are expecting you to do advanced termios programming for this "basic assignment"? Or are they expecting a simple scanf(%c) style approach?

    gg

  9. #9
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Codeplug View Post
    There are implementations that are known to crash when you do this.
    Poppycock. I do not believe that for a second.

    That implementation would crash if the user had run e.g. stty -icanon before running any application. So, name at least one such implementation, please.

    (Yes, I am aware of the possibility of an internal library bug for c_cc[VMIN]==0. Those implementations also crash if the user has run stty -icanon min 0 time 1 or similar before running the application. In particular, I fail to see how any implementation could have any issues with c_cc[VMIN]>0, since the syscall behaviour is unchanged wrt. to normal, canonical terminal.)

    The key here is that we are not modifying the internals of anything. The only thing we do that cannot be done by standard commands prior to running the process is setting the stream to unbuffered. And we use a standard library setvbuf() call to do that.

    The only problematic cases for any implementations are when the minimum number of characters returned by the read is zero:
    • c_cc[VMIN] = 0, c_cc[VTIME] = 0
      If data is available, reads return immediately.
      Otherwise, reads return zero -- which normally means an end of input.
    • c_cc[VMIN] = 0, c_cc[VTIME] > 0
      If data is available within the timeout, it is returned.
      Otherwise, reads return zero -- which normally means an end of input.

    It is possible that a library does extra cleanup, and gets confused if it sees more than one end of input. So, I concede that setting c_cc[VMIN]=0 in the terminal settings might cause problems to some implementations, but that is all.

    Note:

    If you want Ctrl+C to work, omit the
    Code:
        raw.c_iflag |= IGNBRK;
        raw.c_iflag &= ~BRKINT;
        raw.c_lflag &= ~ISIG;
    in the raw termios case, or use cbreak() instead of raw() in curses. In that case you should also install your own SIGINT handler to restore the terminal state, and exit the program. If you don't, you'll leave the terminal in raw state, and the user will think you broke something. (And most users don't know to run the 'reset' or 'tput reset' command, which would reset things back to normal.)

    Quote Originally Posted by Paul Omans View Post
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    
    int getch(void) //Dynamic String Input function from Daniweb.com
    { 
        int ch;
        struct termios oldt;
        struct termios newt;
        tcgetattr(STDIN_FILENO, &oldt); /*store old settings */
        newt = oldt; /* copy old settings to new settings */
        newt.c_lflag &= ~(ICANON | ECHO); /* make one change to old settings in new settings */
        tcsetattr(STDIN_FILENO, TCSANOW, &newt); /*apply the new settings immediatly */
        ch = getchar(); /* standard getchar call */
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt); /*reapply the old settings */
        return ch; /*return received char */
    }
    This does very much the same thing as my code does, just with less care, and for every single my_getch() call. You still should call setvbuf() once at the start like I do, to tell your C library to not buffer standard input.

  10. #10
    Registered User
    Join Date
    Oct 2012
    Posts
    42
    Ok, here's my program:
    Code:
     #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <termios.h> 
    #include <string.h> 
     
    int getch(void) //Dynamic String Input function from Daniweb.com
    {  
        int ch; 
        struct termios oldt; 
        struct termios newt; 
        tcgetattr(STDIN_FILENO, &oldt); //store old settings 
        newt = oldt; // copy old settings to new settings 
        newt.c_lflag &= ~(ICANON | ECHO); // make one change to old settings in new settings 
        tcsetattr(STDIN_FILENO, TCSANOW, &newt); //apply the new settings immediatly 
        ch = getchar(); // standard getchar call 
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // reapply the old settings 
        return ch; // return received char  
    } 
     
    int main(void) 
    { 
        char x; 
        int *temp, *temp2;
        char outputTemp[] = {'H','W',' ','3',' ','i','n','p','u','t',':',' '};
        char *output; 
        x = ' ';
        int i; 
        printf("Enter characters: "); 
        int arraySize = 0; 
        temp=calloc(1, sizeof(int)); 
        if (temp == NULL) exit(1);  
        temp2=calloc(1, sizeof(int)); 
        if (temp2 == NULL) exit(1);  
        while (x != '\n') 
        {  
            x = getch(); 
            printf("%c", x); 
            if (arraySize % 2) //if arraySize is odd 
            { 
                temp[arraySize]=x; 
                //printf("%s", &temp[arraySize]); 
                arraySize++;
                free(temp2); 
                temp2=calloc(arraySize, sizeof(arraySize)); 
                memcpy(temp2, temp, sizeof(temp2)); 
            } 
            else //if arraySize is even 
            { 
                temp2[arraySize]=x; 
                //printf("%s", &temp2[arraySize]); 
                arraySize++;
                free(temp); 
                temp=calloc(arraySize, sizeof(arraySize)); 
                memcpy(temp, temp2, sizeof(temp)); 
            } 
        } 
        printf("Total Characters: %d\n", arraySize-1); 
        if (arraySize % 2) 
        { 
           arraySize++;
           free(temp); 
           temp=calloc(arraySize, sizeof(arraySize)); 
           memcpy(temp, temp2, sizeof(temp));
           temp[arraySize] = '\0';
           int totalSize = arraySize + 12;
           output=calloc(totalSize, sizeof(totalSize));
           memcpy(output, temp, sizeof(arraySize));
           memcpy(output, outputTemp, sizeof(12));
           for (i = 0; i < totalSize; i++) {
              printf("%s", output[i]);
           } 
        } 
        else 
        { 
           arraySize++;
           free(temp2); 
           temp2=calloc(arraySize, sizeof(arraySize)); 
           memcpy(temp2, temp, sizeof(temp2));
           temp2[arraySize] = '\0';
           int totalSize = arraySize + 12;
           output = calloc(totalSize, sizeof(totalSize));
           memcpy(output, temp2, sizeof(arraySize));
           memcpy(output, outputTemp, sizeof(12));
           for (i = 0; i < totalSize; i++) {
              printf("%s", output[i]);
           } 
        } 
    }
    The logic looks right to me, although it seg faults somewhere in the last if/else statement (lines 59-86) and I can't figure out why.

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> So, name at least one such implementation, please.
    It was some linux-distro-VM many years ago - I forget. It crashed and the fix was not to go through the CRT (a simple read() is all that's needed anyways).

    It's also how the glibc manual does it: Noncanon Example - The GNU C Library

    gg

  12. #12
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Codeplug View Post
    It was some linux-distro-VM many years ago - I forget. It crashed and the fix was not to go through the CRT (a simple read() is all that's needed anyways).
    I think I recall a bug years ago, where an unexpected EOF (read() returning zero) followed by a successful data read did crash the library. But that wasn't normal or acceptable behaviour, that was a serious bug.

    Quote Originally Posted by Codeplug View Post
    It's also how the glibc manual does it: Noncanon Example - The GNU C Library
    It's pretty bad code for an example! The name variable is unused. The code does not even bother to check the return value from read(), causing c to retain its previous value, yielding unexpected results, in certain cases!

    If you change even tattr.c_cc[VMIN]=0, it will dump the initial (undefined) value of c to standard output continuously. It's easy to miss, since most terminals just ignore the NUL bytes output, but dump the output to e.g. od -t x1 and you'll see. Or, install a signal handler, and start wondering why you get duplicated bytes on input when signals are delivered.

    Finally, mixing stdio.h and low-level unistd.h I/O to the same terminal is often tricky, since many of the struct termios settings affect output. Canonical/noncanonical/raw mode and disabling echo should not affect any output functionality, though.

    I do personally use a lot of low-level unistd.h I/O, with custom numerical data parsers, for large amounts of data; I do have some low-level input routines if someone is interested. I'd use those only for something like a CLI password dialog, or other tricky/sensitive/special cases.

    For normal terminal applications, the sane and portable approach is to use curses.

    In any case, it is a good thing to keep a sharp eye on the suggestions and examples.

  13. #13
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Paul Omans View Post
    The logic looks right to me, although it seg faults somewhere in the last if/else statement (lines 59-86) and I can't figure out why.
    The compiler is really helpful:
    Code:
    $ make foo
    cc -ggdb3 -Wall -Wextra   -c -o foo.o foo.c
    foo.c: In function ‘main’:
    foo.c:71:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
    foo.c:86:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
    foo.c:89:1: warning: control reaches end of non-void function [-Wreturn-type]
    cc   foo.o   -o foo
    But you have other problems too:
    Code:
    $ valgrind -q ./foo
    Enter characters: X==2667== Invalid write of size 4
    ==2667==    at 0x8048777: main (foo.c:41)
    ==2667==  Address 0x41f209c is 0 bytes after a block of size 4 alloc'd
    ==2667==    at 0x402A56B: calloc (vg_replace_malloc.c:566)
    ==2667==    by 0x80487E6: main (foo.c:54)
    ==2667== 
    X
    Code:
    temp[arraySize]=x;   // line 41
    ...
    arraySize++;
    free(temp);
    temp=calloc(arraySize, sizeof(arraySize));  // line 54
    How many elements are in "temp"?

    Bye, Andreas

  14. #14
    Registered User
    Join Date
    Oct 2012
    Posts
    42
    "temp" and "temp2" are arrays that increase as the user enters in characters.
    so, the user enters in one character -> the character gets put into temp with size one -> temp2 is increased by 1 (now its size is 2) -> temp's values are thrown into temp2
    then the process is reversed for the next character and so on and so forth

  15. #15
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Almost every use of "sizeof()" is incorrect.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Capturing keyboard activity
    By Trooper88 in forum C Programming
    Replies: 2
    Last Post: 02-11-2012, 05:27 PM
  2. Capturing Message Time
    By Cell in forum Linux Programming
    Replies: 4
    Last Post: 05-11-2009, 11:51 AM
  3. How do I input an unbuffered character via the keyboard???
    By Michael_in_Ohio in forum C Programming
    Replies: 1
    Last Post: 03-23-2008, 12:00 PM
  4. capturing program input
    By BKurosawa in forum C++ Programming
    Replies: 6
    Last Post: 08-12-2007, 01:14 PM
  5. keyboard capturing
    By xlnk in forum Linux Programming
    Replies: 4
    Last Post: 01-31-2003, 01:02 PM