Results 1 to 9 of 9

Thread: Getting input and checking for key press

  1. #1
    Join Date
    Dec 2011
    Location
    -bash
    Posts
    515
    Mentioned
    0 Post(s)
    Quoted
    27 Post(s)

    Default Getting input and checking for key press

    So what I need it to do is to request input to fill the vector with an already specified amount of input. It is supposed to do something even when the user presses the enter key (it is not supposed to ignore these). Then it is supposed to keep looping until all valid characters have been entered. We are only allowed to use the following functions to accomplish getting and reading of input as well as output:

    fgets(3), sscanf(3), scanf(3), fscanf(3), fprintf(3), printf(3), cin >>, if you are not adept with linux and shell programming, the numbers in bracket means the man[ual] page where you can find how these functions work.

    My problem is that I can't seem to get it to respond to the pressing of the enter key. I already tried using printf to find out what value is returned from the enter key; and on Macs, it is 10. I haven't tried yet with linux or windows. But even that is still not making it produce the message I want to display when such an occurrence occurs.

    The vector is receiving integers but fscanf is converting it to float/double (which one is it?). Here is the declaration of Vector type:

    C++ Code:
    #include <cstdlib>
        #include <cstdio>
        #include <cassert>
        #include <cctype>
        #include <cstring>
        using namespace std;

        typedef float Elem;

        struct Vector
        {
            Elem* new_Elem;
            int numElements;
        };
    Vector *alloc_vec(void)
        {
            Vector* vect = new Vector;
            assert(NULL != vect);
            return vect;
        }
    #ifdef TESTING
        int main(void)
        {
            int buffer;
            int n_el;
            Vector* myVec = alloc_vec();
            scanf("%d", &myVec->numElements);
            myVec->new_Elem = new float[myVec->numElements];
            assert(0 <= myVec->numElements && (myVec->numElements % 1) == 0 && myVec->numElements < 65535);
           
            for(int e = 0; e < myVec->numElements; e++)
            {
                printf("vector element %d: ", e + 1);
                n_el = fgetc(stdin);
                printf("%d", n_el);
                buffer = fscanf(stdin, "%f", &myVec->new_Elem[e]);
               
                /*if (buffer <= 0)
                {
                    e--;
                    fprintf(stderr, "no value specified\n");                
                }*/

                if (feof(stdin))
                {
                    fprintf(stderr, "\nproblem reading input values\n");
                    exit(EXIT_FAILURE);
                }
            }
    #endif

    p.s. I cheated and used fgetc(3), but I am no supposed to use that

  2. #2
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    I don't understand that code. What exactly are you filling the vector with? Chars? Doubles? Floats?

    According to your code, I see doubles and floats. No chars or Dwords. How do you plan on getting the keypress?
    I am Ggzz..
    Hackintosher

  3. #3
    Join Date
    Dec 2011
    Location
    -bash
    Posts
    515
    Mentioned
    0 Post(s)
    Quoted
    27 Post(s)

    Default

    The vector is receiving integers but fscanf is converting it to float/double (which one is it?). Here is the declaration of Vector type.

    *Updated above post with complete(ish) code*

    Key press can only be received via these functions :
    fgets(3), sscanf(3), scanf(3), fscanf(3), fprintf(3), printf(3), cin >>. And that is my question...how do I get key press with the above functions? I know other functions that could accomplish this better, but my prof only wants us to use those functions. atoi(), atof() can also be used in place of sscanf or w/e

  4. #4
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Are you sure the teacher said key-presses can be detected with the >> operator?

    If so, get a new teacher. I think the only options for the enter-key in the above (without much work/regular-expressions) is either:

    std::cin.get() or fgets.

    Also watch it when allocating and deallocating. I noticed you didn't destruct anything:

    C++ Code:
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>

    typedef int Elem;    //If this is defined as int, then your vector will be a vector of Integers. If this is float, your vector is of Floats.

    struct Vector
    {
        Elem* Element;
        int numElements;
    };

    void ConstructSingleVector(Vector* &vector, int AmountOfElements)
    {
        //Perhaps make sure the user doesn't enter 0 as the amount of elements.
        vector = new Vector;
        vector->Element = new Elem[AmountOfElements];
        vector->numElements = AmountOfElements;
    }

    void DestructSingleVector(Vector* &vector)
    {
        if (vector->numElements <= 1)
        {
            delete vector->Element;
            delete vector;
            vector = NULL;
        }
        else
        {
            delete[] vector->Element;
            delete vector;
            vector = NULL;
        }
    }

    bool IsDigits(char* Buffer, int Length)
    {
        for (int I = 0; I < Length; ++I)
            if (!isdigit(Buffer[I]))
                return false;
        return true;
    }

    void FillVector(Vector* &List)
    {
        for (int I = 0; I < List->numElements; ++I)
        {
            char Buffer[1024] = {0};
            printf("Enter the next element in the vector: ");
            fgets(Buffer, 1024, stdin);

            if (IsDigits(Buffer, strlen(Buffer) - 1))
                List->Element[I] = atoi(Buffer);
            else
                printf("Invalid Input!\n");
        }
    }

    void PrintVector(Vector* List)
    {
        for (int I = 0; I < List->numElements; ++I)
        {
            printf("Element #%i: %i\n", I, List->Element[I]);
        }
    }

    int main()
    {
        int Length = 10;
        Vector* List = NULL;

        ConstructSingleVector(List, Length);

        FillVector(List);
        PrintVector(List);

        DestructSingleVector(List);
    }
    Last edited by Brandon; 10-26-2012 at 02:43 AM.
    I am Ggzz..
    Hackintosher

  5. #5
    Join Date
    Dec 2011
    Location
    -bash
    Posts
    515
    Mentioned
    0 Post(s)
    Quoted
    27 Post(s)

    Default

    No he didn't say key press can only be recieved using >> operator, but since the functions I mentioned above are the only ones we are allowed to use, I assumed one of those has to be the one that could be used to get key press.

    I will just post my entire code here, maybe you can give me an advice or 2 or 3 on how to better make use of them. The function names were all given to us by the prof, so I "have to" use the ones I used in my code.

    C++ Code:
    #include <cstdlib>
        #include <cstdio>
        #include <cassert>
        #include <cctype>
        #include <cstring>
        using namespace std;

        typedef float Elem;

        struct Vector
        {
            Elem* new_Elem;
            int numElements;
        };

        void usage( void )
        {
            puts( " Usage:" );
            puts( "  p   - print vector" );
            puts( "  q,e - quit, end" );
            puts( "  h   - print usage help" );
            puts( "  + <operand> - add <operand> to each element of vector" );
            puts( "  - <operand> - subtract <operand> from each element of vector" );
            puts( "  * <operand> - multiple each element of vector by <operand>" );
            puts( "  / <operand> - divide each element of vector by <operand>" );
            puts( "  a <value> - extend vector by additional value" );
        }

        Vector *alloc_vec(void)
        {
            Vector* vect = new Vector;
            assert(NULL != vect);
            return vect;
        }

        bool print_vec(Vector * vect)
        {
            if (0 == vect->numElements)
            {
                printf("\n");
            }
            else
            {
                for (int i = 0; i < vect->numElements; i++)
                {
                    printf("%f ", vect->new_Elem[i]);
                }
            }
            return true;
        }

        void dealloc_vec(Vector* vect)
        {
            if (1 >= vect->numElements)
            {
                delete vect->new_Elem;
                delete vect;
            }
            else
            {
                delete[] vect->new_Elem;

                vect->numElements = 0;
                delete vect;
            }
        }

        Vector *extend_vec(Vector * vect, Elem new_Elem)
        {
            Vector *vect2 = alloc_vec();
            vect2->numElements = vect->numElements + 1;
            if (0 == vect->numElements)
            {
                vect2->new_Elem[0] = new_Elem;
                vect->new_Elem[vect->numElements] = vect2->new_Elem[0];
                vect->numElements += 1;
                delete vect2->new_Elem;
                vect2->numElements = 0;
                delete(vect2);
            }
            else
            {
                for (int v = 0; v < vect->numElements; v++)
                {
                    vect2->new_Elem[v] = vect->new_Elem[v];
                    vect->new_Elem[v] = vect2->new_Elem[v];
                    if ((v + 1) == vect->numElements)
                    {
                        vect2->new_Elem[v + 1] = new_Elem;
                    }
                }
                vect->numElements += 1;
                vect->new_Elem[vect->numElements] = vect2->new_Elem[vect2->numElements];
                delete[] vect2->new_Elem;
                vect2->numElements = 0;
                delete(vect2);
            }
           
            return vect;
        }

        Vector *scalar_plus(Vector * vect, Elem scalar)
        {
            if (NULL == vect)
            {
                return NULL;
            }
            else
            {
                for (int p = 0; p < vect->numElements; p++)
                {
                    vect->new_Elem[p] = (vect->new_Elem[p] + scalar);
                }
            }
            return vect;
        }

        Vector *scalar_minus(Vector * vect, Elem scalar)
        {
            if (NULL == vect)
            {
                return NULL;
            }
            else
            {
                for (int m = 0; m < vect->numElements; m++)
                {
                    vect->new_Elem[m] = (vect->new_Elem[m] - scalar);
                }
            }
            return vect;
        }

        Vector *scalar_mult(Vector * vect, Elem scalar)
        {
            if (NULL == vect)
            {
                return NULL;
            }
            else
            {
                for (int x = 0; x < vect->numElements; x++)
                {
                    vect->new_Elem[x] = (vect->new_Elem[x] * scalar);
                }
            }
            return vect;
           
        }

        Vector *scalar_div(Vector * vect, Elem scalar)
        {
            if (NULL == vect)
            {
                return NULL;
            }
            else
            {
                for (int d = 0; d < vect->numElements; d++)
                {
                    vect->new_Elem[d] = (vect->new_Elem[d] + scalar);
                }
            }
            return vect;
           
        }

    Btw, do I have to set the vector to NULL (in this function void DestructSingleVector(Vector* &vector)) even after deleting it? I thought that is what delete does?

    The goal of the assignment is to practice TDD, which is why I used the ifdef units to test certain parts and make sure they work before moving on. So right now, I am testing for getting user input which is taking longer than necessary. But I think I will now go with fgets and sscanf and see where those will get me.

    E: Btw in your isDigits() function, it will not catch the new-line character because (maybe this is just on macs) when I used fgetc() to get the value returned by the new_line character, it returned 10. And when I used it get return for end of file character, it returned -1. So your function might only work for EOF. Hmm, I wonder if it only returns the 10 because the fgetc() function returns type integer...

  6. #6
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by [Re]cUrSivE View Post
    No he didn't say key press can only be recieved using >> operator, but since the functions I mentioned above are the only ones we are allowed to use, I assumed one of those has to be the one that could be used to get key press.

    I will just post my entire code here, maybe you can give me an advice or 2 or 3 on how to better make use of them. The function names were all given to us by the prof, so I "have to" use the ones I used in my code.

    .........

    Btw, do I have to set the vector to NULL (in this function void DestructSingleVector(Vector* &vector)) even after deleting it? I thought that is what delete does?

    The goal of the assignment is to practice TDD, which is why I used the ifdef units to test certain parts and make sure they work before moving on. So right now, I am testing for getting user input which is taking longer than necessary. But I think I will now go with fgets and sscanf and see where those will get me.

    E: Btw in your isDigits() function, it will not catch the new-line character because (maybe this is just on macs) when I used fgetc() to get the value returned by the new_line character, it returned 10. And when I used it get return for end of file character, it returned -1. So your function might only work for EOF. Hmm, I wonder if it only returns the 10 because the fgetc() function returns type integer...
    The names of the functions are given to you? OR is it the definition of the function that is given to you? Also don't worry about the function names I used. The logic is what you should see rather than function definition.


    Well it's usually good practice to set global pointers to NULL when they are no longer going to be used. I passed a reference to a pointer and deleted it. It's only right I set it to NULL to guarantee it points to nothing (the standard guarantees this either way) and to make specific to the user that it should not be used. Almost everyone knows that you should not write to a NULL pointer and that reading from it is undefined/garbage.

    Also I showed an example using fgets already :S It does indeed detect the enter key. The IsDigits is passed the length of the buffer - 1. That's so that it ignores the newline/null terminating character at the very end of the array. The thing is, fgets BREAKS on Enter-key press. Thus you know if the value of the vector at that index is 0, the Enter-key was either pressed OR the user entered 0.

    You can test that it works by setting that index to -1 if the buffer-length is 0 as the buffer is within the scope of the for-loop and will be recreated every loop.

    Also I don't think I'd extend the vector like that..


    C++ Code:
    template<typename T>
    void Delete(T* &Type, size_t Size)     //As we delete in the destructor and in resizing and in all C-Style arrays/pointers, might as well template this.
    {
        if (Size > 1)
            delete[] Type;
        else
            delete Type;
        Type = NULL;
    }

    template<typename T>
    void ResizePointer(T* &Array, size_t OldSize, size_t NewSize)  //Templated because it'd be so useful in the future for any array's/pointers. Does NOT work on Void*. For that, use ::Operator New.
    {
        if (OldSize < 1)
        {
            Array = new T[NewSize];
        }
        else if (NewSize > 0)
        {
            T* Temp = new T[NewSize];
            for (int I = 0; I < OldSize; ++I)   //Copy the elements of the old array to a temp array.
                Temp[I] = Array[I];

            Delete(Array, OldSize);            //Delete the old array and allocate a new array using the original pointer.
            Array = new T[NewSize];

            for (int I = 0; I < NewSize; ++I)           //Copy back all the old elements and set all the new ones to default/null
                Array[I] = I < OldSize ? Temp[I] : T(0);

            Delete(Temp, NewSize);       //Clean up the temporary.
        }
        else
            Delete(Array, OldSize);
    }


    //Using the above Templates:

    void ResizeVector(Vector* &List, size_t NewSize)
    {
        ResizePointer(List->new_Elem, List->numElements, NewSize);
        List->numElements = NewSize;
    }


    //Without using the ResizePointer Template:

    void ResizeVector(Vector* &List, size_t NewSize)
    {
        if (NewSize > 0)
        {
            Elem* TempElements = new Elem[NewSize];

            for (int I = 0; I < List->numElements; ++I)
                TempElements[I] = List->new_Elem[I];

            Delete(List->new_Elem, List->numElements);
            List->new_Elem = new Elem[NewSize];

            for (int I = 0; I < NewSize; ++I)
                List->new_Elem[I] = I < List->numElements ? TempElements[I] : 0;

            List->numElements = NewSize;
            Delete(TempElements, NewSize);
        }
        else
            Delete(List->new_Elem, List->numElements);
    }
    Last edited by Brandon; 10-26-2012 at 03:35 PM.
    I am Ggzz..
    Hackintosher

  7. #7
    Join Date
    Dec 2011
    Location
    -bash
    Posts
    515
    Mentioned
    0 Post(s)
    Quoted
    27 Post(s)

    Default

    Can you explain what this part does?
    C++ Code:
    for (int I = 0; I < NewSize; ++I)
               [B] List->new_Elem[I] = I < List->numElements ? TempElements[I] : 0;[/B]

            List->numElements = NewSize;
            Delete(TempElements, NewSize);

    E: Have some questions about fgets
    Does it read in value byte by byte i.e. if the user types in 123434 + return
    Then does fgets store this as [123434\n\0] and the number of characters is 8?

    If the user types -return
    fgets stores this as [\n\0]? And number of characters is 2?

    E2:
    I tried using your is digits function and the fill vector function, but this time it wouldn't wait for input and just goes to the next value...

    Code:
    Vecalc Recu$ ./vecalc.testing 
    3
    vector element 1: vector element 2: 
    vector element 3:
    I used printf to see the values it is storing in myVec elements and here is what I got:
    Code:
    Vecalc Recu$ ./vecalc.testing 
    3
    vector element 1: 
    0.000000vector element 2: 
    
    0.000000vector element 3: 
    
    0.000000
    I think this one will be a better replacement for the isdigits no?
    C++ Code:
    bool Is_ErrNDigits(char* Buffer)
    {
        for (int I = 0; Buffer[I] != '\0'; I++)
        {
            if (isspace(Buffer[I] - 1))
                return false;
        }
        return true;
    }

  8. #8
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by [Re]cUrSivE View Post
    Can you explain what this part does?
    C++ Code:
    for (int I = 0; I < NewSize; ++I)
               [B] List->new_Elem[I] = I < List->numElements ? TempElements[I] : 0;[/B]

            List->numElements = NewSize;
            Delete(TempElements, NewSize);

    For every element in the temporary array, copy it to the new resized array. If there aren't enough elements, fill the rest with 0/default/null.

    C++ Code:
    for (int I = 0; I < NewSize; ++I)
     {
        if (I < List->numElements)                  //Copy all the elements from the temp array to the reallocated array.
        {
            List->numElements[I] = TempElements[I];
        }
        else
        {
            List->numElements[I] = 0;               //Fill the remainding elements with 0/null/default.
        }
    }

    List->numElements = NewSize;                    //Set the size of the new vector.
    Delete(TempElements, NewSize);                  //delete the temporary vector.

    fgets DOES store the enter key. It "Breaks" when enter is pressed. To check if it is stored, you do:

    C++ Code:
    char Buffer[1024] = {0};
    fgets(Buffer, 1024, stdin);

    for (int I = 0; I < strlen(Buffer); ++I)
        printf("%i\n", (int)Buffer[I]);      //Last character that prints should be 10 which is the ascii value of NewLine.

    All the methods above technically break on enter but it will not show if it doesn't have the cast to an int. The strlen(Buffer) -1 is to ignore the enter key press because it isn't an int until casted to. Thus IsDigits would fail upon reaching the last character in the array.



    EDIT:

    Ok now I'm unclear on what you're trying to do. Here's why. First post says that enter should not be ignored (Trap enter) but the E2 above post says it goes to the next element without waiting on input (Don't Trap enter).

    Which one do you need? The code I posted will Trap Enter and when it's pressed, it'll go to the next index in the array. It means that it's up to the user to enter something. If they enter nothing, that index will be filled with 0. If you press Enter 10 times, it will fill the vector with 10 Zeroes.

    If you want to NOT Trap enter (Aka ignore the enter button which will force the user to enter a value), then the following will suffice:

    C++ Code:
    void FillVector(Vector* &List)
    {
        for (int I = 0; I < List->numElements; ++I)
        {
            char Buffer[1024] = {0};
            printf("Enter the next element in the vector: ");
            std::cin>> Buffer;    //Can also just make it enter directly into an int which will require error checking.
            std::cin.ignore();

            if (IsDigits(Buffer, strlen(Buffer) - 1))
                List->Element[I] = atoi(Buffer);
            else
                printf("Invalid Input!\n");
        }
    }
    Last edited by Brandon; 10-26-2012 at 05:46 PM.
    I am Ggzz..
    Hackintosher

  9. #9
    Join Date
    Dec 2011
    Location
    -bash
    Posts
    515
    Mentioned
    0 Post(s)
    Quoted
    27 Post(s)

    Default

    Oh sorry man. I don't want to trap the enter key; I want to force the user to enter a valid input to continue but I want it to display a message when ever the user presses enter...I will try your method above and see what happens

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •