在C中创建数组 [英] Creating arrays in C

查看:109
本文介绍了在C中创建数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在C中创建UNIX Shell.如果是在Java中,那简直是小菜一碟,但是我对C不那么有经验.C中的数组让我有些困惑.我不确定如何声明或访问某些数据结构.

我想创建一个要在每一行中读取的字符串.足够简单:只需一个字符数组即可.我将其初始化如下:

  char行[256];//每行的最大大小为255个字符 

要访问此数组的元素,我将执行以下操作:

  line [0] ='a';//将元素0设置为"a"fgets(line,sizeof line,stdin);//从stdin获取一行并将其放在行中 

以这种方式声明和使用字符串与将其声明为指针有何不同?据我了解,C语言中的数组会衰减为指针.那么,以下内容是否等效?

  char * line =(char *)malloc(sizeof(char)* 256);line [0] ='a';fgets(* line,sizeof(line),stdin); 

何时使用指针字符"*",何时不使用?在上面的示例中,是否在fgets中包含"*",还是正确的?

现在,我想创建一个字符串数组,或更确切地说,是一个指向字符串的指针数组.我会这样做吗?

  char * arr [20];//声明一个包含20个元素的字符串数组 

我将如何访问它?

  arr [0] ="hello"//将arr的元素零设置为"hello" 

这是正确的吗?

如何将这个数组传递给函数?

  execvp("ls",arr);//使用参数向量arr执行ls 

是正确的,还是我将使用指针* arr?如果是这样,为什么?

现在更糟糕的是,我想要一个字符串数组的数组(例如,如果我想保存多个参数向量,以便在管道序列中执行多个命令).会声明如下吗?

  char ** vector_arr [20];//字符串数组的数组 

我将如何访问该数组的元素?

  execvp("ls",vector_arr [0]);//以vector_arr的第一个元素作为参数向量执行ls 

我以为我对指针是什么,甚至数组与指针的关系有一个不错的了解,但是我似乎很难将其与实际代码联系起来.我猜想在处理指针时,我不知道何时引用* var,var或& var.

解决方案

您真的走对了.

在第二个示例中,在使用 malloc()的情况下, fgets()命令的调用方式如下:

fgets(line,sizeof(line),stdin);/* vs. fgets(* line ...),因为您拥有*/

这样做的原因是在C语言中,命名数组变量始终只是一个指针.所以:

字符行[256];

声明(并定义)一个名为 line 的指针,该指针指向在编译时(可能在堆栈上)分配的256个字节的内存.

char * line; 也声明了一个指针,但是它指向的内存不是由编译器分配的.当您调用 malloc 时,会将返​​回值强制转换为 char * 并将其分配给 line ,以便在堆上动态分配内存.

尽管在功能上,变量 line 只是一个 char * (指向char的指针),如果您查看 gets 中的声明,< stdio.h> 文件,您将看到它的第一个参数:

char * fgets(char *限制str,int大小,FILE *限制流);

...即 char * .因此,您可以通过声明它的任何方式传递 line (作为指针或数组).

关于您的其他问题:

char * arr [20]; 声明20个未初始化的指向 char * 的指针.要使用此数组,您需要对 arr 的元素进行20次迭代,并为每个数组分配 malloc()的结果:

  arr [0] =(char *)malloc(sizeof(char *)* 256);arr [1] =(char *)malloc(sizeof(char *)* 256);...arr [19] =(char *)malloc(sizeof(char *)* 256); 

然后,您可以使用20个字符串中的每个字符串.要将第二个参数传递给 fgets ,后者将 char * 作为其第一个参数,则可以执行以下操作:

fgets(arr [1],...);

然后, fgets 获得所需的 char * .

请注意,当然,您必须先调用 malloc(),否则将无法初始化 arr [1] .

您使用execvp()的示例是正确的(假设您首先使用 malloc()分配了所有这些字符串. vector_arr [0] 是char **,其中<[请记住execvp()还希望向量数组的最后一个指针具有 value NULL,请参见手册页进行澄清].

请注意,像这样声明 execvp()(请参见< unistd.h> )

int execvp(const char * file,char * const argv []);

为清晰起见,删除了 const 属性,也可以这样声明它:

int execvp(const char * file,char ** argv);

char ** array 的声明在功能上等同于 char * array [] .

还请记住,在每个使用 malloc()的示例中,您都必须在某个时候使用相应的 free(),否则会泄漏内存

我还将指出,一般而言,尽管您可以创建向量数组(以及向量数组的数组,依此类推),但是随着数组尺寸的扩展,您会发现代码变得越来越难理解和维护.当然,您应该了解这一切的工作原理和实践,直到您完全理解它为止,但是,如果在设计代码的过程中发现自己认为需要数组数组,则可能会使事情复杂化.

I am attempting to create a UNIX shell in C. If it were in Java, it would be a piece of cake, but I am not so experienced in C. Arrays in C confuse me a bit. I am not sure how to declare or access certain data structures.

I would like to create a string to read in each line. Easy enough: simply an array of characters. I would initialize it as follows:

char line[256]; //Maximum size of each line is 255 characters

And to access an element of this array, I would do as follows:

line[0] = 'a'; //Sets element 0 to 'a'
fgets( line, sizeof line, stdin ); //Gets a line from stdin and places it in line

How does declaring and using a string in this manner differ from declaring it as a pointer? From my understanding, an array in C decays to a pointer. So, would the following be equivalent?

char *line = (char*) malloc( sizeof(char) * 256 );
line[0] = 'a';
fgets( *line, sizeof(line), stdin );

When do you use the pointer character '*', and when don't you? In the example above, is including the '*' in fgets necessary, or correct?

Now, I would like to create an array of strings, or rather, an array of pointers which point to strings. Would I do so as follows?

char *arr[20]; // Declares an array of strings with 20 elements

And how would I access it?

arr[0] = "hello" // Sets element zero of arr to "hello"

Is this correct?

How would I pass this array to a function?

execvp("ls", arr); // Executes ls with argument vector arr

Is that correct, or would I use the pointer *arr? If so, why?

Now even worse, I would like an array of arrays of strings (for example, if I wanted to hold multiple argument vectors, in order to execute multiple commands in pipe sequence). Would it be declared as follows?

char **vector_arr[20]; // An array of arrays of strings

And how would I access an element of this array?

execvp("ls", vector_arr[0]); // Executes ls with first element of vector_arr as argument vector

I thought that I grasped a decent understanding of what a pointer is, and even how arrays relate to pointers, however I seem to be having trouble relating this to the actual code. I guess that when dealing with pointers, I don't know when to reference *var, var, or &var.

解决方案

You're really on the right track.

In your second example, where you use malloc(), the fgets() command would be called like so:

fgets( line, sizeof(line), stdin ); /* vs. fgets( *line ... ) as you have */

The reason for this is that in C a named array variable is always just a pointer. So:

char line[256];

declares (and defines) a pointer called line that points to 256 bytes of memory allocated at compile time (probably on the stack).

char *line; also declares a pointer, but the memory it points to is not assigned by the compiler. When you call malloc you typecast the return value to char * and assign it to line so the memory is allocated dynamically on the heap.

Functionally though, the variable line is just a char * (pointer to char) and if you look at the declaration of fgets in the <stdio.h> file, you'll see what it expects as its first argument:

char *fgets(char * restrict str, int size, FILE * restrict stream);

... namely a char *. So you could pass line either way you declared it (as a pointer or as an array).

With respect to your other questions:

char *arr[20]; declares 20 uninitialized pointers to char *. To use this array, you would iterate 20 times over the elements of arr and assign each one with some result of malloc():

arr[0] = (char *) malloc( sizeof(char*) * 256 );
arr[1] = (char *) malloc( sizeof(char*) * 256 );
...
arr[19] = (char *) malloc( sizeof(char*) * 256 );

Then you could use each of the 20 strings. To pass the second one to fgets, which expects a char * as its first argument, you would do this:

fgets( arr[1], ... );

Then fgets gets the char * it expects.

Be aware of course that you have to call malloc() before you attempt this or arr[1] would be uninitialized.

Your example using execvp() is correct (assuming you allocated all these strings with malloc() first. vector_arr[0] is a char **, which execvp() expects. [Remember also execvp() expects the last pointer of your vector array to have the value NULL, see the man page for clarification].

Note that execvp() is declared like so (see <unistd.h>)

int execvp(const char *file, char *const argv[]);

removing the const attribute for clarity, it could also have been declared like so:

int execvp( const char *file, char **argv );

The declaration of char **array being functionally equivalent to char *array[].

Remember also that in every example where we use malloc(), you'll have to at some point use a corresponding free() or you'll leak memory.

I'll also point out that, generally speaking, although you can do an array of vectors (and arrays of arrays of vectors and so on), as you extend your arrays more and more dimensionally you'll find the code gets harder and harder to understand and maintain. Of course you should learn how this all works and practice until you understand it fully, but if in the course of designing your code you find yourself thinking you need arrays of arrays of arrays you are probably overcomplicating things.

这篇关于在C中创建数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆