【问题标题】:How to read in 2d array from function in main如何从主函数中读取二维数组
【发布时间】:2015-10-01 18:25:01
【问题描述】:

好吧,我确信这很简单,但我不知道如何使用函数。到目前为止,我能够处理 main 中的所有内容,但现在我需要使用函数来完成我所做的任何事情。因此,从下面的代码中,我如何读入(或正确的术语是)main 中的函数?

编辑:为了向大家澄清,我的问题是如何访问我在 main 中返回的数组?

下面的代码接受用户输入指定的不同数量学生的考试成绩。

#include <stdio.h>
#include <stdlib.h>

int** getTestData();

int main (){

    ///this is where I'm lost..
    int (*a)[];
    a = getTestData();

}

int** getTestData(){
    int students, numberOfTests, testScores, i, j;
    int** testScoreBank;

    // reads in studens
    scanf("%i", &students);
    testScoreBank = (int**) malloc (sizeof(int)*students);

    for(i=0; i<students;i++){
        //how many number of tests there are
        scanf("%i", &numberOfTests);
        testScoreBank = (int*) malloc (sizeof(int)*numberOfTests);
        for(j=0; j<numberOfTests; j++){
            //the tests themselves
            scanf("%i", &testScores);
            testScoreBank[i][j] = testScores;
        }
    }
    return testScoreBank;
}

【问题讨论】:

  • 在 for 循环之前,您应该在创建指针数组时执行 testScoreBank = malloc(sizeof(int*) * students);。在 for 循环中你应该做testScoreBank[i] = malloc(sizeof(int) * numberOfTests);,你现在所做的没有意义。无论如何,对于这个问题,我不知道你想用这个数组在这个主函数中完成什么。
  • 是的.. 没有很好地解释自己。如何在 main 而不是 getTestData 中打印我的数组?当我返回 testScoreBank 时,我应该返回数组,现在我如何才能在 main 中访问该数组?
  • 您可以先使用int** a = getTestData();,但问题是您不知道有多少学生以及他们每个人进行了多少测试。您可以使用此信息创建一个结构,或者在 main 中声明一些变量并将指向它们的指针传递给您的函数,这样您就可以从那里填写它们,例如您需要学生数量和指向您将放置大小的数组的指针每个数组)。另一种选择是使用全局变量。

标签: c function multidimensional-array


【解决方案1】:

好的,这里有一个全局变量的例子,如何在函数中填充你的数组,并在main()中访问它

#include <stdio.h>
#include <stdlib.h>

int** getTestData();
int numberOfStudents;
int* studentTestSizes;

int main (){
  int** testScoresBank = getTestData();

  int i, j;

  for (i = 0; i < numberOfStudents; i++) {
    for (j = 0; j < studentTestSizes[i]; j++) {
      printf("%d", testScoresBank[i][j]);
    }
  }

  return 0;
}

int** getTestData() {
    int** testScoreBank;

    // reads in studens
    scanf("%d", &numberOfStudents);
    testScoreBank = malloc(sizeof(int*) * numberOfStudents);
    studentTestSizes = malloc(sizeof(int) * numberOfStudents);

    int i;
    for (i = 0; i < numberOfStudents; i++) {
        //how many number of tests there are
        scanf("%d", studentTestSizes + i);
        testScoreBank[i] = malloc(sizeof(int) * studentTestSizes[i]);

        int j;
        for (j = 0; j < studentTestSizes[i]; j++) {
            //the tests themselves
            int testScore;
            scanf("%d", &testScore);
            testScoreBank[i][j] = testScore;
        }
    }
    return testScoreBank;
}

全局变量的替代方法是将全局变量设为局部变量并将指向它们的指针传递给getTestData函数,示例如下:

#include <stdio.h>
#include <stdlib.h>

int** getTestData();

int main (){

  int numberOfStudents;   // those variables are now here
  int* studentTestSizes;

  int** testScoresBank = getTestData(&numberOfStudents, &studentTestSizes); // passing the pointers so we can change values that are pointed to

  int i, j;
  for (i = 0; i < numberOfStudents; i++) {
    for (j = 0; j < studentTestSizes[i]; j++) {
      printf("%d", testScoresBank[i][j]);
    }
  }

  return 0;
}

int** getTestData(int* numberOfStudentsPtr, int** studentTestSizesPtr) {
    int** testScoreBank;

    // reads in studens
    scanf("%d", numberOfStudentsPtr); // it's already a pointer so we must omit &
    int numberOfStudents = *numberOfStudentsPtr; // will be constant from now on

    testScoreBank = malloc(sizeof(int*) * numberOfStudents);

    *studentTestSizesPtr = malloc(sizeof(int) * numberOfStudents);
    int* studentTestSizes = *studentTestSizesPtr;

    int i;
    for (i = 0; i < numberOfStudents; i++) {
        //how many number of tests there are
        scanf("%d", studentTestSizes + i);
        testScoreBank[i] = malloc(sizeof(int) * studentTestSizes[i]);

        int j;
        for (j = 0; j < studentTestSizes[i]; j++) {
            //the tests themselves
            int testScore;
            scanf("%d", &testScore);
            testScoreBank[i][j] = testScore;
        }
    }
    return testScoreBank;
}

【讨论】:

  • 这很有帮助,你不知道。有两个问题,为什么要在 studentTestSizes 上使用 malloc,我将如何处理指针方法?
  • studentTestSizes 是一个数组,其中包含每个学生的测试数组的大小,例如第一个学生有 5 个测试,第二个有 3 个测试,我们需要在某个地方记住这些大小。我们不知道有多少学生,所以必须创建这个数组,并且必须在程序运行期间确定它的大小。稍后我会尝试提供指针示例。
【解决方案2】:

除了其他答案之外,您还有许多微妙的问题需要考虑。两个只是用于编写/调试您的初始应用程序的一般有用提示 (1) 如果您正在接受用户输入,请提示它 - 您可以稍后删除提示,但输入数据以响应信息提示比它更容易是想知道那里闪烁的光标在做什么——程序冻结了吗? (2) 在您的代码中提供足够的间距 - 您可以随时删除空行,但是将您的代码分成功能逻辑块将有助于您保持逻辑的直截了当。

为数值数组分配空间时,最好将所有值初始化为 0 作为分配的一部分(或之后)。这绝对可以防止无意中从未初始化的空间读取。您可以使用calloc 而不是malloc 一次性分配和初始化。这在将 指针数组分配给 char* 时也有好处。

虽然您可能已经修复了分配问题,但您仍然面临知道"How many students and tests do I have?" 的明显问题。这里需要传递一个额外的学生数量指针并将测试数量存储在一个额外的数组索引中。 (还有其他方法可以做到这一点,这只是有效的)。您可以在main 中声明学生人数,并将其指针传递给getTestData。然后在 main 中更新 getTestData 中的学生值。但是,"What if the students have a different number of scores? What then?" 您已经在填充一个整数数组,如果您只是将学生的测试次数存储为第一个整数,那么无论您将数组传递到何处,都可以使该值可用。

最后,您需要更加注意变量types 的选择。对于永远不会为负数的索引和长度,unsignedsize_t 是更好的选择,并且允许编译器指出您可能错误地使用该值的实例。

您需要在每次使用malloccalloc 分配内存时验证,并且您有责任跟踪每次分配开始的地址并在分配时释放它不再需要。

也就是说,这是使这一切正常工作的一种方法。尝试一下。如果您有任何问题,请告诉我:

#include <stdio.h>
#include <stdlib.h>

int **getTestData (size_t *students);

int main (void) {

    int **a = NULL;
    int j;
    size_t i, s = 0;

    if (!(a = getTestData (&s))) {
        fprintf (stderr, "error: getTestData failed to return student data.\n");
        return 1;
    }

    /* print student data */
    putchar ('\n');
    for (i = 0; i < s; i++) 
    {
        printf (" Student[%2zu] scores : ", i+1);

        /* adjust indexes to read no. of tests */
        for (j = 1; j < a[i][0]; j++)
            printf (" %3d", a[i][j]);

        putchar ('\n');
    }
    putchar ('\n');

    /* free allocated memory */
    for (i = 0; i < s; i++)
        free (a[i]);
    free (a);

    return 0;
}

int **getTestData (size_t *students)
{
    size_t tests, testScores, s, t;
    int **testScoreBank;

    /* reads in students */
    printf ("\n No. of students: ");
    scanf ("%zu", students);
    if (!(testScoreBank = calloc (*students, sizeof *testScoreBank))) {
        fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
        return NULL;
    }

    for (s = 0; s < *students; s++) 
    {
        /* how many number of tests there are */
        printf ("\n No. of scores for student[%2zu]: ", s+1);
        scanf ("%zu", &tests);
        tests += 1;    /* allow space for number of tests as [s][0] */
        testScoreBank[s] = calloc (tests, sizeof **testScoreBank);
        testScoreBank[s][0] = tests;

        for (t = 1; t < tests; t++) 
        {
            /* the tests themselves */
            printf ("   student[%2zu]-test[%2zu] score: ", s+1, t);
            scanf ("%zu", &testScores);
            testScoreBank[s][t] = testScores;
        }
    }
    return testScoreBank;
}

使用/输出

$ ./bin/testdata

 No. of students: 2

 No. of scores for student[ 1]: 3
   student[ 1]-test[ 1] score: 88
   student[ 1]-test[ 2] score: 91
   student[ 1]-test[ 3] score: 82

 No. of scores for student[ 2]: 4
   student[ 2]-test[ 1] score: 93
   student[ 2]-test[ 2] score: 95
   student[ 2]-test[ 3] score: 96
   student[ 2]-test[ 4] score: 91

 Student[ 1] scores :   88  91  82
 Student[ 2] scores :   93  95  96  91

【讨论】:

    【解决方案3】:

    (我认为这只是您整体代码的一个 sn-p,还有更多内容,否则您可能会遇到其他问题) 无论如何,您应该能够通过以下修改设置您的二维数组:

    scanf("%i", &students);
    testScoreBank = malloc (sizeof(int*)*students); //sizeof int* instead of sizeof int.
    
    for(i=0; i<students;i++)
        {
        scanf("%i", &numberOfTests);
        *(testScoreBank + i)= malloc (sizeof(int)*numberOfTests); //You forgot the * operator on testScoreBank and to iterate through it.
        for(j=0; j<numberOfTests; j++)
            {
            scanf("%i", &testScores);
            testScoreBank[i][j] = testScores;
            }
        }
    

    【讨论】:

    • 现在我的问题是,如何才能访问我在 main 函数中返回的数组?
    • 使用数组索引 a[ ][ ] 例如一个[2][5]
    • *(testScoreBank + i) 很难说testScoreBank[i]
    猜你喜欢
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    • 2016-06-07
    相关资源
    最近更新 更多