powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определить границы предложений в файле
15 сообщений из 15, страница 1 из 1
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #38673437
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexanderWMЭто ведь не смещение.
ftell() - это смещение.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #38673524
AlexanderWM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlА вообще, я бы сделал на основе двух переменных. Если c1 это знак препинания которым может заканчиваться предложение, а c2 это не знак препинания, то c2 это либо начало нового предложения, либо пробелы между предложениями.... И от этого плясать дальше.
1). Стоп! Если я буду использовать две переменные - то указатель на текущую позицию в файле "ускачет", когда я буду работать с следующим символом. Или как это можно сделать?
2). А как правильно OR писать? Через ||, как сокращенная дизъюнкция?
...
Рейтинг: 0 / 0
Определить границы предложений в файле
    #38673545
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexanderWM1). Стоп! Если я буду использовать две переменные - то указатель на текущую позицию в файле "ускачет", когда я буду работать с следующим символом. Или как это можно сделать?Почему указатель ускачет? Указатель сам по себе, переменные сами по себе.
Ну поименуй эти две переменные как c_previous и c_current. В c_current читай текущий байтик, а потом (после всей логики) переписывай значение из c_current в c_previous и читай следующий байтик в c_current. И так по кругу пока файл не кончится.

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

Спасибо! Очень похоже на то, что нужно. Но есть вопросы. Как поступить с самым первым предложением? Как всё-таки засунуть в буфер содержимое файла? Через fcansf?
...
Рейтинг: 0 / 0
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #38674487
AlexanderWM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
smaldТакой вариантик, используется POSIX, можно заменить дубляжом их boost::interprocess, считает файлы с кодировками ASCII и utf-8.

Спасибо. Попробую запустить и разобраться. Но лишь для собственного развития. Текущая задача - часть более крупной задачи на взаимосвязь DLL и WinAPI. Поэтому в глубину языка лезть не хочу, так стиль простого C мне ближе, а все возможности C++ хоть и можно использовать, но это перебор. Тем более, что С++ для меня "проходной". Мне нужно лишь решить на нём несколько задачек.
...
Рейтинг: 0 / 0
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #38674498
smald
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexanderWMСпасибо. Попробую запустить и разобраться. Но лишь для собственного развития. Текущая задача - часть более крупной задачи на взаимосвязь DLL и WinAPI. Поэтому в глубину языка лезть не хочу, так стиль простого C мне ближе, а все возможности C++ хоть и можно использовать, но это перебор. Тем более, что С++ для меня "проходной". Мне нужно лишь решить на нём несколько задачек.
Что-то не понимаю, Вам оно для сдачи какой зачётки нужно? Или Вы на работе? Если последнее, то не понятно, чем там
занимаетесь. Стиль простого Си устарел, если не собираетесь пилить в ядро, то штудируйте стандарт C++ от корки до корки.
...
Рейтинг: 0 / 0
Определить границы предложений в файле
    #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
Определить границы предложений в файле
    #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
15 сообщений из 15, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Определить границы предложений в файле
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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