sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 «  : 26-10-2011 16:25 »   | 
								
								 | 
							  
							 
							Всем привет. Задание такое: создать программу обработки учебника по программированию с использованием классов: символ, слово, предложение и т.п. Заменить табуляции и последовательности пробелов одним пробелом. То есть, у меня есть файл с текстом (см. в аттаче). Необходимо прочитать текст из этого файла и обработать его. Я написал класс слово (Word.h): class Word { 	char *wrd; 	int len;
  	void SetWord(char *word); public: 	Word(void): wrd(0), len(0) {} 	Word(char *word); 	Word(const Word &obj); 	~Word(void);
  	int GetLen(void) const {return len;} 	int CharCount(char ch) const; 	char GetFirstSymbol(void) const {return *wrd;} 	void GetWord(char *string, int begindx, int endindx);
  	friend ostream &operator<<(ostream &stream, Word &obj); 	friend istream &operator>>(istream &stream, Word &obj); 	Word operator=(const Word &obj); 	Word operator=(char *word); };
 и класс предложение, являющееся массивом слов и завершающееся одним из "завершителей" (!, ., ?). Sentence.h class Sentence { 	int len; 	int size; 	Word *wrds; 	char *sntnce;
  	void SetSentence(char *sentence); 	bool IsSeparator(char symbol); 	void GetWords(void); 	void DelRepeatSpaces(char *sentence); public: 	Sentence(void): len(0), size(0), wrds(0) {} 	Sentence(char *sentence); 	Sentence(const Sentence &obj); 	~Sentence(void);
  	int GetWordsCount(void); 	int GetLen(void) const {return strlen(sntnce);}
  	friend ostream &operator<<(ostream &stream, Sentence &obj); 	friend istream &operator>>(istream &stream, Sentence &obj); 	Sentence operator=(const Sentence &obj); 	Sentence operator=(char *sentence); };
 А вот что делать дальше - я не придумал. Надо создать класс текст, который будет массивом предложений. Проблема в том, что бы считать из файла количество предложений, выделить необходимую память для всех предложений и записать в каждый из элементов массива предложений эти предложения. Плюс ко всему надо сохранить пунктуацию, т.е. обзацы. Подскажите пожалуйста, как реализовать класс текст.  
						 | 
					 
					
						
							
								
									 
									
										  c++.txt (1.7 Кб - загружено 1079 раз.)
									  
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #1 : 26-10-2011 17:24 »   | 
								
								 | 
							  
							 
							а почему ты не используешь хотябы CString, CStringArray или подобное - там хотябы задача прибивания пробелов или других повторов решается одним вызовом. Массивы, списки ?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #2 : 26-10-2011 17:26 »   | 
								
								 | 
							  
							 
							а почему ты не используешь хотябы CString, CStringArray или подобное - там хотябы задача прибивания пробелов или других повторов решается одним вызовом. Массивы, списки ? 
  Да вопрос не в том, что бы использовать имеющиеся классы типа CString. Меня и мой класс с моими функциями устраивает. Тут вопрос в том, как все это прочитать из файла и загрузить в массив предложений.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									«  Ответ #3 : 26-10-2011 17:44 »    | 
								
								 | 
							  
							 
							так в чем проблема, если разбирать файл "с лету" - fgetc(), если через буфер (считать весь файл в память, затем разбор) - fgets()  ? Или ты имеешь ввиду выделение из потока ?
  ps  (?) редактор:абзац   : предложение: слово         :формат  : разметка  . . . .          :разметка . . . .
 
  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 26-10-2011 17:51 от DneprSMV »
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #4 : 26-10-2011 17:49 »   | 
								
								 | 
							  
							 
							Проблема в том, что размер файла я заранее не знаю. И не знаю, какую память выделять под буфер. Потом, в буфер считается часть файла до перехода на новую строку, т.е. 1 обзац. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #5 : 26-10-2011 17:52 »   | 
								
								 | 
							  
							 
							это учебная задача или реально, где неизвестно какой будет файл - 1 к или 1 гиг ? Добавлено через 23 минуты и 57 секунд:Проблема в том, что размер файла я заранее не знаю. И не знаю, какую память выделять под буфер. Потом, в буфер считается часть файла до перехода на новую строку, т.е. 1 обзац.
  Смотря как будешь считывать и из какого файла. Если обычный текстовый - у тебя считвывается не "абзац" а текстовая строка, и не обязательно это предложение. Сторка - завершается символами 0x0D 0x0A (или просто 0x0A). Если такой формат - используй fgets()-fgetc()   char str1[500]; while( !feof(fd) ) int rc = fgets(str1,500, fd ); Если формат который оперирует абзацами, разметкой итд - напр. RTF - то самому писать будет тяжко и бессмысленно. ------------ в твоем файле в строке (в смысле ограничения 0D-0A) записан абзац. За одно fgets считывание в буфере - соответственно абзац. Длину строки-абзаца принимай из более-менее разумной - например до нескольких кб. Хотя можно узнать хар-ки файла - длину, выделить память по длине, и считать файл в двоичном режиме. Далее все операции - с памятью. Можно считать-обработать и в режиме фильтра, но это сложнее.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 26-10-2011 18:16 от DneprSMV »
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #6 : 26-10-2011 18:31 »   | 
								
								 | 
							  
							 
							Задача учебная.  Файл я прикрепил в первом сообщении, он обычный текстовый. Т.е., после  char str1[500]; while( !feof(fd) )  { int rc = fgets(str1,500, fd ); GetSentencesFrom(str1); } в переменой str1 я получу абзац? и потом смогу разбить его на предложения. И таким образом считаю все абзацы и разделю их на предложения? 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							RuNTiME
							
						 | 
						
							
								  | 
								
									
									 « Ответ #7 : 26-10-2011 18:48 »   | 
								
								 | 
							  
							 
							sd, если задача учебная и нет особых претензий к производительности и эффективности программы, то можно использовать функцию realloc(), которая динамически изменяет размер заранее выделенного блока памяти функцией malloc() и возвращает указатель на новый блок. Т.е. общая стратегия получается таковой (цифры могут быть и другими): 1. Если есть еще строки, выделяем блок памяти под новую строку размером 512 байт 2. Считываем из файла строку в этот буфер, если конец строки не найден, а буфер закончился увеличиваем блок памяти функцией realloc() еще на 512 байт и продолжаем считывать строку до тех пор, пока не найдем конец строки. 3. Нашли конец строки, идем в п.1 Таким образом можно считать весь файл, что каждая строка будет храниться в отдельном блоке памяти. Ну либо использовать готовый класс, как писал  DneprSMV. В них уже реализован подобный алгоритм. Да и чтобы не привязывать свою программу к MFC и другим библиотекам реализующим CString посоветую использовать классы из STL к примеру std::string. P.S: Информация по функциям выделения и освобождения памяти:  http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/ 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 26-10-2011 18:54 от RuNTiME »
								 | 
								
									 
									Записан
								 | 
							  
							 
							Любимая игрушка - debugger ... 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #8 : 26-10-2011 19:23 »   | 
								
								 | 
							  
							 
							sd,  Задача учебная.  Файл я прикрепил в первом сообщении, он обычный текстовый. Т.е., после  char str1[500]; while( !feof(fd) )  { int rc = fgets(str1,500, fd ); GetSentencesFrom(str1); } в переменой str1 я получу абзац? и потом смогу разбить его на предложения. И таким образом считаю все абзацы и разделю их на предложения?
  Да, помоему этого достаточно (не буквально - надо пару операторов дописать - работа с файлом).  Возьми хелповский пример по fgets. осле fgets() в буфере получаешь считанную строку (в содержательном смысле - это абзац из документа). он заканчивается символом 0x00. RuNTiME,  Во входном файле могут быть строки произвольной длины - как раз бы прошло CString - чтобы не отвлекаться на обработку-укладку строк наразвес. Достаточно один раз выделить буфер достаточного размера, и использовать его повторно в цикле, а уже разобранную из него информацию упаковывать в классовую модель со списками-массивами, выделением памяти.  За STL - да.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							RuNTiME
							
						 | 
						
							
								  | 
								
									
									 « Ответ #9 : 26-10-2011 19:33 »   | 
								
								 | 
							  
							 
							Достаточно один раз выделить буфер достаточного размера, и использовать его повторно в цикле DneprSMV, Безусловно можно, я всего лишь предложил самый наипростейший вариант. Повторно использовать память можно и нужно. Если говорить о парсинге чего - либо, то можно вообще обойтись буфером фиксированного размера для считывания и разбора файла и динамическими строками для хранения информации в классах.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Любимая игрушка - debugger ... 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #10 : 26-10-2011 20:24 »   | 
								
								 | 
							  
							 
							class MyTextProcesor { . . .  }   MyTextProcesor mtp; int err; mtp.Clear(); err = mtp.LoadFile("C++.txt"); err = mtp.Parse(); if(err) .....  else    mtp.PrintResult();
    
 
 
 
  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #11 : 26-10-2011 21:43 »   | 
								
								 | 
							  
							 
							А можно чуть чуть подробнее про функции LoadFile и Parse? 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #12 : 27-10-2011 08:32 »   | 
								
								 | 
							  
							 
							sd,   так как успехи ? выкладывай   LoаdFile - загрузка текста из файла в память (полностью). Выделение памяти в рамках class MyTextProcesor Parse - собственно разбор загруженной информации на абзацы-предложения-слова и уапковка в объекты class Word, Sentence + .... Можно еще добавить .TrimSpace() и .TrimTab() (или могут входить как protected и отрабатывать скрыто при загрузке файла)  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #13 : 27-10-2011 18:05 »   | 
								
								 | 
							  
							 
							Хотел сделать так: Txt::Txt(char *filename) { 	ifstream in(filename); 	char str[1024];
  	if(!in) { 		cout<<"Can not open file "<<filename; 		exit(1); 	}
  	int count=0, len=0, indx=0, size=0; 	char ch;              //Считаем количество предложений 	while((ch=in.get())!=EOF) {  		size++;
  		if(isEndOfSentence(ch)) 			count++; 	}
  	sntnces=new Sentence[count]; //выделяем для них памят
  	in.close(); 	in.open(filename);
  	if(!in) { 		cout<<"Can not open file "<<filename; 		exit(1); 	}               //выделяем предложения и выводим их на экран 	while((ch=in.get())!=EOF) { 		len=1; 		while(!isEndOfSentence(ch)) { 			len++; 			ch=in.get(); 		} 		int pos=in.tellg(); 		in.seekg(pos-len, ios::beg); 		in.getline(str, len+1); 		cout<<str<<endl; 		in.seekg(pos+1, ios::beg); 	} 	in.close(); }Проблема в том, что выводится только первое предложение, а дальше нет.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Вад
							
						 | 
						
							
								  | 
								
									
									 « Ответ #14 : 27-10-2011 20:27 »   | 
								
								 | 
							  
							 
							А зачем так сложно - открывать файл, пересчитывать предложения, второй раз открывать и пытаться читать? Я бы делал всё сразу на ходу. И, поскольку задача пока учебная, забьём пока на слишком длинные предложения, переполняющие буфер. Или простой буфер на что-нибудь, контролирующее свою длину - std::deque, например. Или вообще std::string. Получится что-то типа Sometype buf; std::ifstream input(name); char c; while (!input.eof()) {   input.get(c);   if (isSeparator(c) && buf.size()) {     // перекладываем содержимое буфера куда надо - это наше предложение.     // и очищаем буфер   }   else {     // кладём c в конец буфера   } }
  Кстати, сам разделитель тоже надо добавлять в предложение, или нет? Я исходил из того, что не надо. Добавлено через 3 минуты и 8 секунд:ЗЫ. Кстати, не обязательно повторно открывать файловый поток. Можно просто сделать seekg в начало файла.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 27-10-2011 20:30 от Вад »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							DneprSMV
							
						 | 
						
							
								  | 
								
									
									 « Ответ #15 : 28-10-2011 09:18 »   | 
								
								 | 
							  
							 
							sd,  по-моему сложновато. Ты все операции хочешь проделать в конструкторе ? (по большому счету, он в начале может быть вообще пустой, Txt::Txt() {) ). Твой текст состоит из абзацев, абзац состоит из предложений, предложения состоят из слов и знаков препинания. Символы веделять в качестве объектов - можно да(а смысл ?) наподобие объекта pixel::pixel(x.y) в графике)  а можно нет . +форматирование. -------- Как бы я делал помолчу, тк. не хочу испортить "обедню" своей метОдой    Но в любом случае вначале надо выделить классы, их методы-интерфейсы. У тебя в конструкторе совмещены 2 операции - чтение файла и его обработка. У меня некоторые представления, что в конструкторе операции по выделению памяти и инициализации объекта. Чтение и обработку я бы вынес в методы-функции. Или "верх" ты стремишься свести к  Txt MyTxt("file"); MyTxt.Yahoo(); ?  Если при работе конструктора произойдет ошибка - кто ее обработает ? (кроме exit(1) ) Обработанную-выделенную инф я бы располагал в виде списков текст - список абзацев абзац - список предложений предложение - список слов и знаков пунктуации с методами Txt.GetAbzatz(....) Abzatz.GetSentence(....) Sentence.GetWord(...) или нечто подобное. У тебя есть ф-ии GetWord(). Попробуй черново прописать программу "сверху" - с красивых ворот   Отладочную печать удобно делать не через поток, а printf - если Win32 Console printf("Отладка строка=<%s> n=%d", ptr_string, n); // n - число int  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							"Не слушайте никаких советов, в том числе и этот" (Сократ ?) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							sd
							
								Постоялец 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #16 : 28-10-2011 21:18 »   | 
								
								 | 
							  
							 
							Сделал так как сделал. Вроде сдал и вроде прокатило. Спасибо вам. Сейчас начну делать след. задание - написание словаря. Буду обращаться наверное. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	 |