Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование на языке Си. Учебно-методическое пособие
.pdf
31
4. Массивы
Массив – это участок памяти, содержащий элементы одного типа,
объединенные одним именем. Чтобы использовать массив, надо его объявить –
выделить место в памяти. Типом массива называется тип входящих в него
элементов. Массивы могут быть разных типов – int, float, char, и т. д. Массив
объявляют так же, как и обычные переменные, но после имени массива в
квадратных скобках записывается количество элементов в нем.
int m[10], float a[20], char c[30];
При объявлении массива можно сразу заполнить его начальными
значениями, перечисляя их внутри фигурных скобок. В этом случае размер
массива в квадратных скобках можно не указывать, он будет определен
автоматически:
Пример:
int a[4] = { 1, 4, 9, 16 };
int a[] = {1, 4, 9, 16 };
int a[3] = { 1, 4, 9, 16 }; - ошибка
int a[4] = { 1, 4}; - добавится 2 нуля
int a[4]={0} все 0
Для повышения универсальности программы размер массива лучше
определять через константу, которой дано имя. В этом случае при изменении
количества элементов в массиве достаточно только поменять значение этой
константы.
Чтобы обратиться к элементу массива, надо написать имя массива и затем
в квадратных скобках номер нужного элемента a[0]; a[1]; a[2];
Пример
const int N = 10
// или #define N 10
int a[N];
for(int i=0; i<N; i++)
a[i]=i*i;
Размер массива не может быть переменной в стандарте. (Можно с версии
С99.)
Следует соблюдать осторожность, выход за границы массива не
контролируется. Нумеруются элементы массива всегда от 0 до N-1. Это надо
учитывать, если описан массив:

32
int a[10];
a[10]=0; - ошибка, выход за границы массива, последний элемент
массива в этом примере имеет индекс 9.
Пример: ввод элементов с клавиатуры и вывод максимального на экран
#include <stdio.h>
int const N=6;
int main() {
int m[N], i;
printf("input mas");
for(int i=0; i<N; i++) scanf("%d",&m[i]);
max=m[0];
for(int i=1; i<N; i++)
if(max<m[i]) max=m;
printf("\n%d",max);
}
Заполнение массива случайными числами
Функция rand() позволяет генерировать псевдослучайные числа в
диапазоне от 0 до RAND_MAX , константа RAND_MAX=32767.
#include <stdio.h>
#include <stdlib.h>
int const N=6;
int main() {
float m[N], i;
for(int i=0; i<N; i++) {
m[i]=rand()%100;
printf("%10.3f",m[i]);
}
printf("\n");
for(int i=0; i<N; i++) {
m[i]=rand()/float(RAND_MAX);
printf("%10.3f",m[i]);
}
}
Если необходимо при каждом запуске программы получать разные
последовательности, генератор надо инициализировать изменяющимся числом,
например, текущим временем.

33
Пример инициализации генератора случайных чисел с помощью функции
srand():
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
long i,t;
t = time(NULL);
printf("%d %s\n", t,ctime(&t));
srand(time(NULL));
for(i=0; i<10; i++)
printf("%d\n", rand() % 100);
}
Пример формирования неповторяющихся случайных чисел:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 5 // количество чискл
#define M (N+1) // диапазон чисел
int main(void){
int i, j, flag;
int a[N]; // массив чисел
int k[M]={0}; //массив подсчета повтров чисел
srand(time(NULL));
printf("Variant 1\n");
for(i=0; i<N;i++) {
do{
a[i]=rand()%M;
flag=0;
for(j=0;j<i;j++)//поиск повторов
if(a[i]==a[j]) {flag=1; break;}
}while(flag);
printf("%4d", a[i]);
}
printf("\nVariant 2\n");
for(i=0;i<N;i++) {
do{
a[i]=rand()%M;

34
}while (k[a[i]]++); //проверка, встречалось ли число ранее
printf("%4d", a[i]);
}
printf("\nk[i]\n");
for(i=0;i<M;i++)
printf("%4d", k[i]);
}
Пример реализации генератора псевдослучайных чисел (ГПСЧ) в языке С.
Использует линейный конгруэнтный метод.
#define RAND_MAX 32767
static unsigned long int next = 1;
int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % RAND_MAX;
}
void srand(unsigned int seed)
{
next = seed;
}
В С11 есть более совершенные ГПСЧ, например, вихрь Мерсенна.
#include <iostream>
#include <time.h>
#include <random>
using namespace std;
int main(){ //2
19937
– период ГПСЧ
mt19937 mersenne(time(0)); // инициализация
for (int count = 0; count < 48; ++count)
{
cout << mersenne() << "\t";
}
}
Примеры программ обработки массивов
1. Подсчитать мат ожидание значение и среднее отклонение от него для
массива из N случ чисел.

35
M=(Σa[i])/N, D=(Σabs(M-a[i]))/N
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int const N=10000;
int main() {
float m[N], i, s=0, d=0;
for(int i=0; i<N; i++) {
m[i]=rand()%101;
s+=m[i];
}
s/=N;
printf("%f\n",s);
for(int i=0; i<N; i++) {
d+=fabs(s-m[i]);
}
d/=N;
printf("%f\n",d);
}
2. Циклическая перестановка элементов массива. 1,2,3,4,5 -> 2,3,4,5,1 (на к
элементов сдвиг)
for(i=0; i<k; i++) t[i]=m[i];
for(int i=0; i<N-k; i++) {
m[i]=m[i+k];
}
for(i=0; i<k; i++) m[N-k+i]=t[i];
for(int i=0; i<N; i++) {
printf("%4d",m[i]);
}
3. Сортировка – рассмотрим простые методы сортировки.
Метод выбора (поиск минимального элемента)
for(int i=0;i<N-1;i++){
int min=i;
for(int j=i+1;j<N;j++){
if( a[j]< a[min])
min=j;
}
t=a[i],a[i]=a[min],a[min]=t;
}

36
Метод пузырька (сравниваются соседние элементы)
k=0;
do {
flag=0;
for(i=N-1; i>k; i--)
if (m[i]<m[i-1]) t=m[i],m[i]=m[i-1],m[i-1]=t,flag=1;
k++;
}while(flag);
Метод вставок (на каждом шаге алгоритма мы выбираем один из
элементов массива и вставляем его на нужную позицию в уже
отсортированной части массива).
for(i=1; i<N; i++) {
int j=i;
while(j>0 && m[j]<m[j-1])
t=m[j],m[j]=m[j-1],m[j-1]=t,j--;
}
4. Поиск в отсортированном массиве.
Пусть элементы массива m уже расставлены по возрастанию и требуется
найти элемент, равный x, среди элементов с номерами от L до R. Для этого
используем следующий алгоритм: выбираем средний элемент между L и R, он
имеет номер с=(L+R)/2, где деление выполняется нацело. Сравним его с
искомым x. Если он равен x, мы нашли то, что искали. Если x меньше m[c],
надо искать дальше между m[L] и m[c], если x больше x[c], дальше ищем
между m[c] и m[R].
Пример.
int l, r, c, k;
l=0; r=N-1; k=0;
while ( l <= r ) {
c = (l + r) / 2;
if ( m[c] == x ) { k = 1; break; }
if ( x < m[c] ) r = c - 1;
else l = c + 1;
}
if ( k )
printf ( "нашли: m[%d]=%d", c, m[c] );
else printf ( "нет элемента" );

37
Многомерные массивы
Часто обычный массив неудобен для хранения данных из-за своей
линейной структуры. Например, таблица умножения, таблица координат. Из
многомерных массивов чаще всего используют 2-х мерные (матрицы).
В языке Си каждый индекс записывается отдельно в квадратных скобках.
int a[3][4];
Каждую строку матрицы можно рассматривать как обычный одномерный
массив. Поэтому можно сказать, что матрица – это массив из массивов.
Существует только два ограничения:
1. Все элементы матрицы должны быть одного типа.
2. Все строки матрицы должны быть одинаковой длины.
Первый индекс элемента матрицы – это номер строки, второй – номер
столбца.
В памяти элементы массива располагаются в следующем порядке:
a[0][0], a[0][1],a[0][2],a[0][3],a[1][0],…. a[2][3]
Инициализация многомерных массивов, пример:
int a[2][3] = {{1, 2, 3},{4, 5, 6}};
Для работы с матрицами обычно требуется вложенный цикл, то есть цикл
в цикле.
Примеры алгоритмов
1. Сформировать таблицу Пифагора. Дополнить каждую строку
матрицы суммой элементов стоки, каждый столбец – суммой
элементов столбца, вычислить сумму элементов диагонали.
int main(){
int i, j, m[N+1][N+1]={0};
for(i=0;i<N;i++)
for(j=0;j<N;j++) m[i][j]=i*j;
for(i=0; i<N;i++) {
m[N][N]+=m[i][i];
for(j=0;j<N;j++) {
m[i][N]+=m[i][j];
m[N][j]+=m[i][j];
}
}
for(i=0;i<=N;i++) {
for(j=0;j<=N;j++) printf("%4d",m[i][j]);

38
printf("\n");
}
}
2. Заполнить матрицу случайными числами. Найти строку с
максимальной суммой элементов и заменить в ней положительные
значения нулями.
int main(){
int i,j,m[N][N]={0},s,n,sm=0;
for(i=0;i<N;i++) {
for(s=j=0;j<N;j++) {
m[i][j]=rand()%100-50;
s+=m[i][j];
printf("%4d",m[i][j]);
}
if(s>sm) sm=s, n=i;
printf("\n");
}
printf("\nn=%d sm=%d\n\n",n,sm);
for(i=0; i<N; i++)
if(m[n][i]>0) m[n][i]=0;
for(i=0;i<N;i++) {
for(j=0;j<N;j++) printf("%4d",m[i][j]);
printf("\n");
}
}
3. Удалить заданные строку и столбец матрицы.
int i,j, ii, jj, m[N][N], a[N-1][N-1];
for(ii=i=0; i<N; i++){
if(i==n) continue;
for(jj=j=0;j<N;j++)
if (j!=n) a[ii][jj++]=m[i][j];
ii++;
}
4. Отсортировать каждую строку матрицы.
for(i=0;i<N;i++)
for(j=0;j<N-1;j++)
for(k=0;k<N-1;k++)
if(m[i][k]>m[i][k+1])
t=m[i][k],m[i][k]=m[i][k+1],m[i][k+1]=t;

39
Контрольные вопросы
Каковы индексы первого и последнего элементов массива, объявленного
как float y[n];?
Как вычислить сумму элементов массива, исключая крайние элементы?
Как вычислить сумму нечётных и чётных элементов массива?
Как объявить двумерный массив? Как инициализировать?

40
5. Строки
Строка – это массив символов. Последний символ строки должен иметь 0
код, он обозначает конец строки. Пример описания строки:
char st[80]; 80 – количество байт, выделяемое под строку в памяти.
При выделении памяти глобальные переменные заполняются нулями, а
локальные содержат «мусор». Начальное значение строки можно задать при
объявлении в двойных кавычках после знака равенства, в этом случае если
размер строки не указан, он определяется автоматически по количеству
символов в начальном значении строки:
char st[80]=”Hello”;
char st[]=”Hello”;
const char hello[] = "Hello";
Ввод стоки с клавиатуры, пример:
printf("Как тебя зовут? ");
scanf("%s", st);
printf("Привет, %s!", st);
scanf – считывает до первого пробела, если надо считать всю строку –
используем gets(st);
Основные функции для работы со строками <string.h>
int n;
char st1[80], st2[80];
1. int strcmp(st1,st2) возвращает ноль если равны, больше нуля если st1>st2 и
меньше нуля если st1<st2 Символы сравниваются попарно (по их кодам)
до первого различия.
strncmp(st1,st2,n); //сравнивается только первые n символов
2. char *strcat(st1,st2) – сцепление строк (к st1 добавляется st2)
char *strncat(st1,st2,n) //добавляются только первые n символов
возвращает указатель на st1
char st1[]=”Hello”;
printf(“%s”,strcat(st1,” Word”);
3. char *strcpy(st1,st2) – st2 копируется в st1
char *strncpy(st1,st2,n); // копируются только первые n символов
возвращает указатель на st1
4. char *strstr(st1,st2) – поиск подстроки st2 в строке st1, возвращает
указатель на первый символ найденной подстроки или NULL
char str1[] = "Hello Word", str2[] = "Wo", *ptr;
ptr = strstr(str1, str2);
printf("The substring is: %s\n", ptr); //(Word)
5. int strlen(st1) – возращает длину строки.
6. char *strtok(char *string, const char *delit);
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
