当您不知道程序开始时的长度时,如何在多个函数中使用数组

时间:2017-07-12 16:35:33

标签: c cs50

我有一个项目,我需要在两个不同的函数中使用一个数组,但它的长度因命令行参数而异,所以直到后来我都不知道它是什么。如何全局初始化数组,但是当我知道后面的长度时我可以改变长度。以下是我可以解决的问题的最简化版本:

#define _XOPEN_SOURCE 500

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


char tile_numbers[1];
void print (void);

int main (void)
{
    int x = 7;
    char tile_numbers[x];
    tile_numbers[0] = 'h';
    tile_numbers[1] = 'e';
    tile_numbers[2] = 'l';
    tile_numbers[3] = 'l';
    tile_numbers[4] = 'o';
    tile_numbers[5] = '!';

    print();

}

void print (void)
{

    for(int i = 0; i < 10 ; i++)
    {
        printf("char: %c", tile_numbers[i]);
    }

}

2 个答案:

答案 0 :(得分:0)

您可以使用malloc()动态分配内存,而不是数组。假设在运行时,您将数组的大小存储在int变量n中。然后,您可以使用

分配内存
char *tile_numbers = (char*)malloc(sizeof(char)*n);

然后,您可以像以前一样为内存位置编制索引,tile_numbers[i]范围为i0范围内的任何n-1

如果您需要它全局声明它,请将声明和赋值分开。在全球范围内,使用

char *tile_numbers;

在获得大小的函数中,

tile_numbers = (char*)malloc(sizeof(char)*n);

此外,如果您需要调整内存量,可以使用realloc()

tile_numbers = (char*)realloc(tile_numbers,new_size);

答案 1 :(得分:0)

不要使用全局 - 在main(或最初分配的位置)中定义数组,然后将其作为参数传递给需要使用的函数它:

void print( size_t size, const char *arr)
{
  for ( size_t i = 0; i < size; i++ )
    printf( "char: %c\n", arr[i] );
}

int main( int argc, char **argv )
{
  // define tileNumbers here -- we'll get into details below

  print( arraySize, tileNumbers );
  return 0;
}

不要养成使用全局(文件范围)变量的习惯 - 这会导致代码难以维护和扩展。 有时它是合理的,但你不知道那些时代到底是什么。通常,函数应该只通过参数或返回值共享信息;他们不应该分享全球状态。

由于您不知道在运行时需要多大tileNumbers,因此您无法将其分配为固定大小的数组,并在以后调整大小。在知道大小之前,您需要推迟数组的定义。

在C99之前,您唯一的选择是使用动态内存(即malloccalloc):

#include <stdlib.h> // for malloc declaration
...
size_t arraySize = getArraySize( );  // where getArraySize is a stand in for any code that sets arraySize

char *tileNumbers = malloc( sizeof *tileNumbers * arraySize );
if ( tileNumbers )
{
  // code to initialize tileNumbers goes here

  print( arraySize, tileNumbers );

  // deallocate memory when we're done with it
  free( tileNumbers );
}

从C99开始,你可以使用所谓的可变长度数组(VLA)。 VLA的行为主要是,就像常规的固定长度数组一样,但由于它的大小直到运行时才知道,所以它不能在文件范围内声明(不能使用)它作为一个全球性的,不能成为structunion类型的成员,并且在其声明中不能有初始化程序。

size_t arraySize = getArraySize( );  // where getArraySize is a stand in for any code that sets arraySize;

char tileNumbers[arraySize];

// code to initialize tileNumbers goes here

print( arraySize, tileNumbers );

无论哪种方式,print的原型都将保持不变。在第一种情况下,我们传递一个指针。在第二种情况下,我们传递一个数组表达式,在计算时衰减到指针表达式。