【问题标题】:Parse a string in C and save it to an array of structs解析 C 中的字符串并将其保存到结构数组中
【发布时间】:2013-05-11 15:43:35
【问题描述】:

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

我的意见:

input = "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:

    struct 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 =参数 2 参数 43 = 参数 3 分段错误

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

【问题讨论】:

  • 你的 main() 是什么样子的,你在哪里调用以上所有内容?您是否尝试过在调试器中单步执行您的代码?
  • 另外,您可以查看strtok man page 中的示例。
  • @W0bble 检查我的答案。我做了你想要的。你可以使用

标签: python c string parsing


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    检查这个解决方案。用 valgrind 测试没有泄漏。 但是我在 freeing 中实现了打印。你可以自己实现查看 free 函数。进一步你可以改进 splitter 函数以实现更好的解析。

    #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);
        }
    
    }
    

    【讨论】:

    • 这个解决方案很棒!没想到会有这么多帮助!谢谢。
    【解决方案3】:

    直接在 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
    

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 2011-12-24
      • 1970-01-01
      相关资源
      最近更新 更多