我有:
char * tokens[50][2];
在此设置中,标记[i] [0]指向参数的开头,标记[i] [1]指向结尾。这些令牌不是空终止。要打印它们我正在使用:
printf("%.*s ",(int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]);
现在我需要使用它们来执行一个函数。我试图用execvp来完成这项工作。我试图避免为这些字符串分配内存,如果可能的话。有没有办法发送有界字符串作为参数?有什么想法吗?
答案 0 :(得分:0)
由于execvp()
仅适用于空终止字符串,因此您必须将null终止字符串或者......实际上,由于所有系统调用都没有或选项使用以null结尾的字符串。
好的:另一种方法是制作字符串的空终止副本,并用副本调用execvp()
。既然你知道它们有多长,你就能够相当有效地完成它 - 但你需要分配足够的内存。
size_t req_size = 0;
for (int i = 0; i < n; i++)
req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
char **argv = malloc((n + 1) * sizeof(argv[0]));
char *args = malloc(req_size);
if (argv == 0 || args == 0)
…report memory allocation failure; do not continue…
char *argp = args;
int i;
for (i = 0; i < n; i++)
{
size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
argv[i] = argp;
memmove(argv[i], com->tokens[i][0], len_i);
argv[i][len_i] = '\0';
argp += len_i + 1;
}
assert(argp == args + req_size);
argv[i] = 0; // Null terminate list of pointers
execvp(argv[0], argv);
嵌入在SSCCE中的代码(Short, Self-Contained, Correct Example):
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct command
{
int n;
char *tokens[50][2];
};
static void print_fixed(struct command *com)
{
printf("fixed:\n");
printf("%d:", com->n);
for (int i = 0; i < com->n; i++)
printf(" [%.*s]", (int)(com->tokens[i][1] - com->tokens[i][0] + 1), com->tokens[i][0]);
putchar('\n');
}
static void print_argv(int argc, char **argv)
{
printf("argv:\n");
for (int i = 0; i <= argc; i++)
{
char *arg = argv[i];
if (arg == 0)
arg = "<<NULL pointer>>";
printf("%d: [%s]\n", i, arg);
}
}
int main(void)
{
char data[] = "command arg1 arg2 arg3 arg4";
struct command cmd =
{
5,
{ { &data[ 0], &data[ 6] }, { &data[ 8], &data[11] },
{ &data[13], &data[16] }, { &data[18], &data[21] },
{ &data[23], &data[26] },
}
};
struct command *com = &cmd;
int n = com->n;
print_fixed(com);
size_t req_size = 0;
for (int i = 0; i < n; i++)
req_size += (com->tokens[i][1] - com->tokens[i][0] + 2);
char **argv = malloc((n + 1) * sizeof(argv[0]));
char *args = malloc(req_size);
if (argv == 0 || args == 0)
{
fprintf(stderr, "Memory allocation failure\n");
exit(1);
}
char *argp = args;
int i;
for (i = 0; i < n; i++)
{
size_t len_i = com->tokens[i][1] - com->tokens[i][0] + 1;
argv[i] = argp;
memmove(argv[i], com->tokens[i][0], len_i);
argv[i][len_i] = '\0';
argp += len_i + 1;
}
assert(argp == args + req_size);
argv[i] = 0; // Null terminate list of pointers
print_argv(i, argv);
return 0;
}
输出:
fixed:
5: [command] [arg1] [arg2] [arg3] [arg4]
argv:
0: [command]
1: [arg1]
2: [arg2]
3: [arg3]
4: [arg4]
5: [<<NULL pointer>>]