[Solved] Need algorithm to solve shifting in C [closed]


like this (error handling is omitted, strtok_r removed if strtok_r can use):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *strtok_r(char *str, const char *delims, char **store){
    char *p, *wk;
    if(str != NULL){
        *store = str;
    }
    if(*store == NULL) return NULL;
    *store += strspn(*store, delims);//skip delimiter
    if(**store == '\0') return NULL;
    p=strpbrk(wk=*store, delims);
    if(p != NULL){
        *p='\0';
        *store = p + 1;
    } else {
        *store = NULL;
    }
    return wk;
}

#define SHIFT_KEYWORD "shift_value"

typedef struct pair {
    char *key;
    int  val;
} Pair;

int cmp(Pair *a, Pair *b){
    return strcmp(a->key, b->key);
}

Pair *parse_command(const char *commands, int *num_cmd){
    char *pc, *cmd = strdup(commands);

    if(NULL!=(pc = strtok(cmd, " ")) && strcmp(pc, "-shift")!=0){
        fprintf(stderr, "command format error!\n");
        *num_cmd = 0;
        free(cmd);
        return NULL;
    }
    char *p;
    pc = strtok(NULL, " ");
    *num_cmd=1;
    for(p=pc;NULL!=(p=strchr(p, ':'));++p){
        ++*num_cmd;//count command
    }
    Pair *cmds = calloc(*num_cmd, sizeof(Pair));
    int c = 0;
    char *pr1, *pr2;
    for(p = pc;NULL!=(p=strtok_r(p, ":", &pr1));p=NULL){
        const int len = sizeof(SHIFT_KEYWORD)-1;
        for(;NULL!=(p=strtok_r(p, "=", &pr2));p=NULL){
            if(strncmp(p, SHIFT_KEYWORD, len)==0)
                cmds[c++].val = atoi(p + len);
            else
                cmds[c].key = strdup(p);
        }
    }
    qsort(cmds, *num_cmd, sizeof(Pair), (int (*)(const void*,const void*))cmp);
    free(cmd);
    return cmds;
}

int count_element(FILE *fp){
    int ch, count =0;
    while(EOF!=(ch=fgetc(fp))){
        if(ch == '=')
            ++count;
    }
    rewind(fp);
    return count;
}

typedef struct vec {
    int value;
    Pair pair;
} Vec;

int cmpv(const void *x, const void *y){
    Vec *a = (Vec*)x;
    Vec *b = (Vec*)y;
    return a->value != b->value ? a->value - b->value : strcmp(a->pair.key, b->pair.key);
}

int main(void){
    const char *command ="-shift p100=shift_value15:p5=shift_value4:p7=shift_value2";
    int num_cmd;
    Pair *cmd_list;

    cmd_list=parse_command(command, &num_cmd);

    FILE *fp=fopen("a.txt","r");
    int num_vec = count_element(fp);
    Vec v[num_vec];
    char buff[1024];
    int c=0;
    while(fgets(buff, sizeof(buff), fp)){
        char *p;
        int value;
        p=strtok(buff, " \n");
        if(*p == '#')
            value = atoi(p+1);
        else {
            fprintf(stderr, "data format error\n");
            exit(1);
        }
        for(;NULL!=(p=strtok(NULL, " \n"));++c){
            Pair *cmd;
            char *pr, *key;
            int event;
            pr=strchr(p, '=');
            *pr="\0";
            key = strdup(p);
            event = atoi(pr+1);
            v[c].value = value;
            v[c].pair.key = key;
            v[c].pair.val = event;
            cmd = bsearch(&v[c].pair, cmd_list, num_cmd, sizeof(Pair), (int (*)(const void*,const void*))cmp);
            if(cmd){
                v[c].value = value + cmd->val;
            }
        }
    }
    fclose(fp);
    qsort(v, num_vec, sizeof(Vec), cmpv);

    //stdout -> fp = fopen("a.txt", "w");
    int i, pre_value=-1;
    for(i=0;i<num_vec;++i){
        if(pre_value != v[i].value){
            if(pre_value!=-1)
                fprintf(stdout, "\n");
            fprintf(stdout, "#%-2d", pre_value=v[i].value);
        }
        fprintf(stdout, " %s=%d", v[i].pair.key, v[i].pair.val);
        free(v[i].pair.key);
    }
    for(i=0;i<num_cmd;++i){
        free(cmd_list[i].key);
    }
    free(cmd_list);
    return 0;
}

1

solved Need algorithm to solve shifting in C [closed]