Обработка математики: 100%
 

printМассивы, строки и структуры

printМассивы

float:right| Если несколько переменных имеют одинаковое назначение в программе, с ними производятся одинаковые действия (семь козлят или семь гномов в сказках), то вместо задания каждой переменной уникального имени мы указываем имя для всего набора таких переменных и их количество:

тип  имя [ количество ];

Для доступа к элементам такого набора используется операция индексации: имя[номер], где номер принимает значения от 0 до (количество-1).

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

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

#include <stdio.h>
// Факториалы целых чисел
int main()
{ int f[13];
  f[0]=1;
  for(int i=1; i<13; ++i)
    f[i]=i*f[i-1];
  for(int i=0; i<13; ++i)
    printf("%d! = %d\n",i,f[i]);
}
Ввод:

Выполнить
Вывод:

В программе несколько раз повторяется число 13. При изменении размера массива придется изменить эти константы на другое значение столько же раз. Для упрощения таких изменений можно

  • использовать операцию sizeof, которая возвращает размер в байтах своего аргумента – для получения количества элементов в массиве f нужно написать sizeof(f)/sizeof(f[0])
  • определить именованную константу, используя команду препроцессора
    #define имя  значение

Имя такой константы рекомендуется писать прописными буквами.

#include <stdio.h>
// Решето Эратосфена для простых чисел
#define N 1000000
char p[N+1];
int main()
{ p[0]=p[1]=1; // 0 и 1 не являются простыми
  for(int i=2; i*i<=N; ++i)
    if(!p[i]) { // не вычеркнуто
      for(int j=i*i; j<=N; j+=i)
        p[j]=1; // вычеркнуть числа, кратные i
    }
  int k=0;
  for(int i=1; i<=N; ++i) 
    if(!p[i]) ++k;
  printf("Количество простых чисел от 1 до %d равно %d\n",N,k);
}
Ввод:

Выполнить
Вывод:

Без инициализации элементы массива, определяемого в стековой памяти, имеют неопределенное значение, в статической – 0.

Можно указать начальные значения элементам массива, количество элементов которого задано константой. Список начальных значений указывается в {} через запятую, начиная с нулевого. Можно явно указать, какому элементу присваивается значение: [номер]=выражение. Если значение какого-либо элемента явно не указано, то он получает значение 0. Если количество элементов в массиве определяется списком инициализации, количество можно не указывать:

int a[]={1,2,3,4,5};
#include <stdio.h>
int a[10]; // статическая память, все элементы 0
int main()
{ int b[10]; // стековая память, неопределенное значение
  int c[10]={1,2,7,[7]=100, [9]=101}; // стековая память, 
      // элементы с номерами 0,1,2,7,9 заданы явно, остальные - 0
  for(int i=0; i<10; ++i)
    printf("%d: %d %d %d\n",i,a[i],b[i],c[i]);
}
Ввод:

Выполнить
Вывод:

Типовые примеры обработки массивов:

// ввод размера массива, создание массива и ввод его элементов
int n;
scanf("%d",&n);
double a[n];
for(int i=0; i<n; ++i) 
  scanf("%lf",&a[i]);

// вывод элементов массива на 1 строке
for(int i=0; i<n; ++i) 
  printf("%lf%c",&a[i], i<n-1?' ':'\n'); // разделяем пробелами, после (n-1)-го переход на новую строку

// поиск индекса максимального элемента в массиве
int imax=0; // предполагаем, что максимальный имеет индекс 0
for(int i=1; i<n; ++i) // проверяем с 0
  if(a[i]>a[imax]) imax=i; // нашли лучше
printf("%d %lf\n", imax, a[imax]); // печать индекса и значение максимума

// поиск индекса первого элемента, который дает минимум некоторого выражения, например, sin(a[i])+cos(a[i])
int imin;
double fmin;
for(int i=0; i<n; ++i) {
  f=sin(a[i])+cos(a[i]); // вычисляем выражение
  if(i==0 || f<fmin) { // первый элемент или нашли лучше
    imin=i; // запоминаем индекс
    fmin=f; // и сам минимум
  }
}
printf("%d %lf\n", imin, fmin); // печать индекса и значение минимума

Для копирования элементов массива вместо цикла можно использовать функции memcpy и memmove, объявленные в <string.h>. memcpy позволяет скопировать один массив в другой (массивы должны быть одинакового типа и размера), memmove используется для копирования части массива, в том числе в пределах одного массива. Чтобы указать в качестве начальной позиции части массива k-й элемент, используется запись (имя_массива+k), а выражение имя_массива означает весь массив с 0-го элемента соответственно. В качестве аргумента можно указать массив-значение: (спецификаторы  тип[ ]){список_значений}

#include <stdio.h>
#include <string.h>
int main()
{ int a[10]={1,2,3,4,5,6,7,8,9,10},
     b[10]; 
  memcpy(b,a,sizeof(a)); // b <- весь a
  for(int i=0; i<10; ++i)
    printf("%d%c",b[i],i<9?' ':'\n'); // вывод массива b
  memmove(b+4,b+6,sizeof(b[0])*3); // b[4],b[5],b[6] <- b[6],b[7],b[8]
  memmove(b+1,(const int[]){-3,-2,-1},sizeof(b[0])*3); // b[1],b[2],b[3] <- -3,-2,-1
  for(int i=0; i<10; ++i)
    printf("%d%c",b[i],i<9?' ':'\n');
}
Ввод:

Выполнить
Вывод:

В качестве элементов массива могут выступать другие массивы, все массивы-элементы должны иметь одинаковый размер:

double uravn[2][3]; // коэффициенты системы из 2 линейных уравнений - матрица 2 x 3

a[i][j] – обращение к элементу в i-й строке, j-м столбце

#include <stdio.h>
int main()
{ int n;
  scanf("%d",&n);
  double a[n][n],c[n][n];
// ввод матрицы
  for(int i=0;i<n;++i)
    for(int j=0;j<n;++j)
      scanf("%lg",&a[i][j]);
// вычисление квадрата матрицы
  for(int i=0;i<n;++i)
    for(int j=0;j<n;++j) {
      c[i][j]=0;
      for(int k=0;k<n;++k)
        c[i][j]+=a[i][k]*a[k][j];
  }
// вывод матрицы
  for(int i=0;i<n;++i)
    for(int j=0;j<n;++j)
      printf("%lg%c",c[i][j],j==n-1?'\n':' ');
}
Ввод:

Выполнить
Вывод:
loading