Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Указатели и операции над адресами
Обращение к объектам любого типа в языке 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 |
||
Последнее изменение этой страницы: 2018-05-10; просмотров: 228. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |