Массивы в языке Си

Язык Си / Массивы в языке Си

 

При решении задач с большим количеством данных одинакового типа использование переменных с различными именами, не упорядоченных по адресам памяти, затрудняет программирование. В подобных случаях в языке Си используют объекты, называемые массивами.

Массив — это непрерывный участок памяти, содержащий последовательность объектов одинакового типа, обозначаемый одним именем.

Массив характеризуется следующими основными понятиями:

Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.
Каждый элемент массива характеризуется тремя величинами:

  • адресом элемента — адресом начальной ячейки памяти, в которой расположен этот элемент;
  • индексом элемента (порядковым номером элемента в массиве);
  • значением элемента.

 
Адрес массива – адрес начального элемента массива.

Имя массива – идентификатор, используемый для обращения к элементам массива.

Размер массива – количество элементов массива

Размер элемента – количество байт, занимаемых одним элементом массива.

Графически расположение массива в памяти компьютера можно представить в виде непрерывной ленты адресов.
Расположение массива в памяти

Представленный на рисунке массив содержит q элементов с индексами от 0 до q-1. Каждый элемент занимает в памяти компьютера k байт, причем расположение элементов в памяти последовательное.

Адреса i-го элемента массива имеет значение

n+k·i

Адрес массива представляет собой адрес начального (нулевого) элемента массива. Для обращения к элементам массива используется порядковый номер (индекс) элемента, начальное значение которого равно 0. Так, если массив содержит q элементов, то индексы элементов массива меняются в пределах от 0 до q-1.

Длина массива – количество байт, отводимое в памяти для хранения всех элементов массива.

ДлинаМассива = РазмерЭлемента * КоличествоЭлементов

Для определения размера элемента массива может использоваться функция

 
int sizeof(тип);


Например,
 
 
 
 
sizeof(char) = 1;
sizeof(int) = 4;
sizeof(float) = 4;
sizeof(double) = 8;

Объявление и инициализация массивов

Для объявления массива в языке Си используется следующий синтаксис:

тип имя[размерность]={инициализация};

Инициализация представляет собой набор начальных значений элементов массива, указанных в фигурных скобках, и разделенных запятыми.

 
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};  // массив a из 10 целых чисел


Если количество инициализирующих значений, указанных в фигурных скобках, меньше, чем количество элементов массива, указанное в квадратных скобках, то все оставшиеся элементы в массиве (для которых не хватило инициализирующих значений) будут равны нулю. Это свойство удобно использовать для задания нулевых значений всем элементам массива.
 
int b[10] = {0}; // массив b из 10 элементов, инициализированных 0

Если массив проинициализирован при объявлении, то константные начальные значения его элементов указываются через запятую в фигурных скобках. В этом случае количество элементов в квадратных скобках может быть опущено.

 
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};


При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках [].

Пример на Си
1
2
3
4
5
6
7
8
#include <stdio.h>
int main()
{
  int a[] = { 5, 4, 3, 2, 1 }; // массив a содержит 5 элементов
  printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);
  getchar();
  return 0;
}

Результат выполнения программы:
Массив из 5 элементов

Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.

 
int a[10];


Для задания начальных значений элементов массива очень часто используется параметрический цикл:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
  int a[5]; // объявлен массив a из 5 элементов
  int i;
  // Ввод элементов массива
  for (i = 0; i<5; i++) 
  {
    printf("a[%d] = ", i);
    scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива
  }
  // Вывод элементов массива
  for (i = 0; i<5; i++)
    printf("%d ", a[i]); // пробел в формате печати обязателен
  getchar(); getchar();
  return 0;
}

Результат выполнения программы
Массив

Многомерные массивы

В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном — несколькими. Примером многомерного массива является матрица.

Общая форма объявления многомерного массива

 
тип имя[размерность1][размерность2]...[размерностьm];


Элементы многомерного массива располагаются в последовательных ячейках оперативной памяти по возрастанию адресов. В памяти компьютера элементы многомерного массива располагаются подряд, например массив, имеющий 2 строки и 3 столбца,
 
int a[2][3];

будет расположен в памяти следующим образом

Двумерный массив

Общее количество элементов в приведенном двумерном массиве определится как

КоличествоСтрок * КоличествоСтолбцов = 2 * 3 = 6.

Количество байт памяти, требуемых для размещения массива, определится как

КоличествоЭлементов * РазмерЭлемента = 6 * 4 = 24 байта.

Инициализация многомерных массивов

Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки {}. Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках [].

Пример на Си

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
  int a[2][3] = { 1, 2, 3, 4, 5, 6 };
  printf("%d %d %d\n", a[0][0], a[0][1], a[0][2]);
  printf("%d %d %d\n", a[1][0], a[1][1], a[1][2]);
  getchar();
  return 0;
}

Результат выполнения
Матрица 2x3

Однако чаще требуется вводить значения элементов многомерного массива в процессе выполнения программы. С этой целью удобно использовать вложенный параметрический цикл.

Пример на Си

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
  int a[2][3]; // массив из 2 строк и 3 столбцов
  int i, j;
  // Ввод элементов массива
  for (i = 0; i<2; i++)  // цикл по строкам
  {
    for (j = 0; j<3; j++) // цикл по столбцам
    {
      printf("a[%d][%d] = ", i, j);
      scanf("%d", &a[i][j]);
    }
  }
  // Вывод элементов массива
  for (i = 0; i<2; i++)  // цикл по строкам
  {
    for (j = 0; j<3; j++) // цикл по столбцам
    {
      printf("%d ", a[i][j]);
    }
    printf("\n"); // перевод на новую строку
  }
  getchar(); getchar();
  return 0;
}

Результат выполнения
Результат выполнения

Передача массива в функцию

Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать

  • адрес массива,
  • размер массива.

 
Исключение составляют функции обработки строк, в которые достаточно передать только адрес.

При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.

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

Пример на Си Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// Функция обмена
void change(int *x, int n)
{
  // x - указатель на массив (адрес массива)
  // n - размер массива
  int i;
  int max, index;
  max = x[0];
  index = 0;
  // Поиск максимального элемента
  for (i = 1; i<n; i++)
  {
    if (x[i]>max)
    {
      max = x[i];
      index = i;
    }
  }
  // Обмен
  x[index] = x[0];
  x[0] = max;
}
// Главная функция
int main()
{
  int a[10];
  int i;
  for (i = 0; i<10; i++)
  {
    printf("a[%d] = ", i);
    scanf("%d", &a[i]);
  }
  change(a, 10);  // вызов функции обмена
          // Вывод элементов массива
  for (i = 0; i<10; i++)
    printf("%d ", a[i]);
  getchar();
  getchar();
  return 0;
}

Результат выполнения
Поменять местами наибольший и первый элементы массива

Пример на Си Дан массив размерности n. Вычислить произведение четных элементов

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// Функция вычисления произведения чётных элементов
int func(int *x, int n)  // произведение четных элементов
{
  int p = 1;  // начальное значение произведения
  int i;
  for (i = 0; i<n; i++) 
  {
    if (x[i] % 2 == 0)  // остаток от деления на 2 равен 0?
      p = p * x[i];
  }
  return p;
}
// Главная функция
int main() 
{
  int a[5]; // объявлен массив a из 5 элементов
  int i;
  int pr;
  // Ввод элементов массива
  for (i = 0; i<5; i++) 
  {
    printf("a[%d] = ", i);
    scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива
  }
  pr = func(a, 5); // вычисление произведения
  printf("\n pr = %d", pr); // вывод произведения четных элементов
  getchar();   getchar();
  return 0;
}

Результат выполнения
Произведение четных элементов массива


Назад: Язык Си

Комментариев к записи: 117

  • Здравствуйте, Елена! Спасибо Вам за статью! У меня есть один вопрос по массивам переменной длины. В одной книге прочел "Понятие переменный в массиве переменной длины вовсе не означает возможность изменения длины массива после его создания. Будучи созданным, массив переменной длины сохраняет тот же самый размер. В действительности понятие переменный означает, что при указании размерностей при первоначальном создании массива можно использовать переменные" Я выполнил упражнение из книги в DevC++, у меня программа запрашивает ввод количества строк и столбцов двумерного массива. Потом производит операции с массивом: вычисляет среднее значение, наибольшее значение в каждом одномерном массиве, наибольшее значение среди всех одномерных массивов и выводит данные на экран. Все это происходит в бесконечном цикле while (1) пока пользователь на запрос не введет значение отличное от 1 - тогда сработает оператор break. У меня в цикле while() каждый раз размер массива вводится с помощью scanf ("%lf", &str ), scanf ("%lf", &stlb ) без всякой динамической памяти и нормально программа работает т.е. пользователь может менять размер массива много раз и код компилируется. Вопрос - почему размер массива меняется и ошибки не выдается? Мне вот это непонятно. Заранее благодарен.
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    #include <stdio.h>
    int str;
    int stlb;

    int vvod_massiva (const double [][stlb]);
    double srednee_znach (const double[][stlb], int n);
    double srednee_znach_vseh (const double[][stlb]);
    double bolshee_znach (const double[][stlb]);
    int vuvod_znach (const double[][stlb], double[], doubledouble);
    int main(void)
    {


    const double massiv[str][stlb];
    double sred [stlb];
    double c;
    double d;
    int i=0;
    int j=0;
    int ch;



    while (1)
    {
    printf ("Введите количество строк\n");
    scanf("%d", &str);
    printf ("Введите количество столбцов\n", stlb);
    scanf("%d", &stlb);
    printf ("Введите %d массива по %d элементов типа double каждый\n", str, stlb );
      
    vvod_massiva(massiv);

    for (i=0, j=0; i<str;i++, j++)
    {
      sred [i]=srednee_znach (massiv, j);
      
    }

    c=srednee_znach_vseh (massiv); 
    d=bolshee_znach (massiv);     

    vuvod_znach (massiv, sred, c, d );

    printf ("Для повтора программы нажмите -1. Для завершения - 2\n");
    scanf("%d", &ch);
    if (ch!=1)
    {
      break;
    }

    }


    return 0;
    }

    int vvod_massiva (const double a[][stlb])

    {
      int stroka;
        int stolbets;
        
        for(stroka=0; stroka<str; stroka++)

    {
      for (stolbets=0; stolbets<stlb; stolbets++)
      {
        scanf("%lf", &a[stroka][stolbets]);
        
      }
      printf ("\n");
      
    }

      
    }
      
    double srednee_znach (const double a[][stlb], int n)
    {
      double sum=0;
      double srednee=0;
      int i;
       
      for(i=0; i<stlb; i++) 
      
      {
        sum+=a[n][i];
        
      }
      
      srednee=sum/stlb;
      
      return srednee;

      
    }

    double srednee_znach_vseh (const double a[][stlb])
    {
      int stroka;
        int stolbets;
        double sum=0;
        double  srednee;
        for(stroka=0; stroka<str; stroka++)
    {
      for (stolbets=0; stolbets<stlb; stolbets++)
      {
      sum+=a[stroka][stolbets];
      
        
      }
      
      
      
      
    }
      srednee=sum/(str*stlb);
      printf("%f\n", sum );
      return srednee;
    }


    double bolshee_znach (const double a[][stlb])
    {   
        int i=0;
        int j;
        int n=1;
        int p1=1;
        double massiv [str];
      int k;
       for(j=0, k=0; j<str; j++, k++)  
    {
      p1=1;
      i=0;  
      while (p1<stlb)
      
    {   
      if(a[j][i]<=a[j][i+n])
      
       {  i=i+n;
          n=1;
        p1++;
         
       }  
        
      else

      {
        
        n++;
        p1++;
        
      }
    }
        massiv [k]=a[j][i];
    }
      p1=1;
      k=0;
        n=1;  
      while (p1<str)
    {   
      if(massiv[k]<=massiv [k+n])
      
       {  k=k+n;
          n=1;
        p1++;
         
       }  
        
      else

      {
        
        n++;
        p1++;
        
      }
    }
          
     return massiv[k];

    }
    int vuvod_znach (const double a[][stlb], double b[], double c, double d)

    {   

      int stroka;
        int stolbets;
        int i;
        int j;
        
        for(stroka=0; stroka<str; stroka++)

    {
      for (stolbets=0; stolbets<stlb; stolbets++)
      {
        printf("%f ", a[stroka][stolbets]);
        
      }
      printf ("\n\n");
      
    }    
      for(i=0; i<str; i++)
      
      {
        printf("Среднее значение %d - массива равно %f\n", i+1, b[i]  );
        
        
      }
      printf("\n" );
      

      
      printf("Среднее значение из %d равно %f\n", (str*stlb), c );
      printf("большее значение из %d равно %f\n", (str*stlb),  d );
      
    }

  • Александр
    Здравствуйте! Помогите, пожалуйста разобраться!
    1
    #define N_ELEMENTS(X) (sizeof(x)/sizeof(*(x)))
    Есть массив
    1
    char mass[]={0x2A,0x22,0xC2,0x22,0x2B,0x22,0x2B}
    Если я в программе пишу :
    1
    display = N_ELEMENTS(mass);
    то на экран дисплея выводится количество элементов массива (7). Попытался функцию создать,чтобы количество элементов выводить так:
    1
    2
    3
    4
    void str_icdRU (char strRU[])
    {
    display = N_ELEMENTS (strRU)
    };
    Выводит на дисплей число 2 для любого массива.

    • Елена Вставская
      Когда мы передаем указатель в функцию, функция не знает ничего о размере массива. Соответственно, sizeof(x) - это размер указателя, а sizeof(*(x)) - это размер элемента.

  • Александр
    помогите пожалуйста как сделать так что бы программа выводила все максимальные серии а не только первую :
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <stdlib.h> 
    #include <stdio.h> 

    void kisa2(double * * , intint);

    int main() {
        int i, j, R, C , y;
        printf("Введите количество строк в матрице:\n");
        scanf("%d", & R);
        printf("Введите количество столбцов в матрице:\n");
        scanf("%d", & C);
        double * * matr = (double * * ) malloc(R * sizeof(double * ));
        for (i = 0; i < R; i++) {
          matr[i] = (double * ) malloc(C * sizeof(double));
        }
     
        
        for (i = 0; i < R; ++i) {
          for (j = 0; j < C; ++j) {
            printf("matr[%d][%d]:", i, j);
            scanf("%lf", & ( * ( * (matr + i) + j)));
            printf("\n");
          }
        }
        for (i = 0; i < R; ++i) {
          for (j = 0; j < C; ++j) {
            printf("%.2lf ", matr[i][j]);
          }
          printf("\n");
        }
        printf("\n\n\n");
        printf("введите номер функции :");
        scanf("%d", & y);
        switch (y) {
          case (2):
            kisa2(matr,  R, C);
            break;
          default:
            printf("видимо вы ошиблись ");
        }
        return 0;
      }


    void kisa2(double * * matr,  int R, int C) {
        int n = R, m = C, i, j, cnt = 0, ipos = -1, maxcnt = 0, icnt = -1;
        for (i = 0; i < n; i++) //поиск
        
        {
          cnt = 0; //номера
          for (j = 1; j < m; j++) { //строки
         
            if (matr[i][j] == matr[i][j - 1]) //в которой
              cnt++; //находится
            else { //самая
              if (cnt > maxcnt) { //длинная
                maxcnt = cnt;
                ipos = i; //серия
                icnt++; //счетчик
              } //одинаковых
              cnt = 0;
            } //элементов
          }
          if (cnt > maxcnt) {
            maxcnt = cnt;
            ipos = i;
            icnt++; //счетчик
          }
        }
        if (-1 == icnt)
          printf("\nСтрок с одинаковыми элементами нет!");
        else
          printf("\nНомер строки, в котором находится самая длинная серия одинаковых элементо в:%d ", ipos);
    }
    }

    • Елена Вставская
      В первом цикле найти длину максимальной серии элементов. Во втором цикле вывести все номера строк с такой длиной серии.

  • Здравствуйте, помогите пожалуйста решить задачу. У меня коды никак не получаются правильные. Определить координату точки А, являющейся началом вектора а={а1, …,аn}, если его конец совпадает с точкой В(у1, …,уn). Спасибо огромное заранее!)

  • Елена, здравствуйте, какое условие применить чтобы решить данное условие: В матрице mхn найти минимальный элемент k-ого столбца и сумму положительных элементов ниже p-ой строки. у меня первая половина задачи работает, но как сделать, чтобы находило сумму ниже введенной строки?

    • Елена Вставская
      1
      2
      3
      4
      5
      6
      7
      8
      9
      int sum=0;
      for(int i=p+1; i<m; i++)
      {
        for(int j=0; j<n; j++)
        {
          if(a[i][j]>0)
            sum+=a[i][j];
        }
      }

      • спасибо огромное! правда начинает считать через одну строчку, но суть я понял!

      • надо
        1
        2
        3
        4
        5
        6
        7
        8
        9
        int sum=0;
        for(int i=p; i<m; i++)
        {
          for(int j=0; j<n; j++)
          {
            if(a[i][j]>0)
              sum+=a[i][j];
          }
        }
        и сразу все как нужно становится

  • Алексей
    Здравствуйте, подскажите пожалуйста как это сделать, используя массив составьте программу для добавления элемента в начало массива.

    • Елена Вставская
      Создать массив, длиной на 1 элемент больше исходного массива (рекомендую через динамическое выделение памяти, если не известна длина исходного массива). Ввести элемент, разместить его в нулевом элементе созданного массива. Остальные элементы (начиная с первого) скопировать из исходного массива.

  • Здраствуйте, подскажите пожалуйста как сделать указатель на двумерный массив,точнее как он корректно выглядит, чтобы потом его можно было использовать как аргумент функции. Касательно функции тоже есть вопросы, к примеру :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void data (int **m, int n){
        for ..
          for ...
           m[i][j] = rand () % 10;
    }

    int main (){
    int mas [3][3], **m_1 = mas;
    data (**m_1, 3);
    }
    Вопрос: Как правильно в подпрограмме обращаться к элементам массива через этот указатель, и как в главной программе правильно вызвать эту функцию? Спасибо.

    • Елена Вставская
      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
      #include <stdio.h>
      #include <stdlib.h>
      void data(int** m, int n) {
        for (int i=0; i<n; i++)
          for (int j=0; j<n; j++)
            m[i][j] = rand() % 10;
      }

      int main() {
        int mas[3][3];
        int** m = (int**)malloc(3 * sizeof(int*)); // или int* m[3];
        for (int i = 0; i < 3; i++)
          m[i] = (int*)mas[i];
        data(m, 3);
        for (int i = 0; i < 3; i++)
        {
          for (int j = 0; j < 3; j++)
          {
            printf("%d ", m[i][j]);
          }
          printf("\n");
        }
        getchar();
        return 0;
      }

  • Добрый день, Елена! Спасибо за статью! При выводе массива на экран с помощью printf() или вводе элементов массива с помощью scanf() всегда необходимо использовать специальный код? Что будет если в качестве спецификатора преобразования в printf()/scanf() использовать %s - для символов/ Правильно ли это?

    • Елена Вставская
      %s используется для ввода строк, а строка - это массив символов, а не один символ.

  • Здравствуйте, подскажите как можно найти 5 максимальных значений в матрице заданной динамически
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <locale.h>
    #include <string.h>
    #include <limits.H>
    #include <malloc.h>

    int main()
    {
      int *a; 
      int i, j, n, m;
      system("chcp 1251");
      system("cls");
      oo:
      printf("Введите количество строк: ");
      scanf("%d", &n);
      if(n>0 && n<=15);
      else
      goto oo;
      pp:
      printf("Введите количество столбцов: ");
      scanf("%d", &m);
      if(m>0 && m<=15);
      else
      goto pp;
      // Выделение памяти
      a = (int*)malloc(n*m * sizeof(int));
      // Ввод элементов массива
      for (i = 0; i<n; i++)  
      {
        for (j = 0; j<m; j++) 
        {
          printf("Элемент[%d][%d] = ", i+1, j+1);
          scanf("%d", (a + i*m + j));
        }
      }
      // Вывод элементов массива
      for (i = 0; i<n; i++)  
      {
        for (j = 0; j<m; j++)  
        {
          printf("%d ", *(a + i*m + j)); 
        }
        printf("\n");
      }
    //Максимальное положительное

      return 0;
    }

    • Елена Вставская
      Посмотрите сортировку прямым выбором и выполните 5 итераций. Хоть матрица и двумерная, никаких ограничений на строки и столбцы не возлагается, и с ней можно работать как с одномерной, содержащей n*m элементов.

  • Добрый день! Подскажите пожалуйста, как можно найти наименьшее общее кратное всех элементов массива (то есть число, кото-рое делится на все элементы).

  • Григорий
    Здравствуйте Елена! Помогите пож. Имеем массив int a [1] [8]; Мне нужно передать [8] в переменную для дальнейшего просмотра каждого элемента этой строки. Просматриваю в дебаге, поэтому printf пока не применял. Я не знаю правильно выражаюсь или нет? Я только учусь.

    • Елена Вставская
      Для работы с массивами внутри функции передаются указатель на массив и размер массива

      • Григорий
        Я три дня не могу с места сдвинутся. Ничего не выходит.
        1
        2
        3
        4
        uint16_t simvol [1] [8] =
        {
          {0x0E,0x11,0x11,0x11,0x1F,0x11,0x11,0x00},
        };
        Как мне обратится к 0, 1, 2 и т.д. Дайте пож. пример.

        • Елена Вставская
          1
          2
          3
          4
          5
          for(int i=0; i<8; i++)
          {
            uint16_t a = simvol[0][i]; // все символы по порядку
          // Что-то с ними делаем
          }


          • Григорий
            Ув. Елена! Ничего у меня не получается. Имеем массив
            1
            const unsigned char chars8_8 [] [8] PROGMEM = {,,,,,,,,,, {0x0E,0x11,0x11,0x11,0x1F,0x11,0x11,0x00},,,,,};// 0x41 ascii A.
            в функции пытаюсь отследить какие значения принимают переменные chars, acsii и i.
            1
            2
            3
            4
             for (uint8_t i=0;i<r;i++)
                    {
            uint16_t chars = pgm_read_byte(chars8_8 [ascii][i]) ;
                          }
            формат функции drawChars( 8,10 ,"A",BLACK ,YELLOW ); В итоге chars 0x92 ? ascii 0x62 ? Все не то что ожидал. Не понятно что принимает chars ? При изменении i значения не меняются. Пож. направьте меня в правильное русло.

          • Елена Вставская
            По тем кускам кода, которые Вы приводите, сложно что-то сказать.

          • Григорий
            Со всем что написано выше удалось разобраться. Осталась одна проблема. Из выше описанного я понял что при вызове символа "А" , вызывается нечто не понятное. Мне кажется не хватает кокой-то библиотеки чтоб Атмел-Студия могла расшифровать мою букву и указать путь в массиве. Так? Что это за библиотека? Ведь А = 0х41. Массив не индексируется согласно таблице ascii?

          • Елена Вставская
            'A' в одинарных апострофах действительно имеет ascii код 0x41

          • Григорий
            Елена подскажите каким способом выходит 0x41? Я так понимаю это значение относиться к символам 8 бит. Я по разному пытался складывать все биты , и младшие и старшие и все вместе, для символа А=41 это 4 хоть старшие хоть младшие а все остальные символы ерунда получается. Так вот в чем вопрос , если применять символы других размеров то программа их уже не найдет?

          • Елена Вставская
            Посмотрите таблицу кодирования символов ASCII

          • Григорий
            Разобрался . Тупанул аж самому стыдно.

  • Тиунов Михаил
    Вопрос: Объявляю массив в модуле M66_Main.c вот так:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     /* M66_Main.c 
     */

    #include "M66_Main.h"

    //---------------------------------------------
    M66_NetWorkOperatorTypedef NetWorkOperators[8] =
    {
      {"\0","\0","\0","\0","\0","\0"},
      {"MTS\0","internet\0","*111*0887#\0","\0","\0","#100#\0"},
      {"MegaFon\0","internet\0","*205#\0","\0","\0","#100#\0\0"},
      {"Beeline\0","internet.beeline.ru\0","*110*10#\0","beeline\0","beeline\0","#102#\0"},
      {"\0","\0","\0","\0","\0","\0"},
      {"\0","\0","\0","\0","\0","\0"},
      {"\0","\0","\0","\0","\0","\0"},
      {"\0","\0","\0","\0","\0","\0"}
    };
    Как сделать, чтобы можно было обращаться к этому массиву из других модулей программы ?

    • Елена Вставская
      Там, где он нужен, прописать
      1
      2
      #include "M66_Main.h"
      extern M66_NetWorkOperatorTypedef NetWorkOperators[8];

  • Добавить 5 перед элементами массива, у которых остаток от деления на 3 равен 1

  • Грустный мальчик по имени Матвей
    Здравствуйте! Подскажите, как правильно делать произведение матрицы? Даны матрицы: А размером m*k и В размером k*n.Получить матрицу С=A*В #include <iostream> using namespace std;
    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
    int main() {
       int m, k, n;
       cin >> n >> m;
       int matrix1[m][k];
       int matrix2[k][n];
       int matrix_pr[k][n] = {0};
       for(int i = 0; i < n; i++){
          for(int j = 0; j < m; j++){
             cin >> matrix1[i][j];
          }
       }
       for(int i = 0; i < n; i++){
          for(int j = 0; j < m; j++){
             cin >> matrix2[i][j];
          }
       }
       for(int i = 0; i < n; i++){
          for(int j = 0; j < m; j++){
             matrix_pr[i][j] = matrix1[i][j] * matrix2[i][j];
             cout << matrix_pr[i][j] << " ";
          }
          cout << endl;
       }
       return 0;
    }

  • "При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение ВНУТРИ вызывающей функции." Наверное, снаружи.

  • Задача заполнить массив случайными числами с последующей сортировкой
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #define CONST 50
    int main()
    {

      int r,a,inner,outer,temp;
      int rnd[CONST]={};
      srand((unsigned)time(NULL));
      puts("Массив случайных чисел:");

      for (a=0;a<CONST;a++)
        {    r=rand();
            rnd[CONST]=(r%100)+1;
      printf("%d\t",rnd[CONST]);
      }
        putchar('\n');

       for(outer=0;outer<CONST-1;outer++)
        {
            for (inner=outer+1;inner<CONST;inner++)
            {
                if(rnd[outer]>rnd[inner])
                {
                    temp=rnd[outer];
                    rnd[outer]=rnd[inner];
                    rnd[inner]=temp;
                }
            }
        }
        puts("Отсортированный массив:");
        for(a=0;a<CONST;a++)
        printf("%d\t",rnd[a]);
        putchar('\n');

          return 0;
      }
    Что не так?После сортировки 0.

    • Елена Вставская
      1
      2
      3
      4
      5
      6
      for (a = 0; a < CONST; a++)
        {
          r = rand();
          rnd[a] = (r % 100) + 1;
          printf("%d\t", rnd[a]);
        }

  • Всеволод
    Здравствуйте, скажите пожалуйста, а как можно написать программу, чтобы количество элементов массива было не задано в коде, а вводилось вручную после запуска программы?

  • Здравствуйте, подскажите пожалуйста, как можно прописать это в программе? Сумма элементов массива, расположенных после последнего нулевого элемента

    • Елена Вставская
      Считать сумму элементов массива. Если элемент равен 0, то сумму обнулять

  • здраствуйте, а как можно ввести размер массива, затем элементы массива, после вывести массив на экран?

  • Задано массив действительных чисел A(2n), n=<200. Сделать программу которая вычисляет сумму тех чисел из A(n+1)....,A(2n), которые превышают среднее ариф значение чисел A(1),.......,A(n)

    • Елена Вставская
      Сначала для первой половины массива вычислить среднее арифметическое. Потом сравнить с ним все элементы из второй половины массива и найти требуемую сумму.



    • Елена Вставская
      Посмотрите публикацию по динамическому выделению памяти

      • Здравствуйте, нужно инициализировать одномерный массив матрицы NxN (если матрица 3/3 то 9 элементов в массиве, заполнить определенным числом по диагонали, а остальные нули без использования индексации, а через указатели. Помогите пожалуйста

        • Елена Вставская
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          #define SIZE 3
          int *a;
          a = (int*)malloc(SIZE*SIZE*sizeof(int));
          for(int i=0; i<SIZE; i++)
            for(int j=0; j<SIZE; j++)
              *(a+i*SIZE+j)=0;
          for(int i=0; i<SIZE; i++)
          {
            cout << "a[" << i << "][" << i << "]= ";
            cin >> *(a+i*SIZE+i); 
          }

          • 1
            2
            3
            4
            5
            double *p_elements = elements; //зануление элементов
            for(int i = 0; i < size*size; i++, p_elements++) 
              *p_elements = 0; //присваивание диагональным
            for(double i = 0; i < size; i++,p_elements = i * (1+col_size)) 
              *p_elements= diagonal_value; 
            __ Примерно как то так, но в данном случае это не работает( А то что вы написали - преподаватель сказал что *(a+i) эквивалентно a[i] и в данном случае он не этого хотел. Как же с ним сложно...

          • Елена Вставская
            Я не совсем поняла, что нужно.
            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
            #include <iostream>
            using namespace std;
            #define SIZE 3
            int main()
            {
              int* a;
              a = (int*)malloc(SIZE * SIZE * sizeof(int));
              int* head = a;
              for (int i = 0; i < SIZE; i++)
                for (int j = 0; j < SIZE; j++)
                  *a++ = 0;
              a = head;
              for (int i = 0; i < SIZE; i++, a+=SIZE+1)
              {
                cout << "a[" << i << "][" << i << "]= ";
                cin >> *a;
              }
              a = head;
              for (int i = 0; i < SIZE; i++)
              {
                for (int j = 0; j < SIZE; j++)
                  cout << *a++ << " ";
                cout << endl;
              }
            }

  • Евгений
    Внутри функции для работы с матрицами объявлен вспомогательный двумерный массив как статический с размерностью - параметром
    1
    2
    3
    4
    void obrat(double **A, int n, double **B)
    double A1[n][n];
      .....
    }
    По идеи компилятор не знает размера и должен обругать. Но все работает корректно. Также работает в версии со scanf
    1
    2
    3
    4
    5
    void obrat(double **A, int n, double **B)
    {  scanf("%i",&n);
       double A1[n][n];
      .....
    }
    Уж здесь то точно компилятор не знает размера. Но все работает корректно. И без динамического выделения памяти. Как это объяснить?


      • Евгений
        Объяснение нашлось. Эта возможность появилась в стандарте C99. Именуется как "массивы переменной длины" (VLA = variable-length array). Не поддерживается в C89 и C++. Так написано в https://cpp.com.ru/shildt_spr_po_c/11/1105.html

    • Это типичное VLA (массивы переменной длины). Поддерживается с C99. Но в C++ обычно не поддерживается. Хотя все зависит от конкретной реализации компилятора.


  • Вычислить значения выражения (3*а+4)/((a^2)-5*a-9) для a=1,2,,100 Результат выполнения занести в массив чисел


      • Елена Вставская
        Что конкретно не понятно? Нужно создать массив из 100 элементов. Дальше в цикле для i от 1 до 100 Вычислить значение выражения и поместить в i-1 элемент массива

  • Создайте целочисленный массив, который принимает пользовательский ввод и сохраняет все входные данные в этом массиве и распечатывает их от наименьшего к наибольшему Создайте массив String, который принимает вводимые пользователем данные, сохраняет все вводимые данные в этом массиве и печатает их в алфавитном порядке. помогите пожалуйста как это сделать

  • Здравствуйте. Подскажите как вводимую пользователем строку из символов/чисел (пример: 823793087) перевести в массивы по 3 символа/цифры (пример: массив а[] = {823, 793, 087} ? Заранее спасибо!

    • Елена Вставская
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      #include <iostream>
      using namespace std;
      int main()
      {
        char str[] = "823793087";
        for (int i = 0; i < strlen(str); i += 3)
        {
          int a = (str[i] - '0') * 100 + (str[i + 1] - '0') * 10 + (str[i + 2] - '0');
          cout << a << endl;
        }
        cin.get();
      }

  • Дмитрий
    Здравствуйте. Подскажите, пожалуйста. В функцию execvp нужно передать не одномерный массив, а двумерный. как это можно сделать? Как работать с одномерным массивом- понятно. Но как в такую функцию правильно передать двумерный массив?

  • Заполнить одномерный массив вводом целых чисел с клавиатуры (среди элементов массива есть положительные, отрицательные числа и нули). Вычислить сумму элементов, расположенных после последнего элемента, равного нулю.

  • Алексей
    Превратить массив таким образом, чтобы сначала располагались все элементы, целая часть которых лежит в интервале [a, b], а затем - остальные. Как сделать это задание ?! Помогите пожалуйста Рассмотрите пожалуйста вопрос побыстрее если можно конечно

    • Елена Вставская
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      int front = 0;
      int back = n-1;
      for(int i=0; i<n; i++)
      {
        if(x[i]<=a || x[i]>=b)
        {
          y[back] = x[i];
          back--;
        }
        else
        {
          y[front]=x[i];
          front++;
        }
      }
      Получили массив y, элементы в котором расположены согласно заданию

  • Есть возможность сначала задать адрес, а потом определить массив с первым элементом в этом адресе? Если да , то как. Заранее спасибо

    • Елена Вставская
      Не совсем поняла вопрос. Сначала мы выделяем память, определяется адрес размещения массива. А затем задаются его элементы.

  • Добрый день, подскажите пожалуйста, как можно прописать это в программе? Произведение элементов массива, расположенных после последнего нулевого элемента; Прописать условие - если в массиве нет нулевого элемента или ноль последний элемент

  • Здравствуйте, как можно сделать массив который заполняется до определенного условия например: вводятся положительные числа и заканчивается ввод, когда были введены как минимум три нечетных числа и четыре четных числа

    • Елена Вставская
      Память для такого массива можно выделить только статически под максимальный размер. Или использовать перевыделение realloc, или список.
      А вообще - в цикле после ввода очередного элемента должна стоять проверка требуемого условия, и если условие выполняется, то выходим из цикла через break;
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      int a[20]; 
      int count = 0;
      int odd = 0;
      int even = 0;
      for(int i=0; i<20; i++)
      {
        printf("a[%d]=", i);
        scanf("%d", &a[i]);
        count++; // количество введенных элементов
        if(a[i] %2 == 0) even++;
        else odd++;
        if((odd >=3) && (even >=4))
          break;
      }

  • Здравствуйте! Подскажите,пожалуйста,как в си задавать константы. Например,я хочу,чтобы у меня массив состоял из N элементов,а для этого надо,чтобы где-то N было задано,тобишь в const. я пробовала так:
    1
    const int N=5;
    но ничего не получалось

  • Спасибо за статью! Она была очень полезна) Вы привели такие примеры которые мне наглядно показали что к чему и я наконец закончил своё задание!)

  • Дан массив из N элементов. Каждый отрицательный элемент заменить полусуммой тех двух элементов, которые стоят рядом с ним справа и слева Напишите мне пожалуйста на с++ , и скиньте мне в почту и желательно по скорее

    • Елена Вставская
      Удачи в решении)
      Услуги по написанию кода "для зачёта" не оказываю.

  • Владимир
    Здравствуйте Елена могли бы пожалуйста разъяснить следующую программу. Tут 6 семей дали свою оценку для анкеты,программа посчитала частоту оценок.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <stdio.h>
    #define SEMYA 6
    #define OCENKI 6

    int main()
    {
      
      int j, i; 
      int otvet[SEMYA] ={2,2,1,3,3,3}; 
      int freq[OCENKI]={};
      for(i=0; i<=SEMYA-1; i++)
      {
        freq[otvet[i]] = freq[otvet[i]]+1; 
      }
      printf(" ocenka:    ferq:\t\n");
      for (j=0;j<=OCENKI-1; j++)
      {
        printf(" \t%d \t%d\n", j, freq[j]);
      }

      return (0);
    }

    • Елена Вставская
      В массиве freq сохраняются значения на 1 больше соответствующих значений массива otvet. Затем значения из массива freq выводятся.

      • Александр
        Вы уверены? Вроде в массиве freq сохраняется частота (freq от frequency частота) встречающихся оценок. То есть "2" встречается 2 раза, "1" только один раз, "3" встречается 3 раза. Если бы массив otvet был бы {5,4,5,4,5,4,2,5}, то результат freq содержал {0,0,1,0,3,4}. Еще раз, otvet содержит сколькотвсего получили оценок "0","1","2","3","4","5". Понятно, почему массив otvet объявлен как otvet[6], оценки то могут быть от 0 до 5

  • Здравствуйте! Можете, пожалуйста, привести пример функции, в которой числа в массиве генерируются случайным образом генератором случайных чисел. Имеется ввиду, чтобы пользователь ввел количество чисел в массиве, а они уже сгенерировались сами. Буду очень признателен! ответ прошу прислать на мой e-mail: mnuriyev101@gmail.com


    • Елена Вставская
      Видимо, через перезаписываемые элементов на новые места. Задачу не совсем поняла.

  • Дмитрий
    Использование getchar или system( "pause" ) - это убогий костыль, призванный оставить открытым окошко консоли в среде программирования под Windows. Если бы программа запускалась непосредственно из консоли (в винде это приложение "Командная строка"), то этот костыль был бы не нужен. И еще дружеский совет: не используйте scanf (а лучше просто забудьте про ее существование). При использовании этой функции очень сложно сделать адекватную обработку ошибок. Для ввода лучше использовать fgets, а затем разбирать полученный результат. Для преобразования чисел в stdlib.h есть отличные функции типа strtol, strtof и т.п.

    • Вот речь не мальчика, но МУЖА!!!! (профи с двух слов положил всех, молодец!!!)

  • Дмитрий
    "Пример Дан массив размерности n. Вычислить произведение четных элементов" Вы тут дважды неправильно поняли задание. Размерность - количество измерений массива, а не его длина. Четных элементов - значит каждого второго элемента, а не всех элементов, делящихся на два без остатка.  

    • Елена Вставская
      Отчасти согласна - условие задачи не должно иметь двоякого толкования. Но, как правило, нужно, чтобы кто-то указал на эту неоднозначность, поскольку самостоятельно ее можно не увидеть. Если понимать задачу в Вашей интерпретации, то как тогда в многомерном массиве находить элементы с четными индексами? И всё-таки, я считаю, что четный элемент подразумевает четность значения элемента. А если речь идет об элементах, расположенных на четных местах в массиве, то это - элементы с четными индексами.

  • Здравствуйте, а что хранится в массиве в случае объявления массива без инициализации?

    • Елена Вставская
      В случае объявления массива без инициализации в массиве хранится мусор. До инициализации значения элементов массива использовать нельзя.

      • Спасибо за ответ, правильно я понимаю, "мусор" - это то, что было в оперативной памяти на данный момент?

        • Елена Вставская
          Не могу утверждать на 100%, что это то, что хранилось в оперативной памяти на данный момент. Мусор - это неизвестные пользователю значения.

      • Имеется ввиду нельзя брать значения из массива мусорные? А, записывать в ячейки массива ведь можно неициализированного? Ну записал, я к примеру, сроку, надо же просто быть уверенным, что длины массива хватит, это раз, а во вторых что нуль-терминатор в конце стоит (если массив символов). Так же? А что там дальше после нуль-терминатора нам же на важно по идее для чтения потом уже этой строки, я правильно понимаю или все таки это важно иницилизировать нулями весь массив в любом случае надо при первом использовании? И еще. Если ли замена стандартной функции копирования строки в массив, чтобы она проверяла все таки что в массиве хватает места для записи? Или это все самому надо в программе проверять прописывать всегда перед записью в массив?

        • Елена Вставская
          Если мы введем часть массива символов, но не все значения, то при выводе может обнаружиться мусор, потому что вывод осуществляется до символа, равного нулю. То, что стоит после нуль-символа, нас действительно не интересует. Стандартная функция strcpy() не следит за выделенной областью памяти, поэтому желательно это проверять самостоятельно или использовать защищённую функцию strcpy_s()


  • Владимир
    Здравствуйте, для чего пишется getchar 2-жды в конце каждой программы?

    • Елена Вставская
      Владимир, getchar() дважды пишется в программах, которые используют ввод с помощью scanf() или cin. Дело в том, что когда пользователь при вводе нажимает Enter, генерируются сразу два символа - перевод строки и возврат каретки. Если в конце программы написать один getchar(), то программа прекратит свое выполнение (закроет консоль), поскольку оставшийся в буфере символ возврата каретки будет воспринят функцией getchar() как введенный. Поэтому есть простое правило: если в программе использовался ввод с помощью scanf() или cin, в конце нужно дважды вызвать функцию getchar(). В тех программах, где нет ввода, можно использовать один getchar(), например здесь. Альтернативой функции getchar() также может служить вызов system("pause"); из библиотеки stdlib.h. При этом пользователю будет выведено сообщение "Для продолжения нажмите любую клавишу...".

    • Подскажите,как СИ знает длину массива? Где хранится длина создаваемого массива? Ведь её тоже НАДО ГДЕ ТО ХРАНИТЬ! Например, я знаю, что языке Forth правилом хорошего тона является прописывание в начальной ячейке массива длины данного массива, чтобы ты, зайдя в первую ячейку смог считать (узнать) длину всего массива. А в языке СИ где хранится длина массива? В какой то другой области памяти или в какой то переменной типа int?

      • Елена Вставская
        В другой области памяти для динамического массива, для статического задаётся константой.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *