tags:

views:

68

answers:

2

hello, i have problem with the third function (GetMatrix) the others are works. i want to catch data from user into the matrix by poiters only

the lines:

typedef int pArr[COLS];

void GetMatrix(pArr* ,int , int );

M[ROWS][COLS];

are constraints

how i need to do the scan, i try to use scanf("%d",*(M+cols*i+j)) but i get error..its probably wrong what is need to do to make it right

thx all

the code :

#pragma warning ( disable: 4996 )
#include <stdio.h> 
#include <string.h>
#define ROWS 2
#define COLS 3

typedef int pArr[COLS];

void MergeStrings(char* str1,char* str2,char* strRes);
void StrReverse(char* strRes,char* strRev);
void GetMatrix(pArr* M ,int rows , int cols);

void main()
{
 char str1[256],str2[256],strRes[256],strRev[256];
 int M[ROWS][COLS];

 printf("Please enter first string:\n");
 flushall();
 gets(str1);
 printf("\nPlease enter second string:\n");
 flushall();
 gets(str2);

 printf("\nMerge of: %s\n",str1);
 printf("with: %s\n",str2);

 MergeStrings(str1,str2,strRes);

 StrReverse(strRes,strRev);

 printf("is:\n");
 printf("==> %s\n",strRes);

 printf("\nthe reversed merged string is:\n");
 printf("==> %s\n\n",strRev);

 GetMatrix(M,ROWS,COLS);
}

void MergeStrings(char* str1,char* str2,char* strRes)
{
 int i=0,j=0,a=0,flag=0,flag2=0;

 do
 {

  while( *(str1+i)==' ')
   i++;

  while( *(str2+j)==' ')
   j++;

  while( *(str1+i)!=' ' && *(str1+i)!='\0')
  {
   *(strRes+a)=*(str1+i);
    i++;
    a++;
  }

  if(flag!=1)
  {
  *(strRes+a)=' ';
  a++;
  }

  if(*(str1+i)=='\0')
  flag=1;

  while( *(str2+j)!=' ' && *(str2+j)!='\0')
  {
   *(strRes+a)=*(str2+j);
   j++;
   a++;
  }

  if(flag2!=1)
  {
  *(strRes+a)=' ';
  a++;
  }

  if(*(str2+j)=='\0')
  flag2=1;

 }while( (*(str1+i)!='\0') || (*(str2+j)!='\0') );

 *(strRes+a)='\0';

}

void StrReverse(char* strRes,char* strRev)
{
 int size,i=0,j=0;
 size=strlen(strRes);

 for(i=size-2 ; i>=0 ;i--)
 {
  *(strRev+j)=*(strRes+i);
  j++;
 }

 *(strRev+size-1)='\0';

}
void GetMatrix(pArr* M ,int rows , int cols )
{


}
A: 
#define ROWS 2
#define COLS 3
typedef int pArr[COLS];
void GetMatrix(pArr* M ,int rows , int cols )
{
  for(int i = 0; i < rows; i++)
    for(int j = 0; j < cols; j++)
      scanf("%d", &(M[i][j]));
}

int main()
{
    int M[ROWS][COLS] = {{100, 101, 102},{103, 104, 105}};
    printf("before\n");
    for(int i = 0; i < ROWS; i++){
        for(int j = 0; j < COLS; j++)
            printf("%d ", M[i][j]);
        printf("\n");
    }
    printf("enter values\n");
    GetMatrix(M, ROWS, COLS);
    printf("after\n");
    for(int i = 0; i < ROWS; i++){
        for(int j = 0; j < COLS; j++)
            printf("%d ", M[i][j]);
        printf("\n");
    }
}

Output:

before
100 101 102 
103 104 105 
enter values
0 1 2 3 4  5
after
0 1 2 
3 4 5 

Inside the function, M is a pointer to an array of three integers. M[i] is the i-th array, and M[i][j] is the j-th element in the i-th array. & operator gives its address to the scanf, which happily stores the read number in there.

Here is what happens when you replace scanf("%d", &(M[i][j])); with scanf("%d",*(M+cols*i+j)):

  for(int i = 0; i < rows; i++)
    for(int j = 0; j < cols; j++)
      scanf("%d", *(M + cols * i + j));

snip..

before
100 101 102 
103 104 105 
enter values
0 1 2 3 4 5
after
0 101 102 
1 104 105 
  • In the first iteration of the inner loop, i and j are zero, and *(M+cols*i+j) becomes *M. Since M is a pointer to an array, dereferencing it gives you an array of integers which decays into pointer to an integer. Thus the first number get stored at the correct place.
  • In the second iteration of the inner loop, j is 1. Thus, it is *(M + 1). Pointer arithmetic comes into picture here. Since M is a pointer to an array of three integers, (M + 1) is a pointer to an array of three integers that points to the second array; dereferencing it gives the array, which decays into pointer and scanf writes the second number there.
  • In the third iteration, j is 2 and (M + 2) points to the third (non existent) array and scanf writes the entered number into that memory location in the stack, thus corrupting the stack.
  • So on and so forth. It attempts to write into every third integer location, leaving our preinitialized values (101, 102, 104, 105) untouched.

If you want to it with pointers, you can cast M as a pointer to int as in:

scanf("%d", (int*)M + cols * i + j);

Once you cast M as int*, pointer arithmetic adds 1 * sizeof(int) to the starting position instead of 1 * sizeof(array of three ints), thus giving the desired results.


Update - answer to the comment I received in Facebook.

Consider the snippet:

int a = 10;
scanf("%d", &a);
printf("%d", a);

Scanf stores the entered value at the specified address - hence we pass a pointer to int as its argument. printf prints the passed value - hence we pass an int as the argument. The same difference applies here. ((int*)M + cols * i + j) is of type int*, pointer to an integer. To print the integer at that location we should dereference it using * operator. Thus it becomes:

printf("%d\t",*((int*)M + cols * i + j));

Oh, and by the way, you'd have received a faster reply if you had posted your doubts here itself instead of my FB. There are lots of good people ready to help hanging out in SO - and I check FB only on weekends.

Amarghosh
but i have constraint not to use [] its have to be just with pointers
eliran
@eliran see the update
Amarghosh
thank you !!!!! very much!!
eliran
ok thanks, you righti will try it
eliran
A: 

do you mean?

int GetMatrix( pArr* M ,int rows , int cols )
{
  return 1==scanf("%d",&M[rows][cols]);
}
no i cant change it to int
eliran
no i cant change the the function to int its need to be void
eliran
i have constraint not to use [] its have to be just with pointers
eliran