Home > front end >  Why does the pointer not reset, in a recursive function call
Why does the pointer not reset, in a recursive function call

Time:11-15

I have been trying to get a variable from an input. So I get each word, and check it if it is part of a reserved array. If it is part of the reserved array, I get the next word from input, which is a variable.

Below is the reserved array:

char *reserved[] = {
            "char", NULL
    };

The program is presented with two inputs. One with type.h, and another with ctype.h.The first input works, but the second doesn't:

#include <stdio.h>     /*works*/
#include <type.h>
char *reserved[] = {
#include <stdio.h>     /* doesn't work */
#include <ctype.h>
char *reserved[] = {

So a function gets a word from the input, and checks to see if it is a reserved word. If it is, it is added to a variable array, but if it isn't a reserved word, the function is run again:

    for(w = word, r = reserved; *r!= NULL; w=word, r  )     /* Go to the next reserved word*/
        for (; *w == **r; (*r)  , w  )               /* check if the reserved word matches the word */
            if (*w == '\0') {                             /* if it does, what follows is a variable */
                getchar();                              /* get the space */
                for (v = var, (c=getchar()) =='*'? c = getchar(): c;  c != ';' && c != '['; *v = '\0', c = getchar())
                    *v   = c;                              /* add the variable to the variable array */
                return var;                                /* return start of variable array */
            }

    if ((isalpha(*var)) == 0) {          /* if variable array is empty, recursively run the function */
        var = getvar(var, reserved);
    }

*r gets incremented when the program checks the input ctype, since ctype's first character and the first character of char reserved word match. But the words don't match and the function runs again this time checking the input char. The pointer r gets set to the start of the reserved function when the function gets called again:

for(w = word, r = reserved; *r!= NULL; w=word, r  )

So **r should point to the character c of the char reserved word, but it points to h of char.

Could you please explain, why the pointer doesn't get pointed to the start, even though I just set it to point to the start of the array, when I said r = reserved.

I have attached the code below, if you would like to run it through a debugger.

#include <stdio.h>
#include <ctype.h>
char *getvar(char *var, char *reserved[]);
int main() {
    char var[100];              /* stored a variable */
    char *v;                    /* pointer to the start of variable array variable */
    char *reserved[] = {
            "char", NULL
    };
    v = getvar(var, reserved);  /* returns the start of a variable array */
    printf("%s", v);            /* prints the variable*/
    return 0;
}

char *getvar(char *var, char *reserved[])
{
    int c;                       /* a character*/
    char *v, *w, **r;           /* a variable, word, and a reserved word character*/
    char word[100];             /* an array with a word */

    while(((isalpha(c = getchar())) == 0) && c != EOF );  /* skip till you get to a name */

    for(w = word; c != ' ' && c!='\n' && c!='\t' && c != EOF; c=getchar(), *w = '\0')
        *w   = c;                                           /* add name to a word */

    for(w = word, r = reserved; *r!= NULL; w=word, r  )     /* Go to the next reserved word*/
        for (; *w == **r; (*r)  , w  )               /* check if the reserved word matches the word */
            if (*w == '\0') {                             /* if it does, what follows is a variable */
                getchar();                              /* get the space */
                for (v = var, (c=getchar()) =='*'? c = getchar(): c;  c != ';' && c != '['; *v = '\0', c = getchar())
                    *v   = c;                              /* add the variable to the variable array */
                return var;                                /* return start of variable array */
            }

    if ((isalpha(*var)) == 0) {          /* if variable array is empty, recursively run the function */
        var = getvar(var, reserved);
    }
    return var;                                            /* return start of variable array */
}

CodePudding user response:

Your code logic is unnecessarily complex, and this makes this function very dificult to debug... There are also many errors in the logic pof your program, whioch make it impossible to debug as is. What I mean is that there is no way that fixing this pointer mistake (or error) will get this program working straight away...

The first rule you want to adhere to is that a program is a collection of simple algorithms divided into functions which you assemble into more complex algorithms.

As in, for example:

// You want to write functions that only do one thing at a time, this will 
// make both your life and the reader's life a much more pleasant experience.
//
// This function reads a word from standard input
// params: 
//  - word:       work buffer to hold result.
//  - max_length: number of bytes in work buffer.
// returns:
//  - the address of buffer 'word'
//  - NULL on error
//
const char* read_input(char* word, int max_length)
{
    // get a word:
    // 1. skip until first alpha char, if EOF function FAILS (used to exit program)
    // 2. read until first non-alpha char (EOF implicitely included)

    char* w = word;
    while (!isalpha(*w = getchar())
        if (*w == EOF)
            return NULL;
    
    while (isalpha(*(  w) = getchar()) 
        if (w >= word   max_length - 1)
            return NULL;   // We're overflowing our storage space !!!
                           // You may want to print an error message here.

    *  w = 0;         // NULL terminate the string.
    return word;      // we're successful
}

// this function looks for word pointed to by 'word' in 
// NULL terminated array 'keywords'
//
// returns:
//  - if successful returns value of pointer 'word'.
//  - if failed, returns NULL
//
const char* find_keyword(const char* word, const char** keywords)
{
    // Loop through array
    // compare strings 
    // return immediately when found

    while (*keywords)
    {
        if (strcmp(word, *keywords) == 0)
            return word;
          keywords;
    }

    return NULL;
 }

 int main()
 {
     char word[100];
     const char* w, *kw;
     const char *reserved[] = { "char", NULL };

     // 1. get next keyword from input, if NULL, exit.
     // 2. check if it is a reserved keyword.
     // 3. give some visual feedback.
     
     while ((w = read_input(word, sizeof(word))) != NULL)
     {
         kw = find_keyword(w, reserved);
         if (kw)
             printf("%s\n", kw);
         else
             printf("keyword \'%s\' not found!\n", w); 
     }
     return 0;
 }

Note that sparating concerns makes the code much easier to write and debug. It also eliminates unnecessary complex, and error-prone, pointer arithmetics.

NOTE: this code is for illustration only. I haven't compiled it, haven't run it, but it should be fairly close to what you want to achieve. If you cannot use strcmp for some reason, comparing 2 strings is a very easy and straightforard function to write, as long as you isolate it from the rest of the code.

  • Related