WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 |   ...   | 10 | 11 || 13 |

ar r libmy1.a *.o Параметр r позволяет вставить файлы в архив, если архива нет, то он создается. Далее указывается имя архива, после чего перечисляются файлы, из которых архив создается.

Объектные файлы нам не нужны, поэтому их можно удалить:

rm *.o В итоге содержимое каталога library должно выглядеть так:

libmy1.a mylib.h source, где libmy1.a — это статическая библиотека.

Создание динамической библиотеки Объектные файлы для динамической библиотеки компилируются особым образом. Они должны содержать так называемый позиционно-независимый код (position independent code).

Наличие такого кода позволяет библиотеке подключаться к программе, когда последняя загружается в память. Это связано с тем, что библиотека и программа не являются единой программой, а значит как угодно могут располагаться в памяти относительно друг друга.

Компиляция объектных файлов для динамической библиотеки должна выполняться с опцией -fPIC компилятора gcc:

gcc -c -fPIC source/*.c В отличие от статической библиотеки динамическую создают при помощи gcc указав опцию -shared:

gcc -shared -o libmy2.so *.o Использованные объектные файлы можно удалить:

rm *.o В итоге содержимое каталога library:

libmy1.a libmy2.so mylib.h source Использование библиотеки в программе Исходный код программы Теперь в каталоге project (который у нас находится на одном уровне файловой иерархии с library) создадим файлы проекта, который будет использовать созданную библиотеку.

Поскольку сама программа будет состоять не из одного файла, то придется здесь также создать заголовочный файл.

Файл data.c:

#include #include "../library/mylib.h" void data (void) { char strs[3][30];

char *prompts[3] = {"Ваше имя: ", "Местонахождение: ", "Пунк прибытия:

"};

int i;

for (i=0; i<3; i++) { printf("%s", prompts[i]);

gets(strs[i]);

} diagonals('~', 7);

for (i=0; i<3; i++) { printf("%s", prompts[i]);

text(strs[i]);

} } Функция data() запрашивает у пользователя данные, помещая их в массив strs. Далее вызывает библиотечную функцию diagonals(), которая выводит на экране "крестик".

После этого на каждой итерации цикла вызывается библиотечная функция text(), которой передается очередной элемент массива; функция text() выводит на экране звездочки в количестве равному длине переданной через указатель строки.

Обратите внимание на то, как подключается заголовочный файл библиотеки: через относительный адрес. Две точки обозначают переход в каталог на уровень выше, т.е.

родительский по отношению к project, после чего путь продолжается во вложенный в родительский каталог library. Можно было бы указать абсолютный путь, например, "/home/sv/c/les_21/library/mylib.h". Однако при перемещении каталогов библиотеки и программы на другой компьютер или в другой каталог адрес был бы уже не верным. В случае с относительным адресом требуется лишь сохранять расположение каталогов project и library относительно друг друга.

Файл main.c:

#include #include "../library/mylib.h" #include "project.h" main () { rect('-',75,4);

data();

rect('+',75,3);

} Здесь два раза вызывается библиотечная функция rect() и один раз функция data() из другого файла проекта. Чтобы сообщить функции main() прототип data() также подключается заголовочный файл проекта.

Файл project.h содержит всего одну строчку:

void data (void);

Из обоих файлов проекта с исходным кодом надо получить объектные файлы для объединения их потом с файлом библиотеки. Сначала мы получим исполняемый файл, содержащий статическую библиотеку, потом — связанный с динамической библиотекой.

Однако с какой бы библиотекой мы не компоновали объектные файлы проекта, компилируются они как для статической, так и динамической библиотеки одинаково:

gcc -c *.c При этом не забудьте сделать каталог project текущим! Компиляция проекта со статической библиотекой Теперь в каталоге project есть два объектных файла: main.o и data.o. Их надо скомпилировать в исполняемый файл project, объединив со статической библиотекой libmy1.a. Делается это с помощью такой команды:

gcc -o project *.o -L../library -lmyНачало команды должно быть понятно: опция -o указывает на то, что компилируется исполняемый файл project из объектных файлов.

Помимо объектных файлов проекта в компиляции участвует и библиотека. Об этом свидетельствует вторая часть команды: -L../library -lmy1. Здесь опция -L указывает на адрес каталога, где находится библиотека, он и следует сразу за ней. После опции -l записывается имя библиотеки, при этом префикс lib и суффикс (неважно.a или.so) усекаются. Обратите внимание, что после данных опций пробел не ставится.

Опцию -L можно не указывать, если библиотека располагается в стандартных для данной системы каталогах для библиотек. Например, в GNU/Linux это /lib/, /urs/lib/ и др.

Запустив исполняемый файл project и выполнив программу, мы увидим на экране примерно следующее:

Посмотрим размер файла project:

sv@seven:~/c/les_21/project$ ls -l project -rwxrwxr-x 1 sv sv 8698 2012-04-03 10:21 project Его размер равен 8698 байт.

Компиляция проекта с динамической библиотекой Теперь удалим исполняемый файл и получим его уже связанным с динамической библиотекой. Команда компиляции с динамической библиотекой выглядит так:

gcc -o project *.o -L../library -lmy2 -Wl,-rpath,../library/ Здесь в отличии от команды компиляции со статической библиотеки добавлены опции для линковщика: -Wl,-rpath,../library/. -Wl - это обращение к линковщику, -rpath - опция линковщика,../library/ - значение опции. Получается, что в команде мы два раза указываем местоположение библиотеки: один раз с опцией -L, а второй раз с опцией -rpath. Видимо для того, чтобы понять, почему так следует делать, потребуется более основательно изучить процесс компиляции и компоновки программ на языке C.



Следует заметить, что если вы скомпилируете программу, используя приведенную команду, то исполняемый файл будет запускаться из командной строки только в том случае, если текущий каталог project. Стоит сменить каталог, будет возникать ошибка из-за того, что динамическая библиотека не будет найдена. Но если скомпилировать программу так:

gcc -o project *.o -L../library -lmy2 -Wl,-rpath,/home/sv/c/les_21/library, т.е. указать для линковщика абсолютный адрес, то программа в данной системе будет запускаться из любого каталога.

Размер исполняемого файла проекта, связанного с динамической библиотекой, получился равным 8604 байта. Это немного меньше, чем при компиляции проекта со статической библиотекой. Если посмотреть на размеры библиотек:

sv@seven:~/c/les_21/library$ ls -l libmy* -rw-rw-r-- 1 sv sv 3624 2012-04-02 10:54 libmy1.a -rwxrwxr-x 1 sv sv 7871 2012-04-02 11:16 libmy2.so, то видно, что динамическая больше статической, хотя исполняемый файл проекта со статической библиотекой больше. Это доказывает, что в исполняемом файле, связанном с динамической библиотекой, присутствует лишь ссылка на нее.

Задание Придумайте и реализуйте проект на языке программирования C, в котором бы использовалась вами же написанная библиотека.

Урок 22. Проверочная работа Выполнение всех задания данного урока предполагает период времени выполнения более чем 1,5 часа. Поэтому если есть ограничения по времени, то оценка работы может выполняться по количеству набранных баллов. Приблизительные баллы указаны в скобках после каждого задания.

1. Напишите программу, предназначенную для наглядной демонстрации различий между такими типами данных как char, short, int, unsigned. (7) 2. Значение какого из ниже представленных массивов совпадает со строкой "Zeitgeist" Почему (1) arrA[9] = {'Z', 'e', 'i', 't', 'g', 'e', 'i', 's', 't'};

arrB[] = {'Z', 'e', 'i', 't', 'g', 'e', 'i', 's', 't', '\0'};

3. Если массив arr содержит строку, то будут ли различаться значения, которые вернут функции sizeof() и strlen() (2) 4. Напишите код, в котором одной переменной присваивается введенное пользователем число, а второй переменной модуль этого числа. После этого значение второй переменной выводится на экран. Используйте условное выражение, а не инструкцию if. (4) 5. Переделайте условное выражение из 4-го задания в макрос. (2) 6. Объявлены и определены целочисленные переменные: a = 10, b = 0, c = -3.

Определите их значения после выполнения следующих двух выражений, а также значения самих выражений: (2) a-- + ++b; --c + b--;

7. Запрограммируйте вывод на экран символов так, как показано на рисунке. Используйте циклы for, а также если необходимо функцию strcat(). (12) 8. Напишите программу, которая определяет в процентном соотношении количество гласных и согласных букв в текстовом файле. Имя файла передается в программу через командную строку. (10) 9. Может ли одна ячейка памяти иметь несколько имен переменных Может ли адрес определенной ячейки памяти содержаться во множестве переменных Ответ поясните. (4) 10. Как изменить приведенную ниже программу так, чтобы среди параметров функции sum() не было указателя, а функция возвращала значение, оставляя тем самым возможность изменить значение любой внешней переменной (3) #include void sum (float *base, float add);

main() { float a=100, b;

scanf("%f", &b);

sum(&a, b);

printf("%.4f\n", a);

} void sum (float *base, float add) { *base = *base + add/2;

} 11. Напишите программу, в которой массив заполняется случайными буквами английского алфавита; значения элементов массива в символьном представлении выводятся на экран.

(4) 12. Напишите функцию, которая принимает указатели на два массива. Функция должна заполнять один массив 25-ю случайными четными числами, а другой — 25 нечетными.

Продемонстрируйте ее работу. (6) 13. Пользователь вводит две строки, каждая строка состоит из двух слов, разделенных пробелом. Требуется сравнить строки лексикографически, начиная со второго слова (т.е.

после пробела). Напишите программу, выполняющую описанную задачу. (6) 14. Пользователь вводит адреса сайтов и их ТИЦ. Данные о каждом сайте сохраняются в элементе динамической структуры. По команде пользователя данные записываются в файл, при этом память, выделенная под динамическую структуру, высвобождается. Далее пользователь может снова начать вводить информацию о сайтах, либо завершить выполнение программы. (25) Примерные решения задач Урок 1. Типы данных и их вывод Напишите программу, которая выводила бы на экране данные примерно так, как на картинке.

При этом используйте возможность задать ширину поля, а также выравнивание по левому и правому краям.

#include main() { printf("\n |%d|\n", 555);

printf(" |%10d|\n", 555);

printf(" |%-10d|\n\n", 555);

printf(" %-10s %7d\n", "Words:", 59);

printf(" %-10s %7d\n", "Letters:", 1004);

printf(" %-10s %7d\n\n", "Digits:", 8);

} Напишите программу, выводящую информацию о количестве байтов, отводимых в памяти под типы данных, которые были изучены на данном уроке.

#include main() { printf("\n%21s: %3lu\n", "Integer", sizeof(int));





printf("%21s: %3lu\n", "Unsigned", sizeof(unsigned));

printf("%21s: %3lu\n", "Shot", sizeof(short));

printf("%21s: %3lu\n", "Unsigned short", sizeof(unsigned short));

printf("%21s: %3lu\n", "Long", sizeof(long));

printf("%21s: %3lu\n", "Unsigned long", sizeof(unsigned long));

printf("%21s: %3lu\n", "Char", sizeof(char));

printf("%21s: %3lu\n", "Float", sizeof(float));

printf("%21s: %3lu\n", "Double", sizeof(double));

printf("%21s: %3lu\n", "Long double", sizeof(long double));

int c[10];

printf("%21s: %3lu\n", "Array of 10 integers", sizeof(c));

printf("%21s: %3lu\n\n", "String ", sizeof("Hello"));

} Урок 2. Символьный тип данных. Специальные символы Напишите программу, в которой объявлены только две переменные символьного типа. Одной переменной присвоен, например, символ '4', а второй — '7'. Функция printf() должна выводить на экран разность и сумму чисел, которые были представлены символами и присвоены переменным.

#include main() { char a='4', b='7';

printf("%d\n", '7' - '4');

printf("%d\n", ('7'-'0') + ('4' – '0'));

} Переменная not_num содержит строку из трех символов-цифр, например "528". Необходимо получить из этой строки соответствующее ему число и присвоить его переменной num.

Вывести на экран результат выражения num – 10. (Подсказка: строка — это массив символов, следовательно, вы можете извлекать символы цифр по их индексам; при вычислении числа первый символ массива, преобразованный в число, будет означать количество сотен, второй — десятков, а третий — единиц.) #include main() { char not_num[] = "567";

int num;

num = (not_num[0] - '0') * 100 + (not_num[1] - '0') * 10 + (not_num[2] - '0');

printf("%d\n", num - 10);

} Известно, что символ A английского алфавита имеет код 65. Напишите программу, определяющую какие символы в этом алфавите стоят на 5, 12 и 19 местах.

printf("%c, %c, %c\n", 'A' + 4, 'A' + 11, 'A' + 18);

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

printf("\\n - %d\n", '\n');

printf("\\t - %d\n", '\t');

printf("\\b - %d\n", '\b');

printf("\\r - %d\n", '\r');

Урок 4. Циклы в языке C Присвойте переменной star значение 0. Пока значение star не достигнет 55 выводите на экран в строку по одной звездочке (*).

int star=0;

while (star < 55) { printf("*");

star += 1;

} printf("\n");

С помощью цикла while запрограммируйте вывод на экран цифровых кодов и значений таблицы символов ASCII от 31 до 127 включительно. При этом после каждого десятого символа осуществляйте переход на новую строку.

unsigned char a;

printf("\n");

a = 31;

while (a < 128) { printf("%4d-%c", a, a);

if (a % 10 == 0) printf("\n");

a = a + 1;

} printf("\n");

Используя внешний и вложенный циклы while организуйте вывод таблицы умножения на экран.

printf("\n");

i = 1;

while (i < 10) { j = 1;

while (j < 10) { printf("%4d", i*j);

j++;

} printf("\n");

i++;

} printf("\n");

Напишите программу с использованием цикла for, выводящую на экран таблицу умножения.

int i, j;

printf("\n");

for (i = 1; i < 10; i++) { for (j = 1; j < 10; j++) printf("%4d", i*j);

printf("\n");

} printf("\n");

Урок 6. Посимвольный ввод и вывод. Понятие буфера Напишите программу, которая считает количество введенных пользователем символов и строк.

Напишите программу, которая подсчитывает количество слов в строке.

#include main() { char ch, flag=-1;

unsigned c=0, n=0, w=0;

while ((ch = getchar()) != EOF) { if (ch == '\n') n++; // строки else c++; // символы if (ch == ' ' || ch == '\n') flag = -1; // слова else if (flag == -1) { flag = 1;

w++;

} } printf("%u %u %u\n", c, n, w);

} Урок 8. Функции. Передача аргументов по значению и по ссылке Напишите программу, в которой помимо функции main() были бы еще две функции: в одной вычислялся факториал переданного числа, в другой — находился n-ый элемент ряда Фибоначчи (n — параметр функции). Вызовите эти функции с разными аргументами.

#include unsigned fibonachi (unsigned num);

unsigned long factorial (unsigned n);

main () { unsigned long result;

result = fibonachi(10);

printf("Значение 10-го элемента ряда Фибоначчи равно %lu\n", result);

result = fibonachi(25);

printf("Значение 25-го элемента ряда Фибоначчи равно %lu\n", result);

result = factorial(5);

printf("5! = %lu\n", result);

result = factorial(12);

printf("12! = %lu\n", result);

} unsigned fibonachi (unsigned num) { unsigned i=1, a=0, b=1, s;

while (i++ < num-1) { s = a;

a = b;

b = s+a;

} return b;

} unsigned long factorial (unsigned n) { unsigned long fact=1;

while (n > 0) fact = fact * n--;

return fact;

} Урок 9. Форматированный ввод данных Напишите программу, которая запрашивает у пользователя две даты в формате дд.мм.гггг.

Дни, месяцы и года следует присвоить целочисленным переменным. Программа должна выводить на экран информацию о том, какая дата более ранняя, а какая более поздняя.

#include main() { int dd1, dd2, mm1, mm2, yy1, yy2;

int i;

printf("Enter first date (dd.mm.yyyy): ");

scanf("%d.%d.%d", &dd1, &mm1, &yy1);

printf("Enter second date (dd.mm.yyyy): ");

Pages:     | 1 |   ...   | 10 | 11 || 13 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.