Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C++ Builder
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.08.2009, 16:03   #1
SteeLeT
 
Регистрация: 13.08.2009
Сообщений: 4
По умолчанию Прикладная программа

Возникли проблемы при решении одной задачи по автоматизации трудоемкого процесса. Столкнулся с необходиомостью редактирования большого количества однотипных файлов следующего содержания:

исходный файл: 641_Гранит_Гранит-Огуднево.omp
содержимое:
NAME '1Гран-Огуд1'
TYPE '1'
LEN '0.01'
MMI '1Гран-Огуд1'
P1_R1 '0.5'
P1_X1 '0.4'
P1_B1 '0'
P0_R0 '0.5'
P0_X0 '0.4'
P0_B0 '0'
P_R1 '0.59'
P_R0 '1.0E10'
P_X1 '3.328'
P_X0 '1.0E10'

NAME '2Гран-Огуд1'
TYPE '1'
LEN '6.68'
MMI '2Гран-Огуд1'
P1_R1 '0.4499'
P1_X1 '0.4316'
P1_B1 '0'
P0_R0 '0.4499'
P0_X0 '0.4316'
P0_B0 '0'
P_R1 '0.01'
P_R0 '0.01'
P_X1 '0.01'
P_X0 '0.01'

таких блоков в некоторых файлах до 30 штук
Привести файлы нужно к следующему виду:

название: fixed641_Гранит_Гранит-Огуднево.omp
содержимое:
NAME 'Участок 1'
TYPE '1'
LEN '0.01'
MMI 'ВЛ Г-Огуднев' - //здесь максимум 12 символов, начало всегда ВЛ, далее первая буква названия измерительной подстанции, через дефис сокращенное название второй подстанции воздушной линии
P1_R1 '0.5'
P1_X1 '0.4'
P1_B1 '0'
P0_R0 '0.5'
P0_X0 '0.4'
P0_B0 '0'
P_R1 '0.59'
P_R0 '1.0E10'
P_X1 '3.328'
P_X0 '1.0E10'

NAME 'Участок 2'
TYPE '1'
LEN '6.68'
MMI 'Участок 2'
P1_R1 '0.4499'
P1_X1 '0.4316'
P1_B1 '0'
P0_R0 '0.4499'
P0_X0 '0.4316'
P0_B0 '0'
P_R1 '0.01'
P_R0 '0.01'
P_X1 '0.01'
P_X0 '0.01'

и далее...
Под рукой был Microsoft Visual C++ 6.0 Builder. С моими скудными познаниями в программировании удалось кое-что реализовать, а именно изменение полей NAME и MMI на необходимые значения "Участок n", но лишь в указанном файле, а не во всех файлах папки как нужно, и лишь с ручным вводом первого MMI, вместо автоматического из названия файла.
Код:
#include <fstream.h>
#include <string.h>

int main()
{
	char name[80],MMI1[12];
	int l=0,n=0,m=0;
	bool check=true;
	cout<<"Input file name:";//ввод имени файла с клавиатуры
	cin>>name;
	cout<<name<<endl;
	ofstream fout("buff.tmp");//открываем/создаем буферный файл для записи
	ifstream fin(name);//открываем исходный файл для чтения
	char one[64];
	while (!fin.eof())
	{
		l++;
		fin.getline(one,64);//перебираем строки
		if (strncmp (one,"NAME",4)==0)//сравниваем с NAME
		{
			cout<<one<<endl;
			n++;//счетчик строк с NAME
			fout<<"NAME\t'Участок "<<n<<"'"<<endl;//записываем измененную строку в буфер
			check=false;
		}
		if (strncmp (one,"MMI",3)==0)//сравниваем с MMI
		{
			cout<<one<<endl;
			m++;
			if (m==1)
			{
				cout<<"Input MMI 1"<<endl;//ввод первого IMM с клавиатуры
				cin>>MMI1;
				fout<<"MMI\t'ВЛ "<<MMI1<<"'"<<endl;
			}
			else
			{
				fout<<"MMI\t'Участок "<<m<<"'"<<endl;//записываем в буфер
			}
			check=false;
		}
		if(check)//запись нередактируемых строк в буфер
		{
			fout<<one<<endl;
		}
		check=true;
	}
	fin.close();
	fout.close();
	return 0;
}
Прошу помочь довести до ума, без этой программы у меня уйдут месяца на обработку этих файлов.

Последний раз редактировалось SteeLeT; 13.08.2009 в 16:28.
SteeLeT вне форума Ответить с цитированием
Старый 14.08.2009, 15:02   #2
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,604
По умолчанию

Цитата:
Под рукой был Microsoft Visual C++ 6.0 Builder
Это что за ужас, летящий на крыльях ночи?
Можете сделать собственный парсер файлов такого типа. Это будет легко, потому что у всех файлов одинаковая структура.
А можете заюзать регулярные выражения.
MaTBeu вне форума Ответить с цитированием
Старый 16.08.2009, 19:30   #3
SteeLeT
 
Регистрация: 13.08.2009
Сообщений: 4
По умолчанию

Не так часто приходилось программировать, поэтому каких-то предпочтений в выборе среды нет.

Да, наверно, если бы я был знал о парсерах не понаслышке, это было бы легко
SteeLeT вне форума Ответить с цитированием
Старый 16.08.2009, 21:36   #4
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

Насчет обработки всех файлов в директории посмотрите вот в этой темке:
http://programmersforum.ru/showthread.php?t=60071
там ищутся все файлы с расширением ".txt". Вам, соответственно, нужны файлы ".omp". Думаю, разберетесь.

А вот суть преобразования я как-то не очень понял.
Было: NAME '1Гран-Огуд1'
Стало: NAME 'Участок 1'
Тут, вроде, все ясно. Вытаскиваем число из названия (1) и добавляем вперед "Участок".

Было: MMI '1Гран-Огуд1'
Стало: MMI 'ВЛ Г-Огуднев'
Вначале "ВЛ", потом пробел. Далее:
Цитата:
первая буква названия измерительной подстанции
вот это откуда берется? Из названия (641_Гранит_Гранит-Огуднево.omp)?

И, наконец,
Цитата:
через дефис сокращенное название второй подстанции воздушной линии
то есть: -Огуднев
Это тоже из названия? (641_Гранит_Гранит-Огуднево.omp).
И все это добро обрезается до 12 символов. Так?

Теперь рассмотрим следующую запись:
Было:
Код:
NAME '2Гран-Огуд1'
TYPE '1'
LEN '6.68'
MMI '2Гран-Огуд1'
стало:
Код:
NAME 'Участок 2'
TYPE '1'
LEN '6.68'
MMI 'Участок 2'
Почему MMI '2Гран-Огуд1' превратилось в NAME 'Участок 2'? о_О
Или это такая опечатка?
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 16.08.2009, 21:48   #5
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,604
По умолчанию

Можно сделать синтаксический анализатор для этого всего, грамматику я уже придумал=) Но это будет как минимум на 40 страниц кода.
MaTBeu вне форума Ответить с цитированием
Старый 16.08.2009, 22:53   #6
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

Ну вот, вроде, работает как надо. Но только для одного файла.
Всю работу делает функция fun, которая принимает ссылку на файловый поток и имя файла.

Код:
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;

void fun(ifstream &fin, char *fname)
{
 char buf[500];
 char str[500];
 char *p,*l;
 int m=0;
 int k;
 
 strcpy(buf,"fixed");
 strcat(buf,fname);
 strcat(buf,"\0");
 ofstream fout(buf);
 
 while(!fin.eof())
  {
   fin.getline(str,500,'\n'); // читаем NAME
   ++m;
   fout<<"NAME\t'Участок "<<m<<"'"<<endl;
   fin.getline(str,500,'\n'); // читаем TYPE
   fout<<str<<endl;
   fin.getline(str,500,'\n'); // читаем LEN
   fout<<str<<endl;
   
   fin.getline(str,500,'\n'); // читаем MMI
   if(m==1)
    {
     fout<<"MMI\t'ВЛ ";
     p = strchr(fname,'_');
     p++;
     strncpy(buf,p,1);
     fout<<buf[0];
     
     p = strrchr(fname,'-');
     k = 0;
     strcpy(buf,"");
     l = buf;
     while(*p!='.' && k++<8)
      *l++ = *p++;
     *l = 0;
     fout<<buf<<"'"<<endl; 
    }
    else
     {
      fout<<"MMI\t'Участок "<<m<<"'"<<endl;
     }
    
    for(int i=0; i<10; i++)
     {
      fin.getline(str,500,'\n');
      fout<<str<<endl;
     }
    
    if(!fin.eof()) 
     {
      fin.getline(str,500,'\n');  
      fout<<endl;
     } 
  } //while
 
 
 fout.close();
}


int main()
{
 ifstream fin("641_Гранит_Гранит-Огуднево.omp");
 
 fun(fin,"641_Гранит_Гранит-Огуднево.omp");
 
 fin.close();
 
return 0; 
}
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 17.08.2009, 00:55   #7
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

А вот полная программа на сях.
Меняет файлы с расширением ".omp" в своем каталоге.

Код:
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

void fun(char *fname)
{
 char buf[500];
 char str[500];
 char *p,*l;
 int m=0;
 int k;
 FILE *fin,*fout;

 strcpy(buf,"fixed");
 strcat(buf,fname);
 strcat(buf,"\0");
 
 fin = fopen(fname,"r");
 fout = fopen(buf,"w");

 while(!feof(fin))
  {
   fgets(str,500,fin); // читаем NAME
   ++m;
   fprintf(fout,"NAME\t'Участок %d'\n",m);
   fgets(str,500,fin); // читаем TYPE
   fputs(str,fout);
   fgets(str,500,fin); // читаем LEN
   fputs(str,fout);

   fgets(str,500,fin); // читаем MMI
   if(m==1)
    {
     fprintf(fout,"MMI\t'ВЛ ");
     p = strchr(fname,'_');
     p++;
     strncpy(buf,p,1);
     fprintf(fout,"%c",buf[0]);

     p = strrchr(fname,'-');
     k = 0;
     strcpy(buf,"");
     l = buf;
     while(*p!='.' && k++<8)
      *l++ = *p++;
     *l = 0;
     fprintf(fout,"%s'\n",buf);
    }
    else
     {
      fprintf(fout,"MMI\t'Участок %d'\n",m);
     }

    for(int i=0; i<10; i++)
     {
      fgets(str,500,fin);
      fputs(str,fout);
     }

    if(!feof(fin))
     {
      fgets(str,500,fin);
      fprintf(fout,"\n");
     }
  } //while


 fclose(fin);
 fclose(fout);
}


int main()
{
 DIR *dir;
 struct dirent *entryPtr=NULL;
 
 int ret = 0;
 int cnt = 0;
 char path[1000];
 char *p;
 
 dir = opendir(".");
 if(dir==NULL) return 1;
 
 entryPtr = readdir(dir);
 while(entryPtr)
  {
   struct stat info;
   if(strncmp(entryPtr->d_name,".",1000)==0 || strncmp(entryPtr->d_name,"..",1000)==0)
    {
     entryPtr = readdir(dir);
     continue;
    }
   
   if(stat(entryPtr->d_name,&info)==0)
    {
     cnt++;
     if(S_ISREG(info.st_mode))
      {
       p = strrchr(entryPtr->d_name,'.');
       if(strcmp(p+1,"omp")==0) fun(entryPtr->d_name);
      }
     
    } //if
   entryPtr = readdir(dir);
  } //while
closedir(dir); 
 
return 0; 
}
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 21.08.2009, 22:29   #8
SteeLeT
 
Регистрация: 13.08.2009
Сообщений: 4
По умолчанию

Цитата:
Сообщение от Sazary Посмотреть сообщение
вот это откуда берется? Из названия (641_Гранит_Гранит-Огуднево.omp)?
Первое слово в названии - измерительная подстанция, дальше два слова через дефис - название линии. Может быть, например: ХХХ_Огуднево_Гранит-Огуднево.omp, тогда первый MMI: ВЛ О-Гранит
Цитата:
Сообщение от Sazary Посмотреть сообщение
то есть: -Огуднев
Это тоже из названия? (641_Гранит_Гранит-Огуднево.omp).
И все это добро обрезается до 12 символов. Так?
Да, именно так.
Цитата:
Сообщение от Sazary Посмотреть сообщение
Теперь рассмотрим следующую запись:
Было:
Код:
NAME '2Гран-Огуд1'
TYPE '1'
LEN '6.68'
MMI '2Гран-Огуд1'
стало:
Код:
NAME 'Участок 2'
TYPE '1'
LEN '6.68'
MMI 'Участок 2'
Почему MMI '2Гран-Огуд1' превратилось в NAME 'Участок 2'? о_О
Или это такая опечатка?
Нет, все верно. Дело в том, что бывает по несколько линий между подстанциями. В названии '2Гран-Огуд1' 2 -номер участка, 1- номер линии. По идее в MMI надо еще и номер линии указывать, но таких файлов мало (1-2 из 50) и проще эти номера вписать вручную.

У меня не выходит собрать ваш код. Просит dirent.h (если я правильно понял как раз эта библиотека позволяет работать с директорией). Пытался скачать с нета, он стал просить еще какие-то библиотеки и указывал на кучу синтаксических ошибок.
SteeLeT вне форума Ответить с цитированием
Старый 22.08.2009, 00:07   #9
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

Цитата:
Сообщение от SteeLeT
У меня не выходит собрать ваш код. Просит dirent.h (если я правильно понял как раз эта библиотека позволяет работать с директорией). Пытался скачать с нета, он стал просить еще какие-то библиотеки и указывал на кучу синтаксических ошибок.
Да, именно с помощью нее ищутся файлы.
По идее, внутри него подключается дополнительно только io.h.
Я пользуюсь средой Dev-C++ (http://wxdsgn.sourceforge.net/). Там она входит в комплект.

Цитата:
Сообщение от SteeLeT
Первое слово в названии - измерительная подстанция, дальше два слова через дефис - название линии. Может быть, например: ХХХ_Огуднево_Гранит-Огуднево.omp, тогда первый MMI: ВЛ О-Гранит
Если так, то в программе нужно сделать поправку, чтобы искать не первый символ '_', а второй. То есть строку
Код:
p = strchr(fname,'_');
нужно заменить на что-то, вроде этого:
Код:
p2 = strchr(fname,'_');
p = strchr(p2+1,'_');
Цитата:
По идее в MMI надо еще и номер линии указывать, но таких файлов мало (1-2 из 50) и проще эти номера вписать вручную.
Ну да. Притом еще до автообработки остальных файлов.
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 23.08.2009, 13:37   #10
SteeLeT
 
Регистрация: 13.08.2009
Сообщений: 4
По умолчанию

Скачал Dev-C++. Ну вот вроде заработало. Только в конце дописывает лишние NAME и MMI. И с поправкой все равно и в первом и во втором случае Г-Огуднев пишет.
SteeLeT вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
экзаменационная задачя Беларуского Государственного Университета - Прикладная математика и информатика breate Общие вопросы C/C++ 2 29.01.2009 02:07
Программа Fartyna3000 Операционные системы общие вопросы 4 06.12.2008 23:39
прикладная информатика в экономике Кентавренок Общие вопросы по программированию, компьютерный форум 9 22.05.2008 11:51
прикладная программа по анализу оборотных активов plexter Помощь студентам 1 19.04.2007 10:57