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++;  
}

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


По-моему это говно, не пытайся его называть умными словами, лучше оно от этого не станет. Алсо, стейт машина без кейса? Копипаста? Чем strtok не нравится?

anonymous
()

Чисто формально - да, так как счетчики изменяются в конечных пределах. На практике автоматом обычно называется код, в котором четко описан набор состояний и переходов, а не любая лапша из циклов и счетчиков

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

Чем strtok не нравится?

Писалось для МК, strtok выполняется за ~2000 тактов, это пример за ~1000.

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

Если плясать от того, что есть, нужно немного иначе построить цикл, проверять *str == ' ' до флагов, а флаги сунуть в switch, остальное в функцию.

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

до флагов, а флаги сунуть в switch

Кажется понял, спасибо.

stD
() автор топика

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

#include <stdio.h>
#include <stdlib.h>
#define VARBUF 8

int main(int argc, char *argv[])
{
    char data[] = "s x1 y1\nm x2 y2\n";
    char var1[VARBUF] = {0};
    char var2[VARBUF] = {0};
    char var3[VARBUF] = {0};
    char var4[VARBUF] = {0};
    sscanf(data,"s x%i y%i\nm x%i y%i\n",&var1[0],&var2[0],&var3[0],&var4[0]);
    printf("%i %i %i %i\n",var1[0],var2[0],var3[0],var4[0]);
    return 0;
}
Deleted
()

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

Если сможешь предстваить в виде одного из канонических предствалений КА (теор множественный, диаграмма состояний, таблица переходов), то можно назвать КА. Если сможешь, то сразу поймешь, что лучше теория или твоя практика. Если не сможешь твой вопрос не имеет смысла, так как ты не имеешь понятия, что такое КА, и сравнивать не в состоянии.

*про оптимизацию и такты*

- зачем подсчитываешь длину строки str_len, если можешь проверять на символ конца строки?
- дай flag и его значениям осмысленные имена, например: state, X1, ..., X%N%
- if(flag == %N% && *str == ' ') - вытащи *str == ' ' в внеший if, заодно общий блок:

str++;
i++;
i2 = 0;
- вытащи for { var%N% } в отдельную функцию с параметром (инлайн или макрос)
- и, вообще, нарисуй нормальный КА для разбора и реализуй его в коде и почувствуй разницу.

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

На sscanf тратится 2800 тактов.

А так?

#include <stdio.h>
#include <stdlib.h>
#define VARBUF 8

void scanxy(char * str,int varout[3])
{
    char buff[VARBUF];
    int c;
    enum{
    sdata , mdata , nodata,
    sxdata, sydata, mxdata, mydata,
    sxend , syend , mxend , myend
    };
    int status = nodata;
    for (int i = 0; str[i] != EOF; ++i)
    {
        switch(str[i])
        {
            case 's': status = sdata;
                      break;
            case 'm': status = mdata;
                      break;
            case 'x': (status == sdata)? status = sxdata,i++:0;
                      (status == mdata)? status = mxdata,i++:0;
                      break;
            case 'y': (status == sdata)? status = sydata,i++:0;
                      (status == mdata)? status = mydata,i++:0;
                      break;
            case ' ': (status == sxdata)?status = sxend:0;
                      (status == sydata)?status = syend:0;
                      (status == mxdata)?status = mxend:0;
                      (status == mydata)?status = myend:0;
                       break;
            case '\n':(status == sxdata)?status = sxend:0;
                      (status == sydata)?status = syend:0;
                      (status == mxdata)?status = mxend:0;
                      (status == mydata)?status = myend:0;
                      break;
            default:  break;
        };

        switch(status)
        {
            case sxdata:buff[c++]=str[i];
            break;
            case sydata:buff[c++]=str[i];
            break;
            case mxdata:buff[c++]=str[i];
            break;
            case mydata:buff[c++]=str[i];
            break;
            case sxend:{
                            varout[0] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = sdata;
                       }break;
            case syend:{
                            varout[1] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = sdata;
                       }break;
            case mxend:{
                            varout[2] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = mdata;
                       }break;
            case myend:{
                            varout[3] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = mdata;
                       }break;
            default:break;
        };
    };
}

int main(int argc, char *argv[])
{
    char data[] = "s x1 y1\nm x2 y2\n";
    int  varout[3];
    scanxy(data,varout);
    printf("%d %d %d %d\n",varout[0],varout[1],varout[2],varout[3]);
    return 0;
}

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

#include <stdio.h>
#include <stdlib.h>
#define VARBUF 8

void scanxy(char * str,int varout[3])
{
    char buff[VARBUF] = {'\0'};
    int c=0;
    enum{
    sdata , mdata , nodata,
    sxdata, sydata, mxdata, mydata,
    sxend , syend , mxend , myend
    };
    int status = nodata;
    for (int i = 0; str[i] != '\0'; i++)
    {
        switch(str[i])
        {
            case 's': status = sdata;
                      break;
            case 'm': status = mdata;
                      break;
            case 'x': (status == sdata)? status = sxdata,i++:0;
                      (status == mdata)? status = mxdata,i++:0;
                      break;
            case 'y': (status == sdata)? status = sydata,i++:0;
                      (status == mdata)? status = mydata,i++:0;
                      break;
            case ' ': (status == sxdata)?status = sxend:0;
                      (status == sydata)?status = syend:0;
                      (status == mxdata)?status = mxend:0;
                      (status == mydata)?status = myend:0;
                       break;
            case '\n':(status == sxdata)?status = sxend:0;
                      (status == sydata)?status = syend:0;
                      (status == mxdata)?status = mxend:0;
                      (status == mydata)?status = myend:0;
                      break;
            default:  break;
        };

        switch(status)
        {
            case sxdata:buff[c++]=str[i];
            break;
            case sydata:buff[c++]=str[i];
            break;
            case mxdata:buff[c++]=str[i];
            break;
            case mydata:buff[c++]=str[i];
            break;
            case sxend:{
                            varout[0] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = sdata;
                       }break;
            case syend:{
                            varout[1] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = nodata;
                       }break;
            case mxend:{
                            varout[2] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = mdata;
                       }break;
            case myend:{
                            varout[3] = atoi(buff);
                            c=0;
                            while(buff[c++]='\0'&&c!=VARBUF);
                            c=0;
                            status = nodata;
                       }break;
            default:break;
        };
    };
}

int main(int argc, char *argv[])
{
    char data[] = "s x1 y1\nm x2 y2\n";
    int  varout[] = {0,0,0,0};
    scanxy(data,varout);
    printf("%d %d %d %d\n",varout[0],varout[1],varout[2],varout[3]);
    return 0;
}
Deleted
()
Ответ на: комментарий от stD

Ну так пофикси )) Вместо buff передавай в функцию 4 массива var и прямо пиши в них там где пишется в buff, *end секции тогда можно удалить оставив только сброс с и i++ убрать что бы символы x/y водили в массив.

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

Писалось для МК, strtok выполняется за ~2000 тактов, это пример за ~1000.

А это прям хотспот или оптимизируем из любви к искусству?

anonymous
()
Ответ на: комментарий от stD
#include <stdio.h>
#include <stdlib.h>
#define VARBUF 8

void scanxy(char * str,char *v1,char *v2,char *v3, char*v4)
{
    char buff[VARBUF] = {'\0'};
    int v1c=0,v2c=0,v3c=0,v4c=0;
    enum{
    sdata , mdata , nodata, smend,
    sxdata, sydata, mxdata, mydata,
    };
    int status = nodata;
    for (int i = 0; str[i] != '\0'; i++)
    {
        switch(str[i])
        {
            case 's': status = sdata;
                      break;
            case 'm': status = mdata;
                      break;
            case 'x': (status == sdata)? status = sxdata:0;
                      (status == mdata)? status = mxdata:0;
                      break;
            case 'y': (status == sdata)? status = sydata:0;
                      (status == mdata)? status = mydata:0;
                      break;
            case ' ': (status == sxdata)?status = sdata:0;
                      (status == sydata)?status = smend:0;
                      (status == mxdata)?status = mdata:0;
                      (status == mydata)?status = smend:0;
                       break;
            case '\n':(status == sxdata)?status = smend:0;
                      (status == sydata)?status = smend:0;
                      (status == mxdata)?status = smend:0;
                      (status == mydata)?status = smend:0;
                      break;
            default:  break;
        };
        switch(status)
        {
            case sxdata: v1[v1c++]=str[i];
            break;
            case sydata: v2[v2c++]=str[i];
            break;
            case mxdata: v3[v3c++]=str[i];
            break;
            case mydata: v4[v4c++]=str[i];
            break;
            default:break;
        };
    };
}

int main(int argc, char *argv[])
{
    char data[] = "s x1 y1\nm x2 y2\n";
    char v1[VARBUF]={0};
    char v2[VARBUF]={0};
    char v3[VARBUF]={0};
    char v4[VARBUF]={0};
    scanxy(data,v1,v2,v3,v4);
    printf("%s %s %s %s\n",v1,v2,v3,v4);
    return 0;
}

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

Это не входит в рамки измеряемого.

  count_tic = 0;
  DWT_CYCCNT = 0;

  for (int i = 0; str[i] != '\0'; i++)
  {
      switch(str[i])
      {
          case 's':
        	  status = sdata;
          break;

          case 'm':
        	  status = mdata;
          break;

          case 'x':
        	  (status == sdata)? status = sxdata:0;
              (status == mdata)? status = mxdata:0;
          break;

          case 'y':
        	  (status == sdata)? status = sydata:0;
        	  (status == mdata)? status = mydata:0;
          break;

          case ' ':
        	  (status == sxdata)?status = sdata:0;
              (status == sydata)?status = smend:0;
              (status == mxdata)?status = mdata:0;
              (status == mydata)?status = smend:0;
          break;

          case '\n':
        	  (status == sxdata)?status = smend:0;
              (status == sydata)?status = smend:0;
              (status == mxdata)?status = smend:0;
              (status == mydata)?status = smend:0;
          break;

          default:
        	  break;
      }

      switch(status)
      {
          case sxdata:
        	  var1[v1c++] = str[i];
          break;

          case sydata:
        	  var2[v2c++] = str[i];
          break;

          case mxdata:
        	  var3[v3c++] = str[i];
          break;

          case mydata:
        	  var4[v4c++] = str[i];
          break;

          default:
        	  break;
      }
  }

count_tic = DWT_CYCCNT;

print...

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

Я не спец по микроконтроллерам, но 1000+ тактов для 15 символов - это что-то с чем-то?

anonymous
()

Нет, это конечным автоматом называть не надо. У КА описываются состояния, состояниям даются красивые понятные имена, в любой момент можно сказать, в каком именно состоянии автомат находится. А тут какая-то «лапша из счетчиков и циклов», как отметили выше.

Deleted
()

а теперь перепишите свой т.н. «КА» так что бы они работали и с потоком байт и с неполными строками и с битыми строками (игнорили мусор) и не ломались.

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

а теперь перепишите

Я сам буду решать, что мне делать.

Целостность строки гарантирована.

...

Не много не точно замеры проводил (было включено прерывание), вот что в итоге получилось...

1. Мой код - 471 такт.

2. Предложеный linux-org-ru (спасибо ещё раз) - 602 такта.

3. strtok - 1356 тактов.

4. sscanf - 3000 тактов.

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

471 такт

Все равно много. 10-15 тактов на символ - вот тогда нормально.

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

А сколько времени занимают вот эти варианты(в обоих случаях не ставится завершающий ноль ибо вначале все четыре буфера и так зануляются, это полное обнуление буферов обязательно? Сколько тактов оно съедает?):

void variantA()
{
#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 i = 0;
    int str_len = (int)strlen(mystr);
    char * str_end = str + str_len;

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

    //skip space before variable 1
    ++str;

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

    //skip space before variable 2
    ++str;

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

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

    //skip space before variable 3
    ++str;

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

    //skip space before variable 4
    ++str;

    //copy variable 4
    i = 0;
    while (*str != '\n' && str < str_end) {
        var4[i] = *str;
        ++i;
        ++str;
    }
}
void variantB()
{
#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,};
    char *start = 0;
    int str_len = (int)strlen(mystr);
    char * str_end = str + str_len;

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

    //skip space before variable 1
    ++str;

    start = str;
    //copy variable 1
    while (*str != ' ' && str < str_end) {
        ++str;
    }
    memcpy(var1, start, str - start);

    //skip space before variable 2
    ++str;

    //copy variable 2
    start = str;
    while (*str != '\n' && str < str_end) {
        ++str;
    }
    memcpy(var2, start, str - start);

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

    //skip space before variable 3
    ++str;

    //copy variable 3
    start = str;
    while (*str != ' ' && str < str_end) {
        ++str;
    }
    memcpy(var3, start, str - start);

    //skip space before variable 4
    ++str;

    //copy variable 4
    start = str;
    while (*str != '\n' && str < str_end) {
        ++str;
    }
    memcpy(var4, start, str - start);
}

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

Покажи свой итоговый вариант, раз уж тут специалтная олимпиада разгорелась.

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

Можешь показать ассемблерный результат компиляции variantA и что за MK? Ассемблерный код может помочь увидеть лишние действия. А что насчет вот этого кода:

  char var1[VARBUF] = {0,};
  char var2[VARBUF] = {0,};
  char var3[VARBUF] = {0,};
  char var4[VARBUF] = {0,};
Так ли надо его обнулять? Вот такой чуть измененный вариант сколько будет?:
void variantA_noBufferInit()
{
#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;
    int str_len = (int)strlen(mystr);
    char * str_end = str + str_len;

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

    //skip space before variable 1
    ++str;

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

    //skip space before variable 2
    ++str;

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

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

    //skip space before variable 3
    ++str;

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

    //skip space before variable 4
    ++str;

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

V1KT0P ★★
()
Ответ на: комментарий от V1KT0P
-    int str_len = (int)strlen(mystr);
-    char * str_end = str + str_len;
+    char * str_end = strchr (str, '\0');
akk ★★★★★
()
Ответ на: комментарий от V1KT0P

Я в ассемблере не силён (мягко говоря).

МК - stm32F1.

Инициализация переменных не учавствует в расчётах, отсчёт начинаеься с первого цикла while.

Последний ваш код показал 312 тактов.

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

okay. а если строка невалидная и где то пропущен пробел?

Так сказано что:

Целостность строки гарантирована.

А так там и значения могут в буфер не влезть. Плюс в оригинальном коде при нахождении пробела сразу происходит чтение переменной, что для меня сразу означает что несколько пробелов подряд идти не могут. Тут много чего может пойти не так, но я так понял автора интересует именно максимально возможный код для парсинга а проверки потом добавить если надо не проблема.

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

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

Убрал у своего кода обнуления и получил 420 тактов. Ваш в любом случае быстрее.

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

Я в ассемблере не силён (мягко говоря).

Для GCC это делается вот так:

gcc -S -o my_asm_output.s helloworld.c

Последний ваш код показал 312 тактов.

Дополнительно 68 тактов для записи нулевых байтов дороговато.

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

Для GCC это делается вот так:

Мне надо разобраться в том, как это сделать в среде TrueStudio.

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

Убрал у своего кода обнуления и получил 420 тактов. Ваш в любом случае быстрее.

Твой вариант медленнее скорее всего из-за лишних точек ветвления. В первом for-е у тебя if-ы будут проверяться даже если они уже не нужны, так-же во вложенных for-ах также есть if который будет проверяться и тратить такты.
Кстати что за компилятор и какая версия?

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

Нельзя так писать. Если у вас while(.... str < str_end) имеет место, то ++str после этого никак допускать нельзя. Правильнее вообще выделить буфер как копию входной строки, *vN сделать указателями на смещения в этом буфере.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от 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
() автор топика
Ответ на: комментарий от V1KT0P

Почему-же, если чтение из «str» происходит только после условия проверки «str < str_end»?

Потому что у вас следующее чтение будет за str_end.

vodz ★★★★★
()
Ответ на: комментарий от 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 ★★
()
Ответ на: комментарий от vodz

Потому что у вас следующее чтение будет за str_end.

Да, действительно моя ошибка, надо поменять местами проверки в условии while.
Пишу на C++ и с голыми указателями почти не работаю, вот мозги и заплывают потихоньку.

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