матрица с использованием указателей - PullRequest
0 голосов
/ 03 сентября 2010

У меня проблема с третьей функцией (GetMatrix), остальные работают. я хочу поймать данные от пользователя в матрицу только по пуайтерам

строки:

typedef int pArr[COLS];

void GetMatrix(pArr* ,int , int );

M[ROWS][COLS];

являются ограничениями

как мне нужно сделать сканирование, я пытаюсь использовать scanf("%d",*(M+cols*i+j)) но я получаю ошибку .. это, вероятно, неправильно что нужно сделать, чтобы все правильно

thx all

код:

#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 )
{


}

Ответы [ 2 ]

0 голосов
/ 03 сентября 2010

ты имеешь в виду?

int GetMatrix( pArr* M ,int rows , int cols )
{
  return 1==scanf("%d",&M[rows][cols]);
}
0 голосов
/ 03 сентября 2010
#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");
    }
}

Выход:

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

Внутри функции M является указателем на массив из трех целых чисел. M[i] - это i-й массив, а M[i][j] - это j-й элемент в i-м массиве. & оператор передает свой адрес в scanf, который с радостью хранит там прочитанное число.

Вот что происходит, когда вы заменяете scanf("%d", &(M[i][j])); на 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));

чик ..

before
100 101 102 
103 104 105 
enter values
0 1 2 3 4 5
after
0 101 102 
1 104 105 
  • На первой итерации внутреннего цикла i и j равны нулю, а *(M+cols*i+j) становится *M. Поскольку M - указатель на массив, разыменование дает массив целых чисел, который превращается в указатель на целое число. Таким образом, первое число сохраняется в правильном месте.
  • Во второй итерации внутреннего цикла j равно 1. Таким образом, оно равно *(M + 1). Здесь указывается арифметика указателя. Поскольку M является указателем на массив из трех целых чисел, (M + 1) является указателем на массив из трех целых чисел, который указывает на второй массив; разыменование дает массив, который распадается на указатель, а scanf записывает туда второе число.
  • На третьей итерации j равен 2, а (M + 2) указывает на третий (несуществующий) массив, и scanf записывает введенный номер в эту ячейку памяти в стеке, тем самым разрушая стек.
  • И так далее, и тому подобное. Он пытается записать каждое третье целое место, оставляя наши предварительно инициализированные значения (101, 102, 104, 105) нетронутыми.

Если вы хотите использовать указатели, вы можете привести M в качестве указателя на int как в:

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

После того, как вы произвели M как int*, арифметика указателя добавляет 1 * sizeof(int) к начальной позиции вместо 1 * sizeof(array of three ints), что дает желаемый результат.


Обновление - ответ на комментарий, который я получил в Facebook.

Рассмотрим фрагмент:

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

Scanf сохраняет введенное значение по указанному адресу - поэтому мы передаем указатель на int в качестве аргумента. printf печатает переданное значение - поэтому мы передаем int в качестве аргумента. Та же разница применяется здесь. ((int*)M + cols * i + j) имеет тип int*, указатель на целое число. Чтобы напечатать целое число в этом месте, мы должны разыменовать его используя оператор *. Таким образом это становится:

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

Да, и, кстати, вы бы получили более быстрый ответ, если бы вы разместили здесь свои сомнения вместо моего FB. В SO много хороших людей, готовых помочь повесить трубку - и я проверяю FB только по выходным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...