powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Найти текстовые блоки разного типа в С.
15 сообщений из 40, страница 2 из 2
Найти текстовые блоки разного типа в С.
    #39382303
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kealon(Ruslan),

да. это самое плохое место. не знаю пока как победить. есть коечно одно решение которое придумали до меня - обрамлять тэги кавычками <SOI>, <EOI>, <SOT>, <EOT> или <I>, <I/>, <T>, <T/>.
но это решение не такое генерик как хотелось бы.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382340
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T,

спасибо. попробую доработать. почему то парсит один блок и выходит.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382348
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7Dima T,

спасибо. попробую доработать. почему то парсит один блок и выходит.
Ты мой код запускал? Там должно быть так
Код: plaintext
1.
* Ne*
* Fo*
т.к. буфер 4 байта и строка с ошибками (красным выделил)
Код: plaintext
"SOI Happy SOT New EOT SOT Year EOI SOI Folks EOI"

Если на какой-то другой строке неправильно работает - давай строку, поправлю.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382354
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T,
моя ошибка. все класно работает. Dima T как всегда крут. :)
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382400
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пользуйся.

Еще думаю неправильно возвращать часть строки если она целиком в буфер не поместилась, наверно лучше пустую возвращать
Код: plaintext
1.
2.
3.
4.
5.
			} else if(s > 1) { // есть место в буфере
...
			} else { // буфер маловат
				*buf = 0;
			}


Сам подумай как правильнее ошибки обрабатывать, что где проверяется я подписал.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382418
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЕще думаю неправильно возвращать часть строки если она целиком в буфер не поместилась, наверно лучше пустую возвращать

лучше не копировать, а возвращать начало текста и длину, проще будет
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39382836
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7у меня голый С.Ну вот, а здесь приличный форум.

jenya7ничего не понимаю. что происходит.Это нормально, вы же задали вопрос на sql.ru.

jenya7задача на несколько строк кода.Только если писать на ультракоротком языке. На C побольше выйдет.

Кстати, форум «C++» -- он и для вопросов по C тоже.

Dima T
Код: plaintext
1.
	char buf[4];

Так вы, Dim, любите буферы фиксированой длины?

kealon(Ruslan)лучше не копировать, а возвращать начало текста и длину, проще будетА я бы вообще ничего не возвращал, а просто вызывал бы функции обработки блоков:
Код: 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 <stdbool.h>
#include <string.h>
#include <stdio.h>

/* только для строковых литералов */
#define SL_LEN(string_lit) (sizeof(string_lit) - 1)

#define INSTRUCTION_START "SOI"
#define INSTRUCTION_END "EOI"
#define TEST_START "SOT"
#define TEST_END "EOT"

bool handle_instruction_block(const char block[], size_t block_len);
bool handle_test_block(const char block[], size_t block_len);

bool parse_blocks(const char text[]) {
  size_t pos, block_start, block_end;
  const char* end_marker;

  pos = 0;
  for (;;) {
    while (text[pos] == ' ') pos++; /* пропускаем пробелы */

    if (text[pos] == '\0')
      break;

    if (strncmp(text + pos, INSTRUCTION_START, SL_LEN(INSTRUCTION_START)) == 0) {
      pos += SL_LEN(INSTRUCTION_START);
      while (text[pos] == ' ') pos++;
      block_start = pos;
      end_marker = strstr(text + pos, INSTRUCTION_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      if (block_start < pos) {
        block_end = pos;
        while (text[block_end - 1] == ' ') block_end--;
        if (!handle_instruction_block(text + block_start, block_end - block_start)) return false;
      } else {
        if (!handle_instruction_block(NULL, 0)) return false;
      }
      pos += SL_LEN(INSTRUCTION_END);
    } else if (strncmp(text + pos, TEST_START, SL_LEN(TEST_START)) == 0) {
      pos += SL_LEN(TEST_START);
      while (text[pos] == ' ') pos++;
      block_start = pos;
      end_marker = strstr(text + pos, TEST_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      if (block_start < pos) {
        block_end = pos;
        while (text[block_end - 1] == ' ') block_end--;
        if (!handle_test_block(text + block_start, block_end - block_start)) return false;
      } else {
        if (!handle_test_block(NULL, 0)) return false;
      }
      pos += SL_LEN(TEST_END);
    } else {
      return false;
    }
  }

  return true;
}

bool handle_instruction_block(const char block[], size_t block_len) {
  if (block != NULL) {
    /* строка block не завершается нулевым char-ом ('\0'), поэтому явно указываем длину */
    printf("instruction '%.*s'\n", (int)block_len, block);
  } else {
    printf("empty instruction\n");
  }
  return true;
}

bool handle_test_block(const char block[], size_t block_len) {
  if (block != NULL) {
    printf("test '%.*s'\n", (int)block_len, block);
  } else {
    printf("empty test\n");
  }
  return true;
}

int main() {
  parse_blocks(" SOI Happy EOI  SOT New EOT  SOT Year EOT  SOT EOT  SOI Folks EOI ");
  return 0;
}

Вывод на консоль:
Код: sql
1.
2.
3.
4.
5.
instruction 'Happy'
test 'New'
test 'Year'
empty test
instruction 'Folks'
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39383090
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр СедовТак вы, Dim, любите буферы фиксированой длины?
в контроллерах всегда овердохера динамической памяти?
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39383408
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пётр Седов,
у Dima T код раза в 3 меньше.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39383558
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7OoCcили использовать готовый регэкс автомат типа такого
у меня голый С.

lib pcre
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39383687
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилПётр СедовТак вы, Dim, любите буферы фиксированой длины?
в контроллерах всегда овердохера динамической памяти?В этой задаче не нужно динамическое распределение памяти, в моём коде его и нет. Кстати, автор вопроса не писал, что задача для controller-а.

jenya7Пётр Седов,
у Dima T код раза в 3 меньше.Это Perl-овская краткость, когда кода мало, но надо мозг сломать, чтобы понять, что тут происходит. Кстати, Perl уже почти никому не нужен , и это неслучайно. По коду Dima T:

* Плохо-читабельный write-only код. Сбивающие с толку приёмы, например указатель p смещается как в заголовке цикла, так и в его теле:
Dima T
Код: plaintext
1.
2.
3.
4.
5.
6.
	const char* p = ...;
	for(;*p != 0; p++) {
		...
			p += 2;
		...
	}


* Использование буфера фиксированной длины. Приемлемо разве что в учебных заданиях, во «взрослом» коде -- почти никогда. Кроме случаев, когда есть гарантированное ограничение на длину строки (например, WinAPI-шная константа MAX_PATH, которая используется в структуре WIN32_FIND_DATA). Но вы такое гарантированное ограничение не упоминаете.

* Код, который обрабатывает блоки, не знает тип блока:
Dima T
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
int main (void) {
	//const char* p = "SOI Happy EOISOT New EOT SOT Year EOT SOI Folks EOI ";
	const char* p = "SOI Happy SOT New EOT SOT Year EOI SOI Folks EOI ";
	char buf[4];
	while(p = parse(p, buf, 4)) {
		printf("*%s*\n", buf);
	}
	return 0;
}

Надо ещё выводить на консоль тип блока -- instruction или test.

* Не удаляются пробелы до и после блоков (" New ", " Folks " -- с пробелами). Хотя, если вам это и не надо, то мой код можно упростить:
Код: 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.
#include <stdbool.h>
#include <string.h>
#include <stdio.h>

/* только для строковых литералов */
#define SL_LEN(string_lit) (sizeof(string_lit) - 1)

#define INSTRUCTION_START "SOI"
#define INSTRUCTION_END "EOI"
#define TEST_START "SOT"
#define TEST_END "EOT"

bool handle_instruction_block(const char block[], size_t block_len);
bool handle_test_block(const char block[], size_t block_len);

bool parse_blocks(const char text[]) {
  size_t pos, block_start;
  const char* end_marker;

  pos = 0;
  for (;;) {
    while (text[pos] == ' ') pos++; /* пропускаем пробелы */

    if (text[pos] == '\0')
      break;

    if (strncmp(text + pos, INSTRUCTION_START, SL_LEN(INSTRUCTION_START)) == 0) {
      pos += SL_LEN(INSTRUCTION_START);
      block_start = pos;
      end_marker = strstr(text + pos, INSTRUCTION_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      if (!handle_instruction_block(text + block_start, pos - block_start)) return false;
      pos += SL_LEN(INSTRUCTION_END);
    } else if (strncmp(text + pos, TEST_START, SL_LEN(TEST_START)) == 0) {
      pos += SL_LEN(TEST_START);
      block_start = pos;
      end_marker = strstr(text + pos, TEST_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      if (!handle_test_block(text + block_start, pos - block_start)) return false;
      pos += SL_LEN(TEST_END);
    } else {
      return false;
    }
  }

  return true;
}

bool handle_instruction_block(const char block[], size_t block_len) {
  /* строка block не завершается нулевым char-ом ('\0'), поэтому явно указываем длину */
  printf("instruction '%.*s'\n", (int)block_len, block);
  return true;
}

bool handle_test_block(const char block[], size_t block_len) {
  printf("test '%.*s'\n", (int)block_len, block);
  return true;
}

int main() {
  parse_blocks(" SOI Happy EOI  SOT New EOT  SOT Year EOT  SOT EOT  SOI Folks EOI ");
  return 0;
}

Вывод на консоль:
Код: sql
1.
2.
3.
4.
5.
instruction ' Happy '
test ' New '
test ' Year '
test ' '
instruction ' Folks '
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39384552
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр СедовКстати, автор вопроса не писал, что задача для controller-а.
это не тайна, есть предыдущие вопросы и ответы
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39385002
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пётр Седов* Использование буфера фиксированной длины. Приемлемо разве что в учебных заданиях, во «взрослом» коде -- почти никогда. Кроме случаев, когда есть гарантированное ограничение на длину строки (например, WinAPI-шная константа MAX_PATH, которая используется в структуре WIN32_FIND_DATA). Но вы такое гарантированное ограничение не упоминаете.


тут в чем проблема. я пишу под эмбедед. если не использоать буфер фиксированной длины то нужна динамическая алокация памяти. а в эмбедед это плохо.
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39385163
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7, если вам надо блоки иметь как ноль-завершаемые строки, и можно менять содержимое исходной строки, то можно поступить так, как делает функция strtok: писать завершающие нулевые char-ы ('\0') прямо в исходную строку:
Код: 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 <stdbool.h>
#include <string.h>
#include <stdio.h>

/* только для строковых литералов */
#define SL_LEN(string_lit) (sizeof(string_lit) - 1)

#define INSTRUCTION_START "SOI"
#define INSTRUCTION_END "EOI"
#define TEST_START "SOT"
#define TEST_END "EOT"

bool handle_instruction_block(char block[]);
bool handle_test_block(char block[]);

/* меняет содержимое строки text */
bool parse_blocks(char text[]) {
  size_t pos, block_start;
  char* end_marker;

  pos = 0;
  for (;;) {
    /* пропускаем пробелы */
    while ((text[pos] == ' ') || (text[pos] == '\t') || (text[pos] == '\r') || (text[pos] == '\n'))
      pos++;

    if (text[pos] == '\0')
      break;

    if (strncmp(text + pos, INSTRUCTION_START, SL_LEN(INSTRUCTION_START)) == 0) {
      pos += SL_LEN(INSTRUCTION_START);
      block_start = pos;
      end_marker = strstr(text + pos, INSTRUCTION_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      text[pos] = '\0'; /* обрубаем строку в том месте, где находится INSTRUCTION_END */
      if (!handle_instruction_block(text + block_start)) return false;
      pos += SL_LEN(INSTRUCTION_END);
    } else if (strncmp(text + pos, TEST_START, SL_LEN(TEST_START)) == 0) {
      pos += SL_LEN(TEST_START);
      block_start = pos;
      end_marker = strstr(text + pos, TEST_END);
      if (end_marker == NULL) return false;
      pos = end_marker - text;
      text[pos] = '\0'; /* обрубаем строку в том месте, где находится TEST_END */
      if (!handle_test_block(text + block_start)) return false;
      pos += SL_LEN(TEST_END);
    } else {
      return false;
    }
  }

  return true;
}

/* может менять содержимое строки block */
bool handle_instruction_block(char block[]) {
  printf("instruction '%s'\n", block);
  return true;
}

/* может менять содержимое строки block */
bool handle_test_block(char block[]) {
  printf("test '%s'\n", block);
  return true;
}

int main() {
  char text[] = " SOI Happy EOI  SOT New EOT  SOT Year EOT  SOT EOT  SOI Folks EOI ";
  parse_blocks(text);
  return 0;
}

Вывод на консоль:
Код: sql
1.
2.
3.
4.
5.
instruction ' Happy '
test ' New '
test ' Year '
test ' '
instruction ' Folks '
...
Рейтинг: 0 / 0
Найти текстовые блоки разного типа в С.
    #39385192
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пётр Седов,
понял. спасибо.
...
Рейтинг: 0 / 0
15 сообщений из 40, страница 2 из 2
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Найти текстовые блоки разного типа в С.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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