我正在编写一个代码,要求用户键入2个矩阵的行数和列数,然后让用户输入其元素。
获取矩阵元素的用户输入后。调用函数matadd
,它接收包含第一和第二矩阵元素,变量地址a[20][20]
,b[20][20]
的数组变量m
,n
的地址没有。行和列的数组,变量s[20][20]
的地址,它将存储两个矩阵的总和。
matadd
功能代码:
int matadd(int *(h)[20], int *(k)[20], int *u, int *l,int *(m)[20])
{
//VARIABLE-DECLARATION
int i = 0, j = 0;
for (i = 0; i < *u; i++)
{
for (j = 0; j < *l; j++)
{
*(*(m + i) + j) = *(*(h + i) + j) + *(*(k + i) + j);
}
}
printf("The Addition of above two given matrices is given below :\n");
printf("-- --\n");
for (i = 0; i < *u; i++)
{
for (j = 0; j < *l; j++)
{
printf("|");
for (j = 0; j < *l; j++)
{
printf("%4d", *(*(m + i) + j));
}
printf(" | ");
printf("\n");
}
}
printf("-- --\n");
return(m);
}
问题出在这行代码*(*(m + i) + j) = *(*(h + i) + j) + *(*(k + i) + j);
,它必须在指针变量m
内逐个分配增值。
但程序停在那里并给我错误:
mATRIX_pROTO.exe中的0x00C124B9抛出异常:0xC0000005:Access 违规读取位置0x00000001。
如果存在此异常的处理程序,则程序可能是安全的 继续进行。
无法找到代码的错误。我正在使用Visual Studio 2015来调试我的代码。
任何帮助都将不胜感激。
这是我的代码:
//CONSTANT-VARIABLE
#define MAX 1000
//USER-DEFINED FUCNTION
int matadd(int *h, int *k, int *u, int *l,int *(m)[20]);
char xgets(char *line, int size, FILE *stdi);
void header(void);
char xgets(char *line, int size, FILE *stdi) {
/* read a line from the user */
fgets(line, size, stdi);
/* strip the \n if present */
line[strcspn(line, "\n")] = '\0';
return line;
}
void header(void)
{
printf("*-*-*-*-*MATRIX_ADD_PTR*-*-*-*-*");
printf("\n\n");
}
//PROGRAM STARTS HERE
int main(void)
{
//FUCNTION CALL-OUT
header();
//VARIABLE-DECLARATION
int a[20][20] = { { 0 } }, b[20][20] = { { 0 } }, c[20][20] = { { 0 } },s[20][20] = { {0} };
int i = 0, j = 0;
int m = 0, n = 0, q = 0, w = 0;
int line[MAX] = { 0 };
printf("Type Same Number of ROWs And COLUMNs for Both Matrx \n\n");
printf("Enter the No. of ROWs needed in First Matrix : ");
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &m);
printf("\n");
printf("Enter the No. of COLUMNs needed in First Matrix : ");
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &n);
printf("\n");
printf("Enter the Elements for 1st ROW then 2nd and So on for First Matrix : \n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &a[i][j]);
}
}
printf("\n");
printf("Enter the No. of ROWs needed in Second Matrix : ");
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &q);
printf("\n");
printf("Enter the No. of COLUMNs needed in Second Matrix : ");
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &w);
printf("\n");
printf("Enter the Elements for 1st ROW then 2nd and So on for Second Matrix : \n");
for (i = 0; i < q; i++)
{
for (j = 0; j < w; j++)
{
xgets(line, sizeof(line), stdin);
sscanf_s(line, "%d", &b[i][j]);
}
}
//OUTPUT OF ENTERED MATRIX
printf("First Matrix : \n\n");
printf("-- --\n");
for (i = 0; i < m; i++)
{
printf("|");
for (j = 0; j < n; j++)
{
printf("%3d", a[i][j]);
}
printf(" | ");
printf("\n");
}
printf("-- --\n\n\n");
printf("Second Matrix : \n\n");
printf("-- --\n");
for (i = 0;i < q;i++)
{
printf("|");
for (j = 0; j < q; j++)
{
printf("%3d", b[i][j]);
}
printf(" | ");
printf("\n");
}
printf("-- --\n\n\n");
//FUCNTION CALL-OUT
matadd(a, b, &m, &n, s);
//TERMINAL-PAUSE
system("pause");
}
int matadd(int *(h)[20], int *(k)[20], int *u, int *l,int *(m)[20])
{
//VARIABLE-DECLARATION
int i = 0, j = 0;
for (i = 0; i < *u; i++)
{
for (j = 0; j < *l; j++)
{
*(*(m + i) + j) = *(*(h + i) + j) + *(*(k + i) + j);
}
}
printf("The Addition of above two given matrices is given below :\n");
printf("-- --\n");
for (i = 0; i < *u; i++)
{
for (j = 0; j < *l; j++)
{
printf("|");
for (j = 0; j < *l; j++)
{
printf("%4d", *(*(m + i) + j));
}
printf(" | ");
printf("\n");
}
}
printf("-- --\n");
return(m);
}
答案 0 :(得分:2)
查看您的附加代码,我们会看到这种模式三次:
*(*(h + i) + j)
上面的表达式应该是int
类型,以便在元素添加的上下文中有意义。这意味着
(*(h + i) + j)
应该是int *
类型,即。指向整数的指针。这也意味着j
应该有意义地转换为size_t
(它是)和
*(h + i)
也属于int *
类型。然后
(h + i)
应该是指向上述类型的指针,因此是int **
。类似于上面的i
应该可以转换为size_t
(它是),而h
应该是相同的类型。
更直接地说,它应该是一个(一个数组)指针指向({1}}(s)的数组。
让我们看看int
中的内容:
main
这是一个数组数组,因此除了与
类似的索引之外int a[20][20];
因为它存储在连续的内存中。这与上面的表达不同!
您需要决定其中一种表示形式。
我尝试使用较小的2对2情况来形象化这一点(我在移动设备上播放,因此这种方式很难):
int a[20*20];
您的功能正在等待您的数据:
data:
1 2
3 4
但是你把它存储起来了:
@some_address:
address_one <--- h points to this
address_two
@address_one:
1
2
@address_two:
3
4
因此,您的函数使用值@some_address:
1 <--- a decays to a pointer pointing to here upon use
2
3
4
和1
作为内存地址。
请注意,我这里只讨论(恕我直言)的主要问题,还有很多事情需要解决,正如另一个答案中的示例编译器消息所示。
答案 1 :(得分:1)
您不能忽略Visual Studio编译器发出的所有警告。添加提到的包含stdlib.h
,stdio.h
和process.h
并将开关/TC
添加到编译器调用后,以下警告
警告C4047:&#39;功能&#39; :&#39; int *&#39;间接水平与&#39; int [20] [20]&#39;
不同警告C4024:&#39; matadd&#39; :正式和实际参数1的不同类型
在
行matadd(a, b, &m, &n, s);
清楚地表明代码中出现了问题。发出这些警告是因为您的函数原型期望int *
您在调用中给出了int [20][20]
。然而,函数原型与matadd
的定义不符。如果我将原型更改为
int matadd(int *(h)[20], int *(k)[20], int *u, int *l,int *(m)[20]);
编译器会发出以下警告:
警告C4047:&#39;功能&#39; :&#39; int **&#39;间接水平与&#39; int [20] [20]&#39;
不同警告C4024:&#39; matadd&#39; :正式和实际参数1的不同类型
您可以通过将原型和定义更改为:
来解决此问题int matadd(int (*h)[20], int (*k)[20], int *u, int *l,int (*m)[20]);
编辑:类型int (*h)[20]
实际上表示指向包含20个元素的数组的指针。如果向指针添加1并使用(*(h+1))
取消引用它,则在(*h)
指向的前20个元素之后获得接下来的20个元素,依此类推。您还可以使用声明int h[][20]
来表达它,该声明更好地显示了作为2D数组的预期用途。请注意,只有第一个维度的大小可以保留未定义。 (讨论here和here的可能性更大,但Visual Studio 2010不支持这些。)
编辑:您可以在没有任何显式指针算法的情况下实现matadd
函数。这是一个精简的例子:
#include <stdio.h>
// specifying the size of the first dimension is optional
void matadd(int h[][20], int k[][20], int u, int l, int m[][20])
{
int i = 0, j = 0;
for (i = 0; i < u; i++)
{
for (j = 0; j < l; j++)
{
m[i][j] = h[i][j] + k[i][j];
}
}
}
int main(void)
{
int i, j, m, n;
int a[20][20] = { { 0 } }, b[20][20] = { { 0 } }, s[20][20] = { {0} };
m = 2; n = 2;
a[0][0] = 1; a[0][1] = 2; a[1][0] = 3; a[1][1] = 4;
b[0][0] = 5; b[0][1] = 6; b[1][0] = 7; b[1][1] = 8;
matadd(a, b, m, n, s);
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%4d | ", s[i][j]);
}
printf("\n");
}
}
您的代码甚至需要更多修复程序,如编译器警告所示;
警告C4013:&#39; strcspn&#39;不确定的;假设extern返回int
因为您忘记加入string.h
。
警告C4047:&#39;功能&#39; :&#39; char&#39;间接级别与&#39; char *&#39;
不同
在return line;
和return(m);
。在这里,您将指针转换为字符。该程序不会在这里发生段错误,因为您很乐意不使用返回值。
警告C4133:&#39;功能&#39; :不兼容的类型 - 来自&#39; int [1000]&#39;到#char;&#39; 警告C4133:&#39;功能&#39; :不兼容的类型 - 来自&#39; int [1000]&#39; to&#39; const char *&#39;
来自xgets
和sscanf_s
的电话。此类型转换也无效。该程序不会出现段错误,因为int [1000]
比相应的char [1000]
更大。
我之前的长篇评论是评论中的讨论的开头,可以找到here。