0

我有 26 个值,我正在考虑作为特殊符号,并且与特殊分隔符“$”一样,值可以从 $A 到 $Z。

同时我有一个预定义的模板:

我有$A,$B,$C.....

现在我允许用户输入一个可以包含特殊符号的字符串和这些示例的值:输入 - $ACar $BBike $CTruck。

那么我的输出应该是: *我有 Car,Bike,Truck... *

现在所有特殊符号都已被其值替换。

注意 1.如果 $A Car $A Bike 是输入值,那么它应该采用 $A 作为 Car rest 应该被丢弃。

如果输入字符串不包含任何特殊符号,则输出应该没有变化,输出将是我有 $A,$B,$C.....

3.if input start as i am a men $A glass然后直到 $A 所有值都应该被丢弃。

我应该遵循哪种方法来实现这一点?

我正在考虑对输入字符串执行strstr并将它们与我的特殊符号进行比较,并将特殊符号的位置存储在列表中,然后根据我想取值的位置,但我认为它不会适用我。

4

2 回答 2

1

通过使用动态字符串简化了处理。

像这样

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

typedef struct dstr {
    size_t size;
    size_t capacity;
    char *str;
} Dstr;//dynamic string

Dstr *dstr_make(void){
    Dstr *s;
    s = (Dstr*)malloc(sizeof(Dstr));
    s->size = 0;
    s->capacity=16;
    s->str=(char*)realloc(NULL, sizeof(char)*(s->capacity += 16));
    return s;
}

void dstr_addchar(Dstr *ds, const char ch){
    ds->str[ds->size] = ch;
    if(++ds->size == ds->capacity)
        ds->str=(char*)realloc(ds->str, sizeof(char)*(ds->capacity += 16));
}

void dstr_addstr(Dstr *ds, const char *s){
    while(*s) dstr_addchar(ds, *s++);
    //dstr_addchar(ds, '\0');
}

void dstr_free(Dstr *ds){
    free(ds->str);
    free(ds);
}

void dic_entry(char *dic[26], const char *source){
    char *p, *backup, ch;

    p = backup = strdup(source);

    for(;NULL!=(p=strtok(p, " \t\n"));p=NULL){
        if(*p == '$' && isupper(ch=*(p+1))){
            if(dic[ch -'A'] == NULL)
                dic[ch -'A'] = strdup(p+2);
        }
    }
    free(backup);
}

void dic_clear(char *dic[26]){
    int i;
    for(i=0;i<26;++i){
        if(dic[i]){
            free(dic[i]);
            dic[i] = NULL;
        }
    }
}

int main(void){
    const char *template = "I have $A,$B,$C.";
    char *dic[26] = { 0 };
    char buff[1024];
    const char *cp;
    Dstr *ds = dstr_make();

    printf("input special value setting: ");
    fgets(buff, sizeof(buff), stdin);
    dic_entry(dic, buff);

    for(cp=template;*cp;++cp){
        if(*cp == '$'){
            char ch;
            if(isupper(ch=*(cp+1)) && dic[ch - 'A']!=NULL){
                dstr_addstr(ds, dic[ch - 'A']);
                ++cp;
            } else {
                dstr_addchar(ds, *cp);
            }
        } else {
            dstr_addchar(ds, *cp);
        }
    }
    dstr_addchar(ds, '\0');
    printf("result:%s\n", ds->str);

    dic_clear(dic);
    dstr_free(ds);
    return 0;
}
/* DEMO
>a
input special value setting: $ACar $BBike $CTruck
result:I have Car,Bike,Truck.

>a
input special value setting: $BBike
result:I have $A,Bike,$C.
*/
于 2013-05-14T10:54:17.353 回答
0

您所描述的称为Macro ProcessorMacro Expander

您可以将符号表存储在由输入字符索引的数组中。

char *symtab[256] = {0};

由于符号名称是单字母,因此您可以使用strchr查找第'$'一个字符并检查下一个字符是否为字母 ( isupper())。

对于实际的替换,它将需要一些精细的内存管理,除非您只使用非常大的缓冲区并确保只提供少量数据。

如果symtab['A'] == "Car"那么你可以loc = strstr(line, "$A")。然后loc-line前缀部分2的长度,是被删除的符号名strlen("Car")的长度,是替换strlen(loc+2)的长度,是后缀部分的长度。所以新的字符串大小应该是

char *result = malloc( (loc-line) - 2 + strlen(symtab['A']) + strlen(loc+2) + 1);

然后修补新字符串是

strcpy(result,line);
strcpy(result + (loc-line), symtab['A']);
strcpy(result + (loc-line) + strlen(symtab['A']), loc+2);

请注意,这些strcpy 不是 strcat将字符串附加在一起的。第二个和第三个strcpy调用覆盖刚刚复制的字符串的尾部。

于 2013-05-14T05:19:07.893 回答