Консультация № 181244
12.12.2010, 09:10
0.00 руб.
0 6 1
Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
Помогите с программой.
Условие:
Матричная арифметика. Элементы матрицы могут быть любого типа с плавающей точкой. Для решения данной задачи использовать шаблон базовых классов (размещение матрицы в динамической памяти и ее инициализация — конструктор, при необходимости — конструктор копирования, деструктор, заполнение матрицы значениями из файла, печать содержимого матрицы в файл) и шаблон производных классов (характеристикой строки матрицы назовем сумму ее положительных элементов, имеющих четные значения индексов; переставляя строки заданной матрицы, расположить их в соответствии с ростом характеристик).

Не понимаю как сделать шаблон базовых классов и шаблон производных классов. Сделал отдельно "характеристикой строки матрицы назовем сумму ее положительных элементов, имеющих четные значения индексов; переставляя строки заданной матрицы, расположить их в соответствии с ростом характеристик", но как его сделать, как шаблон производных классов не понимаю(код в приложении). Также отдельно как сделать "заполнение матрицы значениями из файла, печать содержимого матрицы в файл" знаю, а как сделать шаблон базовых классов не знаю. Помогите правильно, по условию реализовать данное задание.

Приложение:
#include <stdio.h>
#include <stdlib.h>

/* Èìÿ ôàéëà, ñîäåðæàùåãî ýëåìåíòû ìàòðèöû */
#define F_NAME "input.txt"

/* Ôóíêöèÿ äëÿ ñîçäàíèÿ ìàòðèöû ðàçìåðîì [m]x[n] */
int **newMatr(int m, int n);
/* Ôóíêöèÿ äëÿ óäàëåíèÿ ìàòðèöû */
void delMatr(int **matr, int m);
/* Âûâîä ÿ÷ååê êâàäðàòíîé ìàòðèöû â êîíñîëü */
void printM(int **matr, int m, int n);
/* Ôóíêöèÿ äëÿ ñðàâíåíèÿ õàðàêòåðèñòèê ðÿäîâ */
int compRows(const void *lhs, const void *rhs);
/* Êîëè÷åñòâî ñòîëáöîâ */
/* Ãëîáàëüíûé, ò.ê. åãî íóæíî êàê-òî
* ïåðåäàâàòü â ôóíêöèþ compRows() */
int c_cols;


int main()
{
/* Ìàòðèöà */
int **matr;
int c_rows;
/* Ôàéë */
FILE *f_in;
int i, j;

/* Îòêðûâàåì ôàéë */
f_in = fopen(F_NAME, "r");

/* Åñëè ôàéë îòêðûòü íå óäàëîñü */
if (!f_in)
{
printf("Cannot open file "%s"!\n", F_NAME);
return (1);
}

/* ×èòàåì ïåðâûå äâà ÷èñëà â ôàéëå - ðàçìåðíîñòü ìàòðèöû */
if ((fscanf(f_in, "%d", &c_rows) == EOF)
|| (fscanf(f_in, "%d", &c_cols) == EOF))
{
fclose(f_in);
printf("Error: File "%s" is empty!\n", F_NAME);
return (1);
}

/* Ðàçìåð ìàòðèöû */
if ((c_cols <= 0) || (c_rows <= 0))
{
fclose(f_in);
printf("Error: Wrong matrix size!\n");
return (1);
}

/* Äèíàìè÷åñêè ñîçäàåì ìàòðèöó */
matr = newMatr(c_rows, c_cols);
if (!matr)
{
fclose(f_in);
printf("Error: Cannot allocate memory!\n");
return (1);
}

i = j = 0;
/* ×èòàåì ñîäåðæèìîå ôàéëà */
while ((j < c_rows) && (fscanf(f_in, "%d", &matr[j][i]) != EOF))
{
++i;
if (i == c_cols)
{
i = 0;
++j;
}
}

/* Ôàéë áîëüøå íå íóæåí */
fclose(f_in);

/* Åñëè îêàçàëîñü, ÷òî â ôàéëå çàïèñàíî ìåíüøå,
* ÷åì [m_size]x[m_size] ýëåìåíòîâ */
if ((j < c_rows) || i)
{
printf("Error: Wrong file size!\n");
delMatr(matr, c_rows);
return (1);
}


/* Ñîðòèðîâêà ðÿäîâ ìàòðèöû ïî èõ õàðàêòåðèñòèêàì */
qsort(matr, c_rows, sizeof(int*), compRows);

/* Âûâîä ðåçóëüòàòà â êîíñîëü */
printM(matr, c_rows, c_cols);

/* Ìàòðèöà áîëüøå íå íóæíà */
delMatr(matr, c_rows);

/* Óñïåøíîå çàâåðøåíèå ïðîãðàììû */
return (0);
}

int **newMatr(int m, int n)
{
int **matr;
int i;

/* Ïîëó÷àåì ïàìÿòü ïîä ìàòðèöó */
matr = (int**)malloc(sizeof(int*)*m);
if (!matr) return (NULL);

/* Ïîëó÷àåì ïàìÿòü äëÿ êàæäîãî ðÿäà ìàòðèöû */
for (i = 0; i < m; ++i)
{
matr[i] = (int*)malloc(sizeof(int)*n);

if (!matr[i])
{
/* Åñëè êàêîìó-òî ðÿäó ïàìÿòè íå õâàòèëî,
* îñâîáîæäàåì óæå ïîëó÷åííóþ ïàìÿòü */
for (--i; i >= 0; --i) free(matr[i]);
free(matr);
return (NULL);
}
}
return (matr);
}

void delMatr(int **matr, int m)
{
int i;
for (i = 0; i < m; ++i)
free(matr[i]);
free(matr);
}

void printM(int **matr, int m, int n)
{
int i, j;

for (j = 0; j < m; ++j)
{
for (i = 0; i < n; ++i)
printf(" %4d", matr[j][i]);
printf("\n");
}
}

int sumChar(int *row, int m)
{
int i, sum;
sum = 0;

for (i = 0; i < m; ++i)
/* Ñóììèðóåì òîëüêî (ïîëîæèòåëüíûå È ÷åòíûå) */
if ((row[i] > 0) && !(row[i] & 1))
sum += row[i];

return (sum);
}

int compRows(const void *lhs, const void *rhs)
{
int sumL, sumR;
sumL = sumChar(*(int**)lhs, c_cols);
sumR = sumChar(*(int**)rhs, c_cols);
/* Ñðàâíåíèå ðÿäîâ ìàòðèöû ïî êîëè÷åñòâó
* ÷åòíûõ ïîëîæèòåëüíûõ ýëåìåíòîâ */
if (sumR > sumL) return (-1);
if (sumL > sumR) return (1);

return (0);
}

Обсуждение

Неизвестный
16.12.2010, 22:00
общий
это ответ
Здравствуйте, Azarov88!
Вот пример Вашей программы с шаблонами. Создаём базовый и производный классы как шаблоны от типа T1, который будет являться типом данных в матрице. И функции, соответственно, разносим по двум классам. Функцию сравнения, которую Вы передаёте в qsort, надо делать статической, из-за чего приходится пользоваться глобальной переменной, в которую непосредственно перед вызовом сохраняем значение члена класса c_col. Не очень красивое решение, но зато минимальные изменения в Вашем коде.
Про шаблоны классов можете почитать в этом уроке и на Википедии.
Шаблоны в приложении, а вот пример использования:
Код:
#include "BaseMatrix.h"

#define F_NAME "input.txt"


int main()
{

ExMatrix<double> matr;
matr.newMatr (F_NAME);
matr.Sort ();
matr.print (NULL);
return 0;
}

Удачи!

Приложение:
#pragma once

int sort_c;

template <typename T1> class BaseMatrix
{
protected:
T1** matr;
int c_rows;
int c_cols;
public:
BaseMatrix(void);
BaseMatrix (BaseMatrix<T1>& bm);
BaseMatrix (char* fname);
~BaseMatrix(void);
void newMatr (char* fname);
void print (char* fname);
void delMatr ();
};

template <typename T1> class ExMatrix: public BaseMatrix<T1>
{
static int compRows(const void *lhs, const void *rhs);
static T1 sumChar(T1 *row);
public:
void Sort ();
};


template <typename T1> BaseMatrix<T1>::BaseMatrix(void)
{
matr = NULL;
c_cols = 0;
c_rows = 0;
}

template <typename T1> BaseMatrix<T1>::BaseMatrix(char* fname)
{
newMatr (fname);
}


template <typename T1> BaseMatrix<T1>::BaseMatrix(BaseMatrix<T1>& bm)
{
if (bm.matr==NULL && matr!=NULL) delMatr();

matr = (int**)malloc(sizeof(int*)*c_rows);

int i, j;

if (matr) {

for (i = 0; i < m; ++i)
{
matr[i] = (int*)malloc(sizeof(int)*c_cols);

if (!matr[i])
{
for (--i; i >= 0; --i) free(matr[i]);
free(matr);
return;
}
}

for (i=0; i<c_rows; i++)
for (j=0; j<c_cols; j++)
matr[i][j] = bm.matr[i][j];
}
}


template <typename T1> BaseMatrix<T1>::~BaseMatrix(void)
{
if (matr!=NULL) delMatr();
}

template <typename T1> void BaseMatrix<T1>::newMatr (char* fname)
{
FILE *f_in;
int i, j;

f_in = fopen(fname, "r");

if (!f_in)
{
printf("Cannot open file "%s"!\n", fname);
return;
}

if ((fscanf(f_in, "%d", &c_rows) == EOF)
|| (fscanf(f_in, "%d", &c_cols) == EOF))
{
fclose(f_in);
printf("Error: File "%s" is empty!\n", fname);
return;
}

if ((c_cols <= 0) || (c_rows <= 0))
{
fclose(f_in);
printf("Error: Wrong matrix size!\n");
return;
}

matr = (T1**)malloc(sizeof(T1*)*c_rows);
if (!matr) return;

for (i = 0; i < c_rows; ++i)
{
matr[i] = (T1*)malloc(sizeof(T1)*c_cols);

if (!matr[i])
{
for (--i; i >= 0; --i) free(matr[i]);
free(matr);
return;
}
}
if (!matr)
{
fclose(f_in);
printf("Error: Cannot allocate memory!\n");
return;
}

i = j = 0;
while ((j < c_rows) && (fscanf(f_in, "%d", &matr[j][i]) != EOF))
{
++i;
if (i == c_cols)
{
i = 0;
++j;
}
}

fclose(f_in);

if ((j < c_rows) || i)
{
printf("Error: Wrong file size!\n");
delMatr();
return;
}

}

template <typename T1> void BaseMatrix<T1>::print (char* fname)
{
int i, j;
FILE* outf = NULL;
if (fname!=NULL)
outf = fopen (fname, "wt");

if (fname == NULL || outf == NULL) {
for (j = 0; j < c_rows; ++j)
{
for (i = 0; i < c_cols; ++i)
printf(" %4d", matr[j][i]);
printf("\n");
}
} else {
for (j = 0; j < c_rows; ++j)
{
for (i = 0; i < c_cols; ++i)
fprintf(outf, " %4d", matr[j][i]);
fprintf(outf, "\n");
}
}
}

template <typename T1> void BaseMatrix<T1>::delMatr ()
{
if (matr==NULL) return;
int i;
for (i = 0; i < c_rows; ++i)
free(matr[i]);
free(matr);
matr = NULL;
}

template <typename T1> int ExMatrix<T1>::compRows(const void *lhs, const void *rhs)
{
T1 sumL, sumR;
sumL = sumChar(*(T1**)lhs);
sumR = sumChar(*(T1**)rhs);
if (sumR > sumL) return (-1);
if (sumL > sumR) return (1);

return (0);
}

template <typename T1> T1 ExMatrix<T1>::sumChar (T1 *row)
{
int i;
T1 sum = 0;

for (i = 0; i < sort_c; ++i)
if ((row[i] > 0) && i%2==0)
sum += row[i];

return (sum);

}

template <typename T1> void ExMatrix<T1>::Sort ()
{
sort_c = c_rows;
qsort(matr, c_rows, sizeof(T1*), &ExMatrix<T1>::compRows);
}
Неизвестный
18.12.2010, 20:16
общий
Спасибо большое, но компилятор вывод ошибку. На строчку matr.print (NULL); в int main(). А если ее убрать, то 14 ошибок. Подскажите пожалуйста, что не так.
Неизвестный
18.12.2010, 21:24
общий
Какая ошибка на принт и какие 14 без него? У меня программа работала, но я пишу в visual studio.
Неизвестный
18.12.2010, 21:54
общий
открывал через Microsoft Visual C++ 6.0.
на принт ошибка: error C2065: 'NULL' : undeclared identifier

14 ошибок:
error C2065: 'NULL' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function '__thiscall BaseMatrix<double>::BaseMatrix<double>(void)'
c:\users\shtep\videos\shsf\xcnxcx.h(32) : error C2440: '=' : cannot convert from 'int' to 'double ** '
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function '__thiscall BaseMatrix<double>::BaseMatrix<double>(void)'
c:\users\shtep\videos\shsf\xcnxcx.h(74) : error C2446: '!=' : no conversion from 'int' to 'double ** '
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function '__thiscall BaseMatrix<double>::~BaseMatrix<double>(void)'
c:\users\shtep\videos\shsf\xcnxcx.h(74) : error C2040: '!=' : 'double ** ' differs in levels of indirection from 'int'
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function '__thiscall BaseMatrix<double>::~BaseMatrix<double>(void)'
c:\users\shtep\videos\shsf\xcnxcx.h(79) : error C2065: 'FILE' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(79) : error C2065: 'f_in' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(79) : warning C4552: '*' : operator has no effect; expected operator with side-effect
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(82) : error C2065: 'fopen' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(86) : error C2065: 'printf' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(90) : error C2065: 'fscanf' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(90) : error C2065: 'EOF' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(93) : error C2065: 'fclose' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(105) : error C2065: 'malloc' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(114) : error C2065: 'free' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall BaseMatrix<double>::newMatr(char *)'
c:\users\shtep\videos\shsf\xcnxcx.h(209) : error C2065: 'qsort' : undeclared identifier
C:\Users\Shtep\Videos\shsf\shds.cpp(16) : while compiling class-template member function 'void __thiscall ExMatrix<double>::Sort(void)'
Error executing cl.exe.
Неизвестный
19.12.2010, 20:58
общий
установил visual studio и все равно те же ошибки
Неизвестный
20.12.2010, 00:48
общий
Специально проверила ещё в Visual Studio 6.0 (изначально под 2005 писала), всё равно всё работает... Попробуйте добавить заголовочные файлы
Код:
#include <stdio.h>
#include <stdlib.h>
Форма ответа