multiple definition of












1















Сделал вроде все нормально, но вот ругается



В проекте 4е файла:



main.c



/*

Программу подготовил: Буренков Игорь (М8О-206Б-17)

Вариант: АВЛ-дерево

*/
/////////////////////////////////////////////////////////

/* Системные библиотеки */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>

/* Пользовательские библиотеки */
#include "AVL_tree_slimrg.h"
#include "settings_slimrg.h"

/* Структуры */


/* Сигнатуры функций */
unsigned short int InputFiller(); // Ввод и исполнение комманд
void PrintError(unsigned short int ErrorCode); // Вывод ошибок



/* Основной цикл */
int main(){

// Переменные
unsigned short int log_error; // Код ошибки

// Считываем и выполняем команды
log_error = InputFiller();

// Выввод ошибки
PrintError(log_error);

// Пауза при закрытии
if (debug_pauseonclose) system("pause");

// Все ОК
return 0;
}

// Цикл ввода и выполнения
unsigned short int InputFiller(){

// Переменные
char tmpchar[StringLengthPS+1]; // Временный контейнер для символа
char tmpword[StringLengthPS+1]; // Временный контейнер для слова (массива символов)
unsigned long long int tmpkey; // Временный контейнер для ключа
unsigned char errorcode; // Код ошибки
unsigned int i; // Тикер (для циклов и т.д.)

// Создание пустого дерева
struct avltree* AVLTree1 = AVL_Create();

// Пока возможно - считываем первый символ строки
while (scanf("%s", tmpchar) >= 1){
// Перевод в нижний регистр
tmpchar[0] = tolower(tmpchar[0]);
// Определение комманды
switch (tmpchar[0]) {

// Добавить слово
case '+':
// Считываем слово
scanf("%s", tmpword);
// Преобразование в нижний регистр
for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
// Считывание ключа
scanf("%llu", &tmpkey);
// Довавляем лист (с включенным выводом)
AVL_InsertLeaf(tmpword, tmpkey, AVLTree1, true);
break;

// Отладочные комманды
case '!':
// Считываем слово
scanf("%s", tmpword);
// Перевод в нижний регистр
for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
// Распознание слова
if (strcmp(tmpword, "exit") == 0) {
return 0;
} else
if (strcmp(tmpword, "print") == 0) {
AVL_PrintMe(AVLTree1);
} else
if (strcmp(tmpword, "save") == 0) {
AVL_SaveTree(AVLTree1, true);
} else
if (strcmp(tmpword, "load") == 0) {
AVL_LoadTree(AVLTree1, true);
}
break;
// Удаление слова
case '-':
// Считываем слово
scanf("%s", tmpword);
// Преобразование в нижний регистр
for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
// Удаляем лист
AVL_RemoveLeaf(tmpword, AVLTree1, true);
break;
// Заглушка
case 'n':
break;
// Осталось слово
default:
for (i = 0; i < StringLengthPS; i++) tmpchar[i] = tolower(tmpchar[i]);
// Поиск
tmpkey = AVL_FindMe_p(tmpchar, AVLTree1, true);
break;


}
}
return 0;
}

// Печать ошибок
void PrintError(unsigned short int ErrorCode){
}


AVL_tree_slimrg.h



#ifndef AVL_tree_slimrg_h
#define AVL_tree_slimrg_h

// Стандартные заголовки
#include <stdbool.h>
#include <string.h>

// Настройки
#include "settings_slimrg.h"

// Сама структура
struct avltree;

// Создание дерева
struct avltree* AVL_Create();

// Уничтожение дерева
void AVL_FreeAndNil(struct avltree* AVL_Tree);

// Проверка на пустоту
bool AVL_IsEmpty(struct avltree* AVL_Tree);

// Добавить лист
void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVL_Tree, bool PrintStatus);

// Удаление листа по значению
void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

// Поиск значения
bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree);
unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

// Печать дерева
void AVL_PrintMe(struct avltree* AVL_Tree);

// Сохранение дерева
void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus);

// Загрузка дерева
void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus);


#endif


AVL_tree_slimrg.c



#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "AVL_tree_slimrg.h"

// Структура строки
struct String{
char* Text;
unsigned short int count;
};

// Структура листа
struct avlleaf {
struct String key; // Ключ
unsigned long long int llupar; // Значение
long int height; // Высота
struct avlleaf* left; // Левый ребенок
struct avlleaf* right; // Правый ребенок
};

// Структура дерева
struct avltree {
struct avlleaf* root;
};

// Создание дерева
struct avltree* AVL_Create() {
struct avltree* AVL_Tree = malloc(sizeof(struct avltree));
AVL_Tree->root = NULL;
return AVL_Tree;
}

// Уничтожение дерева
void AVL_FreeAndNil(struct avltree* AVL_Tree) {
// Переменные
char tmpword[StringLengthPS+1];
unsigned short int i; // Тикер (для циклов и т.д.)

// Запускаем балалайку ^_^
while (AVL_IsEmpty(AVL_Tree) == false) {
for (i = 0; i <= AVL_Tree->root->key.count; i++) {
tmpword[i] = AVL_Tree->root->key.Text[i];
}
AVL_RemoveLeaf(tmpword, AVL_Tree, false);
}
}

// Проверка на пустоту
bool AVL_IsEmpty(struct avltree* AVL_Tree) {
return (AVL_Tree->root == NULL);
}

// Инициализация листа
struct avlleaf* AVLLeaf_Create(char inputkey[StringLengthPS+1], unsigned long long int llupar) {

// Переменные
struct avlleaf* keim; // Лист
unsigned short int i; // Тикер (для циклов и т.д.)


// Начальная инициализация
keim = malloc(sizeof(struct avlleaf));
keim->right = keim->left = NULL;
keim->llupar = llupar;

// Сложная инициализация
i = 0;
while (inputkey[i] != 0) i++;
keim->key.count = i;
keim->key.Text = malloc(keim->key.count * sizeof(char));
for (i = 0; i <= keim->key.count; i++) {
keim->key.Text[i] = inputkey[i];
}

keim->height = 0;
return keim;
}

// Получение высоты листа
long int AVLLeaf_GetHeight(struct avlleaf* Leaf) {
if (Leaf == NULL) return (-1); else return Leaf->height;
}

// Получение коэффицента балансировки
char AVLLeaf_GetBalance(struct avlleaf* Leaf) {
return (AVLLeaf_GetHeight(Leaf->right) - AVLLeaf_GetHeight(Leaf->left));
}

// Проверка высоты
void AVLLeaf_CheckHeight(struct avlleaf* Leaf) {

// Переменные
long int left, right; // Дети листа Leaf

left = AVLLeaf_GetHeight(Leaf->left);
right = AVLLeaf_GetHeight(Leaf->right);

// Высота получается увеличением максимальной детской высоты на единицу
if (left <= right) Leaf->height = right + 1; else Leaf->height = left + 1;
}

// Малое леве вращение (Small Left)
struct avlleaf* AVL_rotation_SL(struct avlleaf* Leaf) {

// Переменные
struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

aor = Leaf->right;

// Магия вращения... (Вжух...)
Leaf->right = aor->left;
aor->left = Leaf;

// Выправляем высоту
AVLLeaf_CheckHeight(Leaf);
AVLLeaf_CheckHeight(aor);

return aor;
}

// Малое правое вращение (Small Right)
struct avlleaf* AVL_rotation_SR(struct avlleaf* Leaf) {

// Переменные
struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

aor = Leaf->left;

// Магия вращения... (Вжух...)
Leaf->left = aor->right;
aor->right = Leaf;

// Выправляем высоту
AVLLeaf_CheckHeight(Leaf);
AVLLeaf_CheckHeight(aor);

return aor;
}

// Ребалансировка дерева
struct avlleaf* AVL_BalanceMe(struct avlleaf* Leaf) {

// Переменные
char balfac; // Коэффицент баласировки (от -2 до +2)


balfac = AVLLeaf_GetBalance(Leaf);

// Оцениваем баланс и выправляем его
if (balfac < -1) {

// Смотрим, требуется ли большое вращение
if (AVLLeaf_GetBalance(Leaf->left) > 0) {
Leaf->left = AVL_rotation_SL(Leaf->left);
}

return (AVL_rotation_SR(Leaf));

} else if (balfac > 1) {

// Смотрим, требуется ли большое вращение
if (AVLLeaf_GetBalance(Leaf->right) < 0) {
Leaf->right = AVL_rotation_SR(Leaf->right);
}

return (AVL_rotation_SL(Leaf));

} else { // Если нуль

// Вращение НЕ требуется
AVLLeaf_CheckHeight(Leaf);

return Leaf;

}
}

// Поиск места вставки и вставка
struct avlleaf* AVL_FindAndInsert(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
// Если поддерево пустое
if (Leaf == NULL) {

if (PrintStatus) printf("OKn");
return AVLLeaf_Create(key, llupar);

} else if (strcmp(key, Leaf->key.Text) < 0) {

Leaf->left = AVL_FindAndInsert(key, llupar, Leaf->left, PrintStatus);

} else if (strcmp(key, Leaf->key.Text) > 0){

Leaf->right = AVL_FindAndInsert(key, llupar, Leaf->right, PrintStatus);

} else {

if (PrintStatus) printf("Existn");

}

return AVL_BalanceMe(Leaf);

}

// Добавление листа (обертка над функцией выше)
void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
AVLTree->root = AVL_FindAndInsert(key, llupar, AVLTree->root, PrintStatus);
}

// Получение минимального значения
struct String AVL_GetMinKey(struct avlleaf* Leaf) {
while (Leaf->left != NULL) Leaf = Leaf->left;
return Leaf->key;
}

// Получение параметра у листа с минимальным значением
unsigned long long int AVL_GetMinVal(struct avlleaf* Leaf) {
while (Leaf->left != NULL) Leaf = Leaf->left;
return Leaf->llupar;
}

// Поиск и удаление
struct avlleaf* AVL_FindAndRemove(char key[StringLengthPS+1], struct avlleaf* Leaf, bool PrintStatus) {

// Переменные
struct avlleaf* child; // Служебная (для случаев с одним ребенком)
char tmpkey[StringLengthPS+1]; // Временный контейнер для ключа
unsigned short int i; // Тикер (для циклов и т.д.)

if (Leaf == NULL) {
// Нет значения для удаления
if (PrintStatus) printf("NoSuchWordn");
return NULL;

} else if (strcmp(key, Leaf->key.Text) < 0) {

Leaf->left = AVL_FindAndRemove(key, Leaf->left, PrintStatus);
return AVL_BalanceMe(Leaf);

} else if (strcmp(key, Leaf->key.Text) > 0) {

Leaf->right = AVL_FindAndRemove(key, Leaf->right, PrintStatus);
return AVL_BalanceMe(Leaf);

} else { // Найдена позиция

if (PrintStatus) printf("OKn");
// Анализ детей и перемещение
if (Leaf->left != NULL && Leaf->right != NULL) {

Leaf->key = AVL_GetMinKey(Leaf->right);
Leaf->llupar = AVL_GetMinVal(Leaf->right);

for (i = 0; i <= Leaf->key.count; i++) {
tmpkey[i] = Leaf->key.Text[i];
}

Leaf->right = AVL_FindAndRemove(tmpkey, Leaf->right, PrintStatus);

return AVL_BalanceMe(Leaf);

} else if (Leaf->left != NULL) {

// Есть только один ребенок (правый)

child = Leaf->left;
Leaf->key.count = 0;
free(Leaf->key.Text);
free(Leaf);
return child;

} else if (Leaf->right != NULL) {

// Есть только один ребенок (левый)

child = Leaf->right;
Leaf->key.count = 0;
free(Leaf->key.Text);
free(Leaf);
return child;

} else {

// Нет дитей - просто выкидываем
Leaf->key.count = 0;
free(Leaf->key.Text);
free(Leaf);
return NULL;

}

}

}

// Удаление из дерева (обертка над функцией выше)
void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus) {
AVL_Tree->root = AVL_FindAndRemove(key, AVL_Tree->root, PrintStatus);
}

// Поиск элемента в дереве
bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree) {

// Переменные
struct avlleaf* CuP;

CuP = AVL_Tree->root;
while (CuP != NULL) {

if (strcmp (key, CuP->key.Text) == 0) {

return true;

} else if (strcmp(key, CuP->key.Text) < 0) {

CuP = CuP->left;

} else {

CuP = CuP->right;

}

}

return false;

}

// Еще один алгоритм поиска (удобнее для пользователя)
unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus){

// Переменные
struct avlleaf* CuP;

CuP = AVL_Tree->root;
while (CuP != NULL) {

if (strcmp (key, CuP->key.Text) == 0) {

if (PrintStatus){
printf("OK: ");
printf("%llu", (CuP->llupar));
printf("n");
}
return CuP->llupar;

} else if (strcmp(key, CuP->key.Text) < 0) {

CuP = CuP->left;

} else {

CuP = CuP->right;

}

}

if (PrintStatus) printf("NoSuchWordn");
return 0;

}

// Печать дерева
void AVL_print_rec(struct avlleaf* Leaf, long int lvl) {

// Переменные
int i;

if (Leaf == NULL) {
return;
}

AVL_print_rec(Leaf->left, lvl + 1);

for (i = 0; i < lvl; i++) printf("t");

printf("%s", Leaf->key.Text);
printf("%c", '|');
printf("%llu", Leaf->llupar);
printf("n");

AVL_print_rec(Leaf->right, lvl + 1);
}

// Печать дерева (обертка над функцией выше)
void AVL_PrintMe(struct avltree* AVL_Tree){
if (AVL_Tree->root == NULL) {
printf("EMPTYn");
} else {
AVL_print_rec(AVL_Tree->root, 0);
}
}

// Запись лист в файл
void AVL_LeafToFile(struct avlleaf* Leaf, FILE * file){
if (Leaf == NULL) return;

fwrite(&(Leaf->key.count), sizeof(unsigned short int), 1, file);
fwrite(Leaf->key.Text, sizeof(char), Leaf->key.count+1, file);
fwrite(&(Leaf->llupar), sizeof(unsigned long long int), 1, file);

AVL_LeafToFile(Leaf->right, file);
AVL_LeafToFile(Leaf->left, file);
}

// Сохранение дерева
void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus){

// Переменные
char adress[1024];
FILE *file = NULL;

// Открытие файла
scanf("%s", adress);
file = fopen(adress, "wb+");
if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't create filen");
if (file == NULL) return;

// Запись дерева
fwrite(&(UnCo), sizeof(unsigned long long int), 1, file);
AVL_LeafToFile(AVL_Tree->root, file);

// Закрытие
if (PrintStatus) printf("OKn");
fclose(file);
}

// Поиск места вставки и вставка
struct avlleaf* AVL_FindAndInsert_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
// Если поддерево пустое
if (Leaf == NULL) {

return AVLLeaf_Create(key, llupar);

} else if (strcmp(key, Leaf->key.Text) < 0) {

Leaf->left = AVL_FindAndInsert_clean(key, llupar, Leaf->left, PrintStatus);

} else if (strcmp(key, Leaf->key.Text) > 0){

Leaf->right = AVL_FindAndInsert_clean(key, llupar, Leaf->right, PrintStatus);

} else {

if (PrintStatus) printf("ERROR: Broken Filen");

}

return Leaf;

}

// Добавление листа (обертка над функцией выше)
void AVL_InsertLeaf_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
AVLTree->root = AVL_FindAndInsert_clean(key, llupar, AVLTree->root, PrintStatus);
}

// Загрузка листа из файла
void AVL_LeafFromFile(struct avltree* AVL_Tree, FILE * file){

// Переменные
char tmpkey[StringLengthPS+1];
unsigned long long int tmpllupar;
unsigned short int charcount;



while (feof(file) == 0){
fread(&charcount, sizeof(unsigned short int), 1, file);
fread(tmpkey, sizeof(char), charcount+1, file);
fread(&tmpllupar, sizeof(unsigned long long int), 1, file);

AVL_InsertLeaf_clean(tmpkey, tmpllupar, AVL_Tree, false);
}
}

// Загрузка дерева
void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus){

// Переменные
char adress[1024];
FILE *file = NULL;
unsigned long long int FileUnCo;

// Открытие файла
scanf("%s", adress);
file = fopen(adress, "rb");
if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't read filen");
if (file == NULL) return;

// Тест совместимости
fread(&FileUnCo, sizeof(unsigned long long int), 1, file);
if (UnCo != FileUnCo){
printf("ERROR: Unsupported filen");
return;
}

// Уничтожаем ранее созданное дерево
AVL_FreeAndNil(AVL_Tree);

// Загружаем новое дерево
AVL_LeafFromFile(AVL_Tree, file);

// Закрытие
if (PrintStatus) printf("OKn");
fclose(file);
}


settings_slimrg.h



#ifndef settings_h
#define settings_h
/* Settings */

// Настройка ввода
const unsigned int StringLengthPS = 256; // Длина строки (в символах)

// Настройка отладки
const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом

// Номер сборки
const unsigned long long int UnCo = 115700744534137162;

#endif


MakeFile



all:
gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare main.c AVL_tree_slimrg.c -lm -o lb2


Лог (здесь main.c заменен на lb2.c)



gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare lb2.c AVL_tree_slimrg.c -lm -o lb2
/tmp/cc4upHwG.o:(.rodata+0x0): multiple definition of `StringLengthPS'
/tmp/ccORqDAb.o:(.rodata+0x0): first defined here
/tmp/cc4upHwG.o:(.rodata+0x4): multiple definition of `debug_pauseonclose'
/tmp/ccORqDAb.o:(.rodata+0x4): first defined here
/tmp/cc4upHwG.o:(.rodata+0x8): multiple definition of `UnCo'
/tmp/ccORqDAb.o:(.rodata+0x8): first defined here
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1









поделиться|улучшить этот вопрос





























    1















    Сделал вроде все нормально, но вот ругается



    В проекте 4е файла:



    main.c



    /*

    Программу подготовил: Буренков Игорь (М8О-206Б-17)

    Вариант: АВЛ-дерево

    */
    /////////////////////////////////////////////////////////

    /* Системные библиотеки */
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <ctype.h>

    /* Пользовательские библиотеки */
    #include "AVL_tree_slimrg.h"
    #include "settings_slimrg.h"

    /* Структуры */


    /* Сигнатуры функций */
    unsigned short int InputFiller(); // Ввод и исполнение комманд
    void PrintError(unsigned short int ErrorCode); // Вывод ошибок



    /* Основной цикл */
    int main(){

    // Переменные
    unsigned short int log_error; // Код ошибки

    // Считываем и выполняем команды
    log_error = InputFiller();

    // Выввод ошибки
    PrintError(log_error);

    // Пауза при закрытии
    if (debug_pauseonclose) system("pause");

    // Все ОК
    return 0;
    }

    // Цикл ввода и выполнения
    unsigned short int InputFiller(){

    // Переменные
    char tmpchar[StringLengthPS+1]; // Временный контейнер для символа
    char tmpword[StringLengthPS+1]; // Временный контейнер для слова (массива символов)
    unsigned long long int tmpkey; // Временный контейнер для ключа
    unsigned char errorcode; // Код ошибки
    unsigned int i; // Тикер (для циклов и т.д.)

    // Создание пустого дерева
    struct avltree* AVLTree1 = AVL_Create();

    // Пока возможно - считываем первый символ строки
    while (scanf("%s", tmpchar) >= 1){
    // Перевод в нижний регистр
    tmpchar[0] = tolower(tmpchar[0]);
    // Определение комманды
    switch (tmpchar[0]) {

    // Добавить слово
    case '+':
    // Считываем слово
    scanf("%s", tmpword);
    // Преобразование в нижний регистр
    for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
    // Считывание ключа
    scanf("%llu", &tmpkey);
    // Довавляем лист (с включенным выводом)
    AVL_InsertLeaf(tmpword, tmpkey, AVLTree1, true);
    break;

    // Отладочные комманды
    case '!':
    // Считываем слово
    scanf("%s", tmpword);
    // Перевод в нижний регистр
    for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
    // Распознание слова
    if (strcmp(tmpword, "exit") == 0) {
    return 0;
    } else
    if (strcmp(tmpword, "print") == 0) {
    AVL_PrintMe(AVLTree1);
    } else
    if (strcmp(tmpword, "save") == 0) {
    AVL_SaveTree(AVLTree1, true);
    } else
    if (strcmp(tmpword, "load") == 0) {
    AVL_LoadTree(AVLTree1, true);
    }
    break;
    // Удаление слова
    case '-':
    // Считываем слово
    scanf("%s", tmpword);
    // Преобразование в нижний регистр
    for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
    // Удаляем лист
    AVL_RemoveLeaf(tmpword, AVLTree1, true);
    break;
    // Заглушка
    case 'n':
    break;
    // Осталось слово
    default:
    for (i = 0; i < StringLengthPS; i++) tmpchar[i] = tolower(tmpchar[i]);
    // Поиск
    tmpkey = AVL_FindMe_p(tmpchar, AVLTree1, true);
    break;


    }
    }
    return 0;
    }

    // Печать ошибок
    void PrintError(unsigned short int ErrorCode){
    }


    AVL_tree_slimrg.h



    #ifndef AVL_tree_slimrg_h
    #define AVL_tree_slimrg_h

    // Стандартные заголовки
    #include <stdbool.h>
    #include <string.h>

    // Настройки
    #include "settings_slimrg.h"

    // Сама структура
    struct avltree;

    // Создание дерева
    struct avltree* AVL_Create();

    // Уничтожение дерева
    void AVL_FreeAndNil(struct avltree* AVL_Tree);

    // Проверка на пустоту
    bool AVL_IsEmpty(struct avltree* AVL_Tree);

    // Добавить лист
    void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVL_Tree, bool PrintStatus);

    // Удаление листа по значению
    void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

    // Поиск значения
    bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree);
    unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

    // Печать дерева
    void AVL_PrintMe(struct avltree* AVL_Tree);

    // Сохранение дерева
    void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus);

    // Загрузка дерева
    void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus);


    #endif


    AVL_tree_slimrg.c



    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>

    #include "AVL_tree_slimrg.h"

    // Структура строки
    struct String{
    char* Text;
    unsigned short int count;
    };

    // Структура листа
    struct avlleaf {
    struct String key; // Ключ
    unsigned long long int llupar; // Значение
    long int height; // Высота
    struct avlleaf* left; // Левый ребенок
    struct avlleaf* right; // Правый ребенок
    };

    // Структура дерева
    struct avltree {
    struct avlleaf* root;
    };

    // Создание дерева
    struct avltree* AVL_Create() {
    struct avltree* AVL_Tree = malloc(sizeof(struct avltree));
    AVL_Tree->root = NULL;
    return AVL_Tree;
    }

    // Уничтожение дерева
    void AVL_FreeAndNil(struct avltree* AVL_Tree) {
    // Переменные
    char tmpword[StringLengthPS+1];
    unsigned short int i; // Тикер (для циклов и т.д.)

    // Запускаем балалайку ^_^
    while (AVL_IsEmpty(AVL_Tree) == false) {
    for (i = 0; i <= AVL_Tree->root->key.count; i++) {
    tmpword[i] = AVL_Tree->root->key.Text[i];
    }
    AVL_RemoveLeaf(tmpword, AVL_Tree, false);
    }
    }

    // Проверка на пустоту
    bool AVL_IsEmpty(struct avltree* AVL_Tree) {
    return (AVL_Tree->root == NULL);
    }

    // Инициализация листа
    struct avlleaf* AVLLeaf_Create(char inputkey[StringLengthPS+1], unsigned long long int llupar) {

    // Переменные
    struct avlleaf* keim; // Лист
    unsigned short int i; // Тикер (для циклов и т.д.)


    // Начальная инициализация
    keim = malloc(sizeof(struct avlleaf));
    keim->right = keim->left = NULL;
    keim->llupar = llupar;

    // Сложная инициализация
    i = 0;
    while (inputkey[i] != 0) i++;
    keim->key.count = i;
    keim->key.Text = malloc(keim->key.count * sizeof(char));
    for (i = 0; i <= keim->key.count; i++) {
    keim->key.Text[i] = inputkey[i];
    }

    keim->height = 0;
    return keim;
    }

    // Получение высоты листа
    long int AVLLeaf_GetHeight(struct avlleaf* Leaf) {
    if (Leaf == NULL) return (-1); else return Leaf->height;
    }

    // Получение коэффицента балансировки
    char AVLLeaf_GetBalance(struct avlleaf* Leaf) {
    return (AVLLeaf_GetHeight(Leaf->right) - AVLLeaf_GetHeight(Leaf->left));
    }

    // Проверка высоты
    void AVLLeaf_CheckHeight(struct avlleaf* Leaf) {

    // Переменные
    long int left, right; // Дети листа Leaf

    left = AVLLeaf_GetHeight(Leaf->left);
    right = AVLLeaf_GetHeight(Leaf->right);

    // Высота получается увеличением максимальной детской высоты на единицу
    if (left <= right) Leaf->height = right + 1; else Leaf->height = left + 1;
    }

    // Малое леве вращение (Small Left)
    struct avlleaf* AVL_rotation_SL(struct avlleaf* Leaf) {

    // Переменные
    struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

    aor = Leaf->right;

    // Магия вращения... (Вжух...)
    Leaf->right = aor->left;
    aor->left = Leaf;

    // Выправляем высоту
    AVLLeaf_CheckHeight(Leaf);
    AVLLeaf_CheckHeight(aor);

    return aor;
    }

    // Малое правое вращение (Small Right)
    struct avlleaf* AVL_rotation_SR(struct avlleaf* Leaf) {

    // Переменные
    struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

    aor = Leaf->left;

    // Магия вращения... (Вжух...)
    Leaf->left = aor->right;
    aor->right = Leaf;

    // Выправляем высоту
    AVLLeaf_CheckHeight(Leaf);
    AVLLeaf_CheckHeight(aor);

    return aor;
    }

    // Ребалансировка дерева
    struct avlleaf* AVL_BalanceMe(struct avlleaf* Leaf) {

    // Переменные
    char balfac; // Коэффицент баласировки (от -2 до +2)


    balfac = AVLLeaf_GetBalance(Leaf);

    // Оцениваем баланс и выправляем его
    if (balfac < -1) {

    // Смотрим, требуется ли большое вращение
    if (AVLLeaf_GetBalance(Leaf->left) > 0) {
    Leaf->left = AVL_rotation_SL(Leaf->left);
    }

    return (AVL_rotation_SR(Leaf));

    } else if (balfac > 1) {

    // Смотрим, требуется ли большое вращение
    if (AVLLeaf_GetBalance(Leaf->right) < 0) {
    Leaf->right = AVL_rotation_SR(Leaf->right);
    }

    return (AVL_rotation_SL(Leaf));

    } else { // Если нуль

    // Вращение НЕ требуется
    AVLLeaf_CheckHeight(Leaf);

    return Leaf;

    }
    }

    // Поиск места вставки и вставка
    struct avlleaf* AVL_FindAndInsert(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
    // Если поддерево пустое
    if (Leaf == NULL) {

    if (PrintStatus) printf("OKn");
    return AVLLeaf_Create(key, llupar);

    } else if (strcmp(key, Leaf->key.Text) < 0) {

    Leaf->left = AVL_FindAndInsert(key, llupar, Leaf->left, PrintStatus);

    } else if (strcmp(key, Leaf->key.Text) > 0){

    Leaf->right = AVL_FindAndInsert(key, llupar, Leaf->right, PrintStatus);

    } else {

    if (PrintStatus) printf("Existn");

    }

    return AVL_BalanceMe(Leaf);

    }

    // Добавление листа (обертка над функцией выше)
    void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
    AVLTree->root = AVL_FindAndInsert(key, llupar, AVLTree->root, PrintStatus);
    }

    // Получение минимального значения
    struct String AVL_GetMinKey(struct avlleaf* Leaf) {
    while (Leaf->left != NULL) Leaf = Leaf->left;
    return Leaf->key;
    }

    // Получение параметра у листа с минимальным значением
    unsigned long long int AVL_GetMinVal(struct avlleaf* Leaf) {
    while (Leaf->left != NULL) Leaf = Leaf->left;
    return Leaf->llupar;
    }

    // Поиск и удаление
    struct avlleaf* AVL_FindAndRemove(char key[StringLengthPS+1], struct avlleaf* Leaf, bool PrintStatus) {

    // Переменные
    struct avlleaf* child; // Служебная (для случаев с одним ребенком)
    char tmpkey[StringLengthPS+1]; // Временный контейнер для ключа
    unsigned short int i; // Тикер (для циклов и т.д.)

    if (Leaf == NULL) {
    // Нет значения для удаления
    if (PrintStatus) printf("NoSuchWordn");
    return NULL;

    } else if (strcmp(key, Leaf->key.Text) < 0) {

    Leaf->left = AVL_FindAndRemove(key, Leaf->left, PrintStatus);
    return AVL_BalanceMe(Leaf);

    } else if (strcmp(key, Leaf->key.Text) > 0) {

    Leaf->right = AVL_FindAndRemove(key, Leaf->right, PrintStatus);
    return AVL_BalanceMe(Leaf);

    } else { // Найдена позиция

    if (PrintStatus) printf("OKn");
    // Анализ детей и перемещение
    if (Leaf->left != NULL && Leaf->right != NULL) {

    Leaf->key = AVL_GetMinKey(Leaf->right);
    Leaf->llupar = AVL_GetMinVal(Leaf->right);

    for (i = 0; i <= Leaf->key.count; i++) {
    tmpkey[i] = Leaf->key.Text[i];
    }

    Leaf->right = AVL_FindAndRemove(tmpkey, Leaf->right, PrintStatus);

    return AVL_BalanceMe(Leaf);

    } else if (Leaf->left != NULL) {

    // Есть только один ребенок (правый)

    child = Leaf->left;
    Leaf->key.count = 0;
    free(Leaf->key.Text);
    free(Leaf);
    return child;

    } else if (Leaf->right != NULL) {

    // Есть только один ребенок (левый)

    child = Leaf->right;
    Leaf->key.count = 0;
    free(Leaf->key.Text);
    free(Leaf);
    return child;

    } else {

    // Нет дитей - просто выкидываем
    Leaf->key.count = 0;
    free(Leaf->key.Text);
    free(Leaf);
    return NULL;

    }

    }

    }

    // Удаление из дерева (обертка над функцией выше)
    void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus) {
    AVL_Tree->root = AVL_FindAndRemove(key, AVL_Tree->root, PrintStatus);
    }

    // Поиск элемента в дереве
    bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree) {

    // Переменные
    struct avlleaf* CuP;

    CuP = AVL_Tree->root;
    while (CuP != NULL) {

    if (strcmp (key, CuP->key.Text) == 0) {

    return true;

    } else if (strcmp(key, CuP->key.Text) < 0) {

    CuP = CuP->left;

    } else {

    CuP = CuP->right;

    }

    }

    return false;

    }

    // Еще один алгоритм поиска (удобнее для пользователя)
    unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus){

    // Переменные
    struct avlleaf* CuP;

    CuP = AVL_Tree->root;
    while (CuP != NULL) {

    if (strcmp (key, CuP->key.Text) == 0) {

    if (PrintStatus){
    printf("OK: ");
    printf("%llu", (CuP->llupar));
    printf("n");
    }
    return CuP->llupar;

    } else if (strcmp(key, CuP->key.Text) < 0) {

    CuP = CuP->left;

    } else {

    CuP = CuP->right;

    }

    }

    if (PrintStatus) printf("NoSuchWordn");
    return 0;

    }

    // Печать дерева
    void AVL_print_rec(struct avlleaf* Leaf, long int lvl) {

    // Переменные
    int i;

    if (Leaf == NULL) {
    return;
    }

    AVL_print_rec(Leaf->left, lvl + 1);

    for (i = 0; i < lvl; i++) printf("t");

    printf("%s", Leaf->key.Text);
    printf("%c", '|');
    printf("%llu", Leaf->llupar);
    printf("n");

    AVL_print_rec(Leaf->right, lvl + 1);
    }

    // Печать дерева (обертка над функцией выше)
    void AVL_PrintMe(struct avltree* AVL_Tree){
    if (AVL_Tree->root == NULL) {
    printf("EMPTYn");
    } else {
    AVL_print_rec(AVL_Tree->root, 0);
    }
    }

    // Запись лист в файл
    void AVL_LeafToFile(struct avlleaf* Leaf, FILE * file){
    if (Leaf == NULL) return;

    fwrite(&(Leaf->key.count), sizeof(unsigned short int), 1, file);
    fwrite(Leaf->key.Text, sizeof(char), Leaf->key.count+1, file);
    fwrite(&(Leaf->llupar), sizeof(unsigned long long int), 1, file);

    AVL_LeafToFile(Leaf->right, file);
    AVL_LeafToFile(Leaf->left, file);
    }

    // Сохранение дерева
    void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus){

    // Переменные
    char adress[1024];
    FILE *file = NULL;

    // Открытие файла
    scanf("%s", adress);
    file = fopen(adress, "wb+");
    if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't create filen");
    if (file == NULL) return;

    // Запись дерева
    fwrite(&(UnCo), sizeof(unsigned long long int), 1, file);
    AVL_LeafToFile(AVL_Tree->root, file);

    // Закрытие
    if (PrintStatus) printf("OKn");
    fclose(file);
    }

    // Поиск места вставки и вставка
    struct avlleaf* AVL_FindAndInsert_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
    // Если поддерево пустое
    if (Leaf == NULL) {

    return AVLLeaf_Create(key, llupar);

    } else if (strcmp(key, Leaf->key.Text) < 0) {

    Leaf->left = AVL_FindAndInsert_clean(key, llupar, Leaf->left, PrintStatus);

    } else if (strcmp(key, Leaf->key.Text) > 0){

    Leaf->right = AVL_FindAndInsert_clean(key, llupar, Leaf->right, PrintStatus);

    } else {

    if (PrintStatus) printf("ERROR: Broken Filen");

    }

    return Leaf;

    }

    // Добавление листа (обертка над функцией выше)
    void AVL_InsertLeaf_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
    AVLTree->root = AVL_FindAndInsert_clean(key, llupar, AVLTree->root, PrintStatus);
    }

    // Загрузка листа из файла
    void AVL_LeafFromFile(struct avltree* AVL_Tree, FILE * file){

    // Переменные
    char tmpkey[StringLengthPS+1];
    unsigned long long int tmpllupar;
    unsigned short int charcount;



    while (feof(file) == 0){
    fread(&charcount, sizeof(unsigned short int), 1, file);
    fread(tmpkey, sizeof(char), charcount+1, file);
    fread(&tmpllupar, sizeof(unsigned long long int), 1, file);

    AVL_InsertLeaf_clean(tmpkey, tmpllupar, AVL_Tree, false);
    }
    }

    // Загрузка дерева
    void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus){

    // Переменные
    char adress[1024];
    FILE *file = NULL;
    unsigned long long int FileUnCo;

    // Открытие файла
    scanf("%s", adress);
    file = fopen(adress, "rb");
    if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't read filen");
    if (file == NULL) return;

    // Тест совместимости
    fread(&FileUnCo, sizeof(unsigned long long int), 1, file);
    if (UnCo != FileUnCo){
    printf("ERROR: Unsupported filen");
    return;
    }

    // Уничтожаем ранее созданное дерево
    AVL_FreeAndNil(AVL_Tree);

    // Загружаем новое дерево
    AVL_LeafFromFile(AVL_Tree, file);

    // Закрытие
    if (PrintStatus) printf("OKn");
    fclose(file);
    }


    settings_slimrg.h



    #ifndef settings_h
    #define settings_h
    /* Settings */

    // Настройка ввода
    const unsigned int StringLengthPS = 256; // Длина строки (в символах)

    // Настройка отладки
    const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом

    // Номер сборки
    const unsigned long long int UnCo = 115700744534137162;

    #endif


    MakeFile



    all:
    gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare main.c AVL_tree_slimrg.c -lm -o lb2


    Лог (здесь main.c заменен на lb2.c)



    gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare lb2.c AVL_tree_slimrg.c -lm -o lb2
    /tmp/cc4upHwG.o:(.rodata+0x0): multiple definition of `StringLengthPS'
    /tmp/ccORqDAb.o:(.rodata+0x0): first defined here
    /tmp/cc4upHwG.o:(.rodata+0x4): multiple definition of `debug_pauseonclose'
    /tmp/ccORqDAb.o:(.rodata+0x4): first defined here
    /tmp/cc4upHwG.o:(.rodata+0x8): multiple definition of `UnCo'
    /tmp/ccORqDAb.o:(.rodata+0x8): first defined here
    collect2: error: ld returned 1 exit status
    Makefile:2: recipe for target 'all' failed
    make: *** [all] Error 1









    поделиться|улучшить этот вопрос



























      1












      1








      1


      1






      Сделал вроде все нормально, но вот ругается



      В проекте 4е файла:



      main.c



      /*

      Программу подготовил: Буренков Игорь (М8О-206Б-17)

      Вариант: АВЛ-дерево

      */
      /////////////////////////////////////////////////////////

      /* Системные библиотеки */
      #include <stdio.h>
      #include <stdlib.h>
      #include <stdbool.h>
      #include <ctype.h>

      /* Пользовательские библиотеки */
      #include "AVL_tree_slimrg.h"
      #include "settings_slimrg.h"

      /* Структуры */


      /* Сигнатуры функций */
      unsigned short int InputFiller(); // Ввод и исполнение комманд
      void PrintError(unsigned short int ErrorCode); // Вывод ошибок



      /* Основной цикл */
      int main(){

      // Переменные
      unsigned short int log_error; // Код ошибки

      // Считываем и выполняем команды
      log_error = InputFiller();

      // Выввод ошибки
      PrintError(log_error);

      // Пауза при закрытии
      if (debug_pauseonclose) system("pause");

      // Все ОК
      return 0;
      }

      // Цикл ввода и выполнения
      unsigned short int InputFiller(){

      // Переменные
      char tmpchar[StringLengthPS+1]; // Временный контейнер для символа
      char tmpword[StringLengthPS+1]; // Временный контейнер для слова (массива символов)
      unsigned long long int tmpkey; // Временный контейнер для ключа
      unsigned char errorcode; // Код ошибки
      unsigned int i; // Тикер (для циклов и т.д.)

      // Создание пустого дерева
      struct avltree* AVLTree1 = AVL_Create();

      // Пока возможно - считываем первый символ строки
      while (scanf("%s", tmpchar) >= 1){
      // Перевод в нижний регистр
      tmpchar[0] = tolower(tmpchar[0]);
      // Определение комманды
      switch (tmpchar[0]) {

      // Добавить слово
      case '+':
      // Считываем слово
      scanf("%s", tmpword);
      // Преобразование в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Считывание ключа
      scanf("%llu", &tmpkey);
      // Довавляем лист (с включенным выводом)
      AVL_InsertLeaf(tmpword, tmpkey, AVLTree1, true);
      break;

      // Отладочные комманды
      case '!':
      // Считываем слово
      scanf("%s", tmpword);
      // Перевод в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Распознание слова
      if (strcmp(tmpword, "exit") == 0) {
      return 0;
      } else
      if (strcmp(tmpword, "print") == 0) {
      AVL_PrintMe(AVLTree1);
      } else
      if (strcmp(tmpword, "save") == 0) {
      AVL_SaveTree(AVLTree1, true);
      } else
      if (strcmp(tmpword, "load") == 0) {
      AVL_LoadTree(AVLTree1, true);
      }
      break;
      // Удаление слова
      case '-':
      // Считываем слово
      scanf("%s", tmpword);
      // Преобразование в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Удаляем лист
      AVL_RemoveLeaf(tmpword, AVLTree1, true);
      break;
      // Заглушка
      case 'n':
      break;
      // Осталось слово
      default:
      for (i = 0; i < StringLengthPS; i++) tmpchar[i] = tolower(tmpchar[i]);
      // Поиск
      tmpkey = AVL_FindMe_p(tmpchar, AVLTree1, true);
      break;


      }
      }
      return 0;
      }

      // Печать ошибок
      void PrintError(unsigned short int ErrorCode){
      }


      AVL_tree_slimrg.h



      #ifndef AVL_tree_slimrg_h
      #define AVL_tree_slimrg_h

      // Стандартные заголовки
      #include <stdbool.h>
      #include <string.h>

      // Настройки
      #include "settings_slimrg.h"

      // Сама структура
      struct avltree;

      // Создание дерева
      struct avltree* AVL_Create();

      // Уничтожение дерева
      void AVL_FreeAndNil(struct avltree* AVL_Tree);

      // Проверка на пустоту
      bool AVL_IsEmpty(struct avltree* AVL_Tree);

      // Добавить лист
      void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVL_Tree, bool PrintStatus);

      // Удаление листа по значению
      void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

      // Поиск значения
      bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree);
      unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

      // Печать дерева
      void AVL_PrintMe(struct avltree* AVL_Tree);

      // Сохранение дерева
      void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus);

      // Загрузка дерева
      void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus);


      #endif


      AVL_tree_slimrg.c



      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>

      #include "AVL_tree_slimrg.h"

      // Структура строки
      struct String{
      char* Text;
      unsigned short int count;
      };

      // Структура листа
      struct avlleaf {
      struct String key; // Ключ
      unsigned long long int llupar; // Значение
      long int height; // Высота
      struct avlleaf* left; // Левый ребенок
      struct avlleaf* right; // Правый ребенок
      };

      // Структура дерева
      struct avltree {
      struct avlleaf* root;
      };

      // Создание дерева
      struct avltree* AVL_Create() {
      struct avltree* AVL_Tree = malloc(sizeof(struct avltree));
      AVL_Tree->root = NULL;
      return AVL_Tree;
      }

      // Уничтожение дерева
      void AVL_FreeAndNil(struct avltree* AVL_Tree) {
      // Переменные
      char tmpword[StringLengthPS+1];
      unsigned short int i; // Тикер (для циклов и т.д.)

      // Запускаем балалайку ^_^
      while (AVL_IsEmpty(AVL_Tree) == false) {
      for (i = 0; i <= AVL_Tree->root->key.count; i++) {
      tmpword[i] = AVL_Tree->root->key.Text[i];
      }
      AVL_RemoveLeaf(tmpword, AVL_Tree, false);
      }
      }

      // Проверка на пустоту
      bool AVL_IsEmpty(struct avltree* AVL_Tree) {
      return (AVL_Tree->root == NULL);
      }

      // Инициализация листа
      struct avlleaf* AVLLeaf_Create(char inputkey[StringLengthPS+1], unsigned long long int llupar) {

      // Переменные
      struct avlleaf* keim; // Лист
      unsigned short int i; // Тикер (для циклов и т.д.)


      // Начальная инициализация
      keim = malloc(sizeof(struct avlleaf));
      keim->right = keim->left = NULL;
      keim->llupar = llupar;

      // Сложная инициализация
      i = 0;
      while (inputkey[i] != 0) i++;
      keim->key.count = i;
      keim->key.Text = malloc(keim->key.count * sizeof(char));
      for (i = 0; i <= keim->key.count; i++) {
      keim->key.Text[i] = inputkey[i];
      }

      keim->height = 0;
      return keim;
      }

      // Получение высоты листа
      long int AVLLeaf_GetHeight(struct avlleaf* Leaf) {
      if (Leaf == NULL) return (-1); else return Leaf->height;
      }

      // Получение коэффицента балансировки
      char AVLLeaf_GetBalance(struct avlleaf* Leaf) {
      return (AVLLeaf_GetHeight(Leaf->right) - AVLLeaf_GetHeight(Leaf->left));
      }

      // Проверка высоты
      void AVLLeaf_CheckHeight(struct avlleaf* Leaf) {

      // Переменные
      long int left, right; // Дети листа Leaf

      left = AVLLeaf_GetHeight(Leaf->left);
      right = AVLLeaf_GetHeight(Leaf->right);

      // Высота получается увеличением максимальной детской высоты на единицу
      if (left <= right) Leaf->height = right + 1; else Leaf->height = left + 1;
      }

      // Малое леве вращение (Small Left)
      struct avlleaf* AVL_rotation_SL(struct avlleaf* Leaf) {

      // Переменные
      struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

      aor = Leaf->right;

      // Магия вращения... (Вжух...)
      Leaf->right = aor->left;
      aor->left = Leaf;

      // Выправляем высоту
      AVLLeaf_CheckHeight(Leaf);
      AVLLeaf_CheckHeight(aor);

      return aor;
      }

      // Малое правое вращение (Small Right)
      struct avlleaf* AVL_rotation_SR(struct avlleaf* Leaf) {

      // Переменные
      struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

      aor = Leaf->left;

      // Магия вращения... (Вжух...)
      Leaf->left = aor->right;
      aor->right = Leaf;

      // Выправляем высоту
      AVLLeaf_CheckHeight(Leaf);
      AVLLeaf_CheckHeight(aor);

      return aor;
      }

      // Ребалансировка дерева
      struct avlleaf* AVL_BalanceMe(struct avlleaf* Leaf) {

      // Переменные
      char balfac; // Коэффицент баласировки (от -2 до +2)


      balfac = AVLLeaf_GetBalance(Leaf);

      // Оцениваем баланс и выправляем его
      if (balfac < -1) {

      // Смотрим, требуется ли большое вращение
      if (AVLLeaf_GetBalance(Leaf->left) > 0) {
      Leaf->left = AVL_rotation_SL(Leaf->left);
      }

      return (AVL_rotation_SR(Leaf));

      } else if (balfac > 1) {

      // Смотрим, требуется ли большое вращение
      if (AVLLeaf_GetBalance(Leaf->right) < 0) {
      Leaf->right = AVL_rotation_SR(Leaf->right);
      }

      return (AVL_rotation_SL(Leaf));

      } else { // Если нуль

      // Вращение НЕ требуется
      AVLLeaf_CheckHeight(Leaf);

      return Leaf;

      }
      }

      // Поиск места вставки и вставка
      struct avlleaf* AVL_FindAndInsert(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
      // Если поддерево пустое
      if (Leaf == NULL) {

      if (PrintStatus) printf("OKn");
      return AVLLeaf_Create(key, llupar);

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndInsert(key, llupar, Leaf->left, PrintStatus);

      } else if (strcmp(key, Leaf->key.Text) > 0){

      Leaf->right = AVL_FindAndInsert(key, llupar, Leaf->right, PrintStatus);

      } else {

      if (PrintStatus) printf("Existn");

      }

      return AVL_BalanceMe(Leaf);

      }

      // Добавление листа (обертка над функцией выше)
      void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
      AVLTree->root = AVL_FindAndInsert(key, llupar, AVLTree->root, PrintStatus);
      }

      // Получение минимального значения
      struct String AVL_GetMinKey(struct avlleaf* Leaf) {
      while (Leaf->left != NULL) Leaf = Leaf->left;
      return Leaf->key;
      }

      // Получение параметра у листа с минимальным значением
      unsigned long long int AVL_GetMinVal(struct avlleaf* Leaf) {
      while (Leaf->left != NULL) Leaf = Leaf->left;
      return Leaf->llupar;
      }

      // Поиск и удаление
      struct avlleaf* AVL_FindAndRemove(char key[StringLengthPS+1], struct avlleaf* Leaf, bool PrintStatus) {

      // Переменные
      struct avlleaf* child; // Служебная (для случаев с одним ребенком)
      char tmpkey[StringLengthPS+1]; // Временный контейнер для ключа
      unsigned short int i; // Тикер (для циклов и т.д.)

      if (Leaf == NULL) {
      // Нет значения для удаления
      if (PrintStatus) printf("NoSuchWordn");
      return NULL;

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndRemove(key, Leaf->left, PrintStatus);
      return AVL_BalanceMe(Leaf);

      } else if (strcmp(key, Leaf->key.Text) > 0) {

      Leaf->right = AVL_FindAndRemove(key, Leaf->right, PrintStatus);
      return AVL_BalanceMe(Leaf);

      } else { // Найдена позиция

      if (PrintStatus) printf("OKn");
      // Анализ детей и перемещение
      if (Leaf->left != NULL && Leaf->right != NULL) {

      Leaf->key = AVL_GetMinKey(Leaf->right);
      Leaf->llupar = AVL_GetMinVal(Leaf->right);

      for (i = 0; i <= Leaf->key.count; i++) {
      tmpkey[i] = Leaf->key.Text[i];
      }

      Leaf->right = AVL_FindAndRemove(tmpkey, Leaf->right, PrintStatus);

      return AVL_BalanceMe(Leaf);

      } else if (Leaf->left != NULL) {

      // Есть только один ребенок (правый)

      child = Leaf->left;
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return child;

      } else if (Leaf->right != NULL) {

      // Есть только один ребенок (левый)

      child = Leaf->right;
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return child;

      } else {

      // Нет дитей - просто выкидываем
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return NULL;

      }

      }

      }

      // Удаление из дерева (обертка над функцией выше)
      void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus) {
      AVL_Tree->root = AVL_FindAndRemove(key, AVL_Tree->root, PrintStatus);
      }

      // Поиск элемента в дереве
      bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree) {

      // Переменные
      struct avlleaf* CuP;

      CuP = AVL_Tree->root;
      while (CuP != NULL) {

      if (strcmp (key, CuP->key.Text) == 0) {

      return true;

      } else if (strcmp(key, CuP->key.Text) < 0) {

      CuP = CuP->left;

      } else {

      CuP = CuP->right;

      }

      }

      return false;

      }

      // Еще один алгоритм поиска (удобнее для пользователя)
      unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      struct avlleaf* CuP;

      CuP = AVL_Tree->root;
      while (CuP != NULL) {

      if (strcmp (key, CuP->key.Text) == 0) {

      if (PrintStatus){
      printf("OK: ");
      printf("%llu", (CuP->llupar));
      printf("n");
      }
      return CuP->llupar;

      } else if (strcmp(key, CuP->key.Text) < 0) {

      CuP = CuP->left;

      } else {

      CuP = CuP->right;

      }

      }

      if (PrintStatus) printf("NoSuchWordn");
      return 0;

      }

      // Печать дерева
      void AVL_print_rec(struct avlleaf* Leaf, long int lvl) {

      // Переменные
      int i;

      if (Leaf == NULL) {
      return;
      }

      AVL_print_rec(Leaf->left, lvl + 1);

      for (i = 0; i < lvl; i++) printf("t");

      printf("%s", Leaf->key.Text);
      printf("%c", '|');
      printf("%llu", Leaf->llupar);
      printf("n");

      AVL_print_rec(Leaf->right, lvl + 1);
      }

      // Печать дерева (обертка над функцией выше)
      void AVL_PrintMe(struct avltree* AVL_Tree){
      if (AVL_Tree->root == NULL) {
      printf("EMPTYn");
      } else {
      AVL_print_rec(AVL_Tree->root, 0);
      }
      }

      // Запись лист в файл
      void AVL_LeafToFile(struct avlleaf* Leaf, FILE * file){
      if (Leaf == NULL) return;

      fwrite(&(Leaf->key.count), sizeof(unsigned short int), 1, file);
      fwrite(Leaf->key.Text, sizeof(char), Leaf->key.count+1, file);
      fwrite(&(Leaf->llupar), sizeof(unsigned long long int), 1, file);

      AVL_LeafToFile(Leaf->right, file);
      AVL_LeafToFile(Leaf->left, file);
      }

      // Сохранение дерева
      void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      char adress[1024];
      FILE *file = NULL;

      // Открытие файла
      scanf("%s", adress);
      file = fopen(adress, "wb+");
      if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't create filen");
      if (file == NULL) return;

      // Запись дерева
      fwrite(&(UnCo), sizeof(unsigned long long int), 1, file);
      AVL_LeafToFile(AVL_Tree->root, file);

      // Закрытие
      if (PrintStatus) printf("OKn");
      fclose(file);
      }

      // Поиск места вставки и вставка
      struct avlleaf* AVL_FindAndInsert_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
      // Если поддерево пустое
      if (Leaf == NULL) {

      return AVLLeaf_Create(key, llupar);

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndInsert_clean(key, llupar, Leaf->left, PrintStatus);

      } else if (strcmp(key, Leaf->key.Text) > 0){

      Leaf->right = AVL_FindAndInsert_clean(key, llupar, Leaf->right, PrintStatus);

      } else {

      if (PrintStatus) printf("ERROR: Broken Filen");

      }

      return Leaf;

      }

      // Добавление листа (обертка над функцией выше)
      void AVL_InsertLeaf_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
      AVLTree->root = AVL_FindAndInsert_clean(key, llupar, AVLTree->root, PrintStatus);
      }

      // Загрузка листа из файла
      void AVL_LeafFromFile(struct avltree* AVL_Tree, FILE * file){

      // Переменные
      char tmpkey[StringLengthPS+1];
      unsigned long long int tmpllupar;
      unsigned short int charcount;



      while (feof(file) == 0){
      fread(&charcount, sizeof(unsigned short int), 1, file);
      fread(tmpkey, sizeof(char), charcount+1, file);
      fread(&tmpllupar, sizeof(unsigned long long int), 1, file);

      AVL_InsertLeaf_clean(tmpkey, tmpllupar, AVL_Tree, false);
      }
      }

      // Загрузка дерева
      void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      char adress[1024];
      FILE *file = NULL;
      unsigned long long int FileUnCo;

      // Открытие файла
      scanf("%s", adress);
      file = fopen(adress, "rb");
      if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't read filen");
      if (file == NULL) return;

      // Тест совместимости
      fread(&FileUnCo, sizeof(unsigned long long int), 1, file);
      if (UnCo != FileUnCo){
      printf("ERROR: Unsupported filen");
      return;
      }

      // Уничтожаем ранее созданное дерево
      AVL_FreeAndNil(AVL_Tree);

      // Загружаем новое дерево
      AVL_LeafFromFile(AVL_Tree, file);

      // Закрытие
      if (PrintStatus) printf("OKn");
      fclose(file);
      }


      settings_slimrg.h



      #ifndef settings_h
      #define settings_h
      /* Settings */

      // Настройка ввода
      const unsigned int StringLengthPS = 256; // Длина строки (в символах)

      // Настройка отладки
      const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом

      // Номер сборки
      const unsigned long long int UnCo = 115700744534137162;

      #endif


      MakeFile



      all:
      gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare main.c AVL_tree_slimrg.c -lm -o lb2


      Лог (здесь main.c заменен на lb2.c)



      gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare lb2.c AVL_tree_slimrg.c -lm -o lb2
      /tmp/cc4upHwG.o:(.rodata+0x0): multiple definition of `StringLengthPS'
      /tmp/ccORqDAb.o:(.rodata+0x0): first defined here
      /tmp/cc4upHwG.o:(.rodata+0x4): multiple definition of `debug_pauseonclose'
      /tmp/ccORqDAb.o:(.rodata+0x4): first defined here
      /tmp/cc4upHwG.o:(.rodata+0x8): multiple definition of `UnCo'
      /tmp/ccORqDAb.o:(.rodata+0x8): first defined here
      collect2: error: ld returned 1 exit status
      Makefile:2: recipe for target 'all' failed
      make: *** [all] Error 1









      поделиться|улучшить этот вопрос
















      Сделал вроде все нормально, но вот ругается



      В проекте 4е файла:



      main.c



      /*

      Программу подготовил: Буренков Игорь (М8О-206Б-17)

      Вариант: АВЛ-дерево

      */
      /////////////////////////////////////////////////////////

      /* Системные библиотеки */
      #include <stdio.h>
      #include <stdlib.h>
      #include <stdbool.h>
      #include <ctype.h>

      /* Пользовательские библиотеки */
      #include "AVL_tree_slimrg.h"
      #include "settings_slimrg.h"

      /* Структуры */


      /* Сигнатуры функций */
      unsigned short int InputFiller(); // Ввод и исполнение комманд
      void PrintError(unsigned short int ErrorCode); // Вывод ошибок



      /* Основной цикл */
      int main(){

      // Переменные
      unsigned short int log_error; // Код ошибки

      // Считываем и выполняем команды
      log_error = InputFiller();

      // Выввод ошибки
      PrintError(log_error);

      // Пауза при закрытии
      if (debug_pauseonclose) system("pause");

      // Все ОК
      return 0;
      }

      // Цикл ввода и выполнения
      unsigned short int InputFiller(){

      // Переменные
      char tmpchar[StringLengthPS+1]; // Временный контейнер для символа
      char tmpword[StringLengthPS+1]; // Временный контейнер для слова (массива символов)
      unsigned long long int tmpkey; // Временный контейнер для ключа
      unsigned char errorcode; // Код ошибки
      unsigned int i; // Тикер (для циклов и т.д.)

      // Создание пустого дерева
      struct avltree* AVLTree1 = AVL_Create();

      // Пока возможно - считываем первый символ строки
      while (scanf("%s", tmpchar) >= 1){
      // Перевод в нижний регистр
      tmpchar[0] = tolower(tmpchar[0]);
      // Определение комманды
      switch (tmpchar[0]) {

      // Добавить слово
      case '+':
      // Считываем слово
      scanf("%s", tmpword);
      // Преобразование в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Считывание ключа
      scanf("%llu", &tmpkey);
      // Довавляем лист (с включенным выводом)
      AVL_InsertLeaf(tmpword, tmpkey, AVLTree1, true);
      break;

      // Отладочные комманды
      case '!':
      // Считываем слово
      scanf("%s", tmpword);
      // Перевод в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Распознание слова
      if (strcmp(tmpword, "exit") == 0) {
      return 0;
      } else
      if (strcmp(tmpword, "print") == 0) {
      AVL_PrintMe(AVLTree1);
      } else
      if (strcmp(tmpword, "save") == 0) {
      AVL_SaveTree(AVLTree1, true);
      } else
      if (strcmp(tmpword, "load") == 0) {
      AVL_LoadTree(AVLTree1, true);
      }
      break;
      // Удаление слова
      case '-':
      // Считываем слово
      scanf("%s", tmpword);
      // Преобразование в нижний регистр
      for (i = 0; i < StringLengthPS; i++) tmpword[i] = tolower(tmpword[i]);
      // Удаляем лист
      AVL_RemoveLeaf(tmpword, AVLTree1, true);
      break;
      // Заглушка
      case 'n':
      break;
      // Осталось слово
      default:
      for (i = 0; i < StringLengthPS; i++) tmpchar[i] = tolower(tmpchar[i]);
      // Поиск
      tmpkey = AVL_FindMe_p(tmpchar, AVLTree1, true);
      break;


      }
      }
      return 0;
      }

      // Печать ошибок
      void PrintError(unsigned short int ErrorCode){
      }


      AVL_tree_slimrg.h



      #ifndef AVL_tree_slimrg_h
      #define AVL_tree_slimrg_h

      // Стандартные заголовки
      #include <stdbool.h>
      #include <string.h>

      // Настройки
      #include "settings_slimrg.h"

      // Сама структура
      struct avltree;

      // Создание дерева
      struct avltree* AVL_Create();

      // Уничтожение дерева
      void AVL_FreeAndNil(struct avltree* AVL_Tree);

      // Проверка на пустоту
      bool AVL_IsEmpty(struct avltree* AVL_Tree);

      // Добавить лист
      void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVL_Tree, bool PrintStatus);

      // Удаление листа по значению
      void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

      // Поиск значения
      bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree);
      unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus);

      // Печать дерева
      void AVL_PrintMe(struct avltree* AVL_Tree);

      // Сохранение дерева
      void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus);

      // Загрузка дерева
      void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus);


      #endif


      AVL_tree_slimrg.c



      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>

      #include "AVL_tree_slimrg.h"

      // Структура строки
      struct String{
      char* Text;
      unsigned short int count;
      };

      // Структура листа
      struct avlleaf {
      struct String key; // Ключ
      unsigned long long int llupar; // Значение
      long int height; // Высота
      struct avlleaf* left; // Левый ребенок
      struct avlleaf* right; // Правый ребенок
      };

      // Структура дерева
      struct avltree {
      struct avlleaf* root;
      };

      // Создание дерева
      struct avltree* AVL_Create() {
      struct avltree* AVL_Tree = malloc(sizeof(struct avltree));
      AVL_Tree->root = NULL;
      return AVL_Tree;
      }

      // Уничтожение дерева
      void AVL_FreeAndNil(struct avltree* AVL_Tree) {
      // Переменные
      char tmpword[StringLengthPS+1];
      unsigned short int i; // Тикер (для циклов и т.д.)

      // Запускаем балалайку ^_^
      while (AVL_IsEmpty(AVL_Tree) == false) {
      for (i = 0; i <= AVL_Tree->root->key.count; i++) {
      tmpword[i] = AVL_Tree->root->key.Text[i];
      }
      AVL_RemoveLeaf(tmpword, AVL_Tree, false);
      }
      }

      // Проверка на пустоту
      bool AVL_IsEmpty(struct avltree* AVL_Tree) {
      return (AVL_Tree->root == NULL);
      }

      // Инициализация листа
      struct avlleaf* AVLLeaf_Create(char inputkey[StringLengthPS+1], unsigned long long int llupar) {

      // Переменные
      struct avlleaf* keim; // Лист
      unsigned short int i; // Тикер (для циклов и т.д.)


      // Начальная инициализация
      keim = malloc(sizeof(struct avlleaf));
      keim->right = keim->left = NULL;
      keim->llupar = llupar;

      // Сложная инициализация
      i = 0;
      while (inputkey[i] != 0) i++;
      keim->key.count = i;
      keim->key.Text = malloc(keim->key.count * sizeof(char));
      for (i = 0; i <= keim->key.count; i++) {
      keim->key.Text[i] = inputkey[i];
      }

      keim->height = 0;
      return keim;
      }

      // Получение высоты листа
      long int AVLLeaf_GetHeight(struct avlleaf* Leaf) {
      if (Leaf == NULL) return (-1); else return Leaf->height;
      }

      // Получение коэффицента балансировки
      char AVLLeaf_GetBalance(struct avlleaf* Leaf) {
      return (AVLLeaf_GetHeight(Leaf->right) - AVLLeaf_GetHeight(Leaf->left));
      }

      // Проверка высоты
      void AVLLeaf_CheckHeight(struct avlleaf* Leaf) {

      // Переменные
      long int left, right; // Дети листа Leaf

      left = AVLLeaf_GetHeight(Leaf->left);
      right = AVLLeaf_GetHeight(Leaf->right);

      // Высота получается увеличением максимальной детской высоты на единицу
      if (left <= right) Leaf->height = right + 1; else Leaf->height = left + 1;
      }

      // Малое леве вращение (Small Left)
      struct avlleaf* AVL_rotation_SL(struct avlleaf* Leaf) {

      // Переменные
      struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

      aor = Leaf->right;

      // Магия вращения... (Вжух...)
      Leaf->right = aor->left;
      aor->left = Leaf;

      // Выправляем высоту
      AVLLeaf_CheckHeight(Leaf);
      AVLLeaf_CheckHeight(aor);

      return aor;
      }

      // Малое правое вращение (Small Right)
      struct avlleaf* AVL_rotation_SR(struct avlleaf* Leaf) {

      // Переменные
      struct avlleaf* aor; // Ось вращения (Axis Of Rotation)

      aor = Leaf->left;

      // Магия вращения... (Вжух...)
      Leaf->left = aor->right;
      aor->right = Leaf;

      // Выправляем высоту
      AVLLeaf_CheckHeight(Leaf);
      AVLLeaf_CheckHeight(aor);

      return aor;
      }

      // Ребалансировка дерева
      struct avlleaf* AVL_BalanceMe(struct avlleaf* Leaf) {

      // Переменные
      char balfac; // Коэффицент баласировки (от -2 до +2)


      balfac = AVLLeaf_GetBalance(Leaf);

      // Оцениваем баланс и выправляем его
      if (balfac < -1) {

      // Смотрим, требуется ли большое вращение
      if (AVLLeaf_GetBalance(Leaf->left) > 0) {
      Leaf->left = AVL_rotation_SL(Leaf->left);
      }

      return (AVL_rotation_SR(Leaf));

      } else if (balfac > 1) {

      // Смотрим, требуется ли большое вращение
      if (AVLLeaf_GetBalance(Leaf->right) < 0) {
      Leaf->right = AVL_rotation_SR(Leaf->right);
      }

      return (AVL_rotation_SL(Leaf));

      } else { // Если нуль

      // Вращение НЕ требуется
      AVLLeaf_CheckHeight(Leaf);

      return Leaf;

      }
      }

      // Поиск места вставки и вставка
      struct avlleaf* AVL_FindAndInsert(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
      // Если поддерево пустое
      if (Leaf == NULL) {

      if (PrintStatus) printf("OKn");
      return AVLLeaf_Create(key, llupar);

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndInsert(key, llupar, Leaf->left, PrintStatus);

      } else if (strcmp(key, Leaf->key.Text) > 0){

      Leaf->right = AVL_FindAndInsert(key, llupar, Leaf->right, PrintStatus);

      } else {

      if (PrintStatus) printf("Existn");

      }

      return AVL_BalanceMe(Leaf);

      }

      // Добавление листа (обертка над функцией выше)
      void AVL_InsertLeaf(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
      AVLTree->root = AVL_FindAndInsert(key, llupar, AVLTree->root, PrintStatus);
      }

      // Получение минимального значения
      struct String AVL_GetMinKey(struct avlleaf* Leaf) {
      while (Leaf->left != NULL) Leaf = Leaf->left;
      return Leaf->key;
      }

      // Получение параметра у листа с минимальным значением
      unsigned long long int AVL_GetMinVal(struct avlleaf* Leaf) {
      while (Leaf->left != NULL) Leaf = Leaf->left;
      return Leaf->llupar;
      }

      // Поиск и удаление
      struct avlleaf* AVL_FindAndRemove(char key[StringLengthPS+1], struct avlleaf* Leaf, bool PrintStatus) {

      // Переменные
      struct avlleaf* child; // Служебная (для случаев с одним ребенком)
      char tmpkey[StringLengthPS+1]; // Временный контейнер для ключа
      unsigned short int i; // Тикер (для циклов и т.д.)

      if (Leaf == NULL) {
      // Нет значения для удаления
      if (PrintStatus) printf("NoSuchWordn");
      return NULL;

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndRemove(key, Leaf->left, PrintStatus);
      return AVL_BalanceMe(Leaf);

      } else if (strcmp(key, Leaf->key.Text) > 0) {

      Leaf->right = AVL_FindAndRemove(key, Leaf->right, PrintStatus);
      return AVL_BalanceMe(Leaf);

      } else { // Найдена позиция

      if (PrintStatus) printf("OKn");
      // Анализ детей и перемещение
      if (Leaf->left != NULL && Leaf->right != NULL) {

      Leaf->key = AVL_GetMinKey(Leaf->right);
      Leaf->llupar = AVL_GetMinVal(Leaf->right);

      for (i = 0; i <= Leaf->key.count; i++) {
      tmpkey[i] = Leaf->key.Text[i];
      }

      Leaf->right = AVL_FindAndRemove(tmpkey, Leaf->right, PrintStatus);

      return AVL_BalanceMe(Leaf);

      } else if (Leaf->left != NULL) {

      // Есть только один ребенок (правый)

      child = Leaf->left;
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return child;

      } else if (Leaf->right != NULL) {

      // Есть только один ребенок (левый)

      child = Leaf->right;
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return child;

      } else {

      // Нет дитей - просто выкидываем
      Leaf->key.count = 0;
      free(Leaf->key.Text);
      free(Leaf);
      return NULL;

      }

      }

      }

      // Удаление из дерева (обертка над функцией выше)
      void AVL_RemoveLeaf(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus) {
      AVL_Tree->root = AVL_FindAndRemove(key, AVL_Tree->root, PrintStatus);
      }

      // Поиск элемента в дереве
      bool AVL_FindMe(char key[StringLengthPS+1], struct avltree* AVL_Tree) {

      // Переменные
      struct avlleaf* CuP;

      CuP = AVL_Tree->root;
      while (CuP != NULL) {

      if (strcmp (key, CuP->key.Text) == 0) {

      return true;

      } else if (strcmp(key, CuP->key.Text) < 0) {

      CuP = CuP->left;

      } else {

      CuP = CuP->right;

      }

      }

      return false;

      }

      // Еще один алгоритм поиска (удобнее для пользователя)
      unsigned long long int AVL_FindMe_p(char key[StringLengthPS+1], struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      struct avlleaf* CuP;

      CuP = AVL_Tree->root;
      while (CuP != NULL) {

      if (strcmp (key, CuP->key.Text) == 0) {

      if (PrintStatus){
      printf("OK: ");
      printf("%llu", (CuP->llupar));
      printf("n");
      }
      return CuP->llupar;

      } else if (strcmp(key, CuP->key.Text) < 0) {

      CuP = CuP->left;

      } else {

      CuP = CuP->right;

      }

      }

      if (PrintStatus) printf("NoSuchWordn");
      return 0;

      }

      // Печать дерева
      void AVL_print_rec(struct avlleaf* Leaf, long int lvl) {

      // Переменные
      int i;

      if (Leaf == NULL) {
      return;
      }

      AVL_print_rec(Leaf->left, lvl + 1);

      for (i = 0; i < lvl; i++) printf("t");

      printf("%s", Leaf->key.Text);
      printf("%c", '|');
      printf("%llu", Leaf->llupar);
      printf("n");

      AVL_print_rec(Leaf->right, lvl + 1);
      }

      // Печать дерева (обертка над функцией выше)
      void AVL_PrintMe(struct avltree* AVL_Tree){
      if (AVL_Tree->root == NULL) {
      printf("EMPTYn");
      } else {
      AVL_print_rec(AVL_Tree->root, 0);
      }
      }

      // Запись лист в файл
      void AVL_LeafToFile(struct avlleaf* Leaf, FILE * file){
      if (Leaf == NULL) return;

      fwrite(&(Leaf->key.count), sizeof(unsigned short int), 1, file);
      fwrite(Leaf->key.Text, sizeof(char), Leaf->key.count+1, file);
      fwrite(&(Leaf->llupar), sizeof(unsigned long long int), 1, file);

      AVL_LeafToFile(Leaf->right, file);
      AVL_LeafToFile(Leaf->left, file);
      }

      // Сохранение дерева
      void AVL_SaveTree(struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      char adress[1024];
      FILE *file = NULL;

      // Открытие файла
      scanf("%s", adress);
      file = fopen(adress, "wb+");
      if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't create filen");
      if (file == NULL) return;

      // Запись дерева
      fwrite(&(UnCo), sizeof(unsigned long long int), 1, file);
      AVL_LeafToFile(AVL_Tree->root, file);

      // Закрытие
      if (PrintStatus) printf("OKn");
      fclose(file);
      }

      // Поиск места вставки и вставка
      struct avlleaf* AVL_FindAndInsert_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avlleaf* Leaf, bool PrintStatus) {
      // Если поддерево пустое
      if (Leaf == NULL) {

      return AVLLeaf_Create(key, llupar);

      } else if (strcmp(key, Leaf->key.Text) < 0) {

      Leaf->left = AVL_FindAndInsert_clean(key, llupar, Leaf->left, PrintStatus);

      } else if (strcmp(key, Leaf->key.Text) > 0){

      Leaf->right = AVL_FindAndInsert_clean(key, llupar, Leaf->right, PrintStatus);

      } else {

      if (PrintStatus) printf("ERROR: Broken Filen");

      }

      return Leaf;

      }

      // Добавление листа (обертка над функцией выше)
      void AVL_InsertLeaf_clean(char key[StringLengthPS+1], unsigned long long int llupar, struct avltree* AVLTree, bool PrintStatus) {
      AVLTree->root = AVL_FindAndInsert_clean(key, llupar, AVLTree->root, PrintStatus);
      }

      // Загрузка листа из файла
      void AVL_LeafFromFile(struct avltree* AVL_Tree, FILE * file){

      // Переменные
      char tmpkey[StringLengthPS+1];
      unsigned long long int tmpllupar;
      unsigned short int charcount;



      while (feof(file) == 0){
      fread(&charcount, sizeof(unsigned short int), 1, file);
      fread(tmpkey, sizeof(char), charcount+1, file);
      fread(&tmpllupar, sizeof(unsigned long long int), 1, file);

      AVL_InsertLeaf_clean(tmpkey, tmpllupar, AVL_Tree, false);
      }
      }

      // Загрузка дерева
      void AVL_LoadTree(struct avltree* AVL_Tree, bool PrintStatus){

      // Переменные
      char adress[1024];
      FILE *file = NULL;
      unsigned long long int FileUnCo;

      // Открытие файла
      scanf("%s", adress);
      file = fopen(adress, "rb");
      if ((file == NULL)&&(PrintStatus)) printf("ERROR: Couldn't read filen");
      if (file == NULL) return;

      // Тест совместимости
      fread(&FileUnCo, sizeof(unsigned long long int), 1, file);
      if (UnCo != FileUnCo){
      printf("ERROR: Unsupported filen");
      return;
      }

      // Уничтожаем ранее созданное дерево
      AVL_FreeAndNil(AVL_Tree);

      // Загружаем новое дерево
      AVL_LeafFromFile(AVL_Tree, file);

      // Закрытие
      if (PrintStatus) printf("OKn");
      fclose(file);
      }


      settings_slimrg.h



      #ifndef settings_h
      #define settings_h
      /* Settings */

      // Настройка ввода
      const unsigned int StringLengthPS = 256; // Длина строки (в символах)

      // Настройка отладки
      const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом

      // Номер сборки
      const unsigned long long int UnCo = 115700744534137162;

      #endif


      MakeFile



      all:
      gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare main.c AVL_tree_slimrg.c -lm -o lb2


      Лог (здесь main.c заменен на lb2.c)



      gcc -pedantic -Wall -std=c99 -Werror -Wno-sign-compare lb2.c AVL_tree_slimrg.c -lm -o lb2
      /tmp/cc4upHwG.o:(.rodata+0x0): multiple definition of `StringLengthPS'
      /tmp/ccORqDAb.o:(.rodata+0x0): first defined here
      /tmp/cc4upHwG.o:(.rodata+0x4): multiple definition of `debug_pauseonclose'
      /tmp/ccORqDAb.o:(.rodata+0x4): first defined here
      /tmp/cc4upHwG.o:(.rodata+0x8): multiple definition of `UnCo'
      /tmp/ccORqDAb.o:(.rodata+0x8): first defined here
      collect2: error: ld returned 1 exit status
      Makefile:2: recipe for target 'all' failed
      make: *** [all] Error 1






      c компиляция






      поделиться|улучшить этот вопрос















      поделиться|улучшить этот вопрос













      поделиться|улучшить этот вопрос




      поделиться|улучшить этот вопрос








      изменён 4 мар в 13:37









      aleksandr barakin

      55.5k1343166




      55.5k1343166










      задан 4 мар в 12:15









      Alrott SlimRGAlrott SlimRG

      41613




      41613






















          2 ответа
          2






          текущие

          по дате публикации

          голоса


















          4














          const unsigned int StringLengthPS = 256; // Длина строки (в символах)
          const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом
          const unsigned long long int UnCo = 115700744534137162;


          Раз у вас константы в хедере, то они копируются в каждый .c файл, который этот хедер инклудит - отсюда multiple definition.



          Решение:



          Либо сделать переменные static - тогда каждый файл получит свою копию каждой переменной,

          либо заменить переменные на #define.






          поделиться|улучшить этот ответ































            6














            В отличие от С++, в языке С const объекты имеют внешнее связывание по умолчанию. Их нельзя определять в заголовочных файлах.



            Либо явно придайте им внутреннее связывание, т.е. определяйте их как static const, либо идите по традиционному пути: в заголовочный файл кладите, extern const без инициализатора, а в один из .c файлов кладите ваши определения.



            В вашем случае можно также просто заменить ваши константы на макросы или enum.






            поделиться|улучшить этот ответ

























              Ваш ответ






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "609"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "на платформе u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "Пользовательский контент попадает под действие u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003eлицензии cc by-sa 3.0u003c/au003e с u003ca href="https://stackoverflow.com/legal/content-policy"u003eуказанием ссылки на источникu003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              черновик сохранён

              черновик удалён


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fru.stackoverflow.com%2fquestions%2f952205%2fmultiple-definition-of%23new-answer', 'question_page');
              }
              );

              Отправить без регистрации















              Необходима, но никому не показывается

























              2 ответа
              2






              текущие

              по дате публикации

              голоса








              2 ответа
              2






              текущие

              по дате публикации

              голоса









              текущие

              по дате публикации

              голоса






              текущие

              по дате публикации

              голоса









              4














              const unsigned int StringLengthPS = 256; // Длина строки (в символах)
              const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом
              const unsigned long long int UnCo = 115700744534137162;


              Раз у вас константы в хедере, то они копируются в каждый .c файл, который этот хедер инклудит - отсюда multiple definition.



              Решение:



              Либо сделать переменные static - тогда каждый файл получит свою копию каждой переменной,

              либо заменить переменные на #define.






              поделиться|улучшить этот ответ




























                4














                const unsigned int StringLengthPS = 256; // Длина строки (в символах)
                const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом
                const unsigned long long int UnCo = 115700744534137162;


                Раз у вас константы в хедере, то они копируются в каждый .c файл, который этот хедер инклудит - отсюда multiple definition.



                Решение:



                Либо сделать переменные static - тогда каждый файл получит свою копию каждой переменной,

                либо заменить переменные на #define.






                поделиться|улучшить этот ответ


























                  4












                  4








                  4







                  const unsigned int StringLengthPS = 256; // Длина строки (в символах)
                  const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом
                  const unsigned long long int UnCo = 115700744534137162;


                  Раз у вас константы в хедере, то они копируются в каждый .c файл, который этот хедер инклудит - отсюда multiple definition.



                  Решение:



                  Либо сделать переменные static - тогда каждый файл получит свою копию каждой переменной,

                  либо заменить переменные на #define.






                  поделиться|улучшить этот ответ













                  const unsigned int StringLengthPS = 256; // Длина строки (в символах)
                  const bool debug_pauseonclose = true; // Следует ли делать паузу перед выходом
                  const unsigned long long int UnCo = 115700744534137162;


                  Раз у вас константы в хедере, то они копируются в каждый .c файл, который этот хедер инклудит - отсюда multiple definition.



                  Решение:



                  Либо сделать переменные static - тогда каждый файл получит свою копию каждой переменной,

                  либо заменить переменные на #define.







                  поделиться|улучшить этот ответ












                  поделиться|улучшить этот ответ



                  поделиться|улучшить этот ответ










                  ответ дан 4 мар в 12:33









                  HolyBlackCatHolyBlackCat

                  5,6241514




                  5,6241514

























                      6














                      В отличие от С++, в языке С const объекты имеют внешнее связывание по умолчанию. Их нельзя определять в заголовочных файлах.



                      Либо явно придайте им внутреннее связывание, т.е. определяйте их как static const, либо идите по традиционному пути: в заголовочный файл кладите, extern const без инициализатора, а в один из .c файлов кладите ваши определения.



                      В вашем случае можно также просто заменить ваши константы на макросы или enum.






                      поделиться|улучшить этот ответ






























                        6














                        В отличие от С++, в языке С const объекты имеют внешнее связывание по умолчанию. Их нельзя определять в заголовочных файлах.



                        Либо явно придайте им внутреннее связывание, т.е. определяйте их как static const, либо идите по традиционному пути: в заголовочный файл кладите, extern const без инициализатора, а в один из .c файлов кладите ваши определения.



                        В вашем случае можно также просто заменить ваши константы на макросы или enum.






                        поделиться|улучшить этот ответ




























                          6












                          6








                          6







                          В отличие от С++, в языке С const объекты имеют внешнее связывание по умолчанию. Их нельзя определять в заголовочных файлах.



                          Либо явно придайте им внутреннее связывание, т.е. определяйте их как static const, либо идите по традиционному пути: в заголовочный файл кладите, extern const без инициализатора, а в один из .c файлов кладите ваши определения.



                          В вашем случае можно также просто заменить ваши константы на макросы или enum.






                          поделиться|улучшить этот ответ















                          В отличие от С++, в языке С const объекты имеют внешнее связывание по умолчанию. Их нельзя определять в заголовочных файлах.



                          Либо явно придайте им внутреннее связывание, т.е. определяйте их как static const, либо идите по традиционному пути: в заголовочный файл кладите, extern const без инициализатора, а в один из .c файлов кладите ваши определения.



                          В вашем случае можно также просто заменить ваши константы на макросы или enum.







                          поделиться|улучшить этот ответ














                          поделиться|улучшить этот ответ



                          поделиться|улучшить этот ответ








                          изменён 4 мар в 22:53

























                          ответ дан 4 мар в 12:35









                          AnTAnT

                          50.3k33895




                          50.3k33895






























                              черновик сохранён

                              черновик удалён




















































                              Спасибо за ваш ответ на Stack Overflow на русском!


                              • Пожалуйста, убедитесь, что публикуемое сообщение отвечает на поставленный вопрос. Предоставьте как можно больше деталей, расскажите про проведенное исследование!

                              Но избегайте



                              • Просьб помощи, уточнений или ответов на темы не относящиеся к вопросу.

                              • Ответов основанных на мнениях; приводите аргументы основанные только на реальном опыте.


                              Также, обратите внимание на заметку в справочном центре о том, как писать ответы.




                              черновик сохранён


                              черновик удалён














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fru.stackoverflow.com%2fquestions%2f952205%2fmultiple-definition-of%23new-answer', 'question_page');
                              }
                              );

                              Отправить без регистрации















                              Необходима, но никому не показывается





















































                              Необходима, но никому не показывается














                              Необходима, но никому не показывается












                              Необходима, но никому не показывается







                              Необходима, но никому не показывается

































                              Необходима, но никому не показывается














                              Необходима, но никому не показывается












                              Необходима, но никому не показывается







                              Необходима, но никому не показывается







                              Popular posts from this blog

                              How to change which sound is reproduced for terminal bell?

                              Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                              Can I use Tabulator js library in my java Spring + Thymeleaf project?