Russian Qt Forum

Qt => Общие вопросы => Тема начата: nkly777 от Март 30, 2007, 11:05



Название: Выход из цикла по условию
Отправлено: nkly777 от Март 30, 2007, 11:05
У меня в программе есть функция которая читает символы из com порта и складывает их в строку QString. Выход из функции должен происходить по одному из трех условий
1 Получена комбинация "PASSWORD <"
2 Получена комбинация "<"
3 По истечении определенного времени

Вот код этой функции
Код:

int Tread::readATS(void)
{
std::cout <<"начало работы readATS"<<std::endl;
QChar ch;
QString str;
QTime t;
int value = 0;
int timeout =5000; /**Время ожидания приглашения ввода пароля или команды**/
t.start();

while(t.elapsed() <= timeout)
{
ch=fgetc(port);
std::cout<<ch.toAscii();
str=str+ch;
if(str.contains("<",Qt::CaseInsensitive))
{
if(str.contains("PASSWORD",Qt::CaseSensitive))
{
value=1;
std::cout<<"Запрос пароля"<<std::endl;
break;
}
value=2;
std::cout<<"Введите команду"<<std::endl;
break;
}
}
std::cout <<"Завершение работы readATS"<<std::endl;
return value;
}


Если приходит "PASSWORD <" то выход все равно происходит как будто пришло "<"
Что неправильно? Как сделать правильно?

PS Вывод в std я вставил для отладки


Название: Выход из цикла по условию
Отправлено: Mikhail от Март 30, 2007, 12:47
Не полная информация в вопросе.
Где вызвается readATS(void)?
Если Tread - нить, то где ее функция run().


Название: Выход из цикла по условию
Отправлено: nkly777 от Март 30, 2007, 13:09
Функция readATS(void) вызывается в нити Tread
Привожу ее функцию run()
Код:

void Tread::run()
{
answer=rd_wr_port( zapros);
}

Реализация функции rd_wr_port(zapros) следующая
Код:

QString Tread::rd_wr_port(QString zapros)
{
QString otvet;
desc_port=open_port();
init_raw_tty( desc_port);
port = fdopen( desc_port, "w+b" );
tcsendbreak(desc_port,400);
tcflush(desc_port, TCIFLUSH);
int v=readATS();    // Вызов функции readATS()
tcflush(desc_port,TCIFLUSH);
std::cout<<"v="<<v<<std::endl;
tcflush(desc_port,TCIFLUSH);
switch(v)
{
case 0:
{
std::cout<<"readATS() вернула 0, истек период ожидания"<<std::endl;
break;
}
case 1:
{ //PASSWORD
sendpassword(port);
usleep(500000);
sendcommand(zapros);
otvet=getreport();
break;
}
case 2:
{ //Команда
sendcommand(zapros);
otvet=getreport();
break;
}
default:
{
std::cout<<"Функция readATS() вернула "<<v<<" неизвестный ответ."<<std::endl;
}
}

fclose(port);
close(desc_port);
return otvet;
}


Порт открываю со следующими параметрами
Код:

void Tread::init_raw_tty(int desc_port)
{
struct termios newtio;

bzero(&newtio,sizeof(newtio)); //Очищаем структуру newtio
//---------------------------------------------------------1200 BOD,cs7|1,parenb
  newtio.c_cc[VTIME]    = 1;
   newtio.c_cc[VMIN]     = 0;
newtio.c_cflag &=~(CSTOPB|CS5|CS6|CS7|CS8|PARENB|PARODD);
newtio.c_cflag |=(CS7|PARENB|CREAD|CLOCAL);
cfsetospeed(&newtio, B1200);
cfsetispeed(&newtio, B1200);
//------------------------------------------------------------------------------------------------------------------------------
    tcflush(desc_port, TCIFLUSH);
    tcsetattr(desc_port,TCSANOW,&newtio);
}


Название: Выход из цикла по условию
Отправлено: SABROG от Март 30, 2007, 13:31
Ну я и не удивлен, у тебя 2 break'a стоит и на получение пароля и на получение символа "<"
Код:

      if(str.contains("<",Qt::CaseInsensitive))
         {
            if(str.contains("PASSWORD",Qt::CaseSensitive))
               {
                  value=1;
                  std::cout<<"Запрос пароля"<<std::endl;
                  break; // РАЗ
               }
            value=2;
            std::cout<<"Введите команду"<<std::endl;
            break; // ДВАЗ
         }


Оба обрубают цикл while


Название: Выход из цикла по условию
Отправлено: nkly777 от Март 30, 2007, 13:59
Ну так мне и нужно сделать break либо по РАЗ либо по ДВА. Насколько я понимаю при получении PASSWORD выполнится break РАЗ и произойдет выход из цикла WHILE, а break ДВА при этом пробросится. Или я неправ?? Тогда как правильно?


Название: Выход из цикла по условию
Отправлено: SABROG от Март 30, 2007, 15:00
Цитата: "nkly777"
Ну так мне и нужно сделать break либо по РАЗ либо по ДВА. Насколько я понимаю при получении PASSWORD выполнится break РАЗ и произойдет выход из цикла WHILE, а break ДВА при этом пробросится. Или я неправ?? Тогда как правильно?


Цитировать

Если приходит "PASSWORD <" то выход все равно происходит как будто пришло "<"


Ты определись что тебе нужно... break ДВА никуда не пробросится, а ровно также выйдет из цикла WHILE.


Название: Выход из цикла по условию
Отправлено: nkly777 от Март 30, 2007, 15:16
Ты хочешь сказать что break РАЗ не прервет цикл while() а выполнит команду value=2;
Но оператор break - это оператор безусловного выхода из цикла, следовательно если в str обнаружится PASSWORD то должно выполниться value=1и выход из цикла WHILE()


Название: Выход из цикла по условию
Отправлено: SABROG от Март 30, 2007, 15:35
Оба брейка выведут из цикла, ты сам написал, что этого хочешь, ты также написал, что тебе не нравится, что цикл прерывается при нахождении символа "<"...


Название: Выход из цикла по условию
Отправлено: nkly777 от Март 30, 2007, 16:12
Наверное я неправильно объясняю.
В порт может прийти последовательность символов (включая непечатные символы и символы перевода строки) произвольной длины которая заканчивается следующей комбинацией PASSWORD <
В этом случае мне нужно послать пароль и в случае удачного коннекта послать некие команды.
В порт также может прийти последовательность символов (включая непечатные символы и символы перевода строки) произвольной длины которая заканчивается символом "<"
В этом случае мне не нужно посылать пароль а нужно сразу отправить определенную комаду.
Так вот как мне различить какая у меня ситуация, что мне нужно, вводить пароль или посылать команду????
У меня почему-то получается что всегда мне надо вводить команду (функция возвращает value=2) хотя реально иногда нужно вводить пароль(функция должна возвращать value=1)


Название: Выход из цикла по условию
Отправлено: SABROG от Март 30, 2007, 17:50
У тебя неправильно сделано, ты ищешь сначала знак "<" и потом делаешь выводы. Но "PASSWORD <" сам по себе имеет такой символ, отсюда и косяки начинаются.
Тебе надо искать сначала "PASSWORD <", и если строка его не содержит, то уже потом искать "<"


Название: Выход из цикла по условию
Отправлено: Mikhail от Март 30, 2007, 20:02
Твоя нить сработает только один раз и завершится.
Вообще то она нужна при работе с портом постоянно.
Из нити полученная информация должна передаваться в блок анализа.
У тебя же анализ заверщает нить.


Название: Выход из цикла по условию
Отправлено: Вудруф от Апрель 02, 2007, 07:12
SABROG - по-моему, ты чего-то не то говоришь. Если строка содержит "PASSWORD <", то сработают оба условия, и программа должна выйти по break номер РАЗ.
Другое дело, что те же if'ы сработают для строки "1 < 2 && PASSWORD > 5".


Название: Выход из цикла по условию
Отправлено: nkly777 от Апрель 02, 2007, 14:06
Функция readATS() работает правильно. Проблема оказалась совсем в другом месте.При обращении к порту функция читала не то что реально передавала станция, а то что оставалось в буферах от прошлых попыток чтения. Вставил дополнительные функции очистки com порта перед обращением к нему, теперь вроде работает нормально.