Главная страница
Навигация по странице:

  • 7. Массивы и строки 7.1 Одномерные массивы

  • 7.2 Двумерные массивы

  • Практическая работа №3: Строки

  • 8. Работа с файлами в C

  • методичка. Языки C, C++ (1). Методическое пособие для учащихся Москва 2017 Оглавление 2 удк ббк хлебников А. А


    Скачать 2.43 Mb.
    НазваниеМетодическое пособие для учащихся Москва 2017 Оглавление 2 удк ббк хлебников А. А
    Анкорметодичка
    Дата18.09.2022
    Размер2.43 Mb.
    Формат файлаpdf
    Имя файлаЯзыки C, C++ (1).pdf
    ТипМетодическое пособие
    #683739
    страница3 из 6
    1   2   3   4   5   6
    6.4. Арифметические действия над указателями
    Над указателями можно проводить только такие действия, как сложение и вычитание. Предполагается, что если указатель p относится к типу T *, то p указывает на элемент некоторого массива типа T. Тогда р + 1 является указателем на следующий элемент этого массива, а р - 1 – указателем на предыдущий элемент. Аналогично определяются выражения р + n, n + p и р - n, а также действия p++, p–, ++p, –p, p += n, p -= n, где n – целое число. Важно отметить, что арифметические действия с указателями выполняются в единицах того типа, к которому относится указатель. То есть р + n, преобразованное к целому типу, содержит на sizeof(T)* n большее значение, чем p. Из равенства p + n == p1 следует, что p1 - p == n.
    Именно так вводится оператор разности двух указателей: его значением является целое, равное количеству элементов массива от p до p1. Отметим, что это – единственный случай в языке, когда результат бинарного оператора с операндами одного типа принадлежит к принципиально другому типу. Сумма двух указателей не имеет смысла и поэтому не определена. Не определены также арифметические действия над нетипизированными указателями void *. Наконец, все указатели, в том числе и нетипизированные, можно сравнивать, используя операторы отношения:>, <, >=, <=, ==, !=.
    Пример (сумма элементов массива):
    Указатели и массивы тесно взаимосвязаны. Имя массива может быть неявно преобразовано к константному указателю на первый элемент этого массива. Так, &a[0] равноценно a. Вообще, верна формула a[n] == a + n; то есть адрес n-того элемента массива есть увеличенный на n элементов

    Оглавление
    43 указатель на начало массива. Разыменовывая левую и правую части, получаем основную формулу, связывающую массивы и указатели:
    Данная формула, несмотря на простоту, требует нескольких пояснений.
    Во-первых, компилятор любую запись вида a[n] интерпретирует как *(a + n). Во-вторых, формула поясняет, почему в C,
    C++ массивы индексируются с нуля, и почему нет контроля выхода за границы диапазона. Наконец, используя эту формулу, мы можем записать следующую цепочку равенств:
    Таким образом, элемент массива a с индексом 2 можно обозначить не только как a[2], но и как 2[a]

    Оглавление
    44
    7. Массивы и строки
    7.1 Одномерные массивы
    Массив — это структура данных, представленная в виде группы ячеек одного типа, объединенных под одним единым именем. Массивы используются для обработки большого количества однотипных данных.
    Имя массива является указателем. Что такое указатели будет рассказано немного позже. Отдельная ячейка данных массива называется элементом массива. Элементами массива могут быть данные любого типа. Массивы могут иметь как одно, так и более одного измерений. В зависимости от количества измерений массивы делятся на одномерные массивы, двумерные массивы, трёхмерные массивы и так далее до n-мерного массива. Ниже можно увидеть программу, демонстрирующую основные аспекты определения и объявления массивов:
    Строка intarray[10] – объявляет массив, состоящий из 10 элементов.
    Из примера видно, что для использования массива, необходимо его объявить, т.е. указать тип ячеек, имя массива и количество элементов.
    Далее нужно обращаться к элементам используя имя и индекс. Заметьте, что нумерация начинается с 0, т.е для обращения к 1 элементу в скобках вам нужно указать 0, следовательно для n-нного элемента n-1.
    Массив также можно инициализировать вручную при объявлении следующим образом:

    Оглавление
    45
    Если вы не указываете первоначальное значение для какого-либо элемента массива, большинство компиляторов C++ будут инициализировать такой элемент нулем.
    Например, следующее объявление инициализирует первые три из пяти элементов массива

    Оглавление
    46
    7.2 Двумерные массивы
    Работа с двумерными массивами ничем не отличается от работы с одномерными, можете сами убедится:
    При передаче функции массива как аргумента, копия объекта не создается, и работаем мы с тем же массивом. Связано это с тем, что имя массива - это указатель.

    Оглавление
    47
    Откровенно говоря, при определении/объявлении кроме имени нужно указать количество элементов только в первых скобках, вторые можно оставить пустыми. Но чтобы не путаться, лучше писать все.

    Оглавление
    48
    7.3 Строки
    Особым видом массива в C является строка. Она представляет собой массив типа char, завершающийся нулевым символом- ‘\0’. Также строки могут объявляться иначе чем массивы другого типа:
    Функции для манипулирования C – строками объявлены в заголовочном файле string.h (или по стандарту 1998 г. в cstring).
    Прототипы основных функций для работы со строками:
    Она копирует строку src в строку dst, включая нулевой символ, и возвращает указатель на строку dst. При этом выход за границы массива dst не контролируется:
    Для определения длины строки служит функция strlen с прототипом:
    Для добавления одной строки к другой используется функция strcat с прототипом
    Функция strcmp предназначена для лексикографического сравнения строк. Она имеет прототип

    Оглавление
    49
    Практическая работа №3:
    Строки:
    1. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Циклически сдвинуть все слова влево на k слов, удалив при этом лишние пробелы (k заведомо меньше количества слов).
    2. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Циклически сдвинуть все слова вправо на k слов, удалив при этом лишние пробелы (k заведомо меньше количества слов).
    3. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Скопировать в новую строку два самых коротких слова исходной строки. Алгоритм просмотра исходной строки должен быть однопроходным.
    4. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале, в конце строки и между словами). Сформировать новую строку, в которой содержатся все слова-перевертыши (палиндромы) исходной строки. Алгоритм просмотра исходной строки должен быть полуторапроходным (полпрохода на проверку того, является ли слово перевертышем).
    5. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами), а также целочисленный массив перестановок слов. По данной строке и массиву перестановок сформировать новую строку, удалив при этом лишние пробелы. Например, если задана строка « aa bbb c dd eeee» и массив перестановок 5 2 4 3 1, то итоговая строка должна иметь вид: «eeee bbb dd c aa». Указание: вначале сформировать массив указателей на начала слов.

    Оглавление
    50 6. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Сформировать строку, в которой слова из исходной строки упорядочены по алфавиту, удалив при этом лишние пробелы. Указание: для сравнения строк можно воспользоваться библиотечной функцией strcmp(s, s1).
    7. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале, в конце строки и между словами). Сформировать строку, в которой слова из исходной строки упорядочены по длине (а при равной длине порядок их следования остается таким же, как и в исходной строке), удалив при этом лишние пробелы
    8. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале, в конце строки и между словами). Сформировать строку, в которой слова из исходной строки упорядочены по количеству гласных (а при равном количестве гласных порядок их следования остается таким же, как и в исходной строке), удалив при этом лишние пробелы.
    9. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Сформировать строку, в которой удалены лишние пробелы и повторявшиеся ранее слова.
    Порядок слов не менять.
    10. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Сформировать строку, в которой слова упорядочены по повторяемости. Дубликаты слов следует удалить. При одинаковой повторяемости первым должно следовать слово, первое вхождение которого встречается раньше в исходной строке.

    Оглавление
    51 11. Вводится строка слов, разделенных пробелами (возможны лишние пробелы в начале и в конце строки и между словами). Выдать таблицу слов и количество их повторений в строке. Дубликаты слов не выдавать.
    12. Вводится строка. Заменить в ней все цифры их словесными обозначениями: 0 на «zero», 1 на «one», 2 на «two» и т.д.
    13. Удалить из строки s каждое вхождение подстроки s1.
    14. Заменить в строке s каждое вхождение подстроки s1 на подстроку s2.
    15. Даны две строки. Найти индексы (их может быть несколько) и длину самого длинного одинакового участка в обоих массивах. Например, в строках «abracadabra» и «sobrat» самым длинным одинаковым участком будет «bra».
    16. Дан массив строк. Сформировать по нему массив подстрок, удовлетворяющих условию, передаваемому в качестве параметра (условие должно представлять собой функцию, принимающую параметр char * и возвращающую значение логического типа).
    17. Реализовать функцию char *mystrstr(const char *p, const char *q); возвращающую первое вхождение подстроки q в строку p (или 0, если подстрока не найдена).
    18. Реализовать функцию char *mystrpbrk(const char *p, const char *q);| возвращающую указатель на первое вхождение в строку p какого-либо символа из строки q (или 0, если совпадений не обнаружено)

    Оглавление
    52 19. Реализовать функцию size_t mystrspn(const char *p, const char *q); возвращающую число начальных символов в строке p, которые не совпадают ни с одним из символов из строки q.
    20. Реализовать функцию size_t mystrcspn(const char *p, const char *q); возвращающую число начальных символов в строке p, которые совпадают с одним из символов из строки q.21. Реализовать функцию char* mystrtok(const char *p, const char *q, char* t); пропускающую символы разделителей, хранящихся в строке q, считывающую первую лексему в строке p в строку t (до следующего символа разделителя или до конца строки) и возвращающую указатель на первый, не просмотренный символ.

    Оглавление
    53
    Массивы
    Считая, что переменная a описана как a[3][4], расшифруйте выражения
    (пример Указатели. Ссылки):
    - *a;
    - **a;
    - *a+1
    - (*a)[2];
    - *(a[2])
    - *a[2];
    - *2[a];
    - *1[a + 1];
    - &a[0][0];
    - 2[a][3].
    1. Дан массив целых. Оформить функцию count_if, вычисляющую количество элементов в массиве, удовлетворяющих данному условию, передаваемому в качестве параметра (условие должно представлять собой функцию, принимающую параметр типа int и возвращающую значение логического типа).
    2. Дан массив целых. Заполнить его, передавая в качестве параметра функцию, задающую алгоритм генерации следующего значения, вида int f(). Для генерации данная функция может запоминать значения, сгенерированные на предыдущем шаге, либо в глобальных переменных, либо в статических локальных переменных.
    3. Дан массив целых, отсортированный по возрастанию. Удалить из него дубликаты.

    Оглавление
    54 4. Дан массив целых. Составить функцию remove_if, удаляющую из него все элементы, удовлетворяющие условию, передаваемому в качестве параметра.
    5. Дан массив чисел и число a. Переставить элементы, меньшие a, в начало, меняя их местами с предыдущими. Порядок элементов, меньших a, а также порядок элементов, больших a, не менять.
    6. Дан массив целых. Найти в нем пару чисел a и b с минимальным значением f(a, b), где f передается в качестве параметра.
    7. Дан массив целых. Составить функцию accumulate, применяющую функцию f(s, a), передаваемую в качестве параметра, к каждому элементу a массива и записывающую результат в переменную s. С ее помощью найти минимальный элемент в массиве, сумму и произведение элементов массива.
    8. Дан массив целых. Сформировать по нему массив, содержащий длины всех серий (подряд идущих одинаковых элементов). Одиночные элементы считать сериями длины 1.
    9. Дан массив целых. Из каждой серии удалить один элемент.
    10. Дан массив целых. Удалить все серии, длина которых меньше k.
    11. Слить n массивов целых, упорядоченных по возрастанию, в один, упорядоченный по возрастанию. Указание 1. Для упрощения алгоритма следует записать в конец каждого массива барьер – самое большое число соответствующего типа. Барьер, в частности, будет определять, где заканчиваются данные в массиве

    Оглавление
    55
    8. Работа с файлами в C
    При открытии файла с нами связывается поток ввода-вывода.
    Выводимая информация записывается в поток, вводимая информация считывается из потока.
    Когда поток открывается для ввода-вывода, он связывается со стандартной структурой типа FILE, которая определена в .
    Открытие файла осуществляется с помощью функции fopen(), которая возвращает указатель на структуру типа FILE, который можно использовать для последующих операций с файлом. name – имя файла, который вы открываете (включая путь до него) type – способ доступа к файлу:
    “r”– открыть файл для чтения (файл обязан существовать)
    “w” – открыть файл для записи (файл должен быть пустым)
    “a” – дописывает информацию к файлу
    “rb” – открывает двоичный файл для чтения
    “wb” – открывает двоичный файл для записи
    “ab”- дополняет двоичный файл
    “rt” – открывает текстовый файл (символьный) для чтения
    “wt” – открывает текстовый файл (символьный) для записи. Файл должен быть пустым
    “at” – дописывает информацию к текстовому символьному файлу
    После окончания работы с файлом нужно всегда закрывать данный файл. В противном случае произойдет потеря данных. Почему? Будет объяснено чуть ниже.
    Прототип функции, которая закрывает файл.
    Почему произойдет потеря данных? Данные в файл попадают не сразу (из-за специфики строения жесткого диска), они попадают в буфер памяти (cash). И лишь cashпереполняется, они записываются в файл.
    Поэтому, если мы не закроем файл, данные просто останутся в данном буфере памяти.

    Оглавление
    56
    Предположим, что по какой-то причине, ваша программа, которая работает с файлами, рушится. Однако какая-то часть данных застряла в cash’е (предположим, что вы использовали функцию fprintf(), она работает аналогично printf(), только с файлом). То, что мы считали с клавиатуры с помощью fprintf(), останется в буфере памяти. Но программа опять же
    «упала», а данные в файл должны поместиться. Что делать?
    Есть такая функция fflush (FILE *f), которая «проталкивает» данные в файл. Ниже приведен отрывок из кода, где она используется.
    Также рассмотрим несколько функций, которые тоже важны для работы с файлами:
    1.
    Данная функция считывает из файла f количество символов count размером size и помещает их в массив p. Возвращает количество считанных блоков размером (count*size). Возвращает тип size_t.
    Перемещает указатель в файле на количество считанных им символов.
    Пример использования (многие еще неизвестные вам функции объясняются чуть ниже в этом же пункте):
    //Получаем размер файла

    Оглавление
    57
    //Выделяем память для хранения всего файла
    //Копируем файл в буфер
    /* Теперь весь файл находится в буфере */
    // Завершение
    2.
    Эта функция записывает в файл f количество символов count размером size из массива p. Оставшаяся часть аналогична fread(…);
    Примериспользования:
    3.

    Оглавление
    58
    Данная функция помещает указатель в файловом потоке stream на место place, смещая его каждый раз на значение offset. У place есть 3 состояния: 0,1,2, которые соответствуют SEEK_SET, SEEK_CUR,
    SEEK_END – началу файла, текущей позиции и концу файла. В случае успеха функция возвратит нулевое значение.
    Пример использования:
    4.
    Возвращает значение указателя текущего положения потока.
    Пример использования:

    Оглавление
    59 5.
    Устанавливает внутренний указатель в начальное положение, то есть в начало файла. Эквивалентен fseek(…). Но в отличие от fseek(…) его возвращаемое значение void.
    Пример использования:
    6.
    Функция получения текущего положения в потоке stream. Результат помещается в pos. 0 – в случае успеха, иначе отличное от 0 значение и записывается в переменную errno.
    Пример использования:

    Оглавление
    60 7.
    Устанавливает позицию pos в потоке stream. Возвращаемый результат аналогичен fgetpos(…)
    Пример использования:

    Оглавление
    61 8.
    Проверяет, достигнут ли конец файла, связанного с потоком stream
    Пример использования:
    9.
    Меняет название файла с oldname на newname.Возвращает 0, если удалось переименовать, иначе возвращает любое ненулевое значение и устанавливает переменную err no.
    Пример использования:

    Оглавление
    62 10.
    Работают аналогично scanf() и printf().
    Функция fscanf ( ) возвращает количество аргументов, которым действительно были присвоены значения. В их число не входят пропущенные поля (пробелы). Возврат EOF означает, что при чтении была сделана попытка пройти маркер конца файла.
    Функция fprintf ( ) выполняет форматированный вывод в поток. Записывает в указанный поток последовательность символов в формате, указанном аргументом format. После параметра format, функция ожидает, по крайней мере, многие дополнительные аргументы, как указано в прототипе.
    Пример использования одной из них:
    11.
    Кладет в поток stream строку string, введенную с клавиатуры
    Пример использования:

    Оглавление
    63
    Полагаем, что данный кусок кода требует небольших пояснений:
    8 строчка записывает строку из стандартного потока ввода stdin в символьный массив sentence.
    9 строка добавляет строку в файл.
    12.
    Получает символы из файлового потока stream и сохраняет их в строку string, до тех пор, пока не наступит конец файла или строки. num–
    максимальное количество символов доступных для чтения. Нулевой символ включается!
    Пример использования:

    Оглавление
    64 13.
    Используется для связывания существующего потока с новым файлом. Новое имя файла указывается аргументом fname, режим доступа
    — аргументом mode, а поток, который надо связать с новым именем, — аргументом stream
    Пример использования:

    Оглавление
    65
    1   2   3   4   5   6


    написать администратору сайта