Приклад проекту з декількох файлів
Напишемо тепер програму, що складається з двох вихідних файлів і одного заголовного. Для цього візьмемо наш калькулятор і переробимо його. Тепер після введення першого числа треба відразу вводити дію. Якщо дія оперує тільки з одним числом (як у випадку синуса, косинуса, тангенса, квадратного кореня), результат відразу буде виведений. Якщо знадобиться друге число, воно буде спеціально запитуватися.
Створимо каталог проекту kalkul2. У ньому створимо три файли: calculate.h, calculate.c, main.c.
Файл calculate.h:
///////////////////////////////////////
// calculate.h
#ifndef CALCULATE_H_
#define CALCULATE_H_
float Calculate(float Numeral, char Operation[4]);
#endif /*CALCULATE_H_*/
Файл calculate.c:
////////////////////////////////////
// calculate.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "calculate.h"
float Calculate(float Numeral, char Operation[4])
{
float SecondNumeral;
if(strncmp(Operation, "+", 1) == 0)
{
printf("Второе слагаемое: ");
scanf("%f",&SecondNumeral);
return(Numeral + SecondNumeral);
}
else if(strncmp(Operation, "-", 1) == 0)
{
printf("Від’ємник: ");
scanf("%f",&SecondNumeral);
return(Numeral - SecondNumeral);
}
else if(strncmp(Operation, "*", 1) == 0)
{
printf("Множник: ");
scanf("%f",&SecondNumeral);
return(Numeral * SecondNumeral);
}
else if(strncmp(Operation, "/", 1) == 0)
{
printf("Дільник: ");
scanf("%f",&SecondNumeral);
if(SecondNumeral == 0)
{
printf("Помилка: ділення на нуль! ");
return(HUGE_VAL);
}
else
return(Numeral / SecondNumeral);
}
else if(strncmp(Operation, "pow", 3) == 0)
{
printf("Степень: ");
scanf("%f",&SecondNumeral);
return(pow(Numeral, SecondNumeral));
}
else if(strncmp(Operation, "sqrt", 4) == 0)
return(sqrt(Numeral));
else if(strncmp(Operation, "sin", 3) == 0)
return(sin(Numeral));
else if(strncmp(Operation, "cos", 3) == 0)
return(cos(Numeral));
else if(strncmp(Operation, "tan", 3) == 0)
return(tan(Numeral));
else
{
printf("Неправильно введена дія ");
return(HUGE_VAL);
}
}
Файл main.c:
////////////////////////////////////////
// main.c
#include <stdio.h>
#include "calculate.h"
int main(void)
{
float Numeral;
char Operation[4];
float Result;
printf("Число: ");
scanf("%f",&Numeral);
printf("Арифметична дія (+,-,*,/,pow,sqrt,sin,cos,tan): ");
scanf("%s",&Operation);
Result = Calculate(Numeral, Operation);
printf("%6.2f\n",Result);
return 0;
}
У нас є два файли вихідного коду (c-файли) і один заголовний (h-файл). Заголовний включається в обидва c-файли. Скомпілюємо calculate.c.
gcc -c calculate.c
Отримали calculate.o. Потім main.c.
gcc -c main.c
І ось він main.o перед нами! Тепер, як вам вже, напевно, підказує інтуїція, треба з цих двох об'єктних файлів зробити виконавчий.
gcc calculate.o main.o -o kalkul
Але, замість виконавчого файлу, в консолі з'явилось повідомлення не зрозумілого змісту:
calculate.o(.text+0x1b5): In function `Calculate':
calculate.c: undefined reference to `pow'
calculate.o(.text+0x21e):calculate.c: undefined reference to `sqrt'
calculate.o(.text+0x274):calculate.c: undefined reference to `sin'
calculate.o(.text+0x2c4):calculate.c: undefined reference to `cos'
calculate.o(.text+0x311):calculate.c: undefined reference to `tan'
collect2: ld returned 1 exit status
Undefined reference означає посилання на функцію, яка не визначена. В даному випадку gcc не знайшов визначення функцій pow, sqrt, sin, cos, tan. Де ж їх знайти? Як вже говорилося раніше, визначення функцій можуть перебувати в бібліотеках. Це скомпільовані виконавчі файли, що містять колекції однотипних операцій, які часто викликаються з багатьох програм, а тому немає сенсу багаторазово писати їх код в програмах. Стандартне розташування файлів бібліотек - каталоги / usr / lib і / usr / local / lib (при бажанні можна додати шлях). Якщо бібліотечний файл має розширення .a, то це статична бібліотека, тобто при компонуванні весь її двійковий код включається в виконуваний файл. Якщо розширення .so, то це динамічна бібліотека. Це означає, що в виконуваний файл програми поміщається тільки посилання на бібліотечний файл, а вже з нього і запускається функція. Коли ми писали програму hello, ми використовували функцію printf для виведення текстового рядка. Однак, як ви пам'ятаєте, ми ніде не писали визначення цієї функції. Звідки ж вона тоді викликається? Просто при компонуванні будь-якої програми компілятор gcc за замовчуванням включає в файл, що запускається бібліотеку libc. Це стандартна бібліотека мови C. Вона містить функції, необхідні абсолютно у всіх програмах, написаних на C, в тому числі і функцію printf. Оскільки бібліотека libc потрібна у всіх програмах, вона включається за замовчуванням, без необхідності давати окремі вказівки на її включення. Решту бібліотек треба включати явно. Адже не можна ж у всі програми поміщати абсолютно всі бібліотеки. Тоді виконуваний файл роздується до надто великих розмірів. Одним програмам потрібні одні функції, іншим - інші. Навіщо ж засмічувати їх непотрібним кодом! Хай залишається тільки те, що реально необхідно. Нам в даному випадку потрібна бібліотека libm. Саме вона містить всі основні математичні функції. Вона вимагає включення в текст програми заголовка <math.h>.
Крім цього дистрибутиви Linux містять і інші бібліотеки, наприклад:
libGL – виводить тривимірну графіку в стандарті OpenGL. Необхідний заголовний файл <GL /gl.h>.
libcrypt – криптографічні функції. Потрібний заголовний файл <crypt.h>.
libcurses – псевдографіка в символьному режимі. Потрібний заголовний файл <curses.h>.
libform – створення екранних форм в текстовому режимі. Заголовний файл <form.h>.
libgthread – підтримка багатопотокового режиму. Заголовний файл <glib.h>.
libgtk – графічна бібліотека в режимі X Window. Заголовний файл <gtk / gtk.h>.
libhistory – робота з журналами. Заголовний файл <readline / readline.h>.
libjpeg – робота з зображенням у форматі JPEG. Заголовний файл <jpeglib.h>.
libncurses – робота з псевдографікою в символьному режимі. Заголовний файл <ncurses.h>. libpng – робота з графікою у форматі PNG. Заголовний файл <png.h>.
libpthread – багато поточна бібліотека POSIX. Стандартна багато поточна бібліотека для inux. Заголовний файл <pthread.h>.
libreadline – робота з командним рядком. Заголовний файл <readline / readline.h>.
libtiff – робота з графікою у форматі TIFF. Заголовний файл <tiffio.h>.
libvga – низькорівнева робота з VGA і SVGA. Заголовний файл <vga.h>.
А також багато-багато інших. Зверніть увагу, що назви всіх цих бібліотек починаються з буквосполучення lib-. Для їх явного включення в виконуваний файл, потрібно додати до команди gcc опцію -l, до якої додати назву бібліотеки без lib-. Наприклад, щоб включити бібліотеку libvga треба вказати опцію -lvga.
Нам потрібні математичні функції pow, sqrt, sin, cos, tan. Вони, як уже було сказано, знаходяться в математичній бібліотеці libm. Отже, щоб підключити цю бібліотеку, ми повинні вказати опцію -lm.
gcc calculate.o main.o -o kalkul –lm
Наш виконавчий файл створений.
Дата добавления: 2015-04-03; просмотров: 702;