Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определить границы предложений в файле / 15 сообщений из 15, страница 1 из 1
18.06.2014, 17:55
    #38673416
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
Добрый день. Передо мной стоит задача - разбить текст на предложения, попутно определив смещение каждого из них от начала файла. Реализовать это нужно на C++, с которым я почти и не сталкивался. Да и вряд ли когда-нибудь буду использовать. Суть проблемы:

Нужно создать функцию, которая строит индекс предложений в текстовом файле. Индекс - это упорядоченная последовательность пар (порядковый номер предложения – смещение от начала файла) для каждого предложения в
файле.

Как построить этот индекс? Ведь предложение может оканчиваться не только точкой, но и восклицательным знаком (или несколькими), многоточием... Всякие побайтовые функции вернут результат в байтах, а кодировка файлов может быть разной. Это ведь не смещение.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
? Count (TCHAR *path)
{
FILE *f;
    if((f = _wfopen(path, L"rt")) != 0)
                {
                while(!feof(f))
                    {
                        //Тут мне нужно построить индекс
                    }
                    
                    fclose(f);
                    
                }
                else MessageBox(NULL, L"Cannot open file!", NULL, MB_OK);
    
 
 
return index?;
}
...
Рейтинг: 0 / 0
18.06.2014, 18:06
    #38673437
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWMЭто ведь не смещение.
ftell() - это смещение.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
18.06.2014, 18:31
    #38673489
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
Ок. Набросал тут маленькую консольную штуку.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
#include <stdio.h>
#include <conio.h>

int main ()
{
  FILE * pFile;
  int c;
  int i = 0;
  long pos;
  char buffer [256];

  pFile = fopen ("myfile.txt","rt");
  if (pFile==NULL) perror ("Error opening file");
  else while (!feof (pFile)) {
    c=getc (pFile);

    if (c == EOF) break;
	if (c == '.' | c == '...' | c =='!' | c == '!!!')
		{	i++;
			pos = ftell(pFile);
			printf("%d-%d\r\n", i, pos);
	    }

  }
  getch();
  return 0;
}


Правильно строю индекс? Как в C/С++ делают конкатенацию строк/символов? Мне бы хотелось это оформить в виде функции, где вместе printf("%d-%d\r\n", i, pos) всё бы копировалось в буфер, а потом отдавалось через return
...
Рейтинг: 0 / 0
18.06.2014, 18:45
    #38673503
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWMОк. Набросал тут маленькую консольную штуку.
Код: plaintext
1.
	if (c == '.' | c == '...' | c =='!' | c == '!!!')


Правильно строю индекс? Как в C/С++ делают конкатенацию строк/символов? Мне бы хотелось это оформить в виде функции, где вместе printf("%d-%d\r\n", i, pos) всё бы копировалось в буфер, а потом отдавалось через returnДвижешься в правильном направлении, но вот эта строка - не верная. с у тебя может хранить только один символ. И операция логического OR пишется не так.

А вообще, я бы сделал на основе двух переменных. Если c1 это знак препинания которым может заканчиваться предложение, а c2 это не знак препинания, то c2 это либо начало нового предложения, либо пробелы между предложениями.... И от этого плясать дальше.
...
Рейтинг: 0 / 0
18.06.2014, 18:57
    #38673524
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
White OwlА вообще, я бы сделал на основе двух переменных. Если c1 это знак препинания которым может заканчиваться предложение, а c2 это не знак препинания, то c2 это либо начало нового предложения, либо пробелы между предложениями.... И от этого плясать дальше.
1). Стоп! Если я буду использовать две переменные - то указатель на текущую позицию в файле "ускачет", когда я буду работать с следующим символом. Или как это можно сделать?
2). А как правильно OR писать? Через ||, как сокращенная дизъюнкция?
...
Рейтинг: 0 / 0
18.06.2014, 19:18
    #38673545
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWM1). Стоп! Если я буду использовать две переменные - то указатель на текущую позицию в файле "ускачет", когда я буду работать с следующим символом. Или как это можно сделать?Почему указатель ускачет? Указатель сам по себе, переменные сами по себе.
Ну поименуй эти две переменные как c_previous и c_current. В c_current читай текущий байтик, а потом (после всей логики) переписывай значение из c_current в c_previous и читай следующий байтик в c_current. И так по кругу пока файл не кончится.

AlexanderWM2). А как правильно OR писать? Через ||, как сокращенная дизъюнкция?А при чем здесь сокращенная дизъюнкция? Знание дискретной математики это хорошо конечно, но привыкай к тому что если ты переходишь на новый язык программирования, надо зазубрить новый синтаксис. Все они (ну почти все) используют все те операции и принципы которые ты учил на лекциях по дискретке, но записываются эти операции везде по разному. Просто прими это как данность.
И кстати это не только к ЯП относится, к обычным человеческим языкам это тоже относится: возьмешь иностранный учебник тоже напорешься на непривычную запись привычных операций.
...
Рейтинг: 0 / 0
19.06.2014, 08:35
    #38673801
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
Если я правильно понял что вы хотите, то возможно так:


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
#include <stdio.h>
bool isEndSentenses(char* s)
{
	return ((*s == '!') || (*s == '?') || (*s == '.'));
}


int main(int argc, char** argv)
{
	char* buf = "asdasdasdasd asdasdasd .asdasdasdasdasd ....!sdfsdfsdf!!!!!sdfbsdfbsdfj?! sql.ru";
	char* cur = buf;
	unsigned int count_sent = 0;

	while (*cur)
	{
		if (isEndSentenses(cur) && !isEndSentenses(cur + 1) || !(*(cur + 1)))
		{
			count_sent++;
			printf("num_sentenses = %i index %i \n", count_sent, cur - buf);
		}
		cur++;
	}
}



Я бы вынес в отдельную функцию признаки конца предложения.
...
Рейтинг: 0 / 0
19.06.2014, 11:12
    #38673968
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
SashaMercuryЕсли я правильно понял что вы хотите, то возможно так...

Спасибо! Очень похоже на то, что нужно. Но есть вопросы. Как поступить с самым первым предложением? Как всё-таки засунуть в буфер содержимое файла? Через fcansf?
...
Рейтинг: 0 / 0
19.06.2014, 15:00
    #38674420
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
С файлом разобрался. Осталось две вещи. Разобраться с первым предложением и типизацией. В программе везде используется TCHAR, а у меня просто char
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
#include <stdio.h>
#include <conio.h>

bool isEndSentenses(char* s)
{
    return ((*s == '!') || (*s == '?') || (*s == '.'));
}


int main(int argc, char** argv)
{

unsigned int count_sent = 0;
FILE *f;

	if((f = _wfopen(L"myfile.txt", L"rt")) != 0)
	{
    fseek(f, 0, SEEK_END);
    long int size = ftell(f);
    rewind(f);
    char* buf = new char [5000];
    fread(buf,1,size,f);
	fclose(f);
	char* cur = buf;

		while (*cur)
		{
			if (isEndSentenses(cur) && !isEndSentenses(cur + 1) || !(*(cur + 1)))
			{
            count_sent++;
            printf("num_sentenses = %i index %i \n", count_sent, cur - buf);
			}
        cur++;
		}
                    
    }
getch();
}
...
Рейтинг: 0 / 0
19.06.2014, 15:10
    #38674438
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWMС файлом разобрался. Осталось две вещи. Разобраться с первым предложением и типизацией.

Такой вариантик, используется POSIX, можно заменить дубляжом их boost::interprocess, считает файлы с кодировками ASCII и utf-8.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
#include <iostream>
#include <vector>
#include <iterator>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
struct index{ 
  index(uint32_t c, size_t s): num(c), offset(s){};
 void operator()(){ std::cout<<"Num="<<num<<"  Offset="<<offset<<std::endl; };
 uint32_t num;
 size_t offset;
};

template <typename P>
struct parse{

parse(const char* f):file(f){ status=step(); };
const char* file;
P vec;
uint8_t status;

void operator()(){ 
 if(status){ std::cout<<"No \n"; return; }; 
 auto it=vec.begin();
 while(it!=vec.end()){ (*it++)(); };
 };

template <typename T>
int check(T ch, uint8_t state){
 uint8_t s=state;
 switch(ch){
  case '.' :
  case '!' :
  case '?' :
  case ',' :
  case ':' :
  case '\r':
  case '\n':
  case ';' : break;
  case ' ' : if(!s) s=1; break;
  default  : s=~s&1; break;
  };
 return s;
 };

int step(){
 struct stat st;
 size_t count=0, sz=0;
 uint32_t nm=0;
  if(stat(file, &st)==-1) return 1;
  sz=st.st_size;
 int fd=open(file, O_RDONLY);
 if(!fd) return 1;
 void* buf=mmap(NULL, sz, PROT_READ, MAP_PRIVATE,fd,0);
 if(buf==MAP_FAILED){ close(fd); return 1; };
 while(1){ 
 while(check(*(reinterpret_cast<char*>(buf)+count), 1)){ ++count; if(count==sz) return 0; };
  vec.push_back(index(++nm, count));
  while(check(*(reinterpret_cast<char*>(buf)+count), 0)){ ++count; if(count==sz) return 0; };
 };
munmap((void*)buf, sz);
close(fd);
return 0;
 };
};

int main(int c, char** s){
 
 parse<std::vector<index> > r(s[1]);
  r();
 };
  
...
Рейтинг: 0 / 0
19.06.2014, 15:47
    #38674487
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
smaldТакой вариантик, используется POSIX, можно заменить дубляжом их boost::interprocess, считает файлы с кодировками ASCII и utf-8.

Спасибо. Попробую запустить и разобраться. Но лишь для собственного развития. Текущая задача - часть более крупной задачи на взаимосвязь DLL и WinAPI. Поэтому в глубину языка лезть не хочу, так стиль простого C мне ближе, а все возможности C++ хоть и можно использовать, но это перебор. Тем более, что С++ для меня "проходной". Мне нужно лишь решить на нём несколько задачек.
...
Рейтинг: 0 / 0
19.06.2014, 15:49
    #38674490
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
Поторопился выкинуть, вместо

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 while(check(*(reinterpret_cast<char*>(buf)+count), 1)){ ++count; if(count==sz) return 0; };
  vec.push_back(index(++nm, count));
  while(check(*(reinterpret_cast<char*>(buf)+count), 0)){ ++count; if(count==sz) return 0; };
 };
munmap((void*)buf, sz);
close(fd);
return 0;
 };



пишем

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
uint8_t run=1;
 while(run){ 
 while(check(*(reinterpret_cast<char*>(buf)+count), 1)){ ++count; 
                                                        if(count==sz){ run=0; break; };
                                                          };
 if (!run) continue;
 vec.push_back(index(++nm, count));

  while(check(*(reinterpret_cast<char*>(buf)+count), 0)){  ++count; 
                                                        if(count==sz){ run=0; break; };
                                                          };
};

munmap((void*)buf, sz); close(fd);
return 0;
 };
...
Рейтинг: 0 / 0
19.06.2014, 15:53
    #38674498
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWMСпасибо. Попробую запустить и разобраться. Но лишь для собственного развития. Текущая задача - часть более крупной задачи на взаимосвязь DLL и WinAPI. Поэтому в глубину языка лезть не хочу, так стиль простого C мне ближе, а все возможности C++ хоть и можно использовать, но это перебор. Тем более, что С++ для меня "проходной". Мне нужно лишь решить на нём несколько задачек.
Что-то не понимаю, Вам оно для сдачи какой зачётки нужно? Или Вы на работе? Если последнее, то не понятно, чем там
занимаетесь. Стиль простого Си устарел, если не собираетесь пилить в ядро, то штудируйте стандарт C++ от корки до корки.
...
Рейтинг: 0 / 0
19.06.2014, 16:18
    #38674524
AlexanderWM
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
smaldAlexanderWMСпасибо. Попробую запустить и разобраться. Но лишь для собственного развития. Текущая задача - часть более крупной задачи на взаимосвязь DLL и WinAPI. Поэтому в глубину языка лезть не хочу, так стиль простого C мне ближе, а все возможности C++ хоть и можно использовать, но это перебор. Тем более, что С++ для меня "проходной". Мне нужно лишь решить на нём несколько задачек.
Что-то не понимаю, Вам оно для сдачи какой зачётки нужно? Или Вы на работе? Если последнее, то не понятно, чем там
занимаетесь. Стиль простого Си устарел, если не собираетесь пилить в ядро, то штудируйте стандарт C++ от корки до корки.

Делаю задачу по программированию на использование DLL в WinAPI, а конкретнее - нужно создать динамически компонуемую библиотеку, которая будет экспортировать функции (в количестве не менее 3-х), обеспечивающие удобное решение задачи. Задачу я озвучил - построить индекс текстового файла. С библиотеками разобрался, с экспортом функций тоже. Главное - сама задача. Абстрагируясь от всего лишнего - мне нужна функция TCHAR *GetIndex(TCHAR *path), которая принимает путь к текстовому файлу, и возвращает индекс в TCHAR *. Помогите, пожалуйста, исправить нижеследующий код, чтобы он принимал в качестве единственного параметра путь к файлу, а возвращал индекс (строки с инфой разделённые \r\n). И моему счастью не будет предела :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
bool isEndSentenses(TCHAR * s)
{
    return ((*s == '!') || (*s == '?') || (*s == '.'));
}

TCHAR *GetIndex(TCHAR *path)
{
 unsigned int count_sent = 0;
FILE *f;
bool first = false;

 TCHAR *outbuf;
 TCHAR *temp;
 TCHAR *out;


		if((f = _wfopen(path, L"rt")) != 0)
	{
    fseek(f, 0, SEEK_END);
    long int size = ftell(f);
    rewind(f);
    TCHAR* buf = new TCHAR [5000];
    fread(buf,1,size,f);
	fclose(f);
	TCHAR* cur = buf;

		while (*cur)
		{
			if (!first)
			{
				if (isupper(*cur))
				{
				count_sent++;
			   // printf("num_sentenses = %i index %i \n", count_sent, cur - buf);
				sprintf(temp, "num_sentenses = %i index %i \n", count_sent, cur - buf);
				//_tcscpy_s(dest, _countof(dest), _T("Hello"));
				_tcscpy(outbuf,temp);
				first = true;
				}
			}

			if (isEndSentenses(cur) && !isEndSentenses(cur + 1) || !(*(cur + 1)))
			{
            count_sent++;
            //printf("num_sentenses = %i index %i \n", count_sent, cur - buf);
					swprintf(temp, _T("num_sentenses = %i index %i \n"), count_sent, cur - buf);
		//	wcscat(outbuf,temp);
			}
        cur++;
		}
                    
    }
	
				else
				{
				MessageBox(NULL, L"Cannot open file!", NULL, MB_OK);
				}
	
return outbuf;
	 



} 
...
Рейтинг: 0 / 0
19.06.2014, 18:06
    #38674664
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Определить границы предложений в файле
AlexanderWMДелаю задачу по программированию на использование DLL в WinAPI, а конкретнее - нужно создать динамически компонуемую библиотеку, которая будет экспортировать функции (в количестве не менее 3-х), обеспечивающие удобное решение задачи. Задачу я озвучил - построить индекс текстового файла. С библиотеками разобрался, с экспортом функций тоже. Главное - сама задача. Абстрагируясь от всего лишнего - мне нужна функция TCHAR *GetIndex(TCHAR *path), которая принимает путь к текстовому файлу, и возвращает индекс в TCHAR *. Помогите, пожалуйста, исправить нижеследующий код, чтобы он принимал в качестве единственного параметра путь к файлу, а возвращал индекс (строки с инфой разделённые \r\n).

Сумбур. Индекс чего? Строк в файле много. Или требуется выкусить строку, соответствующую регулярному шаблону?
Тогда указатель на строку-шаблон не вижу в сигнатуре GetIndex(TCHAR *path).
Выше привёл кодик, который формирует массив с структурами, каждая из которых содержит смещение начала
какого-то предложения в байтах от начала файла, и порядковый номер предложения. предложения разделяются
символами \n, \r, !,?, . , ; : Единственное, это
тамошние POSIX функции нужно перевести на их аналоги в windows. Без POSIX, будет так, и без mmap тормозить
на очень больших файлах. Как вариант задействовать boost::interprocess::file_mapping. Не знаю, какой аналог mmap
в WinAPI, никогда с ним не работал и не интересовался.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
#include <iostream>
#include <vector>
#include <iterator>
#include <fstream>

struct index{ 
  index(uint32_t c, size_t s): num(c), offset(s){};
 void operator()(){ std::cout<<"Num="<<num<<"  Offset="<<offset<<std::endl; };
 uint32_t num;
 size_t offset;
};

template <typename P>
class _GetIndex{
public:

_GetIndex(const char* f):file(f){ status=step(); };
_GetIndex(_GetIndex&& p): vec(std::move(p.vec)){ file=p.file; status=p.status; };
_GetIndex(const _GetIndex& p)=delete;
_GetIndex& operator()(const _GetIndex& p)=delete;
void operator()(){ 
 if(status){ std::cout<<"No \n"; return; }; 
 auto it=vec.begin();
 while(it!=vec.end()){ (*it++)(); };
 };

private:
const char* file;
P vec;
uint8_t status;

template <typename T>
int check(T ch, uint8_t state){
 uint8_t s=state;
 switch(ch){
  case '.' :
  case '!' :
  case '?' :
  case ',' :
  case ':' :
  case '\r':
  case '\n':
  case ';' : break;
  case ' ' : if(!s) s=1; break;
  default  : s=~s&1; break;
  };
 return s;
 };

int step(){
 char* buf;
 size_t sz=0, nm=0, count=0;
 uint8_t run=1;
 std::fstream fs(file);
  if(!fs.good()) return 1;
   fs.seekg (0, fs.end);
    sz = fs.tellg();
    fs.seekg (0, fs.beg);
 try{
  buf=new char[sz]; }catch(std::bad_alloc& c){  return 1; };
  fs.read(buf, sz);
   fs.close();
 while(run){ 
 while(check(*(buf+count), 1)){
          ++count;  if(count==sz){ run=0; break; };
           };
 if (!run) continue;
 vec.push_back(index(++nm, count));

  while(check(*(buf+count), 0)){ 
                       ++count;   if(count==sz){ run=0; break; };
            };
};

delete [] buf;
return 0;
 };
};
  
 typedef _GetIndex<std::vector<index> > GetIndex;

int main(int c, char** s){
 
 GetIndex g(s[1]);
  g();
 };
  
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определить границы предложений в файле / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]