• Как сохранять значение переменных в input stream?

    includedlibrary
    @includedlibrary
    Я написал простой пример. Для объявления переменной нужно ввести строку символов формата: varname = number. Для вывода значения переменной - строку формата: print varname. Файл htable.c с реализацией хэш-таблицы в вопрос не влез, если его содержимое будет нужным могу сделать гисту.

    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdlib.h>
    #include <string.h>
    #include "htable.h"
    
    typedef struct {
        uint32_t hash;
        char    *var;
        int      val;
    } varnode_t;
    
    uint32_t varnode_hash(hnode_t *_node) {
        varnode_t *node = (varnode_t*)_node;
        return default_hash_func((uint8_t*)node->var, strlen(node->var));
    }
    
    bool varnode_keyeq(hnode_t *_node1, hnode_t *_node2) {
        varnode_t *node1 = (varnode_t*)_node1;
        varnode_t *node2 = (varnode_t*)_node2;
        return !strcmp(node1->var, node2->var);
    }
    
    void varnode_free(hnode_t *_node) {
        varnode_t *node = (varnode_t*)_node;
        free(node->var);
    }
    
    typedef struct {
        char   *input;
        size_t input_size;
        size_t offset;
        char *var;
        int   val;
    } parser_t;
    
    void rollback(parser_t *p) {
        if(p->var) {
            free(p->var);
            p->var = NULL;
        }
    }
    
    bool get_var(parser_t *p) {
        size_t init_offset = p->offset;
        while(p->offset++ < p->input_size) {
            if(p->input[p->offset] == ' ') {
                p->input[p->offset] = '\0';
                p->var = strdup(p->input + init_offset);
                if(!p->var) {
                    perror("failed to allocate memory");
                    return false;
                }
                p->input[p->offset] = ' ';
                while(p->input[p->offset] == ' ' && p->offset < p->input_size)
                    p->offset++;
                return true;
            } else if(p->input[p->offset] < 'a' || p->input[p->offset] > 'z') {
                fputs("error: non-letter character in variable name\n", stderr);
                return false;
            }
        }
        return false;
    }
    
    bool check_eq(parser_t *p) {
        if(p->input[p->offset++] != '=') {
            fputs("error: expected '=' sign\n", stderr);
            return false;
        }
        while(p->input[p->offset] == ' ' && p->offset < p->input_size)
            p->offset++;
        return true;
    }
    
    bool get_val(parser_t *p) {
        if(p->input[p->offset] == '-')
            p->offset++;
        size_t init_offset = p->offset;
        while(p->offset < p->input_size) {
            if(p->input[p->offset] < '0' || p->input[p->offset] > '9') {
                fputs("error: non-digital character in expression\n", stderr);
                return false;
            }
            p->offset++;
        }
    
        p->val = atoi(p->input + init_offset);
    
        return true;
    }
    
    int main() {
        char buf[256];
        parser_t parser = {
            .input = buf,
            .var = NULL
        };
    
        htable_t *vars = htable_create(sizeof(varnode_t), 8,
                                       varnode_hash,
                                       varnode_keyeq,
                                       varnode_free);
        if(!vars)
            return 2;
    
        while(fgets(buf, sizeof(buf)-1, stdin)) {
            parser.offset = 0;
            parser.input_size = strlen(buf);
    
            if(buf[parser.input_size-1] == '\n') {
                buf[parser.input_size-1] = '\0';
                parser.input_size--;
            }
    
            if(strstr(buf, "print")) {
                size_t off = 5;
                while(buf[off] == ' ' && off < parser.input_size)
                    off++;
    
                varnode_t findvar = {
                    .var = buf + off
                };
    
                varnode_t *var = (varnode_t*)htable_lookup(vars, (hnode_t*)&findvar);
                if(!var) {
                    fprintf(stderr, "error: undefined variable %s\n", findvar.var);
                    continue;
                }
    
                printf("%s = %d\n", var->var, var->val);
                continue;
            }
    
            if(!get_var(&parser)  ||
               !check_eq(&parser) ||
               !get_val(&parser)) {
                rollback(&parser);
                continue;
            }
    
            varnode_t *newvar = malloc(sizeof(varnode_t));
            if(!newvar) {
                perror("failed to allocate memory");
                rollback(&parser);
                continue;
            }
    
            newvar->var = parser.var;
            newvar->val = parser.val;
    
            if(!htable_insert(vars, (hnode_t*)newvar)) {
                fprintf(stderr, "error: failed to insert var %s\n", newvar->var);
                rollback(&parser);
                free(newvar);
            }
        }
    
        htable_free(vars);
    }


    htable.h

    #pragma once
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <stddef.h>
    
    typedef struct {
        uint32_t hash;
    } hnode_t;
    
    typedef uint32_t (*htable_hash_func)(hnode_t*);
    typedef bool (*htable_keyeq_func)(hnode_t*, hnode_t*);
    typedef void (*htable_free_func)(hnode_t*);
    typedef struct {
        hnode_t **nodes;
        size_t  node_size;
        size_t  num_nodes;
        size_t  max_nodes;
        int     size_ind;
    
        htable_hash_func  hash_func;
        htable_keyeq_func keyeq_func;
        htable_free_func  free_func;
    } htable_t;
    
    uint32_t default_hash_func(const uint8_t *key, size_t length);
    
    htable_t* htable_create(size_t node_size, size_t max_nodes, htable_hash_func hash_func, htable_keyeq_func keyeq_func, htable_free_func free_func);
    bool htable_insert(htable_t *htable, hnode_t *node);
    hnode_t* htable_lookup(htable_t *htable, hnode_t *node);
    void htable_free(htable_t *htable);

    Ответ написан
    Комментировать