Как создать неровный массив из массива строк - PullRequest
0 голосов
/ 28 марта 2019

Я пишу программу, которая принимает аргументы командной строки, я хочу отделить все аргументы, используя строку «ТРУБА», например, я могу написать ls -la PIPE wc.Мой код

char **args = argv;
int pipes=0;
while(*args)
{
    if(strcmp("PIPE",*args) == 0)
    {
        pipes++;
    }
    args++;
}
int *pipeIndexes = NULL;
if(pipes > 0)
{
    pipeIndexes=(int *)malloc(pipes*sizeof(int));
    args = argv;
    pipeIndexes[pipes];
    int counter=0,i=0;
    while(*args)
    {
        if(strcmp("PIPE",*args) == 0)
        {
            pipeIndexes = (int *)realloc(pipeIndexes,sizeof(int)*(counter+1));
            pipeIndexes[counter] = i;
            counter++;
        }
        i++;
        args++;
    }
}

Теперь я хочу создать еще один массив, в котором будут храниться аргументы для каждой программы?Например.

programs = { {"ls","-la"},{"wc"}}

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

Предложение, в котором каждый (под) массив заканчивается NULL для обозначения его конца, например, ls -la PIPE wc производит { {"ls","-la",NULL},{"wc",NULL},NULL}

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

int main(int argc, char ** argv)
{
  if (argc == 1) {
    puts("at least an argument must be given");
    return -1;
  }

  char *** commands = NULL;
  size_t nCommands = 0;

  do {
    commands = realloc(commands, (nCommands + 2)*sizeof(char **));

    char ** command = NULL;
    size_t n = 0;

    while ((*++argv != NULL) && strcmp(*argv, "PIPE")) {
      command = realloc(command, (n + 2)*sizeof(char *));
      command[n++] = *argv; /* may be strdup(*argv) */
    }
    if (n == 0)
      puts("invalid PIPE");
    else {
      command[n] = NULL; /* marks the end */
      commands[nCommands++] = command;
    }
  } while (*argv);

  if (nCommands == 0)
    puts("no command");
  else {
    commands[nCommands] = NULL; /* marks the end */

    /* debug, print result, free ressources */
    char *** pcommands = commands;

    while (*pcommands) {
      char ** pcommand = *pcommands;

      while (*pcommand)
        printf("%s ", *pcommand++);
      putchar('\n');
      free(*pcommands++);
    }
    free(commands);
  }   
}

Компиляция и выполнение:

/tmp % gcc -g -pedantic -Wall -Wextra aa.c
/tmp % ./a.out ls -la PIPE wc
ls -la 
wc 
/tmp % ./a.out ls
ls 
/tmp % ./a.out 
at least an argument must be given
/tmp % ./a.out ls PIPE PIPE wc
invalid PIPE
ls 
wc 
vxl15036 /tmp % ./a.out ls PIPE 
invalid PIPE
ls 

Исполнение под valgrind

/tmp % valgrind ./a.out ls -la PIPE wc
==9808== Memcheck, a memory error detector
==9808== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==9808== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==9808== Command: ./a.out ls -la PIPE wc
==9808== 
ls -la 
wc 
==9808== 
==9808== HEAP SUMMARY:
==9808==     in use at exit: 0 bytes in 0 blocks
==9808==   total heap usage: 5 allocs, 5 frees, 96 bytes allocated
==9808== 
==9808== All heap blocks were freed -- no leaks are possible
==9808== 
==9808== For counts of detected and suppressed errors, rerun with: -v
==9808== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
0 голосов
/ 28 марта 2019

Поздравляем, вы обнаружили вариант использования char ***. Зубчатый массив в C лучше всего реализовать как массив указателей, поэтому вам нужен массив (динамически размещаемых) массивов указателей.

В следующем фрагменте (непроверенном) это оставлено в качестве упражнения для вызова realloc по мере необходимости для увеличения массивов.

  char ***programs = malloc(10 * sizeof(char **)); /* arbitrary small size */
  int prog = 0, arg = 0;
  for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "PIPE") == 0) {
      programs[prog][arg] = NULL;
      arg = 0;
      prog++;
      /* realloc programs if needed */
      programs[prog] = malloc(20 * sizeof(char *));
    } else {
      programs[prog][arg++] = argv[i];
      /* realloc programs[prog] if needed */
    }
  }
  programs[prog][arg] = NULL;
  /* realloc programs if needed */
  programs[++prog] = NULL;
...