Перейти к содержанию
    

процедура с указателем на строку в памяти программ

2chief_olimp : простите. но то что вы написали - это не find ... это strcpy() причем в извращенной форме.

при чем тут find? если он ничего не возвращет и не сообщает?

Абсолютно согласен. Проблема была не в том что бы написать find. А в том что бы это в тексте выглядело например так

find (text_clcc);

где

PROGMEM char text_clcc[] = "clcc";

Вот весь код процедуры. Ищет конкретное значение произвольной длины в массиве. Возвращает findOK значение "true".

//процедура поиска слова в буффере
void find (const void *findbuff)
{
    findOK = false; 
    unsigned int i=0;
    unsigned char temp,j=0;  
    while(1)
    { 
        temp = pgm_read_byte(findbuff++); 
        if(temp==0) break; 
        FIND[i++] = temp;
    }    
    i=0;
    while (i != USART0_InBufSize)
    {
    if (USART0_InBuf[i] == FIND[j])
         {
            i++;j++;findOK = true;
            if (FIND[j] == 0x00) break;
        }
        else 
        {
            i++;
            if (findOK == true) 
            {
                j=0; i--;
                findOK = false;
            }
        }
    }
}

За подсказку про strstr спасибо. Она кстати тоже работает с ОЗУ. И еще мне нужно будет запоминать позицию конца найденого слова для дальнейшей обработки. С strstr не понятно как это сделать. К тому же неизвесно насколько лучше эта функция работает.

Если кто что подскажет как оптимальнее сделать буду признателен.

Изменено пользователем chief_olimp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я просто в шоке.

 

думаю мои и быстрее и веселее

 

#define bool int //в зависимости от системы char|word|int|long|int64

/* если нет strlen и memcmp

inline int strlen(char* ins)

{

int i=0;

while(ins[i++]);

return i;

}

 

inline int memcmp(char* in1,char* in2,int cc)

{

int i=0;

while(cc--)

{

if(in1[cc]!=in2[cc])

return -1;

};

 

return 0;

}

*/

 

bool find(char* inb)

{

bool retval=-1;

char inc=*inb;

int i=0;

int slen=strlen(inb);

int pp=USART0_InBufSize-slen;

 

while(i<pp)

{

if(USART0_InBuf==inc)

if(memcmp(&USART0_InBuf,inb,slen)==0)

{

retval=i;

break;

}

i++;

}

return retval;

}

 

в вашем случае - при использовании глобальных переменных - меняется

 

void find(char* inb)

{

fndOK=-1;

char inc=*inb;

int i=0;

int slen=strlen(inb);

int pp=USART0_InBufSize-slen;

 

while(i<pp)

{

if(USART0_InBuf==inc)

if(memcmp(&USART0_InBuf,inb,slen)==0)

{

fndOK=i;

break;

}

i++;

}

}

 

 

блин как тут пробелов наставить?

Изменено пользователем rokhan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

думаю мои и быстрее

...

#define bool int //в зависимости от системы char|word|int|long|int64

Ну-ну... при Ваших побайтовых операциях на не 8bit платфмах поминать слово скорость вообще моветон.

и веселее

Это неиспользуемая переменная 'i' в memcmp() для веселья добавлена :)?

блин как тут пробелов наставить?

Прочитать про тэги.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо вы нашли опечатку.

На счет тегов могли бы просто помочь с сылкой а не заявлением.

Изменено пользователем zltigo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Кстати комплилятор ругается на вашу процедуру "warning: passing arg 1 of `find' discards qualifiers from pointer target type"

Изменено пользователем chief_olimp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У автора - используется двойное копирование + двойная проверка...

А я про Вас :( - просто среагировал на рекламный сологан "быстрее и веселее" и не найдя на мой взгляд ни того ни другого (совершенно обычно все) написал ремарку. Добавлю еще, что по нынешним временам библиотечные функции отличаются оптимизированностью (и ASM там не редкое явление)и "сделать" их просто так "в лоб" не получится, если только не за счет наложения дополнительных

ограничений.

Может что и можно сделать с помошью библиотечных функций но меня пока не убедили.

А зачем Вас кому-то убеждать :)? Могу сказать одно (глядя на написанное Вами), что современные библиотечные функции написаны много-мнго более оптимально и Вам следует, как минимум, для начала воспользоваться ими.

Например, та memcmp(), которой я пользовался для ARM лет пять тому назад, до тех пор, пока IAR не "сделал" и ее выпустив очередную свою версию библиотеки.

//---------------------------------------------------------------------------
//  memcmp()
//  compare unsigned char s1[n], s2[n]
//  int (memcmp)(const void *s1, const void *s2, size_t n)
//---------------------------------------------------------------------------
       RSEG CODE:CODE:NOROOT(2)
       ARM

memcmp:
       mov      r3,r0             // Copy 1st arg, p1
       mov      r0,#0             // Set return value = 0
       teq      r2,#0             // Is n == 0 ?
       bxeq     lr                // Return if n == 0

       stmdb    sp!,{r4-r6,lr}    // Save registers on stack

       cmp      r2,#12            // Is n > 12 */
       ble      ByteLoop          // If n <= 12, jump

       sub      r0,r3,r1          // p1 - p2
       ands     r0,r0,#3          // (p1 - p2) & 3
       beq      WordCompare       // Jump if byte offsets match

// The strings begin at different byte offsets WRT word boundaries.
// Loop below processes only a single pair of bytes per iteration.
ByteLoop:
       ldrb     r0,[r3],#1        // b1 = next byte from string 1
       ldrb     r4,[r1],#1        // b2 = next byte from string 2
       subs     r0,r0,r4          // b1 - b2
       bne      ByteBreak         // if b1 != b2, break out of loop
       subs     r2,r2,#1          // --n (decrement loop counter)
       bne      ByteLoop          // Loop again if n > 0

ByteBreak:
TheEnd:
       ldmia    sp!,{r4-r6,lr}    // Return
       bx       lr


// The two strings have same starting byte alignment WRT word boundary.
// Set up inner loop that compares a pair of words per iteration.

WordCompare:
       add      r5,r3,r2          // e1 = p1 + n (point to trailing byte)
       and      lr,r3,#3          // align = p1 & 3 (initial byte offset)
       bic      r3,r3,#3          // p1 &= ~3 (point to word boundary)
       bic      r1,r1,#3          // p2 &= ~3
       add      r2,r5,#3          // e1 + 3
       sub      r2,r2,r3          // e1 + 3 - p1
       mov      r2,r2,lsr #2      // N Words = (e1 + 3 - p1) >> 2

       mvn      r6,#0             // Initialize mask to all 1s
       mov      r0,lr,lsl #3      // Convert byte offset to bit offset
       mov      r6,r6,lsl r0      // Poke holes in mask for invalid bytes
       ldr      r0,[r3],#4        // w1 = *p1++
       and      r0,r0,r6          // Isolate starting bytes in 1st string
       ldr      r4,[r1],#4        // w2 = *p2++
       and      r4,r4,r6          // Isolate starting bytes in 2nd string


// Inner loop:
// Compare the two strings one word at a time to look for a mismatch.
// If the two strings match, return 0.
WordLoop:
       subs     r0,r0,r4          // w1 - w2
       bne      WordBreak         // if w1 != w2, break out of loop
       ldr      r0,[r3],#4        // w1 = *p1++
       subs     r2,r2,#1          // --nWords
       ldr      r4,[r1],#4        // w2 = *p2++
       bne      WordLoop          // Loop again if more words in string
       mov      r0,#0             // Set return argument = 0
       b        TheEnd            // All done. Return


// The strings may still match if the apparent mismatch happened in
// the final pair of words from the two strings (in trailing bytes).
WordBreak:
       teq      r2,#1             // N Words == 1? (mismatch at EOS?)
       bne      FindMismatch      // Jump if nWords != 1

       ands     r5,r5,#3          // Is trailing byte word-aligned?
       beq      FindMismatch      // Jump if word-aligned (real mismatch)

       mvn      r6,#0             // Initialize mask to all 1s
       mov      r5,r5,lsl #3      // Convert byte offset to bit offset
       mvn      r6,r6,lsl r5      // Poke holes in mask for invalid bytes
       ands     r0,r0,r6          // Mask off trailing bytes, string 1
       beq      TheEnd            // If w1 == w2, return val = 0


// We detected a mismatch in the current pair of words from the strings.
// But in which byte position within the words did the mismatch occur?
FindMismatch:
       add      r3,r0,r4          // Restore value w1

NextByte:
       and      r0,r3,#0xff       // b1 = w1 & 0xff (isolate byte)
       and      r2,r4,#0xff       // b2 = w2 & 0xff
       subs     r0,r0,r2          // Return val = b1 - b2 ?

       bne      TheEnd            // If val != 0 - Return

       mov      r3,r3,lsr #8      // w1 >>= 8 (position next byte)
       mov      r4,r4,lsr #8      // w2 >>= 8
       b        NextByte          // If b1 != b2, loop again

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Теоретически вы правы. На практике могут проявиться нюансы. Как-то, приведение типа указателя без операции извлечения адреса не работает. А приведение типа в данном случае необходимо, т.к. указатель и массив имеют разный тип. IAR, например, сругался бы без приведения типа. Насчет char и unsigned char нужно опять же смотреть опции компилятора. Либо твердо помнить, что в строковых переменных используем только KOI-7 и/или только латиницу.
Я хочу сказать, что при грамотном проектировании программы приводить типы проактически не требуется - это загромождает программу. У автора ошибка в проектировании он почему-то решил применять разные типы данных для сущности и передачи указателя в функцию на эту сущность. Мне это совершенно не ясно. И это при том, что сущность едина в "двух лицах" - это строка типа чар. Вся таблица ascii прекрасно ложится в тип чар (это минимум 8 бит в нынешнем понимании, а иногда и немного больше) и пусть этот чар будет хоть со знаком, хот без - это может варьироваться от системы или опций компилятора. Повторюсь ещё раз строки должны состоять из обычных чаров - всё остальное от лукавого:) Вот мой аргумент:

const char slovo[] = "slovo";
if (slovo[0]=='s')
{
}

Видите тип 's' - это char (я така понимаю). Поэтому я правомерно могу писать такой код. Комар носа не подточит.

Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.

Большинство компиляторов (все, что я видел до сих пор) имеют char по умолчанию unsigned. Но именно потому, что он переключается, char, unsigned char и signed char разные типы. Полное право имеет ругаться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Теоретически вы правы. На практике могут проявиться нюансы. Как-то, приведение типа указателя без операции извлечения адреса не работает.
Я не совсем понял. Под расхождением теории и приктики подразумевается несоответствие поведениея компилятора спецификации языка? Тогда не лучше ли сменить компилятор, чем подгонять программу под его баги? Если же я понял неправильно, хочется увидеть пример, где при наличии unsigned char blabla[] требуется писать (unsigned char *)blabla.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Большинство компиляторов (все, что я видел до сих пор) имеют char по умолчанию unsigned.

Жутко "повезло", ибо по жизни издревле принято (хотя и отдано на откуп компилятору/платформе) с точностью до наоборот signed и это пожалуй, правильно (или просто больше привык :) ). То, что Вы встречали, очевидно, уже сложилось под влиянием узкозаточенности под чего-нибудь embedded на платформах 8bit или наоборот жестких 32битовиках типа ARM. На той-же x86, если увижу unsigned char по умолчанию, очень даже поплююсь на такой компилятор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void find(char* inb)
{
fndOK=-1;
char inc=*inb;
int i=0;
int slen=strlen(inb); 
int pp=USART0_InBufSize-slen;

while(i<pp)
{
if(USART0_InBuf[i]==inc)
if(memcmp(&USART0_InBuf[i],inb,slen)==0)
{
fndOK=i;
break;
}
i++;
}
}

 

ну не работает у меня этот код с строкой в программе типа

find (text_clcc);

где

PROGMEM char text_clcc[] = "clcc";

И еще не смотря на компактность написания мой код на две строчки длинее всего.

Может автор сможет лучше с моим кодом сравнить по объему и быстродействию. Буду очень признателен. Сам я с асма только перелез и это моя первая программа на си. Поэтому и функциями библиотечными мало пользуюсть так как мало о них знаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сам я с асма только перелез и это моя первая программа на си. Поэтому и функциями библиотечными мало пользуюсть так как мало о них знаю.
Ну так и надо начать программирование с изучения документации. С чтения WinAVR/doc/avr-libc/FAQ.htm и остальной документации в этой папке. Хотя бы тех разделов, в которых поиск находит слово PROGMEM.

Если вы писали на асме, то должны четко представлять, что для обращения к данным в озу используются команды LD, LDD, LDS, а для чтения из программной памяти - LPM. И должны понимать, что компилятор не может только по значению обычного указателя понимать, какую команду использовать. Иными словами, функции strlen(), memcmp() не могут работать и со строками в ОЗУ и со строками во флеше. Чтобы обойти эту нестыковку стандарта языка С и процессоров с несколькими адресными пространствами придуманы аналоги этих функций для работы с флеш. Еще в ответе №4 Tiro вам подсказал, где вы можете найти ответ. Вы не читаете ответов или не хотите следовать данным в них советам? Вы не хотите прочитать документацию? Тогда неудивительно, что код не работает и "так мало о них знаю".

void find(prog_char const * inb)
{
    prog_char const * found = strstr_P(USART0_InBuf, inb);
    if (!found)
        fndOK=-1;
    else
        fndOK = found - USART0_InBuf;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Большинство компиляторов (все, что я видел до сих пор) имеют char по умолчанию unsigned. Но именно потому, что он переключается, char, unsigned char и signed char разные типы.
Примеры компиляторов? Это небось только узкоспециализированные и заточенные под мало разрядные MCU. Я солидарен с zltigo и в основном всегда char знаковый. Проведите аналогию с int.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Документацию я как раз читаю. Только напоминаю я на си пишу месяц с лишним. Скажите у Вас у самого код что сверху работает со словами из FLASH? Мой код у меня работает и меня лично вполне устаивает. Здесь же вместо того что бы подсказать посылают по ссылкам которые я уже читал и эти знания успешно применяю в других кусках программы. Код что выше у меня не работает, и выдает ошибку что не понимает аттрибута функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я хочу сказать, что при грамотном проектировании программы приводить типы проактически не требуется - это загромождает программу.
Я с вами согласен, что нужно писать так, чтобы типы приводить не приходилось. Но я-то писал в применении к конкретному коду, а не к коду "вообще" или "в принципе".

Вот мой аргумент:

const char slovo[] = "slovo";
if (slovo[0]=='s')
{
}

Видите тип 's' - это char (я така понимаю). Поэтому я правомерно могу писать такой код. Комар носа не подточит.

Именно тут - да, можете. А что произойдет в случае сравнения на больше/меньше? Тоже будете уповать на то, что по-умолчанию char как unsigned char используется?

Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.
Ага! Так все-таки "стоит покопаться в опциях" ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...