LINUX.ORG.RU

Конечный автомат

 


0

2

Здравствуйте.

Есть задача - распарсить строку «s x1 y1\nm x2 y2\n» разложив x1, y1, x2, y2 по отдельным массивам...

  #define VARBUF 8
  char mystr[] = "s x1 y1\nm x2 y2\n";
  char *str = mystr;
  char var1[VARBUF] = {0,};
  char var2[VARBUF] = {0,};
  char var3[VARBUF] = {0,};
  char var4[VARBUF] = {0,};
  int flag = 1, i = 0, i2 = 0;
  int str_len = (int)strlen(mystr);
  
  for(; i < str_len; i++)
  {
	  if(flag == 1 && *str == ' ')
	  {                               
		  flag = 2;
		  str++;
		  i++;
		  i2 = 0;
		  for(; i < str_len && i2 < VARBUF - 1; i++, i2++, str++)
		  {
			  var1[i2] = *str;
			  if(*str == ' ') 
			  {
				  var1[i2] = 0;
				  break;
			  }
		  }
	  }
	  
	  if(flag == 2 && *str == ' ')
	  {                               
		  flag = 3;
		  str++;
		  i++;
		  i2 = 0;
		  for(; i < str_len && i2 < VARBUF - 1; i++, i2++, str++)
		  {
			  var2[i2] = *str;
			  if(*str == '\n') 
			  {
				  var2[i2] = 0;
				  break;
			  }
		  }
	  }	  
 
	  if(flag == 3 && *str == ' ')
	  {                              
		  flag = 4;
		  str++;
		  i++;
		  i2 = 0;
		  for(; i < str_len && i2 < VARBUF - 1; i++, i2++, str++)
		  {
			  var3[i2] = *str;
			  if(*str == ' ') 
			  {
				  var3[i2] = 0;
				  break;
			  }
		  }
	  }		  
	  
	  if(flag == 4 && *str == ' ')
	  {                              
		  flag = 0;
		  str++;
		  i++;
		  i2 = 0;
		  for(; i < str_len && i2 < VARBUF - 1; i++, i2++, str++)
		  {
			  var4[i2] = *str;
			  if(*str == '\n') 
			  {
				  var4[i2] = 0;
				  break;
			  }
		  }
	  }	
	  
	  str++;  
}

Можно ли назвать представленный выше код конечным автоматом?


Ответ на: комментарий от stD

Всё верно, целостность строки гарантирована.

Если есть 100% гарантия правильности строки, то можно использовать вот такой небезопасный код:

void variantA_unsafe()
{
#define VARBUF 8
    char mystr[] = "s x1 y1\nm x2 y2\n";
    char *str = mystr;
    char var1[VARBUF];
    char var2[VARBUF];
    char var3[VARBUF];
    char var4[VARBUF];
    int i = 0;

    //skip first name
    while (*str != ' ') {
        ++str;
    }

    //skip space before variable 1
    ++str;

    //copy variable 1
    while (*str != ' ') {
        var1[i] = *str;
        ++i;
        ++str;
    }
    var1[i] = 0;

    //skip space before variable 2
    ++str;

    //copy variable 2
    i = 0;
    while (*str != '\n') {
        var2[i] = *str;
        ++i;
        ++str;
    }
    var2[i] = 0;

    //skip second name
    while (*str != ' ') {
        ++str;
    }

    //skip space before variable 3
    ++str;

    //copy variable 3
    i = 0;
    while (*str != ' ') {
        var3[i] = *str;
        ++i;
        ++str;
    }
    var3[i] = 0;

    //skip space before variable 4
    ++str;

    //copy variable 4
    i = 0;
    while (*str != '\n') {
        var4[i] = *str;
        ++i;
        ++str;
    }
    var4[i] = 0;
}

V1KT0P ★★
()
Ответ на: комментарий от V1KT0P

Сделал я ассемблерный файл. Там 7000 строк и ссылки на другие файлы. Никогда в этом не разберусь.

stD
() автор топика
Ответ на: комментарий от stD

Сделал я ассемблерный файл. Там 7000 строк и ссылки на другие файлы. Никогда в этом не разберусь.

Если ты добавил вот эту опцию:

-fverbose-asm
То на выходе в листинге ассемблера в виде комментариев будут строки соответствующего кода, по ним можешь поиском найти и на глаз определить какой кусок асм кода тебе нужен:
# main.cpp:94:     while (*str != ' ' && str < str_end) {
	.loc 1 94 0
	movq	-80(%rbp), %rax	# str, tmp106
	movzbl	(%rax), %eax	# *str_13, _3
	cmpb	$32, %al	#, _3
	je	.L22	#,
# main.cpp:94:     while (*str != ' ' && str < str_end) {
	.loc 1 94 0 is_stmt 0 discriminator 1
	movq	-80(%rbp), %rax	# str, tmp107
	cmpq	-72(%rbp), %rax	# str_end, tmp107
	jnb	.L22	#,
# main.cpp:95:         ++str;
	.loc 1 95 0 is_stmt 1
	addq	$1, -80(%rbp)	#, str
# main.cpp:94:     while (*str != ' ' && str < str_end) {
	.loc 1 94 0
	jmp	.L23	#
.L22:
# main.cpp:99:     ++str;
	.loc 1 99 0
	addq	$1, -80(%rbp)	#, str
.L25:

V1KT0P ★★
()
Ответ на: комментарий от V1KT0P

Тогда уже:

void variantA_unsafe()
{
#define VARBUF 8
    const char *inp = "s x1 y1\nm x2 y2\n";
    char var1[VARBUF], var2[VARBUF], var3[VARBUF], var4[VARBUF], *outp;

    while (*inp != ' ') ++inp; // skip "s"
    while (*inp == ' ') ++inp; // skip spaces
    outp = var1;
    while (*inp != ' ') *outp++ = *inp++; // copy variable 1
    *outp = '\0';

    while (*inp == ' ') ++inp; // skip spaces
    outp = var2;
    while (*inp != '\n') *outp++ = *inp++; // copy variable 2
    *outp = '\0';

    while (*inp != ' ') ++inp; // skip "\nm"
    while (*inp == ' ') ++inp; // skip spaces
    outp = var3;
    while (*inp != ' ') *outp++ = *inp++; // copy variable 3
    *outp = '\0';

    while (*inp == ' ') ++inp; // skip spaces
    outp = var4;
    while (*inp != '\n') *outp++ = *inp++; // copy variable 3
    *outp = '\0';

    printf("[%s] [%s] [%s] [%s]\n", var1, var2, var3, var4);
}

Или, если формат строки действительно гарантируется, вплоть до количества пробелов:

void variantA_realunsafe()
{
#define VARBUF 8
    const char *inp = "s x1 y1\nm x2 y2\n";
    char var1[VARBUF], var2[VARBUF], var3[VARBUF], var4[VARBUF], *outp;
    
#define SKIP_AND_COPY_TO(OFFSET, TOVAR, ENDCHAR) \
      inp += OFFSET; \
      outp = TOVAR; \
      while (*inp != ENDCHAR) *outp++ = *inp++; \
      *outp = '\0';

    SKIP_AND_COPY_TO(2, var1, ' ');  // skip "s " and copy variable 1
    SKIP_AND_COPY_TO(1, var2, '\n'); // skip " " and copy variable 2
    SKIP_AND_COPY_TO(3, var3, ' ');  // skip "\nm " and copy variable 3
    SKIP_AND_COPY_TO(1, var4, '\n'); // skip " " and copy variable 4

#undef SKIP_AND_COPY_TO

    printf("[%s] [%s] [%s] [%s]\n", var1, var2, var3, var4);
}

Думаю, это уже не победить.

anonymous
()
Ответ на: комментарий от stD

Не забудьте включить компилятору оптимизацию по скорости: опция -O3 или что там для ваших контроллеров есть.

anonymous
()
Ответ на: комментарий от anonymous

или что там для ваших контроллеров есть

Всё то же самое, что и в большом компьютере, только добавьте к этому таймеры, прерывания, приоритеты, регистры, работу с многочисленными интерфейсами и конечно даташиты. )))

Оптимизация по размеру -Оs.

stD
() автор топика
Последнее исправление: stD (всего исправлений: 3)
Ответ на: комментарий от stD

Оптимизация по размеру -Оs.

Все-же удобно было бы глянуть ассемблерный вывод. Мало ли что там компилятор нагенерит.

V1KT0P ★★
()
Ответ на: комментарий от stD

С каким кодом сгенерить файлик, с Вашим или моим?

Сгенерируй с вариантом «variantA_unsafe», он хоть и не безопасный но зато должен быть максимально приближен к предельной скорости. Кстати сколько тактов на этом варианте?

V1KT0P ★★
()
Ответ на: комментарий от V1KT0P

Чего-то не получается, файл создаётся но в нем не слова про нужный код. Буду ковыряться.

stD
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.