我如何两次标记一个char数组以将其转换为3D char数组?

时间:2019-05-16 16:43:10

标签: c arrays

我是C语言的新手,我需要帮助。我想对以下字符流进行两次标记,首先是在遇到“ |”时然后(对于数组中的每个新元素)遇到一个空格。

例如

input = "command arg | command arg2 | command arg3 arg4"

commands[0][0] = "command"
commands[0][1] = "arg"

commands[1][0] = "command"
commands[1][1] = "arg2"

commands[2][0] = "command"
commands[2][1] = "arg3"
commands[2][2] = "arg4"

我尝试了以下方法:

int _pipe(char* input){
    char** commands[MAX_ARGS];
    memcpy(commands, tokenize_pipe(input), sizeof(commands));
    return 1;
}

char*** tokenize_pipe(char* input){

    static char* args[MAX_ARGS];
    static char** args2[MAX_ARGS];

    int args_size = 0;
    int args_size2 = 0;

    char* token = NULL;

    token = strtok(input, "|");

    while(token != NULL) {
        args[args_size] = token;
        token = strtok(NULL, "|");
        args_size++;
    }

    args[args_size] = NULL;

    for(int i = 0; i < args_size; i++){

        token = strtok(args[i], " ");

        while(token != NULL) {
            args2[i][args_size2] = token;
            token = strtok(NULL, " ");
            args_size2++;
        }

        args2[i][args_size2] = NULL;
        args_size2 = 0;
    }
    return args2;
}

我不知道我可以解决这个问题或改变什么。感谢您能提供的任何帮助。

2 个答案:

答案 0 :(得分:2)

tokenize_pipe中,您要做

 args2[i][args_size2] = token;  

无需初始化args2[i]

_pipe中有一种替换方法

char** commands[MAX_ARGS];

作者

char* commands[MAX_ARGS][MAX_ARGS];

,并在tokenize_pipe中替换

  

静态字符** args2 [MAX_ARGS];

作者

static char* args2[MAX_ARGS][MAX_ARGS];

但是当然使用大数组,请考虑使用动态数组,先使用 malloc 然后使用 realloc 调整大小。

这里有一个建议,其中tokenize_pipe返回一个3D数组,其中所有数组均已分配,我还复制了令牌。 NULL用于指示行和列的结尾

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

char*** tokenize_pipe(char* input)
{
  char *** r = malloc(1);
  size_t nCommands = 0;
  char * savePtrCmds;
  char * fullcmd = strtok_r(input, "|", &savePtrCmds);

  while (fullcmd != NULL) {
    char ** tokens = malloc(1);
    size_t nTokens = 0;
    char * token = strtok(fullcmd, " ");

    while (token != 0) {
      tokens = realloc(tokens, (nTokens + 2) * sizeof(char *));
      tokens[nTokens++] = strdup(token); /* also duplicate the token to allows input to disapear */
      token = strtok(NULL, " ");
    }
    tokens[nTokens] = NULL;

    r = realloc(r, (nCommands + 2) * sizeof(char **));
    r[nCommands++] = tokens;
    fullcmd = strtok_r(NULL, "|", &savePtrCmds);
  }

  r[nCommands] = NULL;
  return r;
}

int main()
{
  char *** r;

  {
    char input[] = "command1 arg | command2 arg2 | command3 arg3 arg4";

    r = tokenize_pipe(input);
  }

  /* here input does not exist anymore */

  /* debug */
  for (char *** pcmds = r; *pcmds; ++pcmds) {
    for (char ** pcmd = *pcmds; *pcmd; ++pcmd)
      printf("%s ", *pcmd);
    putchar('\n');
  }

  /* free resources */
  for (char *** pcmds = r; *pcmds; ++pcmds) {
    for (char ** pcmd = *pcmds; *pcmd; ++pcmd)
      free(*pcmd);
    free(*pcmds);
  }
  free(r);

  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra t.c
pi@raspberrypi:/tmp $ ./a.out
command1 arg 
command2 arg2 
command3 arg3 arg4 

valgrind 下执行:

==7301== Memcheck, a memory error detector
==7301== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7301== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7301== Command: ./a.out
==7301== 
command1 arg 
command2 arg2 
command3 arg3 arg4 
==7301== 
==7301== HEAP SUMMARY:
==7301==     in use at exit: 0 bytes in 0 blocks
==7301==   total heap usage: 22 allocs, 22 frees, 1,186 bytes allocated
==7301== 
==7301== All heap blocks were freed -- no leaks are possible
==7301== 
==7301== For counts of detected and suppressed errors, rerun with: -v
==7301== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

答案 1 :(得分:1)

您没有分配args2内存

    args2[i][args_size2] = token;

应该是

 for(...)
 {
    args2[i] = malloc(sizeof(char *)*Some_Length);

    while(token != NULL) {
        args2[i][args_size2] = token;
        token = strtok(NULL, " ");
        args_size2++;
    }
  }

也  如下进行指针分配不是一个好主意,因为input字符串可能会在某个时间点改变。

    args2[i][args_size2] = token;

代替

    args2[i][args_size2] = strdup(token);