如何在C语言中将字符数组传递给函数

4

我是一个自制命令提示符的制作者(学校项目),我想要跟踪用户使用的最后10个命令。所以我有了一个数组:

char* history[10];

据我理解,这意味着我有一个指向字符串的指针数组。我的问题是我有另一个变量input,它是用户的输入。但每当用户输入新内容时,input的值都会改变,这意味着我的数组中所有字符串都会改变为用户的新输入。

我想知道如何解决这个问题?

我尝试将我的数组更改为以下内容:

char *history[10][MAX]    //Where MAX = 256

我本可以使用strcpy,但是我无法弄清如何将一个数组的数组输入到方法中,然后使用strcpy将字符串复制到数组的数组中。

这是我的当前方法:

char* updateHistory(char *history[], char command[], int histIndex) {
    history[histIndex] = command;      
    return *history;
}

有没有其他解决方案或者如何让我的解决方案起作用的帮助?


MAX是否代表单个命令中的最大字符数? - Pooya
返回 return *history; 的意义是什么? - Giorgi Moniava
4个回答

3
你的指针数组需要指向在堆上分配的内存,听起来你指向了一些会发生变化的缓存区。所以像下面这样做应该是可行的:
#define MAX_HISTORY 10

char* history[MAX_HISTORY];

if (fgets(input, sizeof(input), stdin) != NULL)
{
  input[strlen(input)-1] = '\0'; // remove \n
  history[n++] = strdup(input); // allocates and copies the input string
  if ( n == MAX_HISTORY )
  {
    // throw away the oldest and move pointers forward one step
  }
}

strdup 的概念与

相同
malloc( ) + strcpy() 

因此,当您向前移动指针并且想要清除历史记录时,需要释放指针指向的内容。

或者,如果您不想使用堆栈,可以有一个大缓冲区来存储历史记录。

char history[MAX_HISTORY][MAX_CMD_LEN] 但是,这样做需要移动更多的数据,不够优雅/有效,或者需要一些复杂的索引系统来跟踪内容。


2
意思是我的所有数组字符串都会改变成用户的新输入。
这可能是因为在`updateHistory`函数中,您只有一个变量与`command`相关。所以,每次您在`updateHistory`函数的第一行进行赋值时,指向指针数组中所有指针的相同内存位置- `command`。
为解决此问题,您需要像这样分配指针数组(例如,可以在函数外部执行此操作):
char *history[10];
for ( i=0; i < 10; i++ )
{
    history[i] = malloc(MAXLEN);
}

接着复制字符串(这可以放在你的函数内部):

strcpy(history[i], command);

还要别忘了最后释放数组中每个变量的内存


1
谢谢您的回答。它似乎是最容易理解的,并且快速高效地解决了我的问题。 - Logan
@Anon 如果有帮助到就很高兴。 - Giorgi Moniava

1

虽然你可以使用malloccalloc在堆上分配空间,但如果你将历史记录限制在合理的大小范围内,一个简单的二维静态声明字符数组同样适用。例如:

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

/* constants for max pointers, max chars */
enum {MAXP = 10, MAXC = 256};

int main (void) {

    char history[MAXP][MAXC] = {{0}};
    char buf[MAXC] = {0};
    size_t i, n = 0;

    while (printf ("prompt > ") && fgets (buf, MAXC, stdin)) {
        size_t buflen = strlen (buf);
        buf[--buflen] = 0;  /* strip newline */

        /* check buflen to prevent saving empty strings */
        if (!buflen) continue;

        strncpy (history[n++], buf, buflen);

        if (n == MAXP) /* handle full history */
            break;
    }

    for (i = 0; i < n; i++)
        printf (" history[%zu] : %s\n", i, history[i]);

    return 0;
}

例子使用/输出
$ ./bin/fgets_static2d_hist
prompt > ls -al
prompt > mv a b/foo.txt
prompt > rsync ~/tmp/xfer hostb:~/tmp
prompt > du -hcs
prompt > cat /proc/cpuinfo
prompt > grep buflen *
prompt > ls -rt debug
prompt > gcc -Wall -Wextra -Ofast -o bin/fgets_static2d_hist fgets_static2d_hist.c
prompt > objdump obj/fgets_static2d.obj
prompt > source-highlight -i fgets_static2d.c -o fgets_static2d.html
 history[0] : ls -al
 history[1] : mv a b/foo.txt
 history[2] : rsync ~/tmp/xfer hostb:~/tmp
 history[3] : du -hcs
 history[4] : cat /proc/cpuinfo
 history[5] : grep buflen *
 history[6] : ls -rt debug
 history[7] : gcc -Wall -Wextra -Ofast -o bin/fgets_static2d_hist fgets_static2d_hist.c
 history[8] : objdump obj/fgets_static2d.obj
 history[9] : source-highlight -i fgets_static2d.c -o fgets_static2d.html

从静态声明的数组中获得的好处是自动内存管理和来自堆栈分配的内存效率略微提高。两者都可以,只是看你要管理多少信息。

0

当您想要将指针数组传递给函数时,可以在调用函数时使用'&'符号来传递地址。
例如:
这是您声明的一个数组char* history[10];
这是您使用的函数:

char* updateHistory(char *history[], char command[], int histIndex) {
    history[histIndex] = command;      
    return *history;
}

所以,在main()函数体中调用该函数时,像这样调用它

main()
{
updateHistory(&history, command, histIndex);
}

希望这能对你有所帮助..好的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接