从用户输入

时间:2017-03-10 18:57:04

标签: c arrays segmentation-fault malloc

我知道有很多问题属于"多维数组"。由于我找不到能解决问题的具体问题,我终于要问了。

目标:存储其值从用户输入的2D数组。

Method-01 :为数组使用任意大的初始大小。

代码

int method_arbit()
{
 int n, m;
 int i, j;
 float myarray[100][100];

 printf("Enter the number of rows: ");
 scanf("%d", &m);

 printf("Enter the number of columns: ");
 scanf("%d", &n);

 for(i=0; i<m; i++)
 {
     for(j=0; j<n; j++)
         scanf("%f", &myarray[i][j]);
 }

 for(i=0; i<m; i++)
 {
     for(j=0; j<n; j++)
         printf("[%d][%d] = %f", i, j, myarray[i][j]);
 }
}

评论:此功能按预期工作!

方法-02 :使用动态内存分配。

代码

int method_dynamic()
{
 int n, m;
 int i, j;
 float **myarray; // m x n matrix

 printf("Enter the number of rows: ");
 scanf("%d", &m);

 printf("Enter the number of columns: ");
 scanf("%d", &n);

 myarray = malloc(m*sizeof(float*));
 for(i=0; i<m; i++)
     myarray[m] = malloc(n*sizeof(float));

 for(i=0; i<m; i++)
 {
     for(j=0; j<n; j++)
         scanf("%f", &myarray[i][j]);
 }

 for(i=0; i<m; i++)
 {
     for(j=0; j<n; j++)
         printf("[%d][%d] = %f", i, j, myarray[i][j]);
}
}

评论:此方法在接受输入时会产生分段错误。

Q1:我很难调试这个。而且,我发现更难理解这种行为背后的原因。 我对指针和动态内存分配有基本的了解。 我希望详细解释我所犯的错误以及我可能忽略的概念。

Q2:如果我们在编译时不知道数组的大小,我们应该总是动态分配数组吗? OR
什么时候建议使用动态分配的数组? 我知道的一个用例是在处理函数和从它们返回数组时。

4 个答案:

答案 0 :(得分:0)

OP的问题是使用错误的索引@forcebru

 myarray = malloc(m*sizeof(float*));
 assert(myarray); // Do some allocation check;
 for(i=0; i<m; i++) {
     //         v----- here
     // myarray[m] = malloc(n*sizeof(float));
     myarray[i] = malloc(n*sizeof(float));   
     assert(myarray[i]);
 }

答案 1 :(得分:0)

您可以将多维数组声明为大数组。

 int n, m;
 int i, j;
 float* myarray; // m x n matrix

 std::cout<<"Enter the number of rows: \n";
 scanf("%d", &m);

 std::cout << "Enter the number of columns: \n";
 scanf("%d", &n);

 myarray = (float*)malloc( m * n * sizeof(float) );

 for(i=0; i<m; i++)
 {
     for (j = 0; j<n; j++) {
         scanf("%f", &(myarray[i * n  + j]));
     }
 }

 for(i=0; i<m; i++)
 {
     for(j=0; j<n; j++) {
         printf("[%d][%d] = %f", i, j, (myarray[i * n  + j]));
     }
 }

答案 2 :(得分:0)

Q1 :你需要一块内存来容纳一个2维的浮点数,你的初始代码为

float **myarray;
myarray = malloc( m * sizeof(float*) );

m = 3;   // for this example
n = 5;   // for this example

是一个问题,因为您的两个维度是 m n 。您没有在那里使用 n 。你也在做sizeof(float*)并且你不希望指针的大小浮动。发生的事情是,如果sizeof( pointer to float) = {64位系统上的8个字节,32位系统上的4个字节},那么您的malloc分别保留24或12个字节。但是当你真正需要 m x n 单位时,只有 m 单位的内存{15个单位的15个唯一值,类型为float}

所以你想要一个 float 占用内存的大小。因此你应该做

float *myarray;  // not a double pointer
myarray = (float *) malloc( m * n * sizeof( float ) );

例如,如果sizeof(float)= 4个字节,那么如果m = 3且n = 5,则得到4x15 = 60个字节的内存。 malloc返回一个指向那块内存的指针,然后将它的类型转换为你声明的指针。

此时,您需要索引60个字节的总块,其中*myarray指向它的开头,就是这样。除了指向它的开头的指针myarray之外,编译器不知道如何排列或使用该块内存,它是浮点数据类型。 malloc或编译器无法知道您在使用myarray[][]约定时尝试使用的行或列大小 m n

在你的系统上,如果sizeof(float)是4,那么60字节块中的每4个字节可以是一个浮点值,给你15个值。

如果你想使用约定myarray[i][j]你不能,因为你使用了malloc,它不知道如何划分60字节的内存块。 您必须手动将[row] [col]索引编入myarray,例如

m = 3;   // max rows
n = 5;   // max columns

row = 2;  // value entered by user, must be < m
col = 3   // value entered by user, must be < n

*(myarray + (row*n) + col) = 1.2345;

Q2:是的我认为最好不要知道你需要的内存大小,编写好的代码来获取所有用户输入,然后计算你的内存大小我需要。然后使用 malloc calloc 来分配该内存,如果不成功{系统没有足够},则处理该条件并相应地编写代码。唯一的缺点是,如果你编写重复调用malloc或calloc的代码,那么释放它并多次重复这个过程,这会产生很多开销。

答案 3 :(得分:0)

你永远不会“真实地”这样做。让用户通过标准输入输入二维矩阵是一个教学玩具问题,给人们学习C.这个练习的一个缺点是没有一个好的答案,有一些方法你可以做到像创建超大缓冲区,或重新分配内存以增长,或在输入变量之前查询用户的宽度和高度。但没有什么是完全令人满意的。

实际上,数据很可能采用CSV等文件格式。解析CSV文件相当困难,但并不难以让任何有能力的程序员无法实现它。通常的方法是将结构读入内存结构,然后“解析解析器的输出”以将其转换为平面2D数组(或一维结构数组,对于CSV文件非常常见)。