C程序 - 将值存储在指针变量

时间:2016-02-21 12:28:23

标签: c arrays pointers matrix

我正在编写一个代码,要求用户键入2个矩阵的行数和列数,然后让用户输入其元素。

获取矩阵元素的用户输入后。调用函数matadd,它接收包含第一和第二矩阵元素,变量地址a[20][20]b[20][20]的数组变量mn的地址没有。行和列的数组,变量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);

}

2 个答案:

答案 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.hstdio.hprocess.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数组的预期用途。请注意,只有第一个维度的大小可以保留未定义。 (讨论herehere的可能性更大,但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;

来自xgetssscanf_s的电话。此类型转换也无效。该程序不会出现段错误,因为int [1000]比相应的char [1000]更大。

我之前的长篇评论是评论中的讨论的开头,可以找到here