Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Программирование циклических процессов

Поиск

С использованием одномерных массивов и строк

 

Цель работы:

Изучить правила работы с одномерными массивами, а также особенности работы со строковы­ми объектами как одномерными символьными массивами.

 

Краткие теоретические сведения

Массив – конечномерная последовательность данных одного типа. Массив – объект сложного типа. Каждый элемент массива определяется именем массива и индексом (целое число), по которому к элементу массива производится доступ. Рассмотрим одномерные массивы. Индексы массивов в языке С начинаются с 0. В программе одномерный массив объявляется следующим образом:

<Тип> <имя массива>[размер];

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

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

Пример объявления массива целого типа:

int a [5];

в массиве а первый элемент а [0], второй – а [1], …, пятый - а [4]. В языке С не проверяется выход индекса за пределы массива. Корректность использования индексов элементов массива должен контролировать программист.

Пример работы с одномерным массивом

В массиве целых чисел найти индекс и значение максимального эле­мента и переставить его с первым элементом. Программа также дол­ж­на подсчитать количество положительных и отрицательных элементов данного массива.

Текст программы может быть следующим:

 

#include <stdio.h>

#include <conio.h>

void main(void)

{ // Объявление с инициализацией,

int a[4]={-1,-20,4,100}; // индексы принимают значения от 0 до 3

int i,index,max,kp=0,ko=0,zam,n=4;

clrscr();

puts("\n Исходный массив ");

for (i=0; i<n; i++)

printf("%d ",a[i]); // Вывод элементов исходного массива

max=a[0];

for (i=1; i<n; i++)

{

if (a[i]>max)

{

max=a[i]; index=i; }

}

zam=a[0];a[0]=a[index];a[index]=zam;

for (i=0;i<n;i++)

{

if (a[i]<0) ko++;

else kp++;

}

puts("\n Результаты работы программы ");

for (i=0; i<n; i++)

printf("%d ",a[i]); // Вывод элементов массива

printf("\n положительных элементов: %d \n",kp);

printf("\n отрицательных элементов: %d \n\n Press any key...",ko);

getch();

}

Строки как одномерные массивы символов

Работа со строками в языке С реализована путем использования одномерных мас­сивов типа char, т.е. строка символов – это одномерный массив типа char, заканчиваю­щийся нулевым байтом. Нулевой байт – это байт, каждый бит которого равен нулю, при этом для нулевого байта определена символьная константа ´\0´ (признак окончания строки или нуль-терминатор). Поэтому, если строка должна состоять из k символов, то в описании массива необходимо указать размер k+1.

Например, описание char a[7], означает, что строка содержит шесть символов, а последний байт отведен под нуль-терминатор.

Строковая константа в языке С – это набор символов, заключенных в двойные кавычки. Например: “Лабораторная работа по строкам”. В конце строковой константы явно указывать символ ´\0´ не нужно, так как это сделает компилятор языка С.

Строки можно инициализировать при декларировании, например:

char S1[10]=”123456789”, S2[ ]=”12345”;

в последнем случае размер строки будет установлен по фактическому количеству символов.

Для ввода строки с клавиатуры дисплея используются две стандартные библи­отечные функции, прототипы которых приведены в файле stdio.h.

Функция scanf () вводит значения для строковых переменных спецификатором ввода %s. Но надо помнить, что функция scanf() вводит символы до появления первого символа “пробел”.

Библиотечная функция gets () обеспечивает ввод строки с пробелами внутри этой строки. При этом ввод строки символов завершается нажатием клавиши ENTER.

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

Вывод строк выполняют функции printf () или puts (). Обе функции выводят символьный массив до первого нулевого байта. Функция printf() не переводит курсор после вывода на начало новой строки, программист должен предусмотреть такой перевод в строке формата. Функция puts() автоматически переводит курсор после вывода строковой информации в начало новой строки.

Операции над строками как объектами сложного типа, рекомендуется выполнять, используя стандартные функции. Декларации функций для работы со строками размещены в файле string.h. Рассмотрим наиболее часто используемые:

1. Функция strcpy (S1, S2) - копирует содержимое строки S2 в строку S1.

2. Функция strcat (S1, S2) - присоединяет строку S2 к строке S1 и помещает ее в массив, где находилась строка S1, при этом строка S2 не изменяется. Нулевой байт, который завершал строку S1, заменяется первым символом строки S2.

3. Функция strcmp (S1, S2) сравнивает строки S1 и S2 и возвращает значение =0, если строки равны, т.е. содержат одно и то же число одинаковых символов; значение <0, если S1<S2; значение >0, если S1>S2.

4. Функция strlen (S) возвращает длину строки, т.е. количество символов, начиная с первого (S[0]) и до нуль-терминатора, который не учитывается.

5. Функции преобразования строки S в число:

- целое: int atoi (S);

- длинное целое: long atol (S);

- действительное: double atof (S);

при ошибке данные функции возвращают значение 0.

6. Функции преобразования числа V в строку S:

- целое: itoa (int V,char S,int kod);

- длинное целое: ltoa (long V,char S,int kod); 2<=kod<=36, для отрицательных чисел kod=10.

Операция sizeof

Для определения размера памяти, необходимого для размещения объектов в языке С, используется унарная операция sizeof (параметр), параметр – тип объекта или его идентификатор (только не имя функции). Операция sizeof вычисляет размер памяти в байтах, отводимый под объект. Если указан идентификатор сложного объекта (массив, структура, объединение), то результатом является размер всего сложного объекта. Например:

sizeof(int) результат 2 байта;

int b[5]; sizeof(b) результат 10 байт;

int c[3][4]; sizeof(c) результат 24 байта.

Указатели и операции над адресами

Обращение к объектам любого типа в языке C может проводиться по имени, как мы до сих пор делали, и по указателю (косвенная адресация).

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

Указатель объявляется следующим образом:

<тип> * <идентификатор>;

Например:

int *a, *d;

float *f;

Здесь объявлены указатели a, d, которые можно инициализировать адресами целочисленных переменных, и указатель f, который можно инициализировать адресами вещественных переменных.

С указателями связаны две унарные операции: & и *. Операция & означает «взять адрес». Данная операция допустима только над переменными. Операция * - «значение, расположенное по указанному адресу» и работает следующим образом:

- определяется местоположение в оперативной памяти переменной типа указатель;

- извлекается информация из этого участка памяти и трактуется как адрес переменной с типом в объявлении указателя;

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


Пример:

int x, // переменная типа int

*y; // указатель на элемент данных типа int

y=&x; // y - адрес переменной x

*y=1; // по адресу y записать 1, в результате x = 1

 

Связь указателей и массивов

Указатели и массивы в языке С тесно связаны между собой. Имя массива является указателем на его первый элемент, т.е. для массива int v [10] v и v [0] имеют одинаковые значения, т.к. адрес первого (с индексом 0) элемента массива - это адрес начала последовательно расположенных элементов массива. Рассмотрим обращение к элементам массива на примере. Пусть объявлены - массив из 100 объектов типа float и указатель на объект типа float:

float p[100];

float *q;

int i;

если выполнить операцию q=p; то обращения к элементу массива p: p[i], *(q+i) и *(p+i) эквивалентны.

Таким образом, для любых указателей можно использовать две эквивалентные формы выражений для доступа к элементам массива: q[i] и *(q+i). Первая форма удобнее для читаемости текста, но вторая обычно эффективнее по быстродействию программы.

Очевидна эквивалентность выражений

&q[0] <-> &(*q) <-> q

*q <-> q[0]

 

Пример 1: Упорядочить по алфавиту массив строк (не более 20) длиной не более 10 символов в каждой.

 

#include<conio.h>

#include<stdio.h>

#include<string.h>

void main()

{

char s[20][10],r[10];

int i,j,n;

clrscr();

puts(" Введите количество слов ";

scanf(“%d”,&n);

for(i=0;i<n;i++)

scanf("%s",&s[i]);

for(i=0;i<(n-1);i++)

for(j=(i+1);j<n;j++)

if(strcmp(s[i],s[j])>0)

{

strcpy(r,s[i]);

strcpy(s[i],s[j]);

strcpy(s[j],r);

}

for(i=0;i<n;i++)

printf("\n %s",s[i]);

getch();

}

 

Пример 2: Проверить, является ли введенная строка (не более 80 символов) палиндромом (справа налево читается так же, как и слева направо).

#include <stdio.h>

#include <string.h>

#include <conio.h>

 

void main(void)

{

char s[80],s1[80];

int i, k;

clrscr();

puts(" Введите исходную строку (не более 80 символов) ");

gets(s);

k=strlen(s);

puts(" Результаты работы программы ");

for (i=0; i<k; i++)

printf("%c",s1[i]=s[k-i-1]); // Переворачиваем строку s

s1[k]=’\0’; // Устанавливаем конец строки

printf(“ %s\n”,strcpy(s1,s)? ” YES - Pаlindrom!”:” NO!”)

printf("\n Press any key...");

getch();

}

 

Массивы указателей

В языке С можно использовать массивы указателей, элементы которых содержат, как правило, указатели на строковые данные. Объявляется такой массив, например, так char *m[5]. Здесь массив m[5] – массив, который может содержать пять адресов данных типа char.

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

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

 

#include <stdio.h>

#include <conio.h>

 

void main(void)

{

int i,k;

char *m[]={

"Winter",

"Spring",

"Summer",

"Automn"};

k=sizeof(m)/sizeof(*m);

printf("\n Количество строк = %d",k);

for(i=0; i<k; i++)

printf("\n Номер - %d; Адрес - %p; Строка: %s", i+1, m[i], m[i]);

getch();

}

В результате получим:

Количество строк = 4

Номер - 1; Адрес - 0042007C; Строка: Winter

Номер - 2; Адрес - 00420074; Строка: Spring

Номер - 3; Адрес - 0042006C; Строка: Summer

Номер - 4; Адрес - 00420064; Строка: Automn

 

Конкретные значения адресов зависят от ряда причин: архитектуры компьютера, типа и размера оперативной памяти и т.д.

Замечание. Функция printf() и спецификатор преобразования %S допускают использование в качестве параметра указатель на строку, однако при этом выводится не значение указателя m[i], а содержимое адресуемой им строки, в то время как спецификатор %P выводит значение указателя m[i].

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

В качестве примера приведена программа упорядочения одномерного массива по возрастанию и убыванию без перестановки его элементов.

 

#include <stdio.h>

#define b 6

void main ()

{ float array [ ]={5.0,2.0,3.0,1.0,6.0,4.0};

float *pmin[b], *pmax[b], *e;

int i,j;

for (i=0;i<b;i++)

pmin[i]=pmax[i]=&array[i];

for(i=0;i<b-1;i++)

for(j=i+1;j<b;j++)

{

if(*pmin[i]<*pmin[j])

{ e=pmin[i];

pmin[i]=pmin[j];

pmin[j]=e;}

if(*pmax[i]>*pmax[j])

{ e=pmax[i];

pmax[i]=pmax[j];

pmax[j]=e;}

}

printf(’’ \n По убыванию: \n”);

for(i=0;i<b;i++)

printf(“\t %5.3f”,*pmin[i]);

printf(“\n По возрастанию: \n”);

for(i=0;i<b;i++)

printf(“\t%5.3f”,*pmax[i]);

}

 

Варианты индивидуальных заданий

1. Ввести целое число N. Выделить из этого числа цифры, кратные 3, и записать их в одномерный массив.

2. Для заданного целого числа N определить цифру а, наиболее часто встречающуюся в числе. Сформировать одномерный массив из 5 элементов: a, а2, а3, а4, а5.

3. Элементы заданного массива X циклически сдвинуть на K позиций вправо (влево).

4. Дано число N целого типа. Определить, симметрично ли оно, т.е. одинаковы ли цифры слева и справа (12321). Записать 3 последние цифры в одномерный массив.

5. Упорядочить элементы массива X по возрастанию.

6. Даны координаты n точек на плоскости: x1,y1, x2,y2,…. xn,yn. Найти номера двух точек, расстояние между которыми наибольшее.

7. Заданы два массива по N целых чисел. Найти наименьшее среди чисел первого массива, которое не входит во второй массив.

8. Дан массив из N целых чисел. Определить количество инверсий в этом массиве (т.е. таких пар элементов, в которых большее число находится слева от меньшего: xi > xj при i < j).

9. Ввести строку символов. Определить длину введенной строки L, и если длина L четная, то удаляются 2 первых и 2 последних символа.

10. Ввести строку символов. Определить длину введенной строки L, и если длина L нечетная, то удаляется символ, стоящий посередине строки.

11. Ввести строку символов. Заменить в ней каждый второй символ! на $.

12. Ввести строку символов. Заменить в ней пробелы на символ $.

13. Ввести строку символов. Определить длину введенной строки L, и если длина L>10, то удалить все цифры.

14. Ввести строку символов. Определить длину введенной строки L, и если длина L кратна 3, то удаляются все числа, делящиеся на 3.

15. Ввести строку символов. Определить длину введенной строки L, и если длина L кратна 5, то подсчитывается количество скобок всех видов.

16. Ввести строку символов. Определить длину введенной строки L, и если длина L кратна 4, то первая часть строки меняется местами со второй.

17. Ввести строку символов. Определить длину введенной строки L, и если длина L=10, то удаляются все буквы - A... Z.

18. Ввести строку символов. Определить длину введенной строки L, и если длина L >15, то удаляются все буквы - a…z.

19. В строке символов поменять местами символы на четных и нечетных позициях.

20. Ввести строку символов. Определить длину введенной строки L, и если длина L>6, то выделяется подстрока в { } скобках.

Контрольные вопросы

 

1. Укажите типы массивов, применяемых в языке С.

2. Формы (способы) работы с элементами массива.

3. Как описываются строки в языке С?

4. Чем отличаются функции scanf() и gets(), printf() и puts()?

ЛАБОРАТОРНАЯ РАБОТА № 4



Поделиться:


Последнее изменение этой страницы: 2016-04-08; просмотров: 859; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.81.173 (0.012 с.)