0

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 */
}
11
  • "input below it works". Your description is confusing. The first block of code that you say works is exactly the same as the block that doesn't work except "type.h has changed to ctype.h. Is that really what you are trying to highlight? Commented Nov 14, 2021 at 21:59
  • 1
    it is far too complicated for SO question. Strip it to the minimal example Commented Nov 14, 2021 at 21:59
  • @0___________ I'll strip it down Commented Nov 14, 2021 at 22:00
  • 2
    for (v = var, (c=getchar()) =='*'? c = getchar(): c; c != ';' && c != '['; *v = '\0', c = getchar()) this line is not "hacky" - it is error prone, horrible and after one day you will forget what it is supposed to do. Do not save keyboard. Split it into multiline logical block. Commented Nov 14, 2021 at 22:23
  • 2
    This program is small enough that you can step through it line by line. You should have noticed that (*r)++ modifies the contents of reserved which means that the recursive call receives a corrupted reserved array. Commented Nov 14, 2021 at 22:52

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much. I was trying to wrap my head around why the pointer gave an error. But this solution is very helpful. Thank you so much for the helpful tips
My pleasure. The divide and conquer strategey is a the single most important cpncept in programming.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.