Консультация № 178394
14.05.2010, 19:31
0.00 руб.
0 5 1
Доброго времени суток, дорогие эксперты.

Требуется решить задачу на Code::Block

Дан файл, компонентами которого являются n-мерные векторы (n-const).
Векторы с наибольшим модулем перенести в конец файла.

Если возможно, то не использовать вспомогательный фаил.

Алгоритм(помогите запрограммировать:
1)открыть фаил для чтения и для записи(не стирая содержимого, так как там векторы будут)
2)Среди всех записей векторов найти те векторы, чьи модули равны и самые большие по отношению к другим модулям других векторов.
3)Перенести эти Векторы с максимальным модулем в конец.
4) закрыть фаил

Фаил должен быть представлен как текстовый!

Спасибо за внимание.

Обсуждение

Неизвестный
17.05.2010, 13:27
общий
Юдин Евгений Сергеевич:
Это должно быть на Си или С++?
Вообще, довольно затруднительно не использовать здесь временный файл... Если просто переписывать векторы в конец, то на их местах что тогда будет - пустые строки что ли? Можно, конечно, сначала все просмотреть, запомнить позицию и модуль, потом отсортировать и переставлять векторы местами прямо в файле, но это, мягко говоря, не оптимальный алгоритм.
Неизвестный
18.05.2010, 13:33
общий
Если уж реально без фаила невозможна и проблемно очень то с фаилом тогда.. А вместо векторов которые ушли в конец ничего не осуществлять..... На сволько я знаю можно вставлять записи и потом отсекать
Неизвестный
18.05.2010, 13:34
общий
на си или си++ без разницы
Неизвестный
18.05.2010, 20:34
общий
Юдин Евгений Сергеевич:
Можно затереть одну запись другой, если файл открыт для записи и чтения, не более того. То есть можно, например, затереть строку пробелами. Но при любом варианте так никогда не делают, потому что работа с файлом напрямую - очень затратная операция в смысле ресурсов, да и в целом так работать опасно, потому что можно потерять данные из-за какой-нибудь непредвиденной ошибки алгоритма. File mapping, который Вам рекомендовали в том вопросе, конечно, хорошая вещь, но, подозреваю, для Вам не требуется такое серьёзное решение (можете тут почитать, что это такое).
Посмотрите мой ответ в мини-форуме Вашего вопроса 178390, эта задача аналогична за исключением того, что там бинарный файл, а здесь - текстовый, что добавляет мороки. Если Вас такой алгоритм устраивает, могу переписать и для этой задачи.
Неизвестный
19.05.2010, 02:45
общий
это ответ
Здравствуйте, Юдин Евгений Сергеевич.
Сделано по аналогии с Вашим вопросом 178390. Опять же, с использованием временного файла. Единственное различие в том, что здесь нужно считывать строку и разбирать её на числовые компоненты (чтобы посчитать модуль). Числа в файле должны быть разделены пробелами, например, файл может выглядеть так:
Код:
1 2 3 
3 4 5
1 2 3

Проверялось также на Visual Studio.
Удачи!

Приложение:
#include <iostream>
#include <string.h>
#include <math.h>
#include <conio.h>
#include <stdio.h>
using namespace std;

#define n 3 //размерность

void CreateFile () //например, так можно создать файл
{
FILE* fl;
fopen_s (&fl, "c:\\in", "wb");
int a[] = {3, 4, 5};
int b[] = {1, 2, 3};
for (int i=0; i<3; i++) {
fwrite (a, sizeof(int), n, fl);
fwrite (b, sizeof(int), n, fl);
}
fclose (fl);
}

double Module (int* a) //вычисление модуля
{
double s = 0;
for (int i=0; i<n; i++)
s+=(a[i]*a[i]);
return sqrt (s);
}

int main(int argc, char* argv[])
{
//CreateFile (); - можно создать файл
FILE* fl, *tmp;
fopen_s (&fl, "c:\\in.txt", "rt"); //входной
fopen_s (&tmp, "c:\\tmpout.txt", "wt"); //временный

int buf[n]; //буфер для чтения
double max; //максимальный модуль
int maxmod = 100; //число векторов, если будет больше, будем расширять вектор
double *mod = new double [maxmod]; //модули
char str[256], *p; //строка для чтения
int ind = 0;

while (!feof(fl)) { //считаем модули векторов и сохраняем
fgets (str, 255, fl);
p = strtok (str, " "); //разбираем строку на элементы
for (int i=0; i<n; i++) {
if (p!=NULL)
buf[i] = atoi (p); //получаем число
else buf[i] = 0;
p = strtok (NULL, " ");
}
mod[ind] = Module (buf);
ind++;
if (ind>=maxmod) { //если кончилось место - расширяем
double *t = mod;
mod = new double [maxmod*2];
memcpy (mod, t, sizeof(double)*maxmod);
maxmod*=2;
delete [] t;
}
}
fseek (fl, SEEK_SET, 0); //идём в начало файла

max = mod[0]; //ищем максимальный модуль
for (int i=1; i<ind; i++)
if (mod[i]>max) max=mod[i];

bool lnf = false; //Флаг, чтобы вставить перенос строки, если векторы будем перемещать после последнего
for (int i=0; i<ind; i++) { //переписываем все, кроме максимальных
fgets (str, 255, fl);
if (mod[i]==max) continue;
if (i==ind-1) lnf=true;
fputs (str, tmp);
}
fseek (fl, SEEK_SET, 0);
for (int i=0; i<ind; i++) { //переписываем максимальные
fgets (str, 255, fl);
if (mod[i]!=max) continue;
if (lnf) {fputs ("\r\n", tmp); lnf=false;}
fputs (str, tmp);
}
fclose (fl); //закрываем файлы
fclose (tmp);

remove ("c:\\in.txt"); //удаляем старый
rename ("c:\\tmpout.txt", "c:\\in.txt"); //переименовываем новый в старый

delete [] mod;

cout << "Success";

_getch();
return 0;
}
Форма ответа