Оптимальный алгоритм поиск текста в массиве

rene
Offline
Зарегистрирован: 21.01.2014

Доброго времени суток!

Подскажите начинающему оптимальный алгоритм поиск текста в массиве.

Например есть массив char sym[] = "alpha beta gamma delta"

необходимо определить в нем наличие слова gamma

как это можно реализовать в наилучшем виде?

SunX
SunX аватар
Offline
Зарегистрирован: 04.10.2014
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Единого наилучшего алгоритма нет и не может существовать в принципе.

Во-первых, два существенно различающихся варианта, когда входной массив отсортирован, и когда - нет.

Потом поиск можкт быть регистро-зависимый и независимый и т.п.

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

rene
Offline
Зарегистрирован: 21.01.2014

Почитал по ссылке, понял что мне нет необходимости реализовывать весь алгоритм поиска.

Объясню что пытаюсь реализовать.

В массив попадают данные принимаемые GPRS модулем. Мне необходимо определить момент приема СМС сообщения. Все СМС начинаются с +CMT:

т.е. это можно реализовать просто:

if (sym[0] == "+") &&
    (sym[1] == "C") &&
    (sym[2] == "M") &&
    (sym[3] == "T") &&
    (sym[4] == ":")
    {
    Serial.print("SMS")
    }

Смущает детский подход к реализации. Есть ли более красивое решение?

SunX
SunX аватар
Offline
Зарегистрирован: 04.10.2014

Как говорится: Если работает, не трож!

А вообще есть функция strcmp или strncmp, которая сравнивает две строки (или только первые n символов строк) и говорит, равны они или нет. В Вашем случае, как я понимаю, она должна вполне подойти.

rene
Offline
Зарегистрирован: 21.01.2014

Спасибо!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А чем не кошерна специально для этого предназначенная функция strstr?

char *s = "123456789";
char *p = strstr(s,"56");

 

rene
Offline
Зарегистрирован: 21.01.2014

Да, это хороший вариант, спасибо за совет!

toc
Offline
Зарегистрирован: 09.02.2013

rene, вы получаете данные из serial?
Хороший вариант обрабатывать их побайтно с помощью автомата, а не складировать во временную строку, imho

rene
Offline
Зарегистрирован: 21.01.2014

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

rus2014
Offline
Зарегистрирован: 11.09.2014

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

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

rene
Offline
Зарегистрирован: 21.01.2014
/*--------------------------------------------------------------
 ----------------------- ИНИЦИАЛИЗАЦИЯ --------------------------
 --------------------------------------------------------------*/

#include <SoftwareSerial.h> // библиотека для работы с GPRS модулем

SoftwareSerial GPRS(7, 8); // пины для работы с GPRS модулем (програмный серийный порт)
char buffer[64]; // буфер для принятия данных с GPRS модуля
int count = 0;   // счетчик символов буфера

/*--------------------------------------------------------------
 -------------------- ПЕРВИЧНАЯ НАСТРОЙКА -----------------------
 --------------------------------------------------------------*/

void setup()
{
  GPRS.begin(19200);               // скорость работы порта GPRS
  Serial.begin(9600);             // скорость работы серийного порта

  _StartGPRS();  // Запуск устройства
}

/*--------------------------------------------------------------
 ---------------------- ТЕЛО ПРОГРАММЫ --------------------------
 --------------------------------------------------------------*/

void loop()
{
  // Проверяем наличие входящих данных с GPRS модуля
  if (GPRS.available())              // if date is comming from softwareserial port ==> data is comming from gprs shield
  {
    _GPRSRead();
    
    // Проверям не СМС ли это сообщение
    if ((buffer[2] == '+') &&
      (buffer[3] == 'C') &&
      (buffer[4] == 'M') &&
      (buffer[5] == 'T') &&
      (buffer[6] == ':'))
    {
      Serial.println("SMS");
    }
    
    // Или входящий звонок
    else if ((buffer[2] == 'R') &&
      (buffer[3] == 'I') &&
      (buffer[4] == 'N') &&
      (buffer[5] == 'G'))
    {
      Serial.println("RING");
    }
  }
  
  if (Serial.available())            // если есть данные поступающие с ПК
    GPRS.write(Serial.read());       // отправляем их на GPRS модуль. Позволяет вводит вручную АТ команды
}

/*--------------------------------------------------------------
 -------------------------- ФУНКЦИИ -----------------------------
 --------------------------------------------------------------*/

// ------------- Функция инициализации GPRS модуля ------------- 
void _StartGPRS()
{
  while (true)
  {
    _GPRSPower();  // функция для програмного включения GPRS модуля
    _AT("ATE0"); // отключаем эхо

    // Ждем ответа ОК
    if (_OK)
    {
      // Настраиваем приём сообщений с других устройств
      _AT("AT+CMGF=1\r");
      _AT("AT+IFC=1, 1\r");
      _AT("AT+CPBS=\"SM\"\r");
      _AT("AT+CNMI=1,2,2,1,0\r");
      break;
    }
    delay(5000);
  }
}

// ------------- Функция програмного включения GPRS модуля ------------- 
void _GPRSPower()
{
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  delay(1000);
  digitalWrite(9, HIGH);
  delay(2000);
  digitalWrite(9, LOW);
  delay(3000);
}

// ------------- Функция отправки АТ комманд на GPRS модуль ------------- 
void _AT(char* at)
{
  Serial.print("> ");
  Serial.println(at);
  GPRS.print(at);
  GPRS.print("\r");
  delay(500);
  _GPRSRead();
}

// ------------- Функция наличия ответа ОК с GPRS модуля ------------- 
boolean _OK()
{
  if ((buffer[2] == 'O') &&
    (buffer[3] == 'K')) return true;
  else return false;
}

// ------------- Функция чтения ответов с GPRS модуля ------------- 
void _GPRSRead()
{
  count = 0;                       // set counter of while loop to zero
  while (GPRS.available())         // reading data into char array
  {
    buffer[count++] = GPRS.read();   // writing data into array
    if (count == 64) break;
  }
  Serial.println(buffer);           // if no data transmission ends, write buffer to hardware serial port
}

// ------------- Функция отправки СМС ------------- 
void _SendTextMessage() {
  // Устанавливает текстовый режим для SMS-сообщений
  GPRS.print("AT+CMGF=1\r");
  delay(100); // даём время на усваивание команды
  // Устанавливаем адресата: телефонный номер в международном формате
  GPRS.println("AT + CMGS = \"+79170000000\"");
  delay(100);
  // Пишем текст сообщения
  GPRS.println("ALARM!");
  delay(100);
  // Отправляем Ctrl+Z, обозначая, что сообщение готово
  GPRS.println((char)26);
}





 

rus2014
Offline
Зарегистрирован: 11.09.2014

Спасибо!

rene
Offline
Зарегистрирован: 21.01.2014

toc пишет:
rene, вы получаете данные из serial? Хороший вариант обрабатывать их побайтно с помощью автомата, а не складировать во временную строку, imho

Если не трудно, приведите пожалуйста како нибудь простой код обработки побайтно, с помощью автомата

rene
Offline
Зарегистрирован: 21.01.2014

!

rene
Offline
Зарегистрирован: 21.01.2014

rus2014 пишет:

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

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

Вот окончательный вариант. Последняя функция _SendTextMessage() в программе не используется, оставил на случай необходимости отправки СМС.

/*--------------------------------------------------------------
 ----------------------- ИНИЦИАЛИЗАЦИЯ --------------------------
 --------------------------------------------------------------*/

#include <SoftwareSerial.h> // библиотека для работы с GPRS модулем

SoftwareSerial GPRS(7, 8); // пины для работы с GPRS модулем (програмный серийный порт)
char buffer[64]; // буфер для принятия данных с GPRS модуля
int count = 0;   // счетчик символов буфера
unsigned long updateTime = 0; // счетчик времени обновления

/*--------------------------------------------------------------
 -------------------- ПЕРВИЧНАЯ НАСТРОЙКА -----------------------
 --------------------------------------------------------------*/

void setup()
{
  GPRS.begin(19200);               // скорость работы порта GPRS
  Serial.begin(9600);             // скорость работы серийного порта
  pinMode(13, OUTPUT);            // пин для включения кнопки ДУ
  _StartGPRS();  // Запуск устройства
}

/*--------------------------------------------------------------
 ---------------------- ТЕЛО ПРОГРАММЫ --------------------------
 --------------------------------------------------------------*/

void loop()
{
  // Проверяем наличие входящих данных с GPRS модуля
  if (GPRS.available())
  {
    _GPRSRead();

    // Проверям не СМС ли это сообщение
    if ((buffer[2] == '+') &&
      (buffer[3] == 'C') &&
      (buffer[4] == 'M') &&
      (buffer[5] == 'T') &&
      (buffer[6] == ':'))
    {
      Serial.println("SMS");
      digitalWrite(13, HIGH); // включаем на секунду пин 13
      delay(1000);
      digitalWrite(13, LOW);
    }

    // Или входящий звонок
    else if ((buffer[2] == 'R') &&
      (buffer[3] == 'I') &&
      (buffer[4] == 'N') &&
      (buffer[5] == 'G'))
    {
      _AT("AT+CLCC"); // узнать номер звонящего
      _AT("AT+CHUP"); // отклонить вызов
      // _AT("ATH"); // повесить трубку
      digitalWrite(13, HIGH); // включаем на секунду пин 13
      delay(1000);
      digitalWrite(13, LOW);
    }
  }

  // Переодическая проверка доступности GPRS модуля
  if (millis() >= updateTime)
  {
    _AT("AT");
    if (!_OK()) _StartGPRS(); // если нет ответка ОК, перезагружаем устройство
    updateTime = millis() + 60000; // переодичность проверки
  }

  if (Serial.available())            // если есть данные поступающие с ПК
    GPRS.write(Serial.read());       // отправляем их на GPRS модуль. Позволяет вводит вручную АТ команды
}

/*--------------------------------------------------------------
 -------------------------- ФУНКЦИИ -----------------------------
 --------------------------------------------------------------*/

// ------------- Функция инициализации GPRS модуля -------------
void _StartGPRS()
{
  while (true)
  {
    _GPRSPower();  // включение GPRS модуля
    _AT("ATE0"); // отключаем эхо
    _AT("AT"); // проверяем доступность GPRS модуля

    // Ждем ответа ОК
    if (_OK())
    {
      // Настраиваем приём сообщений с других устройств
      _AT("AT+CMGF=1\r");
      _AT("AT+IFC=1, 1\r");
      _AT("AT+CPBS=\"SM\"\r");
      _AT("AT+CNMI=1,2,2,1,0\r");
      break;
    }
    delay(1000);
  }
}

// ------------- Функция програмного включения GPRS модуля -------------
void _GPRSPower()
{
  Serial.println("> PressPowerKey\n");
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  delay(1000);
  pinMode(9, INPUT);
  delay(3000);
}

// ------------- Функция отправки АТ комманд на GPRS модуль -------------
void _AT(char* at)
{
  Serial.print("> ");
  Serial.println(at);
  GPRS.print(at);
  GPRS.print("\r");
  delay(500);
  _GPRSRead();
}

// ------------- Функция наличия ответа ОК с GPRS модуля -------------
boolean _OK()
{
  if ((buffer[2] == 'O') &&
    (buffer[3] == 'K')) return true;
  else return false;
}

// ------------- Функция чтения ответов с GPRS модуля -------------
void _GPRSRead()
{
  count = 0;                       // обнуляем счетчик
  for (int i = 0; i < 64; i ++)    // обнуляем буфер
  {
    buffer[i] = 0;
  }

  while (GPRS.available())         // запысываем все поступающие данные в буфер
  {
    buffer[count++] = GPRS.read();
    if (count == 64) break;
  }
  Serial.println(buffer);
}

// ------------- Функция отправки СМС -------------
void _SendTextMessage()
{
  // Устанавливает текстовый режим для SMS-сообщений
  GPRS.print("AT+CMGF=1\r");
  delay(100); // даём время на усваивание команды
  // Устанавливаем адресата: телефонный номер в международном формате
  GPRS.println("AT + CMGS = \"+79172676866\"");
  delay(100);
  // Пишем текст сообщения
  GPRS.println("ALARM!");
  delay(100);
  // Отправляем Ctrl+Z, обозначая, что сообщение готово
  GPRS.println((char)26);
}