Помощь - Поиск - Пользователи - Календарь
Полная версия: Использование шаблонов
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
klem4
Есть хедер type.h, вот его содержимое :

//Структуры для хранения данных и ключей в массиве
# ifndef _DATA // защита от повторного включения этого файла
# define _DATA // в другой
# include <iostream.h>
# ifdef _NUMBER //ключ - число (типа int, long, float и т.д.)
//шаблоны позволяют использовать один и тот же код
//для различных типов данных и ключей
template <class Key,class Data>
struct Record
{Key key;
Data data;
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b) {return key > b.key;}
int operator < ( Record & b) {return key < b.key;}
int operator <= ( Record & b) {return key <= b.key;}
int operator == ( Record & b) {return key == b.key;}
// перегрузка операции = для ключа
void operator = (Key n){key=n};
//печать ключа
void PrnKey (){ cout << key<<' ';}
};
//обмен
template <class Key,class Data>
inline void swap(Record<Key,Data> & a,Record<Key,Data> & b )
{Record<Key,Data> t;
t=a;a=b;b=t;
}
//обмен, если 1-ый ключ > 2-го
template <class Key,class Data>
inline void IfMoreThenSwap(Record<Key,Data> & a,Record<Key,Data> & b )
{if (a > b) { Record<Key,Data> t; t=a;a=b;b=t;}
}
// сравнение ключей
template <class Key,class Data>
inline int compare (Record<Key,Data> & a,Record<Key,Data> & b )
{return a>b?1:a==b?0:-1;
}
# elif defined _STR_N //ключ - строка длиной LEN_STR
# include <string.h>
//в программе перед # include <type.h> определять const LEN_STR = число;
typedef char Key[LEN_STR+1]; //+1 для хранения признака конца строки - '\0'
template <class Data> struct Record
{Key key;
Data data;
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b)
{return _fstrcmp(key,b.key)>0;
}
int operator < ( Record & b)
{return _fstrcmp(key,b.key)<0;
}
int operator <= ( Record & b)
{return _fstrcmp(key,b.key)<=0;
}
int operator == ( Record & b)
{return _fstrcmp(key,b.key) == 0;
}
void operator = ( char *s); //запись ключа в структуру типа Record
void PrnKey() { char *w=key; cout << w <<' ';}
}
template <class Data>
int compare ( Record<Data> & a, Record<Data> & b)
{return _fstrcmp(a.key,b.key);}
template <class Data>
void Record<Data> :: operator = ( char *s)
{
int j=0;
for(;j<LEN_STR && *s !='\0';j++) key[j] =*s++;
key[j]='\0';
}
# elif defined _CHAR_PTR //ключ - строка Си
# include <string.h>
// т.к. С++ не допускает перегрузки операций для встроенных типов
// создадим обертку для char * в виде структуры
typedef struct Key { char * key_ptr;};
template <class Data> struct Record
{Key key; //ключ
Data data; //данные
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b)
{return _fstrcmp(key.key_ptr,b.key.key_ptr)>0;
}
int operator < ( Record & b)
{return _fstrcmp(key.key_ptr,b.key.key_ptr)<0;
}
//запись ключа в структуру типа Record
void operator = (char *s) { key.key_ptr =s;}
void PrnKey() { cout << key.key_ptr <<' ';}
}//struc Record
template <class T>
inline int compare (Record<T> & a,Record<T> & b )
{return _fstrcmp(a.key.key_ptr,b.key.key_ptr;)
}
# endif //типа ключа
//функции обмена для строк
//если ключ - строка длиной LEN_STR или указатель на char
# if defined _STR_N || defined _CHAR_PTR
//обмен
template <class Data>
inline void swap(Record<Data> & a,Record<Data> & b )
{Record<Data> t;
t=a;a=b;b=t;
}
//обмен, если 1-ый ключ > 2-го
template <class Data>
inline void IfMoreThenSwap(Record<Data> & a,Record<Data> & b )
{if (a > b) { Record<Data> t; t=a;a=b;b=t;}
}
# endif // строк
# endif //защиты от повторного использовани



Вот то что написано в методичке (как надо работать с этим хэдером)

Цитата
Первые два этапа выполняются на небольшом массиве, задаваемом программно в наиболее общем случае так :
Record <тип ключа, тип данных> ИмяМ%u
volvo
klem, у тебя в хидере ошибка smile.gif

вот так пиши в CPP:
#define _NUMBER

#include "type.h"

int main() {

Record <int,int> a[] = {{12,456}, {12,0}};
return 0;

}


А в хидере одна запятая не на своем месте smile.gif
klem4
shok.gif как же тяжело когда не знаешь язык ... А type.h препод писал smile.gif У нас кстати в группе мало кто сомневался в том, что в нем нем ошибки, не смотря на что что никто не мог понять вообще что там написано smile.gif)
klem4
Помогите пожалуйста написать шаблон для вывода массивов, ковырялся, эксперементировал, но так ничего и не получилось ...

На сколько я понял, чтобы совершать какие-лиюо операции с переменно типа Record, их сначала нужно переопределить... ? И еще вопрос

Из type.h :

Цитата
int operator > ( Record & b) {return key > b.key;}


.b - это вообще от куда взялось ?
volvo
Цитата
.b - это вообще от куда взялось ?

Формальный параметр?

(Кстати, этот оператор надо бы перегружать вот так:
Цитата
int operator > (const Record &b) {return key > b.key;}

- на всякий случай, чтобы объект по ссылке ни в коем случае не изменился, а то знаем мы этих любознательных экспериментаторов... smile.gif )

Хм... Шаблон для вывода массивов...
Переопределяй для начала операцию вывода в ostream для Record-а:
// В любом месте ПОСЛЕ описания struct Record { ... }
template <class Key, class Data>
ostream&
operator << (ostream &os, Record<Key, Data> &r) {

os << r.key << ", " << r.data << endl;
return os;
}

// И в основной программе распечатывай весь свой массив:
int main() {
Record<int, int> a[] = {{10, 10}, {12, 15}};

long n = sizeof(a) / sizeof(a[0]);
for(int i = 0; i < n; ++i)
cout << (a[i]); // Вызывается переопределенная выше операция

return 0;
}


P.S. На MinGW точно работает - проверил... Не уверен, что TC++ сможет это проглотить...
klem4
Спасибо, TC ++ пишет illegal structure operation .. Щас попробую на MinGW, правда там у меня какие-то другие проблемы были ... щас посмотрю.
klem4
В общем для массивов int и unsigned int все прошло гладко, а вот для массива строк ругается на type.h ... Помогите чем можите ;(

# define _CHAR_PTR
const LEN_STR = 4;

# include <iostream.h>
# include <stdio.h>
# include <conio.h>

# include "type.h"
# include "funcsort.h"


void print(Record<char*> a[LEN_STR], long n){
for (long i = 0; i < n; i++) printf("%s\n", a[i]);
}



int main (void){

Record<char*> a[LEN_STR] = {{"abcd",0}, {"adcb",0}, {"aabc",0}};

clrscr();

long N = sizeof(a) / sizeof(a[0]);


cout << "\nBefore sorting :\n ";
print(a, N);
SortInsert(a, N);
cout << "\nAfter sotring :\n";
print(a, N);


getch();
return 0;
}



type.h

//Структуры для хранения данных и ключей в массиве
# ifndef _DATA // защита от повторного включения этого файла
# define _DATA // в другой
# include <iostream.h>
# ifdef _NUMBER //ключ - число (типа int, long, float и т.д.)
//шаблоны позволяют использовать один и тот же код
//для различных типов данных и ключей
template <class Key,class Data>
struct Record
{Key key;
Data data;
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b) {return key > b.key;}
int operator < ( Record & b) {return key < b.key;}
int operator <= ( Record & b) {return key <= b.key;}
int operator == ( Record & b) {return key == b.key;}

char operator << (Record & b) {return data;}

void operator = (Key n){key=n;}

void PrnKey (){ cout << key<<' ';}
};

/* My proc*/
template <class Key, class Data>
ostream&
operator << (ostream &os, Record<Key, Data> &r) {

os << r.key << ", " << r.data << endl;
return os;
}

/* End My proc*/
template <class Key,class Data>
inline void swap(Record<Key,Data> & a,Record<Key,Data> & b )
{Record<Key,Data> t;
t=a;a=b;b=t;
}
//обмен, если 1-ый ключ > 2-го
template <class Key,class Data>
inline void IfMoreThenSwap(Record<Key,Data> & a,Record<Key,Data> & b )
{if (a > b) { Record<Key,Data> t; t=a;a=b;b=t;}
}
// сравнение ключей
template <class Key,class Data>
inline int compare (Record<Key,Data> & a,Record<Key,Data> & b )
{return a>b?1:a==b?0:-1;
}
# elif defined _STR_N //ключ - строка длиной LEN_STR
# include <string.h>
//в программе перед # include <type.h> определять const LEN_STR = число;
typedef char Key[LEN_STR+1]; //+1 для хранения признака конца строки - '\0'
template <class Data> struct Record
{Key key;
Data data;
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b)
{return _fstrcmp(key,b.key)>0;
}
int operator < ( Record & b)
{return _fstrcmp(key,b.key)<0;
}
int operator <= ( Record & b)
{return _fstrcmp(key,b.key)<=0;
}
int operator == ( Record & b)
{return _fstrcmp(key,b.key) == 0;
}
void operator = ( char *s); //запись ключа в структуру типа Record
void PrnKey() { char *w=key; cout << w <<' ';}
}
template <class Data>
int compare ( Record<Data> & a, Record<Data> & b)
{return _fstrcmp(a.key,b.key);}
template <class Data>
void Record<Data> :: operator = ( char *s)
{
int j=0;
for(;j<LEN_STR && *s !='\0';j++) key[j] =*s++;
key[j]='\0';
}
# elif defined _CHAR_PTR //ключ - строка Си
# include <string.h>
// т.к. С++ не допускает перегрузки операций для встроенных типов
// создадим обертку для char * в виде структуры
typedef struct Key { char * key_ptr;};
template <class Data> struct Record
{Key key; //ключ
Data data; //данные
//перегрузка операций > и < для сравнения ключей структур
int operator > ( Record & b)
{return _fstrcmp(key.key_ptr,b.key.key_ptr)>0;
}
int operator < ( Record & b)
{return _fstrcmp(key.key_ptr,b.key.key_ptr)<0;
}
//запись ключа в структуру типа Record
void operator = (char *s) { key.key_ptr =s;}
void PrnKey() { cout << key.key_ptr <<' ';}
}//struc Record
template <class T>
inline int compare (Record<T> & a,Record<T> & b )
{return _fstrcmp(a.key.key_ptr,b.key.key_ptr;))
}
# endif //типа ключа
//функции обмена для строк
//если ключ - строка длиной LEN_STR или указатель на char
# if defined _STR_N || defined _CHAR_PTR
//обмен
template <class Data>
inline void swap(Record<Data> & a,Record<Data> & b )
{Record<Data> t;
t=a;a=b;b=t;
}
//обмен, если 1-ый ключ > 2-го
template <class Data>
inline void IfMoreThenSwap(Record<Data> & a,Record<Data> & b )
{if (a > b) { Record<Data> t; t=a;a=b;b=t;}
}
# endif // строк
# endif //защиты от повторного использовани файла

klem4
Тек-с ... вроде вопрос снят, методом научного тыка - добавлением недостающий точек с запятой и скобок type.h - исправлен.
volvo
Исправляй вот тут (TYPE.H):
# elif defined _CHAR_PTR // ключ - строка Си
...
template <class T>
inline int compare (Record<T> & a,Record<T> & b )
{
return _fstrcmp(a.key.key_ptr,b.key.key_ptr); // <-- !!! Должно быть так !!!
}


После этого все компилируется, правильность работы не проверял...
klem4
Решил немного разобраться с этими шаблонами, как там и что. Написал упрощенную версию того что мне нужно, только вот в MinGW это компилируется и отрабатывает без ошибок (видимых по карйней мере), а вот TC++ это компилить не хочет, у меня указывает на ф-ю Sort и говорит что Undefined structure 'array<type>'. Как заставить это пахать на TC++ ? И у кого есть возможность,. попробуйте пожалуйста запустить это на билдере и/или VC++.

# include <iostream.h>

template <class type>
struct array{
type Data; // naii cia?aiea yeaiaioa ianneaa

int operator > (array & b) {return Data > b.Data;}
int operator < (array & b) {return Data < b.Data;}
int operator >= (array & b) {return Data >= b.Data;}
int operator <= (array & b) {return Data <= b.Data;}

void PrintData() {cout << Data << '\n';};
};

template <class type>
void Print(type arr[], int n){
for (int i = 0; i < n; i++) arr[i].PrintData();
}

template <class type>
void Swap(type *a, type *b){
type T;
T = *a;
*a = *b;
*b = T;
};


template <class type>
void Sort(array<type> arr[], int n){
bool flag;
do{
flag = true;
for (int i = 0; i < n - 1; i++)
if (!(arr[i] >= arr[i+1])){
Swap(&arr[i], &arr[i+1]);
flag = false;
}
} while (!flag);
};



int main(void){

array <int> a[] = {{3}, {2}, {13}, {-12}, {0}, {0}, {1}};
//array <char*> c[] = {{"bca"}, {"bac"},{"cba"},{"cab"},{"acb"},{"abc"}};

int N = sizeof(a) / sizeof(a[0]);
Sort(a, N);
Print(a, N);

return 0;
}
volvo
ТС спокойно отрабатывает (c int-ом, для char * нужно другое определение операций равенства - специальное определение шаблонного класса. Показать, как? ):
# include <iostream.h>

template <class type>
struct array{
type Data; // naii cia?aiea yeaiaioa ianneaa

int operator > (array & b) {return Data > b.Data;}
int operator < (array & b) {return Data < b.Data;}
int operator >= (array & b) {return Data >= b.Data;}
int operator <= (array & b) {return Data <= b.Data;}

void PrintData() {cout << Data << '\n';};
};

template <class type>
void Print(type arr[], int n){
for (int i = 0; i < n; i++) arr[i].PrintData();
}

template <class type>
void Swap(type *a, type *b){
type T;
T = *a;
*a = *b;
*b = T;
};


template <class type>
void Sort(array<type> *arr, int n){
int flag;
do{
flag = 1;
for (int i = 0; i < n - 1; i++)
if (!(arr[i] >= arr[i+1])){
Swap(&arr[i], &arr[i+1]);
flag = 0;
}
} while (!flag);
};



int main(void){

array<int> a[] = {{3}, {2}, {13}, {-12}, {0}, {0}, {1}};
//array <char*> c[] = {{"bca"}, {"bac"},{"cba"},{"cab"},{"acb"},{"abc"}};

int N = sizeof(a) / sizeof(a[0]);
Sort(a, N);
Print(a, N);

return 0;
}


ICC 8.0 работает с первым вариантом так же, как и со вторым... Остальных компилеров нету sad.gif

P.S. все-таки, Swap лучше наверное делать со ссылками, а не с указателями...
klem4
Цитата
специальное определение шаблонного класса. Показать, как? ):


Ээ, если я ничего не пропустил, покажи .. вроде строки нормально сравнивает ..

Цитата
P.S. все-таки, Swap лучше наверное делать со ссылками, а не с указателями...


И вот это тоже smile.gif
volvo
Цитата(klem4 @ 12.03.2006 21:45)
вроде строки нормально сравнивает ..

abc
acb
cab
cba
bac
bca

Как-то не очень по алфавиту, тебе не кажется?

Цитата(klem4 @ 12.03.2006 21:45)
И вот это тоже smile.gif

template <class type>
void Swap(type &a, type &b){
type T = a;
a = b;
b = T;
};

// Вызывать так:
Swap(arr[i], arr[i+1]);
klem4
Ну да, я посмотрел что у гения препода в файле, так он для переопределения операция для разныех типов использовал define-ы, а на сколько я понял можно(и нужно) как -то сделать без них ? Буду благодарен если объяснишь как, сегодня буду Подельского на лекциях читать smile.gif
volvo
Смотри:
# include <iostream.h>
# include <string.h>

template <class type>
struct array{
type Data;

int operator > (const array & b);
int operator < (const array & b);
int operator >= (const array & b);
int operator <= (const array & b);

void PrintData() {
cout << Data << '\n';
};
};

// Это - общее определение операций для шаблонного класса
template <class T>
int array<T> :: operator > (const array<T> & b)
{ return Data > b.Data; }
template <class T>
int array<T> :: operator < (const array<T> & b)
{ return Data < b.Data; }
template <class T>
int array<T> :: operator >= (const array<T> & b)
{ return Data >= b.Data; }
template <class T>
int array<T> :: operator <= (const array<T> & b)
{ return Data <= b.Data; }

// А вот это - конкретизация для array<char *>
// т.е. вместо той, общей операции будет работать именно эта,
// специально для char * и ТОЛЬКО для него созданная...

int array<char *> :: operator > (const array<char *> &b) {
return (strcmp(Data, b.Data) > 0);
}
int array<char *> :: operator < (const array<char *> &b) {
return (strcmp(Data, b.Data) < 0);
}
int array<char *> :: operator >= (const array<char *> &b) {
return (strcmp(Data, b.Data) >= 0);
}
int array<char *> :: operator <= (const array<char *> &b) {
return (strcmp(Data, b.Data) <= 0);
}


// Дальше - опять все общее...
template <class type>
void Print(type arr[], int n){
for (int i = 0; i < n; i++) arr[i].PrintData();
}

template <class type>
void Swap(type &a, type &b){
type T = a;
a = b;
b = T;
};


template <class type>
void Sort(array<type> *arr, int n){
int flag;
do{
flag = 1;
for (int i = 0; i < n - 1; i++)
if (!(arr[i] >= arr[i+1])){
Swap(arr[i], arr[i+1]);
flag = 0;
}
} while (!flag);
};



int main(void){

// array<int> a[] = {{3}, {2}, {13}, {-12}, {0}, {0}, {1}};
array <char*> a[] = {{"bca"}, {"bac"},{"cba"},{"cab"},{"acb"},{"abc"}};

int N = sizeof(a) / sizeof(a[0]);
Sort(a, N);
Print(a, N);

return 0;
}

Ну, и как? Нужны define-ы ? Или все-таки так проще понять? wink.gif
klem4
Спасибо !
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.