通过引用传递指针数组
Passing an array of pointers by reference
我正在尝试以与命令行参数类似的方式从键盘获取命令 int main( int argc, char *argv[] )
但是在一个单独的函数中。当我在 getCmd()
函数的范围内解析和打印它们时,它们的外观和行为都符合预期,但是一旦它们 return 到主函数,它们就会变成一堆垃圾。我的问题在代码下面。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
void getCmd(char *cmd, char *args[])
{
char input[81] = { 0 };
char *next_token = NULL;
printf("$ ");
fgets(input, 81, stdin);
input[strcspn(input, "\n")] = 0;
cmd = strtok_s(input, " ", &next_token);
if (!strcmp(cmd, "mv"))
{
args[0] = strtok_s(NULL, " ", &next_token);
args[1] = strtok_s(NULL, " ", &next_token);
printf("\n\n%s\n%s\n%s\n\n", cmd, args[0], args[1]);
}
}
int main(void)
{
char *cmd = NULL, *args[5];
cmd = (char *)calloc(20,sizeof(char));
for (size_t i = 0; i < (size_t)5; i++)
{
args[i] = (char *)calloc(20,sizeof(char));
}
getCmd(cmd, args);
printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);
return 0;
}
我认为它不相关,但我在 64 位处理器上使用 VS 2015 社区和 Visual C++ 编译器,Windows 7 OS.
我的问题:
- How should I pass the cmd and args[] by reference?
- Are there any widely accepted idioms that deal with this sort of situations?
我已经查看了一些类似的问题,但找不到适合这种情况的解决方案,如果问题重复,请告诉我,我会关闭 it.Since 我'我是 Whosebug 的新手,我将不胜感激任何问题格式提示。干杯! (:
strtok_s()
return 指向正在解析的缓冲区的指针(此处为 input
)。
input
存在于 getCmd()
堆栈中。它在 getCmd()
return 秒时死去。从那时起,指向 input
且已存储在 args
元素中的地址不再指向有效内存。
代码需要分配新内存并复制 strtok_s()
return 指向的指针。
看看如何做到这一点:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getCmd(char **pcmd, char *args[], size_t s)
{
char input[81] = { 0 };
char *next_token = NULL;
printf("$ ");
fgets(input, 81, stdin);
input[strcspn(input, "\n")] = 0;
(*pcmd) = _strdup(strtok_s(input, " ", &next_token));
if (!strcmp(*pcmd, "mv"))
{
args[0] = _strdup(strtok_s(NULL, " ", &next_token));
args[1] = _strdup(strtok_s(NULL, " ", &next_token));
printf("\n\n%s\n%s\n%s\n\n", *pcmd, args[0], args[1]);
}
}
#define ARGS_MAX (5)
int main(void)
{
char *cmd, *args[ARGS_MAX] = {0};
getCmd(&cmd, args, ARGS_MAX);
printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);
/* Clean up. */
free(cmd);
for (size_t i = 0; i < ARGS_MAX; ++i)
{
free(args[i]);
}
return 0;
}
有许多不同的方法可以解决这个问题。虽然您可以自由地为 cmd
和 args
数组动态分配内存,但实际上没有必要,对于这种有限的内存量,您可以对所有内存使用静态声明。不需要单独的 input
数组,您可以为此目的使用 cmd
,然后标记化 cmd
。这提供了在调用 strtok
后在 cmd
中留下第一个标记 nul-terminated 的好处。
注意: 在下面的示例中,使用了 strtok
,strtok_s
是 C11 中的可选编译器添加,不幸的是,我没有有一个实现该选项的编译器,因此我使用 strtok
进行测试。您可以轻松地为 VS 进行更改。
#include <stdio.h>
#include <string.h>
enum { NARGS = 5, MAXC = 128 };
size_t getcmd (char *cmd, char (*args)[MAXC]);
int main (void) {
char cmd[MAXC] = "", args[NARGS][MAXC] = { "" };
size_t i, n;
if (!(n = getcmd (cmd, args))) return 1;
printf (" %s", cmd);
for (i = 0; i < n; i++)
printf(" %s", args[i]);
putchar ('\n');
return 0;
}
size_t getcmd (char *cmd, char (*args)[MAXC])
{
char *delim = " ,.\t\n";
char *p = NULL;
size_t idx = 0;
printf ("$ ");
if (!fgets (cmd, MAXC, stdin)) {
fprintf (stderr, "error: invalid input.\n");
return 0;
}
strtok (cmd, delim); /* terminate after 1st token */
for (p = strtok (NULL, delim); p; p = strtok (NULL, delim)) {
strncpy (args[idx++], p, MAXC); /* limit to avail chars */
if (idx == NARGS) break; /* limit to available bounds */
}
return idx;
}
注意上面,getcmd
的return类型是size_t
。总是选择一个有意义的类型来 return 指示 success/failure 以及 returning 一些需要的信息(这里的参数数量)。还要注意 C 风格指南不喜欢 camelCase variable/function 名称更喜欢全部小写。为 C++ 保留 camelCase 名称。参见例如NASA - C Style Guide, 1994
例子Use/Output
$ ./bin/getcmd
$ mv /this/here/file /that/there/file
mv /this/here/file /that/there/file
$ ./bin/getcmd
$ mv -i --strip-trailing-slashes /this/here/file /that/there/file
mv -i --strip-trailing-slashes /this/here/file /that/there/file
仔细阅读,如果您还有其他问题,请告诉我。
我正在尝试以与命令行参数类似的方式从键盘获取命令 int main( int argc, char *argv[] )
但是在一个单独的函数中。当我在 getCmd()
函数的范围内解析和打印它们时,它们的外观和行为都符合预期,但是一旦它们 return 到主函数,它们就会变成一堆垃圾。我的问题在代码下面。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
void getCmd(char *cmd, char *args[])
{
char input[81] = { 0 };
char *next_token = NULL;
printf("$ ");
fgets(input, 81, stdin);
input[strcspn(input, "\n")] = 0;
cmd = strtok_s(input, " ", &next_token);
if (!strcmp(cmd, "mv"))
{
args[0] = strtok_s(NULL, " ", &next_token);
args[1] = strtok_s(NULL, " ", &next_token);
printf("\n\n%s\n%s\n%s\n\n", cmd, args[0], args[1]);
}
}
int main(void)
{
char *cmd = NULL, *args[5];
cmd = (char *)calloc(20,sizeof(char));
for (size_t i = 0; i < (size_t)5; i++)
{
args[i] = (char *)calloc(20,sizeof(char));
}
getCmd(cmd, args);
printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);
return 0;
}
我认为它不相关,但我在 64 位处理器上使用 VS 2015 社区和 Visual C++ 编译器,Windows 7 OS.
我的问题:
- How should I pass the cmd and args[] by reference?
- Are there any widely accepted idioms that deal with this sort of situations?
我已经查看了一些类似的问题,但找不到适合这种情况的解决方案,如果问题重复,请告诉我,我会关闭 it.Since 我'我是 Whosebug 的新手,我将不胜感激任何问题格式提示。干杯! (:
strtok_s()
return 指向正在解析的缓冲区的指针(此处为 input
)。
input
存在于 getCmd()
堆栈中。它在 getCmd()
return 秒时死去。从那时起,指向 input
且已存储在 args
元素中的地址不再指向有效内存。
代码需要分配新内存并复制 strtok_s()
return 指向的指针。
看看如何做到这一点:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getCmd(char **pcmd, char *args[], size_t s)
{
char input[81] = { 0 };
char *next_token = NULL;
printf("$ ");
fgets(input, 81, stdin);
input[strcspn(input, "\n")] = 0;
(*pcmd) = _strdup(strtok_s(input, " ", &next_token));
if (!strcmp(*pcmd, "mv"))
{
args[0] = _strdup(strtok_s(NULL, " ", &next_token));
args[1] = _strdup(strtok_s(NULL, " ", &next_token));
printf("\n\n%s\n%s\n%s\n\n", *pcmd, args[0], args[1]);
}
}
#define ARGS_MAX (5)
int main(void)
{
char *cmd, *args[ARGS_MAX] = {0};
getCmd(&cmd, args, ARGS_MAX);
printf("\n\n%s \n%s\n%s", cmd, args[0], args[1]);
/* Clean up. */
free(cmd);
for (size_t i = 0; i < ARGS_MAX; ++i)
{
free(args[i]);
}
return 0;
}
有许多不同的方法可以解决这个问题。虽然您可以自由地为 cmd
和 args
数组动态分配内存,但实际上没有必要,对于这种有限的内存量,您可以对所有内存使用静态声明。不需要单独的 input
数组,您可以为此目的使用 cmd
,然后标记化 cmd
。这提供了在调用 strtok
后在 cmd
中留下第一个标记 nul-terminated 的好处。
注意: 在下面的示例中,使用了 strtok
,strtok_s
是 C11 中的可选编译器添加,不幸的是,我没有有一个实现该选项的编译器,因此我使用 strtok
进行测试。您可以轻松地为 VS 进行更改。
#include <stdio.h>
#include <string.h>
enum { NARGS = 5, MAXC = 128 };
size_t getcmd (char *cmd, char (*args)[MAXC]);
int main (void) {
char cmd[MAXC] = "", args[NARGS][MAXC] = { "" };
size_t i, n;
if (!(n = getcmd (cmd, args))) return 1;
printf (" %s", cmd);
for (i = 0; i < n; i++)
printf(" %s", args[i]);
putchar ('\n');
return 0;
}
size_t getcmd (char *cmd, char (*args)[MAXC])
{
char *delim = " ,.\t\n";
char *p = NULL;
size_t idx = 0;
printf ("$ ");
if (!fgets (cmd, MAXC, stdin)) {
fprintf (stderr, "error: invalid input.\n");
return 0;
}
strtok (cmd, delim); /* terminate after 1st token */
for (p = strtok (NULL, delim); p; p = strtok (NULL, delim)) {
strncpy (args[idx++], p, MAXC); /* limit to avail chars */
if (idx == NARGS) break; /* limit to available bounds */
}
return idx;
}
注意上面,getcmd
的return类型是size_t
。总是选择一个有意义的类型来 return 指示 success/failure 以及 returning 一些需要的信息(这里的参数数量)。还要注意 C 风格指南不喜欢 camelCase variable/function 名称更喜欢全部小写。为 C++ 保留 camelCase 名称。参见例如NASA - C Style Guide, 1994
例子Use/Output
$ ./bin/getcmd
$ mv /this/here/file /that/there/file
mv /this/here/file /that/there/file
$ ./bin/getcmd
$ mv -i --strip-trailing-slashes /this/here/file /that/there/file
mv -i --strip-trailing-slashes /this/here/file /that/there/file
仔细阅读,如果您还有其他问题,请告诉我。