1

我对 Python 编码非常熟悉,但现在我必须在 C 中进行字符串解析。

我的输入:

输入=“command1 args1 args2 arg3;command2 args1 args2 args3;cmd3 arg1 arg2 arg3”

我的 Python 解决方案:

input = "command1 args1 args2 arg3;command2 args1 args2 args3;command3 arg1 arg2 arg3"
compl = input.split(";")
tmplist =[]
tmpdict = {}

for line in compl:
    spl = line.split()
    tmplist.append(spl)

for l in tmplist:
     first, rest = l[0], l[1:]
     tmpdict[first] = ' '.join(rest)

print tmpdict

#The Output: 
#{'command1': 'args1 args2 arg3', 'command2': 'args1 args2 args3', 'cmd3': 'arg1 arg2 arg3'}

预期输出:以命令为键的字典,并将参数作为字符串连接到值中

到目前为止我的 C 解决方案:

我想将我的命令和参数保存在这样的结构中:

struct cmdr{
    char* command;
    char* args[19];
};
  1. 我创建了一个 struct char* 数组来保存由“;”分隔的 cmd + args:

    结构 ari { char* value[200];};

功能:

struct ari inputParser(char* string){
    char delimiter[] = ";";
    char *ptrsemi;  
    int i = 0;
    struct ari sepcmds;
    ptrsemi = strtok(string, delimiter);

    while(ptrsemi != NULL) {
        sepcmds.value[i] = ptrsemi;
        ptrsemi = strtok(NULL, delimiter);
        i++;

    }
return sepcmds;     
  1. 按空格分隔命令和数组并将它们保存在我的结构中:

首先我添加了一个帮助结构:

struct arraycmd {
struct cmdr lol[10];
};



struct arraycmd parseargs (struct ari z){
    struct arraycmd result;
    char * pch;
    int i;
    int j = 0;

    for (i=0; i < 200;i++){
         j = 0;
         if (z.value[i] == NULL){
               break;
             }
            pch = strtok(z.value[i]," ");
    while(pch != NULL) {
        if (j == 0){
            result.lol[i].command = pch;    
            pch = strtok(NULL, " ");
            j++;
        } else {
        result.lol[i].args[j]= pch;
        pch = strtok(NULL, " ");
        j++;
        }
    }
    pch = strtok(NULL, " ");
      }
         return result; 

我的输出函数如下所示:

void output(struct arraycmd b){ 
int i;
int j;

for(i=0; i<200;i++){
     if (b.lol[i].command != NULL){
        printf("Command %d: %s",i,b.lol[i].command);
    }
    for (j = 0; j < 200;j++){
        if  (b.lol[i].args[j] != NULL){
            printf(" Arg %d = %s",j,b.lol[i].args[j]);
        }
    }   
    printf(" \n");  
}    
}

但它只产生垃圾(与我的python解决方案中的输入相同):(
command1 args1 args2 arg3;command2 args1 args2 args3;command3 arg1 arg2 arg3)

命令 0:command1 Arg 0 = command2 Arg 1 = args1 Arg 2 = args2 Arg 3 = arg3 Arg 19 = command2 Arg 21 = args1 Arg 22 = args2 Arg 23 = args3 Arg 39 = command3 Arg 41 = arg1 Arg 42 = arg2 Arg 43 = arg3 分段错误

所以我希望有人可以帮助我解决这个问题。

4

3 回答 3

1

您的问题是您依赖于将结构中的指针初始化为 NULL。

它们只是随机值,因此是 SEGV。

当结构只有 10 个命令和 19 个参数时,您还会打印 200 个命令和 200 个参数。

于 2013-05-16T17:08:10.057 回答
1

检查这个解决方案。用 valgrind 测试没有泄漏。但是我在释放内实现了打印。你可以自己实现查看自由功能。进一步你可以改进拆分器功能以实现更好的解析。

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

typedef struct arr {
    char** words;
    int count;
} uarr;
#define null 0

typedef struct cmdr {
    char* command;
    char** argv;
    int argc;
} cmd;

typedef struct list {
    cmd* listcmd;
    int count;

} cmdlist;

uarr splitter(char* str, char delim);
cmdlist* getcommandstruct(char* string);
void freecmdlist(cmdlist* cmdl);

int main(int argc, char** argv) {
    char input[] = "command1 arg1 arg2 arg3 arg4;command2 arg1 arg2 ;command3 arg1 arg2  arg3;command4 arg1 arg2  arg3";

    cmdlist* cmdl = getcommandstruct((char*) input);
    //it will free . also i added print logic inside free u can seperate
    freecmdlist(cmdl);
    free(cmdl);
    return (EXIT_SUCCESS);
}

/**
 * THIS FUNCTION U CAN USE FOR GETTING STRUCT
 * @param string
 * @return 
 */
cmdlist* getcommandstruct(char* string) {
    cmdlist* cmds = null;
    cmd* listcmd = null;
    uarr resultx = splitter(string, ';');
    //lets allocate
    if (resultx.count > 0) {
        listcmd = (cmd*) malloc(sizeof (cmd) * resultx.count);
        memset(listcmd, 0, sizeof (cmd) * resultx.count);
        int i = 0;
        for (i = 0; i < resultx.count; i++) {
            if (resultx.words[i] != null) {

                printf("%s\n", resultx.words[i]);
                char* def = resultx.words[i];
                uarr defres = splitter(def, ' ');

                listcmd[i].argc = defres.count - 1;
                listcmd[i].command = defres.words[0];
                if (defres.count > 1) {
                    listcmd[i].argv = (char**) malloc(sizeof (char*) *(defres.count - 1));
                    int j = 0;
                    for (; j < defres.count - 1; j++) {
                        listcmd[i].argv[j] = defres.words[j + 1];
                    }

                }
                free(defres.words);
                free(def);
            }
        }

        cmds = (cmdlist*) malloc(sizeof (cmdlist));
        cmds->count = resultx.count;
        cmds->listcmd = listcmd;
    }
    free(resultx.words);
    return cmds;

}

uarr splitter(char* str, char delim) {
    char* holder = str;
    uarr result = {null, 0};
    int count = 0;
    while (1) {
        if (*holder == delim) {
            count++;
        }
        if (*holder == '\0') {
            count++;
            break;
        };
        holder++;
    }
    if (count > 0) {

        char** arr = (char**) malloc(sizeof (char*) *count);
        result.words = arr;
        result.count = count;
        //real split
        holder = str;
        char* begin = holder;
        int index = 0;
        while (index < count) {
            if (*holder == delim || *holder == '\0') {
                int size = holder + 1 - begin;
                if (size > 1) {
                    char* dest = (char*) malloc(size);
                    memcpy(dest, begin, size);
                    dest[size - 1] = '\0';
                    arr[index] = dest;
                } else {
                    arr[index] = null;
                }
                index++;
                begin = holder + 1;
            }
            holder++;
        }

    }
    return result;
}

void freecmdlist(cmdlist* cmdl) {
    if (cmdl != null) {
        int i = 0;
        for (; i < cmdl->count; i++) {
            cmd def = cmdl->listcmd[i];
            char* defcommand = def.command;
            char** defargv = def.argv;
            if (defcommand != null)printf("command=%s\n", defcommand);
            free(defcommand);
            int j = 0;
            for (; j < def.argc; j++) {
                char* defa = defargv[j];
                if (defa != null)printf("arg[%i] = %s\n", j, defa);
                free(defa);
            }
            free(defargv);
        }
        free(cmdl->listcmd);
    }

}
于 2013-05-16T19:41:15.810 回答
1

直接在 python 中获取 C 逻辑可能更容易。这更接近 C,您可以尝试将其音译为 C。您可以使用它strncpy来提取字符串并将它们复制到您的结构中。

str = "command1 args1 args2 arg3;command2 args1 args2 args3;command3 arg1 arg2 arg3\000"

start = 0
state = 'in_command'

structs = []

command = ''
args = []
for i in xrange(len(str)):
    ch = str[i]
    if ch == ' ' or ch == ';' or ch == '\0':
        if state == 'in_command':
            command = str[start:i]
        elif state == 'in_args':
            arg = str[start:i]
            args.append(arg)
        state = 'in_args'
        start = i + 1
    if ch == ';' or ch == '\0':
        state = 'in_command'
        structs.append((command, args))
        command = ''
        args = []

for s in structs:
    print s
于 2013-05-16T17:02:18.223 回答