GotAI.NET

Форум: Проблемы искусственного интеллекта

 

Регистрация | Вход

 Все темы | Новая тема Стр.1 (3)След. > >>   Поиск:  
 Автор Тема: парсер *.csv и управление миром
гость
109.70.100.*
парсер *.csv и управление миром
Добавлено: 03 окт 19 11:16
тот кто в состоянии написать парсер *.csv на С++ - может завладеть миром, как Владимир Владимирович и Дональд Трамп

дьявол в деталях
[Ответ][Цитата]
гость
188.170.193.*
На: парсер *.csv и управление миром
Добавлено: 03 окт 19 12:09
Цитата:
Автор: гость

тот кто в состоянии написать парсер *.csv на С++ - может завладеть миром, как Владимир Владимирович и Дональд Трамп

дьявол в деталях

Я уже давно написал этот дебильный парсер, но я не могу завладеть миром. Да, С++ дает мне возможность внести в мир значительные необратимые изменения, но я не хочу этого.

Путин не владеет ни РФ, ни тем более миром, вы ошиблись. Это ноль без палочки, просто человек на должности, который соблюдает интересы экономических группировок, поделивших РФ. Если вдруг Путин изменится и начнет реально (а не на словах) наводить порядок в стране (например, в той же лесной промышленности устранить воровство леса в Китай) - его очень быстро уберут (будет выглядеть как самостоятельный уход) и на досрочных выборах выберут Путина №2. Реальная власть в РФ - это воры.
[Ответ][Цитата]
гость
109.70.100.*
На: парсер *.csv и управление миром
Добавлено: 04 окт 19 5:49
Цитата:
Автор: гость
Я уже давно написал этот дебильный парсер
где код?
Цитата:
Автор: гость
Да, С++ дает мне возможность внести в мир значительные необратимые изменения
доказательства
[Ответ][Цитата]
гость
162.247.73.*
На: парсер *.csv и управление миром
Добавлено: 04 окт 19 12:00
Цитата:
Автор: гость

тот кто в состоянии написать парсер *.csv на С++ - может завладеть миром, как Владимир Владимирович и Дональд Трамп

дьявол в деталях
Владеет миром - написавщий многослойный персптрон на С++
[Ответ][Цитата]
гость
188.170.193.*
На: парсер *.csv и управление миром
Добавлено: 04 окт 19 12:16
Цитата:
Автор: гость
где код?

А зачем он вам? Ну вот, есть простейший, довольны? Это для фиксированного числа строк и столбцов, но мог бы написать и не для фиксированного.
//C++ Builder, на форме список и кнопка.


void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
float duration; clock_t start, finish; //переменные для замера времени
AnsiString path = "D:\\dataset.csv"; //путь файла .csv
int flen=0;// длина файла
int i=0; //счетчик цикла
int a=100001; //количество строк в таблице
int b=52; //количество столбцов в таблице
int max = 20; //максимальное количество символов в ячейке
int m=0; //счетчик символов во вспомогательном массиве
int s=0; //счетчик записей
int f =0; //счетчик строк

//вспомогательный массив для считывания в него 1 записи
char *vsp = new char [max]; for (i = 0; i < max; i++) { vsp = 100;}

start = clock();
// двумерный массив для считывания в него информации
AnsiString **mass = new AnsiString* [a]; for (i = 0; i < a; i++) { mass[i] = new AnsiString[b]; }

//=========считывание файла в массив======
FILE *F;
F = fopen(path.c_str(),"r");
flen = filelength(fileno(F));
char *String = new char [flen];
fread ( &String[0], 1, flen, F);
fclose(F);
//=================================================


//======считывание символов из массива символов в массив AnsiString=====
for(i=0; i < flen; i++)
{
vsp[m]=String[i];
if (String[i]==44) { vsp[m]=0; m=-1; mass[f][s] = AnsiString(vsp); i1++; s++;}

if (String[i]==10)
{
vsp[m]=0; mass[f][s] = AnsiString(vsp); s=0; m=-1; f++; i1++;
}
m++;
}
// удаление мусора
delete [] String; delete [] vsp; for (i = 0; i < a; i++) delete[]mass[i]; delete[]mass;

finish = clock();
duration = (float)(finish - start) / CLOCKS_PER_SEC;

//вывод информации в список
ListBox1->Items->Add("размер файла " + IntToStr(flen));
ListBox1->Items->Add("время выполнения программы " + FloatToStr(duration));
}


Цитата:
[i]Автор: гость
доказательства

Доказать можно единственным способом - внести эти изменения, а потом все будут расхлебывать (и я тоже), мне это не нужно.
[Ответ][Цитата]
гость
185.220.101.*
На: парсер *.csv и управление миром
Добавлено: 05 окт 19 7:12
Изменено: 05 окт 19 18:02, автор изменений: admin
vector<vector<double>> csvParse(string path, char token)
{
ifstream read(path);
vector<string> lines;
string line;
while (getline(read, line)) lines.push_back(line);
vector<vector<double>> result;
for (int i = 0; i < lines.size(); ++i)
{
stringstream test(lines[i]);
vector<double> seglist;
string segment;
while (getline(test, segment, token))
{
double val = 0;
val = stod(segment);
seglist.push_back(val);
}
result.push_back(seglist);
}
return result;
}
[Ответ][Цитата]
cortl
Сообщений: 258
На: парсер *.csv и управление миром
Добавлено: 06 окт 19 20:59
Изменено: 06 окт 19 23:21
2 гость 185.220.101.*

>> vector<string> lines;
>> string line;
>> while (getline(read, line)) lines.push_back(line);
Зачем создавать копию данных из файла в памяти если вы не планируете её использовать в дальнейшем? Работайте с файлом.

С list-ом было бы быстрее.

В ячейках csv необязательно хранятся double, в общем случае (w)string.
А если не брать во внимание языки, не укладывающиеся в ascii, можно c char* побаловаться.

>> double val = 0; << и другие
Многократное выделение и освобождение памяти в цикле. Фрагментация.

>> = 0 << в той же строке лишний тормоз.
[Ответ][Цитата]
TimKruz
Сообщений: 323
На: парсер *.csv и управление миром
Добавлено: 08 окт 19 9:28
Цитата:
Автор: гость

написать парсер *.csv на С++


А таки почему на C++? Почему не C, без объектов?
Почему вообще речь о каком-то мейнстриме, когда труЪ пишут всё на Ассемблере?
[Ответ][Цитата]
гость
109.70.100.*
На: парсер *.csv и управление миром
Добавлено: 08 окт 19 9:42
Цитата:
Автор: TimKruz
А таки почему на C++? Почему не C, без объектов?
Почему вообще речь о каком-то мейнстриме, когда труЪ пишут всё на Ассемблере?
Согласен, Си это тру, Ассемблер это слишком тру, труЪ как Вы сказали, всему нужна мера. На самом деле чистый Си это идеал, всё остальное с душком политического гавнеца, какаято демагогия в контексте ЯП.
[Ответ][Цитата]
TimKruz
Сообщений: 323
На: парсер *.csv и управление миром
Добавлено: 08 окт 19 11:07
Изменено: 08 окт 19 11:18
гость 109.70.100.*, не вижу причин считать Си идеалом... Защиты от ошибок нет, но и возможностей расширения языковых средств тоже нет, текст в большинстве случаев нечитабелен для людей, используется много спец-символов и т.д.

Преимущество Си только в том, что у него есть компиляторы под любую платформу и библиотеки готового кода для решения чуть менее, чем любой задачи. У других ЯП компилятор как правило существует для ограниченного круга платформ, а база готового кода не настолько обширна, соответственно многое приходится делать вручную, а программисты по своей сути лентяи (любая прикладная программа решает единственную реальную проблему - "мне лень делать это вручную").

Из личного интереса набросал простенький парсер CSV на FreePascal:
program CSVParser;
uses
Classes;
var
CSVData: TStringList;
Buffer, Element: String;
StartFrom, I: Integer;
begin
CSVData := TStringList.Create;
repeat
ReadLn(Buffer);
StartFrom := 1;
for I := 1 to Length(Buffer) do
if Buffer[I] = ',' then
begin
Element := Copy(Buffer, StartFrom, I - StartFrom);
if Length(Element) > 0 then
CSVData.Add(Element);
StartFrom := I + 1;
end;
until EoF(Input);

WriteLn('Всего элементов: ', CSVData.Count);
for Element in CSVData do
WriteLn(Element + ';');
CSVData.Free;
end.

(как работает см. на ideone по ссылке выше)
[Ответ][Цитата]
гость
141.255.162.*
На: парсер *.csv и управление миром
Добавлено: 13 окт 19 7:39
Цитата:
Автор: TimKruz

гость 109.70.100.*, не вижу причин считать Си идеалом... Защиты от ошибок нет, но и возможностей расширения языковых средств тоже нет, текст в большинстве случаев нечитабелен для людей, используется много спец-символов и т.д.

Преимущество Си только в том, что у него есть компиляторы под любую платформу и библиотеки готового кода для решения чуть менее, чем любой задачи. У других ЯП компилятор как правило существует для ограниченного круга платформ, а база готового кода не настолько обширна, соответственно многое приходится делать вручную, а программисты по своей сути лентяи (любая прикладная программа решает единственную реальную проблему - "мне лень делать это вручную").

Из личного интереса набросал простенький парсер CSV на FreePascal:
program CSVParser;
uses
Classes;
var
CSVData: TStringList;
Buffer, Element: String;
StartFrom, I: Integer;
begin
CSVData := TStringList.Create;
repeat
ReadLn(Buffer);
StartFrom := 1;
for I := 1 to Length(Buffer) do
if Buffer[I] = ',' then
begin
Element := Copy(Buffer, StartFrom, I - StartFrom);
if Length(Element) > 0 then
CSVData.Add(Element);
StartFrom := I + 1;
end;
until EoF(Input);

WriteLn('Всего элементов: ', CSVData.Count);
for Element in CSVData do
WriteLn(Element + ';');
CSVData.Free;
end.

(как работает см. на ideone по ссылке выше)
паскаль всётаки уже не то
[Ответ][Цитата]
гость
178.62.192.*
На: парсер *.csv и управление миром
Добавлено: 19 ноя 19 9:26
Цитата:
Автор: гость


А зачем он вам? Ну вот, есть простейший, довольны? Это для фиксированного числа строк и столбцов, но мог бы написать и не для фиксированного.
//C++ Builder, на форме список и кнопка.


void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
float duration; clock_t start, finish; //переменные для замера времени
AnsiString path = "D:\\dataset.csv"; //путь файла .csv
int flen=0;// длина файла
int i=0; //счетчик цикла
int a=100001; //количество строк в таблице
int b=52; //количество столбцов в таблице
int max = 20; //максимальное количество символов в ячейке
int m=0; //счетчик символов во вспомогательном массиве
int s=0; //счетчик записей
int f =0; //счетчик строк

//вспомогательный массив для считывания в него 1 записи
char *vsp = new char [max]; for (i = 0; i < max; i++) { vsp[i] = 100;}

start = clock();
// двумерный массив для считывания в него информации
AnsiString **mass = new AnsiString* [a]; for (i = 0; i < a; i++) { mass[i] = new AnsiString[b]; }

//=========считывание файла в массив======
FILE *F;
F = fopen(path.c_str(),"r");
flen = filelength(fileno(F));
char *String = new char [flen];
fread ( &String[0], 1, flen, F);
fclose(F);
//=================================================


//======считывание символов из массива символов в массив AnsiString=====
for(i=0; i < flen; i++)
{
vsp[m]=String[i];
if (String[i]==44) { vsp[m]=0; m=-1; mass[f][s] = AnsiString(vsp); i1++; s++;}

if (String[i]==10)
{
vsp[m]=0; mass[f][s] = AnsiString(vsp); s=0; m=-1; f++; i1++;
}
m++;
}
// удаление мусора
delete [] String; delete [] vsp; for (i = 0; i < a; i++) delete[]mass[i]; delete[]mass;

finish = clock();
duration = (float)(finish - start) / CLOCKS_PER_SEC;

//вывод информации в список
ListBox1->Items->Add("размер файла " + IntToStr(flen));
ListBox1->Items->Add("время выполнения программы " + FloatToStr(duration));
}



Доказать можно единственным способом - внести эти изменения, а потом все будут расхлебывать (и я тоже), мне это не нужно.
Это уж простите детский лепет.

Нормальный парсер цсв будет какой то такой:

#include <csv_parser.hpp>


/* BEGIN DEFINITION FOR PUBLIC METHODS */
bool csv_parser::init(FILE * input_file_pointer)
{
input_fp = input_file_pointer;

if (input_fp == NULL)
{
fprintf(stderr, "Fatal error : unable to open input file from file pointer\n");

return false;
}

/* Resetting the internal pointer to the beginning of the stream */
rewind(input_fp);

more_rows = true;

_skip_lines();

return true;
}

bool csv_parser::init(const char * input_file)
{
const size_t filename_length = strlen(input_file);

if (!filename_length)
{
fprintf(stderr, "Fatal error : invalid input file %s\n", input_file);

return false;
}

input_filename = (char *) malloc(filename_length + 1);

if (input_filename == NULL)
{
fprintf(stderr, "Fatal error : unable to allocate memory for file name buffer %s\n", input_file);

return false;
}

memset(input_filename, 0, filename_length + 1);

strcpy(input_filename, input_file);

input_fp = fopen(input_file, "r");

if (input_fp == NULL)
{
fprintf(stderr, "Fatal error : unable to open input file %s\n", input_file);

CSV_PARSER_FREE_BUFFER_PTR(input_filename);

return false;
}

more_rows = true;

_skip_lines();

return true;
}

void csv_parser::set_enclosed_char(char fields_enclosed_by, enclosure_type_t enclosure_mode)
{
if (fields_enclosed_by != 0)
{
enclosed_char = fields_enclosed_by;
enclosed_length = 1U;
enclosure_type = enclosure_mode;
}
}

void csv_parser::set_field_term_char(char fields_terminated_by)
{
if (fields_terminated_by != 0)
{
field_term_char = fields_terminated_by;
field_term_length = 1U;
}
}

void csv_parser::set_line_term_char(char lines_terminated_by)
{
if (lines_terminated_by != 0)
{
line_term_char = lines_terminated_by;
line_term_length = 1U;
}
}

csv_row csv_parser::get_row(void)
{
csv_row current_row;

/* This will store the length of the buffer */
unsigned int line_length = 0U;

/* Character array buffer for the current record */
char * line = NULL;

/* Grab one record */
_read_single_line(&line, &line_length);

/* Select the most suitable field extractor based on the enclosure length */
switch(enclosure_type)
{
case ENCLOSURE_NONE : /* The fields are not enclosed by any character */
_get_fields_without_enclosure(¤t_row, line, &line_length);
break;

case ENCLOSURE_REQUIRED : /* The fields are enclosed by a character */
_get_fields_with_enclosure(¤t_row, line, &line_length);
break;

case ENCLOSURE_OPTIONAL : /* The fields may or may not be enclosed */
_get_fields_with_optional_enclosure(¤t_row, line, &line_length);
break;

default :
_get_fields_with_optional_enclosure(¤t_row, line, &line_length);
break;
}

/* Deallocate the current buffer */
CSV_PARSER_FREE_BUFFER_PTR(line);

/* Keeps track of how many times this has method has been called */
record_count++;

return current_row;
}

/* BEGIN DEFINITION FOR PROTECTED METHODS */


/* BEGIN DEFINITION FOR PRIVATE METHODS */

void csv_parser::_skip_lines(void)
{
/* Just in case the user accidentally sets ignore_num_lines to a negative number */
unsigned int number_of_lines_to_ignore = abs((int) ignore_num_lines);

while(has_more_rows() && number_of_lines_to_ignore)
{
const csv_row row = get_row();

number_of_lines_to_ignore--;
}

record_count = 0U;
}

void csv_parser::_get_fields_without_enclosure(csv_row_ptr row, const char * line, const unsigned int * line_length)
{
char * field = NULL;

if (*line_length > 0)
{
field = (char *) malloc(*line_length);

memset(field, 0, *line_length);

register unsigned int field_start = 0U;
register unsigned int field_end = 0U;
register unsigned int char_pos = 0U;

while(char_pos < *line_length)
{
char curr_char = line[char_pos];

if (curr_char == field_term_char)
{
field_end = char_pos;

const char * field_starts_at = line + field_start;

/* Field width must exclude field delimiter characters */
const unsigned int field_width = field_end - field_start;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);

/* This is the starting point of the next field */
field_start = char_pos + 1;

} else if (curr_char == line_term_char)
{
field_end = char_pos;

const char * field_starts_at = line + field_start;

/* Field width must exclude line terminating characters */
const unsigned int field_width = field_end - field_start;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);
}

/* Move to the next character in the current line */
char_pos++;
}

/* Deallocate memory for field buffer */
CSV_PARSER_FREE_BUFFER_PTR(field);
}
}

void csv_parser::_get_fields_with_enclosure(csv_row_ptr row, const char * line, const unsigned int * line_length)
{
char * field = NULL;

if (*line_length > 0)
{
field = (char *) malloc(*line_length);

memset(field, 0, *line_length);

register unsigned int current_state = 0U;
register unsigned int field_start = 0U;
register unsigned int field_end = 0U;
register unsigned int char_pos = 0U;

while(char_pos < *line_length)
{
char curr_char = line[char_pos];

if (curr_char == enclosed_char)
{
current_state++;

/* Lets find out if the enclosure character encountered is
* a 'real' enclosure character or if it is an embedded character that
* has been escaped within the field.
*/
register char previous_char = 0x00;

if (char_pos > 0U)
{
/* The escaped char will have to be the 2rd or later character. */
previous_char = line[char_pos - 1];

if (previous_char == escaped_char)
{
--current_state;
}
}

if (current_state == 1U && previous_char != escaped_char)
{
/* This marks the beginning of the column */
field_start = char_pos;

} else if (current_state == 2U)
{
/* We have found the end of the current field */
field_end = char_pos;

/* We do not need the enclosure characters */
const char * field_starts_at = line + field_start + 1U;

/* Field width must exclude beginning and ending enclosure characters */
const unsigned int field_width = field_end - field_start - 1U;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);

/* Reset the state to zero value for the next field */
current_state = 0U;
}
}

/* Move to the next character in the current line */
char_pos++;
}

/* If no enclosures were found in this line, the entire line becomes the only field. */
if (0 == row->size())
{
string entire_line = line;

row->push_back(entire_line);

} else if (current_state == 1U)
{
/* The beginning enclosure character was found but
* we could not locate the closing enclosure in the current line
* So we need to copy the remainder of the line into the last field.
*/

/* We do not need the starting enclosure character */
const char * field_starts_at = line + field_start + 1U;

/* Field width must exclude beginning characters */
const unsigned int field_width = *line_length - field_start - 1U;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);
}

/* Release the buffer for the field */
CSV_PARSER_FREE_BUFFER_PTR(field);
}
}

void csv_parser::_get_fields_with_optional_enclosure(csv_row_ptr row, const char * line, const unsigned int * line_length)
{
char * field = NULL;

/*
* How to extract the fields, when the enclosure char is optional.
*
* This is very similar to parsing the document without enclosure but with the following conditions.
*
* If the beginning char is an enclosure character, adjust the starting position of the string by + 1.
* If the ending char is an enclosure character, adjust the ending position by -1
*/
if (*line_length > 0)
{
field = (char *) malloc(*line_length);

memset(field, 0, *line_length);

register unsigned int field_start = 0U;
register unsigned int field_end = 0U;
register unsigned int char_pos = 0U;

while(char_pos < *line_length)
{
char curr_char = line[char_pos];

if (curr_char == field_term_char)
{
field_end = char_pos;

const char * field_starts_at = line + field_start;

/* Field width must exclude field delimiter characters */
unsigned int field_width = field_end - field_start;

const char line_first_char = field_starts_at[0];
const char line_final_char = field_starts_at[field_width - 1];

/* If the enclosure char is found at either ends of the string */
unsigned int first_adjustment = (line_first_char == enclosed_char) ? 1U : 0U;
unsigned int final_adjustment = (line_final_char == enclosed_char) ? 2U : 0U;

/* We do not want to have any negative or zero field widths */
field_width = (field_width > 2U) ? (field_width - final_adjustment) : field_width;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at + first_adjustment, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);

/* This is the starting point of the next field */
field_start = char_pos + 1;

} else if (curr_char == line_term_char)
{
field_end = char_pos;

const char * field_starts_at = line + field_start;

/* Field width must exclude line terminating characters */
unsigned int field_width = field_end - field_start;

const char line_first_char = field_starts_at[0];
const char line_final_char = field_starts_at[field_width - 1];

/* If the enclosure char is found at either ends of the string */
unsigned int first_adjustment = (line_first_char == enclosed_char) ? 1U : 0U;
unsigned int final_adjustment = (line_final_char == enclosed_char) ? 2U : 0U;

/* We do not want to have any negative or zero field widths */
field_width = (field_width > 2U) ? (field_width - final_adjustment) : field_width;

/* Copy exactly field_width bytes from field_starts_at to field */
memcpy(field, field_starts_at + first_adjustment, field_width);

/* This must be a null-terminated character array */
field[field_width] = 0x00;

string field_string_obj = field;

row->push_back(field_string_obj);
}

/* Move to the next character in the current line */
char_pos++;
}

/* Deallocate memory for field buffer */
CSV_PARSER_FREE_BUFFER_PTR(field);
}
}

void csv_parser::_read_single_line(char ** buffer, unsigned int * buffer_len)
{
long int original_pos = ftell(input_fp);
long int current_pos = original_pos;

register int current_char = 0;

/* Checking one character at a time until the end of a line is found */
while(true)
{
current_char = fgetc(input_fp);

if (current_char == EOF)
{
/* We have reached the end of the file */
more_rows = false;

break;

} else if (current_char == line_term_char)
{
/* We have reached the end of the row */
current_pos++;

break;

} else {

current_pos++;
}
}

/* Let's try to peek one character ahead to see if we are at the end of the file */
if (more_rows)
{
current_char = fgetc(input_fp);

more_rows = (current_char == EOF) ? false : true;
}

/* Find out how long this row is */
const size_t length_of_row = current_pos - original_pos;

if (length_of_row > 0)
{
*buffer_len = length_of_row * sizeof(char) + 1;

*buffer = (char *) realloc(*buffer, *buffer_len);

memset(*buffer, 0, *buffer_len);

/* Reset the internal pointer to the original position */
fseek(input_fp, original_pos, SEEK_SET);

/* Copy the contents of the line into the buffer */
fread(*buffer, 1, length_of_row, input_fp);
}
}
[Ответ][Цитата]
гость
188.170.195.*
На: парсер *.csv и управление миром
Добавлено: 19 ноя 19 11:47
Цитата:
Автор: гость
Это уж простите детский лепет.

Нормальный парсер цсв будет какой то такой:

Я надеюсь, вы не по объему кода судите, какой парсер "детский лепет", а какой "нормальный". Вы этот код запускали хоть у себя на компьютере, что вы его сюда копируете откуда-то?

p.s Я могу, конечно, улучшить свой код, добавить предупреждение при неправильном чтении файла, сделать парсер универсальным, не зависящим от размеров таблицы, но зачем, спрашивается..
[Ответ][Цитата]
Ilya Geller
Сообщений: 4879
На: парсер *.csv и управление миром
Добавлено: 19 ноя 19 13:54
Искусственый Интеллект есть тексты, которые структуированы в код.
Для того чтобы структуировать тексты в код нужно понять чего добивался NIST TREC QA. А добивался он нахождения ответов на заданые вопросы не только в их ЯВНЫХ контекстах, но и в НЕЯВНЫХ подтекстах. И тогда, после того как ответ на вызов NIST TREC был найден, т.е. было найдено что такое подтексты, обнаружен объективный метод ИИ-разбора текстов, когда появилась возможность структуировать тексты, то появилась и возможность сделать все тексты кодами. Без помощи програмёров.
Так что ваш парсинг никому не нужен, батенька.
[Ответ][Цитата]
гость
185.220.101.*
На: парсер *.csv и управление миром
Добавлено: 20 ноя 19 7:54
ИМХО цсвпарсер это куйня, школьный левел, другое дело json-парсер
[Ответ][Цитата]
 Стр.1 (3): [1]  2  3След. > >>