Консультация № 178286
08.05.2010, 17:31
0.00 руб.
0 13 2
Здравствуйте, уважаемые эсперты! Не могли бы вы помочь с решением 2х задач:
1) Дана квадратная целочисленная матрица размера N×N. Удалить из матрицы строку,
содержащую максимальную разницу между элементами главной и побочной диагоналей.
Полученную матрицу вывести на экран.
Не знаю как огранизовать цикл для подсчета разности.
2) Бинарный файл содержит вещественные числа. Увеличить в два раза все значения
меньшие среднего арифметического значения всего файла.
Спасибо заранее.

Обсуждение

давно
Академик
320937
2216
10.05.2010, 14:43
общий
Беляев Валерий Сергеевич:
Добрый день!
1. Что означает "максимальная разница"? По абсолютной величине?
2. Что означает "удалить строку"? Число строк задается динамически? Или перенести в конец и не печатать?
Неизвестный
11.05.2010, 09:10
общий
1) Да, по модулю. Разница считается так: а11-а1n, a22-a2(n-1), a33-a3(n-2)... Я так понимаю )
2) Размеры матрицы вводит пользователь. Строку надо удалить полностью.
давно
Академик
320937
2216
13.05.2010, 11:44
общий
это ответ
Добрый день! Ответ на второй вопрос. Code::Blocks/G++
Код:
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
int i;
int numbers, count;
time_t t;
double d; // считываемое число
double sum; // сумма
double avg; // среднее
long begin, end;
int size;

srand(time(&t)); // инициализируем генератор случайных чисел

// создаем файл
ofstream fdata("data.dat", ios::binary|ios::out|ios::trunc);

if (!fdata)
{
cerr << "Unable to write to data.dat" << endl;
system("Pause");
exit(1);
}

// записали случайное количество случайных чисел
// в файл "data.dat"
numbers = (25+rand()%100)/5;

for (int i = 0; i < numbers; i++)
{
d = rand()%100-50+static_cast<double>(rand())/100;
fdata.write((char *)&d, sizeof(double));
}

fdata.close();

fstream bin_data("data.dat", ios::binary|ios::in|ios::out);
if (!bin_data)
{
cerr << "Unable to write to data.dat" << endl;
system("Pause");
exit(1);
}
// Вычисляем размер файла
bin_data.seekg(0, ios::end);
end=bin_data.tellg();

bin_data.seekg(0, ios::beg);
begin=bin_data.tellg();

size = (end-begin)/sizeof(double);

// Содержимое файла до изменения
bin_data.seekg(0);
cout << "Before ";
for (int i=0; i<size; i++)
{
bin_data.read((char *)&d, sizeof(double));
cout << d << ' ';
}
cout << endl;

// Вычисление суммы и среднего
sum = 0;
bin_data.seekg(0);
for (int i=0; i<size; i++)
{
bin_data.read((char *)&d, sizeof(double));
sum+=d;
}
avg = sum / size;

cout << endl;
cout << "sum = " << sum << endl;
cout << "numbers= " << numbers << endl;
cout << "avg = " << avg << endl;

// Внесение изменений
bin_data.seekg(0);
for (int i=0; i<size; i++)
{
long curr=bin_data.tellp();
bin_data.read((char *)&d, sizeof(double));
if (d<avg)
{
d*=2;
bin_data.seekp(curr, ios::beg);
bin_data.write((char *)&d, sizeof(double));
}
}

// Содержимое файла после изменений
bin_data.seekg(0);
cout << endl << "After ";
for (int i=0; i<size; i++)
{
bin_data.read((char *)&d, sizeof(double));
cout << d << ' ';
}
cout << endl;

bin_data.close();
system("pause");
return 0;
}


Пример работы
Код:
Before 327.84 314.4 106.42 257.3 6.97 255.51 -5.39 320.55 103.89 122.96 283.81 139.22 38.58 2.61 237.54 61.85 330.36 147.77 34.96 

sum = 3087.15
numbers= 19
avg = 162.482

After 327.84 314.4 212.84 257.3 13.94 255.51 -10.78 320.55 207.78 245.92 283.81 278.44 77.16 5.22 237.54 123.7 330.36 295.54 69.92
Для продолжения нажмите любую клавишу . . .


Неизвестный
14.05.2010, 17:00
общий
это ответ
Здравствуйте, Беляев Валерий Сергеевич.

Предлагаю решение первой задачи (см. приложение).
Чтобы не вводить матрицу вручную, создайте файл, содержащий матрицу в требуемом формате (см. комментарии в теле программы) и воспользуйтесь
перенаправлением ввода:

178286.exe < file_with_matrix

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

Программа протестирована в MSVC++ 6.0 и MS Visual Studio 2005.

Успехов!

Приложение:
/*
Дана квадратная целочисленная матрица размера NxN. Удалить из матрицы строку,
содержащую максимальную разницу между элементами главной и побочной диагоналей.
Полученную матрицу вывести на экран.
*/

#include <conio.h>
#include <iostream> // заменить на iostream.h для Borland C++
#include <string.h>
using namespace std; // удалить для Borland C++

class Matrix
{
public:
Matrix( int nRows, int nCols );
~Matrix();

int* operator[]( int iRow );
const int* operator[]( int iRow ) const;
int searchMaxDif();
void deleteRow( int iRow );

// Оператор ввода
friend istream& operator>>( istream& stream, Matrix& m );
// Оператор вывода
friend ostream& operator<<( ostream& stream, const Matrix& m );

protected:
int m_nRows, m_nCols;
int* m_x;
};

// возвращает указатель на первый элемент строки iRow (нумерация с 0)
inline int* Matrix::operator[]( int iRow )
{
return m_x + iRow*m_nCols;
}

inline const int* Matrix::operator[]( int iRow ) const
{
return m_x + iRow*m_nCols;
}


Matrix::Matrix( int nRows, int nCols ) :
m_nRows( nRows ), m_nCols( nCols )
{
m_x = new int[ nRows*nCols ];
}

Matrix::~Matrix()
{
delete m_x; m_x = 0;
}

// Функция ищет строку, содержащую максимальную разницу между
// элементами главной и побочной диагоналей.
int Matrix::searchMaxDif()
{
if( m_nRows != m_nCols ) return -1; // ошибка, нужна квадратная матрица

int maxdif = -1; // максимум разницы
int imax = -1; // индекс соответствующей строки

for( int i = 0; i < m_nRows; ++i ) {
int* pRow = (*this)[i];
int dif = pRow[i] - pRow[m_nCols-i-1];
if( dif < 0 ) dif = -dif;
// контрольный вывод для отладки
// cout << '|' << pRow[i] << " - " << pRow[m_nCols-i-1] << "| = " << dif << endl;
if( dif > maxdif ) { maxdif = dif; imax = i; }
}
return imax;
}

// удаляет строку iRow из матрицы
void Matrix::deleteRow( int iRow )
{
if( iRow < m_nRows ) {
// Если надо удалить последнюю строку, то просто уменьшаем
// значение m_nRows. При удалении из середины дополнительно
// перемещаем значения.
if( iRow < --m_nRows ) {
int* pRow = (*this)[iRow];
memmove( pRow, pRow+m_nCols, sizeof(int)*m_nCols );
}
}
}


// чтение матрицы со стандартного ввода
istream& operator>>( istream& stream, Matrix& m )
{
for( int i=0; i < m.m_nRows; i++ )
for( int j=0; j < m.m_nCols; j++ )
stream >> m[i][j];

return stream;
}

// печать матрицы на стандартный вывод
ostream& operator<<( ostream& stream, const Matrix& m )
{
for( int i=0; i < m.m_nRows; i++ ) {
for( int j=0; j < m.m_nCols; j++ ) {
stream.width(3);
stream << m[i][j];
}
stream << endl;
}
return stream;
}


/*
Пример (исходный файл):
5
2 3 4 5 6
8 10 12 14 16
3 3 3 3 3
1 5 10 15 15
1 2 3 2 1

Программа выводит на экран:

-- input --
2 3 4 5 6
8 10 12 14 16
3 3 3 3 3
1 5 10 15 15
1 2 3 2 1
-- result --
2 3 4 5 6
8 10 12 14 16
3 3 3 3 3
1 2 3 2 1

Чтобы не вводить матрицу вручную, создайте файл, содержащий матрицу в
таком формате и воспользуйтесь перенаправлением ввода:

178286.exe < file_with_matrix
*/
int main()
{
// читаем матрицу со стандартного ввода
// размер
int n;
cin >> n;

Matrix matrix( n, n );
cin >> matrix;

// исходная матрица
cout << "-- input --\n" << matrix;

// обрабатываем матрицу
int iRow = matrix.searchMaxDif();
if( iRow >=0 )
matrix.deleteRow( iRow );

// выводим результат
cout << "-- result --\n" << matrix;

cout << "\nPress any key to exit...";
getch();
return 0;
}
Неизвестный
14.05.2010, 19:08
общий
Забыл сказать: язык должен быть С.
Неизвестный
14.05.2010, 19:21
общий
Беляев Валерий Сергеевич:
Вот здорово!
Переписать самостоятельно с C++ на C сможете? Если затрудняетесь, то вот наметки:
class --> struct
Matrix::func --> func( Matrix* )
cin >> --> scanf или gets/sscanf
cout << --> printf
new --> malloc
delete --> free

Попытайтесь это сделать самостоятельно - это поможет лучше понять и сами программы, и классы в C++. Если уж совсем никак, то обращайтесь.
давно
Академик
320937
2216
14.05.2010, 19:42
общий
Беляев Валерий Сергеевич:
Добрый вечер!
Цитата: 286649
Забыл сказать: язык должен быть С

Так к задаче про вещественные числа тоже относится?
Неизвестный
14.05.2010, 20:22
общий
К обоим задачам.
давно
Академик
320937
2216
14.05.2010, 21:53
общий
Беляев Валерий Сергеевич:
Смогу только в понедельник. Выложу в мини-форуме.
Неизвестный
14.05.2010, 22:58
общий
Хорошо. А пока попробую сам.
давно
Академик
320937
2216
15.05.2010, 08:50
общий
Беляев Валерий Сергеевич:
Сделаете раньше - выкладывайте свой код, если по нему потребуется помощь.
Неизвестный
15.05.2010, 11:08
общий
хорошо
давно
Академик
320937
2216
17.05.2010, 13:23
общий
Беляев Валерий Сергеевич:
Добрый день! Вынужден принести извинения, до конца недели внезапный "аврал".
Форма ответа