Форум программистов, компьютерный форум CyberForum.ru

Не могу разобраться как работает данная программа - C++

Восстановить пароль Регистрация
 
.Malek.
5 / 5 / 0
Регистрация: 20.03.2011
Сообщений: 180
20.04.2011, 11:49     Не могу разобраться как работает данная программа #1
Помогите пожалуйста разобраться как работает данная программа ниже дано задание и готовый листинг. Я запутался тут с этими указателями.
Код
Реализовать программу демонстрирующую  решение поставленной задачи: В прямоугольной матрице определить элемент, который по модулю наименее отличается от среднего арифметического  всех элементов матрицы. 
В программе необходимо реализовать следующее:
ввод размеров многомерных массивов;
формирование динамических массивов заданных размеров;
заполнение массивов значениями;
печать в наглядном виде массива - результата;
удаление динамических массивов;
Код
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
void main()
{
        clrscr();
        cout<<"Enter n:"<<endl;
        int n;
        cin>>n;
        cout<<"Enter m:"<<endl;
        int m;
        cin>>m;

        int** M=new int*[n];
        int i;
        for(i=0; i<n; i++)
        {
                M[i]=new int[m];
        }

        int j;
        randomize();
        for(i=0; i<n; i++)
        {
                for(j=0; j<m; j++)
                {
                        M[i][j]=random(100)-50;
                        cout<<M[i][j]<<" ";
                }
                cout<<endl;
        }

        double Average=0;
        for(i=0; i<n; i++)
        {
                for(j=0; j<m; j++)
                {
                        Average+=M[i][j];
                }
        }
        Average/=(double)(n*m);
        cout<<"Average: "<<Average<<endl;
        int iA=0;
        int jA=0;
        int Nearest=M[0][0];
        for(i=0; i<n; i++)
        {
                for(j=0; j<m; j++)
                {
                        if( abs(abs(Nearest)-abs(Average)) > abs(abs(M[i][j]) - abs(Average)) )
                        {
                                Nearest=M[i][j];
                                iA=i;
                                jA=j;
                        }
                }
        }
        cout<<"The nearest number is: "<<Nearest<<" at ("<<iA<<"; "<<jA<<")."<<endl;
        
        getch();
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
mimicria
return (true);
 Аватар для mimicria
1956 / 1093 / 91
Регистрация: 19.04.2011
Сообщений: 2,344
20.04.2011, 11:56     Не могу разобраться как работает данная программа #2
Объявление динамического массива n*m
C++
1
2
3
4
5
6
        int** M=new int*[n];
        int i;
        for(i=0; i<n; i++)
        {
                M[i]=new int[m];
        }
Заполнение массива случайными значениями
C++
1
M[i][j]=random(100)-50;
Сумма всех элементов массива делится на размер, получаем среднее значение
C++
1
2
3
4
Average+=M[i][j];
                }
        }
        Average/=(double)(n*m);
Полным перебором ищется наименее отличающийся от среднего элемент
C++
1
if( abs(abs(Nearest)-abs(Average)) > abs(abs(M[i][j]) - abs(Average)) )
.Malek.
5 / 5 / 0
Регистрация: 20.03.2011
Сообщений: 180
20.04.2011, 11:58  [ТС]     Не могу разобраться как работает данная программа #3
а можно подробней что значит данная строка int** M=new int*[n];
mimicria
return (true);
 Аватар для mimicria
1956 / 1093 / 91
Регистрация: 19.04.2011
Сообщений: 2,344
20.04.2011, 12:04     Не могу разобраться как работает данная программа #4
Двумерный массив - это массив обычных массивов (масло масляное).
Если обычный массив представляем как строку элементов int t[]={1,2,3,4,5}, то двумерный - несколько таких строк.
Каждая строка объявляется тут:
C++
1
M[i]=new int[m];
а объявление массива строк тут
C++
1
int** M=new int*[n];
.Malek.
5 / 5 / 0
Регистрация: 20.03.2011
Сообщений: 180
20.04.2011, 12:11  [ТС]     Не могу разобраться как работает данная программа #5
а где тут удаление динамических массивов
mimicria
return (true);
 Аватар для mimicria
1956 / 1093 / 91
Регистрация: 19.04.2011
Сообщений: 2,344
20.04.2011, 12:20     Не могу разобраться как работает данная программа #6
Цитата Сообщение от .Malek. Посмотреть сообщение
а где тут удаление динамических массивов
В вашем исходнике нет удаления.
А вообще как создаются, так и удаляются
C++
1
2
3
4
5
for(i=0; i<n; i++)
        {
                delete [] M[i];
        }
 delete [] M;
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2011, 13:20     Не могу разобраться как работает данная программа #7
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdlib.h> // Подключение головы
#include <iostream.h> // Подключение ещё одной головы
#include <math.h> /// Подключение третьей головы
void main() // Первая операция этой функции - точка входа в прогу
{// начало тела функции
 clrscr(); // фиг его знает, но в принципе должна быть очистка экрана
 cout<<"Enter n:"<<endl; // Вывести в поток текст "Enter n:" и перейти на следующую строку
 int n; // Целая переменная n
 cin>>n; // Вводим переменную n из потока
 cout<<"Enter m:"<<endl; //Вывести в поток текст "Enter m:" и перейти на следующую строку
 int m; Целая переменная m
 cin>>m; // Вводим переменную n из потока 
 int** M=new int*[n]; // Указатель M на указатель на целое. Внтуренняя реализация сёвых массивов основана на указателе на начало массива, а многомерные масивы на сях заменяются массивами массивов, пока все массивы не будут одномерными. Соостветвенно многомерный массив это тоже массив указателей на начала массвов, то есть указатель на начало массива указателй на начала маасивов. Указатель декларирован и сразу же создан, по нему выделена память для хранения массива указатеелй, но пока эти указатели ещё не созданы
 int i; // Целая переменная i
 for(i=0; i<n; i++) // Цикл по перемнной i от 0 с увеличением пока i<n
 {// Начало тела цикла
  M[i]=new int[m]; // M[i] -ячейка для хранения целого, оттоящая от той, на которую оказывает M на i*(размер указетля на целое), то есть i-тый элмент массива, на начало которого указывает M. Здесь в этой ячейке создаётся указатель на начало массива целых
 }// Конец тенла цикла
 int j; // Целая переменная j
 randomize(); // судя по всему, старт генератора случайных чисел.
 for(i=0; i<n; i++) // Цикл по перемнной i от 0 с увеличением пока i<n. Для меня загадка, зачем нужны два раздельных цикла по одной переменной
 {// Начало тела цикла
   for(j=0; j<m; j++) // Вложенный цикл по перемнной j от 0 с увеличением пока j<m.
   {// Начало тела цикла
     M[i][j]=random(100)-50; // M[i] уже разобран выше. По аналогии M[i][j] - j-тый элемент массвиа, на начало которого указывает M[i], то есть элемент двумерного массива, реализованного на указаетле M с индексами [i,j]. Здесь он заполняется случайным числом. Берётся случайное число в диапазоне от 0 ло 100, из него вычитается 50 и получается случайное число в диапазоне от -50 до 50, оно записывается в элмент массива.
     cout<<M[i][j]<<" "; // Здесь этот элемент выводится в поток
   }// Конец тела цикла
  cout<<endl; // Переход на следующуу строку
 }// Конец тела цикла
 double Average=0; // действительаня переменная Average двойной точности, по дефолту равная нолю
 for(i=0; i<n; i++) // Опять цикл по i, выше он уже прокомментирван
 {// Начало цикла по i
  for(j=0; j<m; j++) // Цикл по j. Он тоже уже прокоментирвоан выше
  {//Начало тела цикла
   Average+=M[i][j]; // Переменная Average увеличивается на элмента массива, чья адресация разобрана выше, таким способом в этйо переменнйо накапливается сумма. Для меня загадка, почему переменная Average обнулена не в заголовке цикла, а в декларации самой переменной
  }//Конец тела цикла
 }//Конец тела цикла
 Average/=(double)(n*m);// Сумму накопили, а теперь делим её на колчиество слагаемых, в результате получаем среднее арифметическое. Так быстрее, чем сразу делить
 сout<<"Average: "<<Average<<endl; Выыодим в поток текст "Average: ", потом значение переменной Average и переходим на следующую строку
 int iA=0; // целая переменная iA, по дефолту равна нолю
 int jA=0; // целая переменная jA, по дефолту равна нолю
 int Nearest=M[0][0]; // целая переменная Nearest, по дефолту равна нолю элменту массива с индексами [0,0]. Какой то элмент надо предположить и в принципе он может быть любым, две предыдущие переменные его индексы, их значения должны быть на всякий случай согласованы с этим предположением (вдруг сразу угадали?)
 for(i=0; i<n; i++)// Этот цикл уже разбирали
 {// Начало тела цикла
  for(j=0; j<m; j++) // И этот цикл уже разбирали
   {// Начало тела цикла
    if( abs(abs(Nearest)-abs(Average)) > abs(abs(M[i][j]) - abs(Average)) )// Если модуль разности между значениями элмента массива и средним для текущего элмента меньше, чем для того, чьё значение валяется в Nearest, то мы нашли, чем надо заменить значение Nearest. Именено для этого сравнения и необходимо начальное предположение о позиции искомого элемента.
     {// Если условие истинно, то будем делать то, что в этих скобках. Начало блока.
      Nearest=M[i][j];// Заменяем Nearest
      iA=i;// Мы нашли, чем заменить Nearest? Эйси, но это означает, что найдены и индексы ближайшего к среденму из числа обработанных элментов. Заменяем iA.
      jA=j; Мы нашли, чем заменить Nearest? Эйси, но это означает, что найдены и индексы ближайшего к среденму из числа обработанных элментов. Заменяем jA.
     }// Если условие истинно, то будем делать то, что в этих скобках. Конец блока.
   }// Конец тела цикла
  }// Конец тела цикла
 cout<<"The nearest number is: "<<Nearest<<" at ("<<iA<<"; "<<jA<<")."<<endl; Выводим в поток текст "The nearest number is: ", потом значение переменной Nearest (сейчас там действительно занчение искомого элмента массива), потом текст " at (", потом значение переменной iA (в енй валяется первый индекс искомого элемента), потмо текст "; ", потом значение переменной jA (в ней ваоляется второй индекс искомого элемента), потом текст ")." и переходим на следующую строку.   
 getch(); // Ждём нажатия на кнопку Enter
}// Конец тела функции
В следующий раз форматируй тегом.

Добавлено через 5 минут
И должно быть так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <stdlib.h> // Подключение головы
#include <iostream.h> // Подключение ещё одной головы
#include <math.h> /// Подключение третьей головы
void main() // Первая операция этой функции - точка входа в прогу
{// начало тела функции
 clrscr(); // фиг его знает, но в принципе должна быть очистка экрана
 cout<<"Enter n:"<<endl; // Вывести в поток текст "Enter n:" и перейти на следующую строку
 int n; // Целая переменная n
 cin>>n; // Вводим переменную n из потока
 cout<<"Enter m:"<<endl; //Вывести в поток текст "Enter m:" и перейти на следующую строку
 int m; Целая переменная m
 cin>>m; // Вводим переменную n из потока 
 int** M=new int*[n]; // Указатель M на указатель на целое. Внтуренняя реализация сёвых массивов основана на указателе на начало массива, а многомерные масивы на сях заменяются массивами массивов, пока все массивы не будут одномерными. Соостветвенно многомерный массив это тоже массив указателей на начала массвов, то есть указатель на начало массива указателй на начала маасивов. Указатель декларирован и сразу же создан, по нему выделена память для хранения массива указатеелй, но пока эти указатели ещё не созданы
 int i; // Целая переменная i
 for(i=0; i<n; i++) // Цикл по перемнной i от 0 с увеличением пока i<n
 {// Начало тела цикла
  M[i]=new int[m]; // M[i] -ячейка для хранения целого, оттоящая от той, на которую оказывает M на i*(размер указетля на целое), то есть i-тый элмент массива, на начало которого указывает M. Здесь в этой ячейке создаётся указатель на начало массива целых
 }// Конец тенла цикла
 int j; // Целая переменная j
 randomize(); // судя по всему, старт генератора случайных чисел.
 for(i=0; i<n; i++) // Цикл по перемнной i от 0 с увеличением пока i<n. Для меня загадка, зачем нужны два раздельных цикла по одной переменной
 {// Начало тела цикла
   for(j=0; j<m; j++) // Вложенный цикл по перемнной j от 0 с увеличением пока j<m.
   {// Начало тела цикла
     M[i][j]=random(100)-50; // M[i] уже разобран выше. По аналогии M[i][j] - j-тый элемент массвиа, на начало которого указывает M[i], то есть элемент двумерного массива, реализованного на указаетле M с индексами [i,j]. Здесь он заполняется случайным числом. Берётся случайное число в диапазоне от 0 ло 100, из него вычитается 50 и получается случайное число в диапазоне от -50 до 50, оно записывается в элмент массива.
     cout<<M[i][j]<<" "; // Здесь этот элемент выводится в поток
   }// Коненц тела цикла
  cout<<endl; // Переход на следующуу строку
 }// Конец тела цикла
 double Average=0; // действительаня переменная Average двойной точности, по дефолту равная нолю
 for(i=0; i<n; i++) // Опять цикл по i, выше он уже прокомментирван
 {// Начало цикла по i
  for(j=0; j<m; j++) // Цикл по j. Он тоже уже прокоментирвоан выше
  {//Начало тела цикла
   Average+=M[i][j]; // Переменная Average увеличивается на элмента массива, чья адресация разобрана выше, таким способом в этйо переменнйо накапливается сумма. Для меня загадка, почему переменная Average обнулена не в заголовке цикла, а в декларации самой переменной
  }//Конец тела цикла
 }//Конец тела цикла
 Average/=(double)(n*m);// Сумму накопили, а теперь делим её на колчиество слагаемых, в результате получаем среднее арифметическое. Так быстрее, чем сразу делить
 сout<<"Average: "<<Average<<endl; Выыодим в поток текст "Average: ", потом значение переменной Average и переходим на следующую строку
 int iA=0; // целая переменная iA, по дефолту равна нолю
 int jA=0; // целая переменная jA, по дефолту равна нолю
 int Nearest=M[0][0]; // целая переменная Nearest, по дефолту равна нолю элменту массива с индексами [0,0]. Какой то элмент надо предположить и в принципе он может быть любым, две предыдущие переменные его индексы, их значения должны быть на всякий случай согласованы с этим предположением (вдруг сразу угадали?)
 for(i=0; i<n; i++)// Этот цикл уже разбирали
 {// Начало тела цикла
  for(j=0; j<m; j++) // И этот цикл уже разбирали
   {// Начало тела цикла
    if( abs(abs(Nearest)-abs(Average)) > abs(abs(M[i][j]) - abs(Average)) )// Если модуль разности между значениями элмента массива и средним для текущего элмента меньше, чем для того, чьё значение валяется в Nearest, то мы нашли, чем надо заменить значение Nearest. Именено для этого сравнения и необходимо начальное предположение о позиции искомого элемента.
     {// Если условие истинно, то будем делать то, что в этих скобках. Начало блока.
      Nearest=M[i][j];// Заменяем Nearest
      iA=i;// Мы нашли, чем заменить Nearest? Эйси, но это означает, что найдены и индексы ближайшего к среденму из числа обработанных элментов. Заменяем iA.
      jA=j; Мы нашли, чем заменить Nearest? Эйси, но это означает, что найдены и индексы ближайшего к среденму из числа обработанных элментов. Заменяем jA.
     }// Если условие истинно, то будем делать то, что в этих скобках. Конец блока.
   }// Конец тела цикла
  }// Конец тела цикла
 cout<<"The nearest number is: "<<Nearest<<" at ("<<iA<<"; "<<jA<<")."<<endl; Выводим в поток текст "The nearest number is: ", потом значение переменной Nearest (сейчас там действительно занчение искомого элмента массива), потом текст " at (", потом значение переменной iA (в енй валяется первый индекс искомого элемента), потмо текст "; ", потом значение переменной jA (в ней ваоляется второй индекс искомого элемента), потом текст ")." и переходим на следующую строку.
 for(i=0; i<n; i++)// Этот цикл уже разбирали
 {// Начало тела цикла
  delete M[i]; // Удаляем i-тый элемент массива
 }// Конец тела цикла
 delete [] M; // Удаляем весь массив
 getch(); // Ждём нажатия на кнопку Enter
}// Конец тела функции
Добавлено через 5 минут
Если
C++
1
i++
заменить на
C++
1
++
i, а
C++
1
j++
на
C++
1
++j
, то будет быстрее. А если ещё и
C++
1
for (i=0; i<n; ++i)
заменить на
C++
1
for (i=n-1; i>=0; --i)
, а
C++
1
for (j=0; j<m; ++j)
заменить на
C++
1
for (j=m-1; j>=0; --j)
, то ещё быстрее, но так можно делать уже только в тех циклах, где нет ввода/вывода, так как это даст противоположный порядок выполнения циклов.
easybudda
20.04.2011, 14:58
  #8

Не по теме:

Цитата Сообщение от taras atavin Посмотреть сообщение
C++
1
2
3
#include <stdlib.h> // Подключение головы 
#include <iostream.h> // Подключение ещё одной головы 
#include <math.h> /// Подключение третьей головы
Змей Горыныч v1.0

Слава Кондратье
1 / 1 / 0
Регистрация: 21.12.2011
Сообщений: 75
14.04.2013, 12:34     Не могу разобраться как работает данная программа #9
а почему у меня stdlib не подключается?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
14.04.2013, 20:35     Не могу разобраться как работает данная программа #10
Цитата Сообщение от Слава Кондратье Посмотреть сообщение
stdlib не подключается?
stdlib.h
или
cstdlib
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.04.2013, 11:48     Не могу разобраться как работает данная программа
Еще ссылки по теме:

Как работает эта функция? Не могу никак разобраться! C++
Не могу разобраться, как работает программа C++
C++ Arrays, как работает данная программа?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Слава Кондратье
1 / 1 / 0
Регистрация: 21.12.2011
Сообщений: 75
15.04.2013, 11:48     Не могу разобраться как работает данная программа #11
stdlib.h
Yandex
Объявления
15.04.2013, 11:48     Не могу разобраться как работает данная программа
Ответ Создать тему
Опции темы

Текущее время: 04:37. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru