Как дважды токенизировать массив символов, чтобы превратить его в массив трехмерных символов? - PullRequest
0 голосов
/ 16 мая 2019

Я совершенно новый в 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 ]

2 голосов
/ 16 мая 2019

В 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];

by

static char* args2[MAX_ARGS][MAX_ARGS];

Но, конечно, при использовании больших массивов рассмотрите возможность использования динамических массивов, используя malloc затем realloc для их изменения.

Вот предложение, где tokenize_pipe возвращает трехмерный массив, где все выделено, я также продублирую токены.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 голос
/ 16 мая 2019

Вы не выделяете 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...