Как привести char * к char * const * в C - PullRequest
0 голосов
/ 30 июня 2019

Я пытаюсь использовать функцию execv ().

Я пытаюсь передать свою команду аргумента левой стороне.

 execv(file,arguments);

Я использую символ * для анализа входящего пользовательского ввода для моей оболочки.

Второй аргумент execv принимает символ * const *.

Есть ли способ, которым я могу привести char * const к char * const *?

Я попробую это ниже,

char * arg;
char *const a[] = (char *const)arg;

error: invalid initializer
      char *const a[] = (char *const)arg;
                        ^

Но это не работает и дает мне ошибки.

Помощь будет принята с благодарностью.

Ответы [ 3 ]

3 голосов
/ 01 июля 2019

Ошибка в char *const a[] = (char *const)arg; не связана с неправильным преобразованием.Это потому, что char *const a[] объявляет массив, и инициализаторы для массива должны быть в скобках 1 , { … }, но вы указали только один инициализатор без скобок.

Кроме того,параметр argv для execv должен быть массивом указателей, в котором первые указывают на строку, содержащую имя файла исполняемой программы (это условно, не обязательно), а последний - нулевой указатель.Таким образом, ваше определение a должно быть примерно таким:

char * const a[] = { FileNameOfProgram, arg, NULL };

Сноска

1 За исключением случаев, когда строковый литерал используется для инициализации массива, ноэто не тот случай.

0 голосов
/ 01 июля 2019

Вполне нормально сделать execv после исключения имени команды и некоторых первых параметров. Например, если у вас есть такой код (вам лучше опубликовать полный и проверяемый пример), давайте предположим, что вы делаете что-то вроде этого (если вам нужен пример, поищите справочную страницу xargs(1), у вас есть команда, и после обработки опций и их параметров вы хотите исключить все из них и выполнить остальные, как если бы это была командная строка, например, у меня есть команда для многократного выполнения команды с задержкой на некоторое указанное время, например:

cont -t 0.1 -- df -k .

Я использую <getopts.h> для обработки параметров моей программы cont, затем повторно выполняю команду df -k. Опции позволяют показать версию программы, указать время ожидания, быть подробным или количество раз выполнения команды. Я написал это только сейчас, чтобы показать вам, как это сделать (пример включает в себя fork(2) use, execvp(2) и перенаправление для захвата выходных данных команды, чтобы иметь возможность вернуться к источнику, когда известно число строк мы получили, программа использует экранирование ANSI, чтобы переместить курсор назад в начало.)

#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define F(_fmt) "%s:%d: " _fmt, __FILE__, __LINE__

#define FLAG_VERBOSE        (1<<0)
#define FLAG_VERSION        (1<<1)
#define FLAG_DELAY          (1<<2)
#define FLAG_NTIMES         (1<<3)

int flags = 0;
useconds_t delay = 1000000;
size_t ntimes;

void doVersion(void)
{
    fprintf(stderr, 
            "cont: v1.0\n"
            "(C) Luis Colorado.  All rights reserved.\n"
            "License: BSD\n");
    exit(EXIT_SUCCESS);
}

ssize_t loop(int argc_unused, char **argv)
{
    int fd[2];
    int res = pipe(fd);

    res = fork();
    if (res < 0) {
            fprintf(stderr,
                    F("fork: ERROR %d: %s\n"),
                    errno,
                    strerror(errno));
            return -1;
    } else if (res == 0) { /* child */
            close(fd[0]); /* not going to use it */
            dup2(fd[1], 1); /* redirect output to pipe */
            close(fd[1]);

            execvp(argv[0], argv);

            fprintf(stderr,
                    F("execv: ERROR %d: %s\n"),
                    errno, strerror(errno));
            return -1;
    } else { /* parent */
            pid_t cld_pid = res;
            close(fd[1]); /* no writing to the pipe */
            FILE *f = fdopen(fd[0], "rt"); /* just reading */
            int c;
            size_t lines = 0;
            while((c = fgetc(f)) != EOF) {
                    if (c == '\n') lines++;
                    putc(c, stdout);
            }
            wait(NULL);
            return lines;
    }

} /* loop */

int main(int argc, char **argv)
{
    int opt;
    float t;

    while ((opt = getopt(argc, argv, "t:Vvn:")) >= 0) {
            switch(opt) {
            case 't': flags |= FLAG_DELAY;
                              t = atof(optarg);
                              break;
            case 'V': flags |= FLAG_VERSION;
                              break;
            case 'v': flags |= FLAG_VERBOSE;
                              break;
            case 'n': flags |= FLAG_NTIMES;
                              ntimes = atoi(optarg);
                              break;
            /* ... */
            }
    }

    if (flags & FLAG_VERSION)
            doVersion();

    /* the next pair of sentences is like `shift optind' in the shell. */
    /* trick, don't move the parameters, just move the pointer */
    argc -= optind; /* adjust the number of parameters. */
    argv += optind; /* advance the pointer to the proper place */

    /* NOW, argc && argv are identical to the original ones, but lacking the
     * first `optind' argument strings.  As the original string array ended
     * in a NULL, there's no need to construct it from allocating memory.
     * Anyway, we're not going to use after it's consumed in main().  */

    if (flags & FLAG_VERBOSE) {
            char *sep = "About to execute: ";
            int i;
            for (i = 0; i < argc; i++) {
                    fprintf(stderr, "%s%s", sep, argv[i]);
                    sep = " ";
            }
            fprintf(stderr, "\n");
    }

    if (flags & FLAG_DELAY) {
            delay = t * 1.0E6;
    }

    size_t total_lines = 0;
    ssize_t n = 0;
    while(!(flags & FLAG_NTIMES) || ntimes--) {

            /* move up as many lines as input from subcommand */
            if (n) printf("\r\033[%ldA@\b", n);

            n = loop(argc, argv);

            if (n < 0) {
                    /* we have already written the error */
                    exit(EXIT_FAILURE);
            }

            usleep(delay);

            total_lines += n;
    }
    if (flags & FLAG_VERBOSE) {
            fprintf(stderr,
                    F("Total lines: %lu\n"),
                    total_lines);
    }
    exit(EXIT_SUCCESS);
}

Вы можете скачать полную версию этой программы с Github

0 голосов
/ 01 июля 2019

Вы пытаетесь инициализировать массив.Вместо этого

char * arg;
char *const a[] = (char *const)arg;

сделайте следующее:

char * arg;
char *const a[] = {(char *const)arg};
...