通过引用传递String数组来实现和修改C中的内容

时间:2012-11-01 00:09:22

标签: c arrays pointers char

我在做错了,将char数组传递给函数,并在函数中给出每个索引内存(使用malloc()),然后使用gets()从键盘插入一些东西。

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

void test(char *arr[]);
int main(){
  char *arr[2];//2 is the rows
 /* arr[0] = malloc(80);//This commented code works
  arr[1] = malloc(80);
  strcpy(arr[0], "hey");
  strcpy(arr[1], "whats up");
*/

  test(*arr);
  printf("in array[0]: %s", arr[0]);
  printf("in array[1]: %s", arr[1]);
  return 0;
}
void test(char *arr[]){
  int index;
  char *input = malloc(80);
  for(index = 0; index < 2; index++){
  arr[index] = malloc(80);
  gets(input);
  strcpy(arr[index], input);
  //arr[0] = input;
  }
}

这是一个非常基本的程序,由于某些原因我遇到了麻烦。还有一个问题当我声明一个数组时这些形式之间有什么区别

char *array

反对

char *array[size]

char **array

谢谢, 凯文

3 个答案:

答案 0 :(得分:3)

您将arr声明为char *arr[2]。然后,您传入*arr,其类型为char*进行测试。但测试需要char *[]。这样就行不通了。您应该直接传递arr,即test(arr)

char * array是指向字符的指针,通常用于指向字符数组中的第一个字符,即字符串。 char **array是指向字符指针的指针。通常用于表示字符串数组。 char *array[size]大致相当于上面的那个,但它不同,那个,顶级指针已经指向一个有效的数组,所以数组不需要malloc ed。

顺便说一句,您的test函数可以简化一点:strcopy是不必要的。

void test(char *arr[])
{
    int i;
    for(i=0;i<2;i++)
    {
        arr[i] = malloc(80);
        gets(arr[i]);
    }
}

答案 1 :(得分:1)

好的,在C声明中,您只能获得从声明中读取的第一个分配内容。

在您了解如何阅读声明之前,这有点模糊。

运算符具有优先权,该优先权适用于声明。为简单起见,请:

() - Either raises precedence, or means "function taking parameters and returning..."
[] - Array of
* - Pointer to (right associative)

所以,宣言:

char *a[3];

是&#34;指向char&#34;的3个指针的数组,而

char (*a)[3];

是一个&#34;指向3 char&#34;数组的指针。 (指向行数为3的多调焦字符数组的行的指针)

编译器在堆栈上分配第一个东西。因此,在第一个示例中,您将获得三个能够指向(尚未分配的)字符的指针。

| ptr | --> (unallocated char)
| ptr | --> (unalloc char)
| ptr | --> (unalloc char)

在第二个:

| ptr | --> (unallocated block of 3 char)

下一个规则是:如果你有一个指针,你有一个数组。因此,在这两种情况下,您最终都会得到多维数组。

在第一个中,行数是固定的(您已经分配了它),但每行可以有不同的大小,因为编译器知道指针可以被char偏移以到达下一个char。

在第二种情况下,你有一个固定的行大小,但编译器知道如何偏移你的基指针(每个3个字符),所以你有任意数量的行。

C也是一种按值调用的语言。所以,如果你宣布了一个变量:

char *a[3];
然后&#39; a&#39;本身是&#34;一个3 ptr到char&#34;的数组,但是[0]是&#34; ptr到#&#34;和[0] [0]是char。

当你编写一个期望的函数时:

void f(char *arg[]) {
...
}

你必须传递一个指向char的指针数组。它并不关心有多少行(你必须跟踪它)...它只关心类型是否正确。

所以,如果你有&#39;在我们的第一个例子中声明,你必须调用f(a)。函数调用对函数args执行类似赋值的操作:

f(a)表示用(arg = a)调用f。

优先规则特别重要,您应该继续处理这些规则,直到您可以阅读这样的声明:

int (*f(int (*a)[4], void (*f)()))[6];

which is "f is a function that takes:
  - a pointer to arrays of 4 int
  - a pointer to a function that takes nothing and returns nothing)
and (then f) returns a pointer to arrays of 6 int".

答案 2 :(得分:0)

char * array创建一个指向内存字节的指针。 char * array [size]创建一个指向长度为'size'的数组的指针。 char **数组只是一个指向内存字节指针的指针

正如您所看到的,代码的问题在于您试图将测试函数传递给它不期望的东西。测试函数需要一个指向指针的指针,你只需给它一个指针。正确的段落是: 试验(ARR);

将第二个视角置于透视图中:在制作命令行程序时会看到这种情况(等等)。

考虑以下代码:

#include<stdio.h>

int main(int argc, char *argv[]) {
    printf("%s\n", argv[0]);
    return 0;
}

argv指针指向命令行参数,每个参数都是一个字符串(只是一个指针或一个数组)。因此,假设您为Linux执行了以下操作:

./ some_program -option opt-input

每个都被视为自己的字符串。 char * argv []指向每个字符串。第一个printf将打印出./some_program,因为这是argv指向的第一个字符串。