ЛАБОРАТОРНАЯ РАБОТА№ 2-3
ЦЕЛЬ РАБОТЫ: Изучить работу со строками в программах на языке Си. Научиться создавать свои функции преобразования строк и использовать готовые библиотечные функции. Изучить правила передачи указателя в функцию и возврата указателя из функции на примере символьных массивов.
1. Порядок выполнения работы.
1.1. В программе 1 изменить взаиморасположение объектов index, dates, a, bills. Проанализировать отличие между результа¬тами исходной программы и модифицированной.
1.2. Доказать, что имя массива определяет адрес его первого эле¬мента, т.е. если дан массив а[], то а==&a[0].
1.3. В программе 2 в строке 1 массив А[] описать с типом static. Сравнить результаты работы двух версий программы.
/* Программа 1 */ // Указатели и расположение объектов в памяти
#include <stdio.h>
void main() {
int index,dates[4],*pti,a;
float bills[4],*ptf;
for (index=0;index<4;index++)
printf(«Адреса %d значения массивов %u %u\n»,index,&dates[index],&bills[index]);
pti=dates;
ptf=bills;
for (index=0;index<4;index++)
printf(«Указатель + %d %u %u\n», index,pti+index,ptf+index);
printf («Адрес переменной index = %u\n»,&(index));
printf («Адрес переменной a = %u»,&(a));
}
/* Программа 2 */ // Операции с указателями
#include <stdio.h>
#define PR(x) printf(«x= %u,*x= %d,&x= %u\n»,x,*x,&x)
void main() {
int A[]={100,200,300,400}; // строка 1
int *pt1,*pt2;
pt1=A; // строка 2
printf («A= %u\n»,A);
printf («A[0]= %u\n»,A[0]);
printf («A[2]= %u\n»,*(pt1+2)); // строка 3
pt2=&A[2];
*pt2=500;
printf («pt2= %u\n»,pt2);
PR(pt2);
printf («A[2]= %u\n»,A[2]);
printf («&A[0]= %u\n»,&A[0]);
printf («&A[1]= %u\n»,&A[1]);
printf («&A[3]= %u\n»,&A[3]);
printf («&A[4]= %u\n»,&A[4]);
PR(pt1);
printf(«Адрес А =%u\n»,&A); // строка 4
pt1++; // строка 5
PR(pt1);
++pt2;
PR(pt2);
printf(«pt2-pt1 = %u\n»,pt2-pt1); // строка 6
2. Индивидуальные задания
Задача №1.
1. Написать программу, которая спрашивает имя пользователя и здоровается с ним.
2. Написать программу, которая спрашивает имя и отчество пользователя и здоровается с ним. Для ввода использовать функцию getch().
3. Написать программу, которая вычисляет длину введенной с клавиатуры строки.
4. Написать программу, которая выводит на экран сообщения в “телеграфном” стиле: буквы с должны появляться по одной с некоторой задержкой.
5. Написать программу, которая в веденной с клавиатуры строке преобразует строчные буквы русского алфавита в прописные.
6. Написать программу, которая удаляет из введенной с клавиатуры строки начальные пробелы.
7. Написать программу, которая проверяет, является ли введенная с клавиатуры строка целым числом.
8. Написать программу, которая проверяет, является ли введенная с клавиатуры строка двоичным числом.
9. Написать программу, которая проверяет, является ли введенная с клавиатуры строка шестнадцатеричным числом.
10. Написать программу, которая проверяет, является ли введенная с клавиатуры строка дробным числом.
11. Написать программу, которая преобразует введенное с клавиатуры восьмиразрядное двоичное число в десятичное.
12. Написать программу, которая вычисляет значение введенного с клавиатуры арифметического выражения.
13. Написать программу, которая подсчитывает самую длинную последовательность подряд идущих букв ‘a’.
Задача №2.
1. В программе вводятся по очереди символьные строки. Количество слов в этих строках подсчитывается в функции, и это число возвращается в основную программу. Конец ввода строк это ввод нулевой строки.
2. В программе вводятся по очереди символьные строки. Количество букв ‘а’ в этих строках подсчитывается в функции, и это число возвращается в основную программу. Конец ввода строк это ввод нулевой строки.
3. В программе вводятся по очереди символьные строки и передаются в функцию. Определить самое длинное слово в строке и передать его адрес в основную программу. Распечатать это слово в основной программе. Конец ввода строк это ввод нулевой строки.
4. В программе вводятся по очереди символьные строки и передаются в функцию. Определить сколько раз в строке встречается подстрока “abc…”. Вернуть это число в основную программу. Конец ввода строк это ввод нулевой строки.
5. В программе вводятся по очереди символьные строки и передаются в функцию. Определить сколько раз каждая буква встречается в строке. Вернуть эти числа в основную программу. Конец ввода строк это ввод нулевой строки.
6. В программе вводится массив фамилий студентов группы. В функции определить для каждого студента сколько у него однофамильцев. Вернуть эти числа в основную программу и распечатать. (Иванов – 2, Петров – 3, Сидоров –1)
7. В записке слова зашифрованы – каждое из них написано наоборот. Написать функцию, которая получает сроку и расшифровывает ее в новый символьный массив. Распечатать записку в основной программе.
8. В программе вводятся по очереди символьные строки, содержащие буквы и цифры и передаются в функцию. В функции сформировать новую строку, состоящую только из цифр. Распечатать эту строку в основной программе. Конец ввода строк это ввод нулевой строки.
9. Мистер Браун, человек со странностями, всегда читает справо налево. Составить функцию, облегчающую диалог с мистером Брауном, для которой передается указатель на введенную строку, и которая возвращает указатель на строку, обратную к введенной. Например: ввод «Галина», вывод «анилаГ». Обратную строку вывести на экран. Создать программу обрабатывающую произвольное количество строк.
10. Составить свою функцию поиска подстроки в строке текста, получающую указатель на строку и указатель на подстроку. Если подстрока не найдена ввести другую и продолжить поиск. Если же найдена — вернуть в основную программу ее начальную позицию в строке.
11. В программе вводятся по очереди символьные строки, содержащие текст заключенный в скобки и передаются в функцию. В функции сформировать новую строку, из которой удален это текст. Распечатать эту строку в основной программе. Конец ввода строк это ввод нулевой строки.
12. В программе вводятся по очереди символьные строки, содержащие несколько пробелов между словами, и передаются в функцию. В функции сформировать новую строку, из которой удалены лишние пробелы. Распечатать эту строку в основной программе. Конец ввода строк это ввод нулевой строки.
13. Написать программу-телеграф, которая принимает от пользователя сообщения по очереди, передает в функцию и выводит его на экран в виде последовательности точек и тире. Вывод точек и тире можно сопровождать звуковым сигналом разной длительности. Азбука Морзе приведена ниже:
А .- Б -… В .— Г —.
Д -.. Е . Ж …- З —..
И .. Й .— К -.- Л .-..
М — Н -. О — П .—.
Р .-. С … Т — У ..-
Ф ..-. Х …. Ц -.-. Ч —.
Ш —- Щ —.- Ъ -..- Ы -.—
Ь -..- Э ..-. Ю ..— Я .-.-
3. Содержание отчета
1. Разобрать работу программы 1. Записать в отчет данные, выводимые на экран.
2. Разобрать работу программы 2. Записать в отчет данные, выводимые на экран.
3. Описать результаты изменения в программах 1 и 2.
4. Занести в отчет тексты программ индивидуального задания.
4. Вопросы по лабораторной работе
1. Что такое указатель? Роль указателя в программе.
2. Как определяется указатель? Как присвоить ему адрес переменной, массива?
3. Как обратиться к переменной через указатель?
4. Операции над указателями.
5. Передача адреса переменной в функцию.
6. Передача адреса массива в функцию.
7. Что такое символьная строка.
8. Как определить в программе строковую константу?
9. Как ввести строку с клавиатуры, массив строк?
10. Как передать строку в функцию?
11. Что такое «рваный» массив строк?
12. Как вернуть из функции адрес строки?
13. Библиотечные функции работы со строками.
ПРИЛОЖЕHИЕ.
1. Указатель – это переменная, значением которой является адрес некоторой величины.
При определении указателя, мы описываем, на какой тип переменной она будет указывать, и что это указатель символ *.
int* ptr;
float* pmas;
char* pc;
Присваивается адрес:
int *ptr;
int x = 5;
ptr = &x;
Для доступа к переменной, адрес которой помещен в ptr, используется операция косвенной адресации.
int val=*ptr; //val=x
*ptr = 10; //x=10
В функцию можно передавать не только значения переменных, но и их адреса. В этом случае в вызываемой функции можно изменять значение локальных переменных, определенных в вызывающей функции.
void swap(int*,int*);
void main()
{
int x=5, y=10;
printf («Первичные значения х=%d, y=%d\n»,x, y);
swap (&x, &y);
printf («Новые значения х=%d, y=%d\n», x, y);
}
void swap (int*v, int*z)
{
int u;
u=*v;
*v=*z; //x=y
*z=u;
}
Переменные х, y являются локальными в функции main, но мы таким образом можем на них воздействовать в другой функции.
2. Указатели позволяют эффективно работать с массивами. Обозначение массива представляет собой скрытую форму указателя.
mas -> &mas[0]; — определяется адрес 1-го элемента массива. Оба выражения являются константными выражениями и не меняются на протяжении работы программы. Их можно присваивать переменной типа указатель.
int *ptm = mas;
При работе с двумерными массивами
int mas[2][2], *pti;
pti=mas[0]; //pti=&mas[0][0]
pti+1<=>&mas[0][1]; //так как элементы массива расположены в
pti+2<=>&mas[1][0]; //памяти последовательно и сначала
//меняется второй индекс.
mas[0]<=> &mas[0][0];
mas[1] <=>&mas[1][0]; //Это важное свойство, потому что можно
//работать с 2-м массивом как с одномерным.
Передавать одномерный массив функцию можно следующим образом:
sum(mas);
void sum (int year[]) {} Описатель int year[] — создает указатель на массив mas.
Можно по другому.
void sum (int*pm) {}.
pm+3<=>year[3] <=> mas[3] одно и тоже pm[3].
int* pm и int pm[]; — одно и тоже
3. Строки определяются в программе как символьные массивы. Символы+’\0′ записыватся в последовательные ячейки памяти.
char mas[] = «Это одна строка»;
mas — адрес строки -> &m[0] *mas==’Э’.
Можно использовать указатель для создания строки.
char *str = «Таблица результатов»;
char str[]= «Таблица результатов».
Сама строка размещается в области данных, а указатель инициализируется адресом.
Если требуется несколько строк, то организуем двумерный массив
char mas[4][81];
4. Строки в символьный массив можно вводить с клавиатуры.
char mas[80];
scanf(«%S»,mas);
5. Если требуется несколько строк, то организуем цикл ввода
char mas[4][81];
for (i=0; i<4; i++)
sсanf(«%S», mas[i]); // &mas[i][0]
6. Указатель можно передавать в функцию в качестве аргумента и возвращать из функции.
#include<string.h>
char* strcopy(char*, char*);
void main()
{
char target [24];
char* cptr;
cptr=strcpy (target, «Персональная»); //target+12
cptr=strcpy (cptr, «IBM»); //target+16
}
char* strcpy (char*tptr, char*cptr)
{
while (*tptr++=*cptr++); // while (*cptr!=’\0′)
// *tptr++=*cptr++;
return (tptr);
}
7. Библиотечные функции, работающие со строками:
Функции, определеные в заголовочном файле stdio.h.
1. Функция gets(char *) — вводит строку в массив с клавиатуры
2. Функция puts(char *) — выводит строку на экран
3. Функция int getc(stdin) – вводит символ в переменную с клавиатуры.
4. Функция int putc(int c, stdout) – выводит символ на экран.
Функции, определеные в заголовочном файле string.h.
1. int strlen(char *) — опредляет длинну строки без’\0′;
2. char * strcat(char *, char *) — объединяет две строки в одну.
3. char * strncat(char *, char *,int) — объединяет 1-ю строку и n-байтов второй строки в одну.
4. int strcmp(char *, char *) — сравнение строк.
Функция возвращает 0, если строки одинаковы. Сравнение идёт до признака конца строки — ‘\0’, а не до конца массива, или до первого несравнения:
5. int strncmp(char *, char *,int) — сравнение n байт у 2-х строк .
6. char * strcpy(char *, char *) — копирование строк
7. char * strтcpy(char *, char *,int) — копирование n байт строки
8. char *strdup(char *) – выделяет память и копирует строку.
9. char *strupr(char *) – преобразует строчные буквы в прописные.
10. char *strlwr(char *) – преобразует прописные буквы в строчные.
11. char *strrev(char *) – реверсирует строку.
12. char *strchr(char *, int ) – устанавливает позицию первого вхождения символа
14. char *strrchr(char *, int c) – устанавливает позицию последнего вхождения символа с.
15. char *strstr(char *, char *) — устанавливает позицию первого вхождения подстроки str2 в строку str1.
16. int stricmp(char *, char *) – сравнивает не различая строчные и прописные буквы.
Преобразование символьных строк
Функции, определеные в заголовочном файле stdlib.h.
1. int atoi() — строку в целое.
2. double atof() — строку в число с плавающей точкой.
3. itoa(int val, char *str, int radix) — целое в строку, где
int val – число;
char *str – строка;
int radix – система счисления.
4. ltoa(long val, char *str, int radix) — с плавающей точкой в строку.
Функции, определеные в заголовочном файле ctype.h.
Выполняют преобразования только с буквами английского алфавита.
1. Преобразование строчной буквы в прописную — int toupper(int c)
2. Проверка буква прописная или нет — int isupper(int c)
3. Преобразование прописной буквы в строчную — int tolower(int c)
4. Проверка буква строчная или нет — int islower(int c)
