【发布时间】:2016-04-30 18:22:37
【问题描述】:
如果我有一个像矩阵或树这样的数据结构,并且我想从一个包含上述变量的非常大的函数中提取一个 for 循环,那么调用应该是什么样子?我尝试了以下方法,但出现分段错误。
void write_command(int w, char *argv[], char *string[]) {
char *dest;
for (int r = 0; argv[r] != NULL; r++) {
dest = malloc(sizeof(char *) * strlen(argv[r]) + 1);
*dest = '0';
strcpy(dest, argv[r]);
string[w][r] = *dest;
free(dest);
}
}
我想你明白我在做什么,但我应该如何声明变量?我在string[w][r] = *dest; 收到段错误。
我认为您不想看到我正在重构的内容,但它是有史以来最大且最不可读的函数。
static int runCmd(const char *cmd) {
const char *cp;
pid_t pid;
int status;
struct command structcommand[15];
char **argv = 0;
int argc = 1;
bool pipe = false;
char *string[z][z];
char *pString3[40];
char *pString2[40];
int n = 0;
char **ptr1;
char string1[z];
bool keep = false;
char *pString1[z];
char *pString[z];
*pString1 = "\0";
*pString = "\0";
char *temp = {'\0'};
int w = 0;
bool b = false;
int j = 0;
int i;
int p = 0;
char **ptr;
char *tmpchar;
char *cmdtmp;
bool b1 = false;
char *dest;
int y = 0;
i = 0;
int h = 0;
nullterminate(string);
if (cmd) {
for (cp = cmd; *cp; cp++) {
if ((*cp >= 'a') && (*cp <= 'z')) {
continue;
}
if ((*cp >= 'A') && (*cp <= 'Z')) {
continue;
}
if (isDecimal(*cp)) {
continue;
}
if (isBlank(*cp)) {
continue;
}
if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
(*cp == '+') || (*cp == '=') || (*cp == '_') ||
(*cp == ':') || (*cp == ',') || (*cp == '\'') ||
(*cp == '"')) {
continue;
}
}
}
if (cmd) {
cmdtmp = malloc(sizeof(char *) * strlen(cmd) + 1);
strcpy(cmdtmp, cmd);
tmpchar = malloc(sizeof(char *) * strlen(cmd) + 1);
if (tmpchar == NULL) {
printf("Error allocating memory!\n"); /* print an error message */
return 1; /* return with failure */
}
strcpy(tmpchar, cmd);
ptr1 = str_split(pString3, cmdtmp, '|');
if (strstr(cmd, "|") == NULL) { /* not a pipeline */
makeArgs(cmd, &argc, (const char ***) &argv, pipe, 0, 0);
for (j = 0; j < argc; j++) {
string[0][j] = argv[j];
structcommand[i].argv = string[0]; /*process;*/
}
n++;
}
else {
for (i = 0; *(ptr1 + i); i++) { /* tokenize the input string for each pipeline*/
n++; /* save number of pipelines */
int e = 0; /* a counter */
*pString = "\0"; /* should malloc and free this? */
strcpy(string1, *(ptr1 + i));
if ((string1[0] != '\0') && !isspace(string1[0])) { /* this is neither the end nor a new argument */
ptr = str_split(pString2, *(&string1), ' '); /* split the string at the arguments */
h = 0;
for (j = 0; *(ptr + j); j++) { /* step through the arguments */
/* the pipeline is in cmdtmp and the argument/program is in ptr[i] */
if (ptr + j && !b && strstr(*(ptr + j), "'")) {
b = true;
strcpy(temp, *(ptr + j));
if (y < 1) {
y++;
}
}
while (b) {
if (*(ptr + j) && strstr(*(ptr + j), "'")) { /* end of quote */
b = false;
if (y < 1) {
string[i][j] = strcpy(temp, *(ptr + j));
}
y = 0;
}
else if (*(ptr + j)) { /* read until end of quote */
string[i][j] = temp;
continue;
} else {
b = false;
break;
}
}
if (ptr + j) {
if (*(ptr + j)[0] == '{') {
keep = true;
}
if (testFn(*(ptr + j))) { /* test for last char */
string[i][j - p] = concat(*pString1, *(ptr + j));
keep = false;
free(*pString1);
goto mylabel;
}
if (keep) {
*pString1 = concat(*pString1, *(ptr + j));
*pString1 = concat(*pString1, " ");
p++;
} else {
// strcpy(temp, *(ptr + j));
b1 = false;
int q = j;
for (e = 0; *(ptr + q + e); e++) { /* step through the string */
b1 = true;
if (*(ptr + e + q)) {
*pString = concat(*pString, *(ptr + e + q));
*pString = concat(*pString, " ");
}
j = e;
}
if (makeArgs(*pString, &argc, (const char ***) &argv, pipe, i, h)) {
write_command(&w, argv, string[w]);
/*for (int r = 0; argv[r] != NULL; r++) {
dest = malloc(sizeof(char *) * strlen(argv[r]) + 1);
*dest = '0';
strcpy(dest, argv[r]);
string[w][r] = dest;
}*/
w++;
} else {
if (!b1) { /* no args (?) */
for (int r = 0; argv[r] != NULL; r++) {
string[i][r] = argv[r];
}
}
}
}
}
}
mylabel:
free(ptr);
dump_argv((const char *) "d", argc, argv);
}
}
free(ptr1);
free(cmdtmp);
free(tmpchar);
}
for (i = 0; i < n; i++) {
for (j = 0; DEBUG && string[i][j] != NULL; j++) {
if (i == 0 && j == 0) printf("\n");
printf("p[%d][%d] %s\n", i, j, string[i][j]);
}
structcommand[i].argv = string[i];
}
fflush(NULL);
pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
/* If we are the child process, then go execute the string.*/
if (pid == 0) {
/* spawn(cmd);*/
fork_pipes(n, structcommand);
}
/*
* We are the parent process.
* Wait for the child to complete.
*/
status = 0;
while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR));
if (pid < 0) {
fprintf(stderr, "Error from waitpid: %s", strerror(errno));
return -1;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "pid %ld: killed by signal %d\n",
(long) pid, WTERMSIG(status));
return -1;
}
}
return WEXITSTATUS(status);
}
【问题讨论】:
-
是
char *string[]一个错误输入的char *string[z][z]实例,还是其他变量? -
不,实际上,不清楚您要做什么。我最好的猜测是您正在尝试对给定的
argv数组进行深层复制,但在这种情况下,您开始使用的变量声明char *string[z][z];是否适合图片并不清楚。也不清楚为什么你似乎在释放函数内部分配的内存。 -
我试图重构一个大函数,将一个for循环分解为一个函数并调用该函数,但我不习惯传递指针,因为我是OOP。关键的见解是了解我不需要将矩阵作为参数传递,可以将矩阵作为数组传递。现在我尝试通过
struct进行下一次重构,但我遇到了类似的问题,因为我不是 C 程序员专家。 -
函数
write_command将int w作为第一个参数,但它使用&w调用。这不会编译,更不用说段错误。
标签: c function refactoring