реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> процедура с указателем на строку в памяти программ, помогите разобраться
chief_olimp
сообщение Dec 24 2008, 20:15
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 249
Регистрация: 31-10-05
Из: Украина Нетешин
Пользователь №: 10 344



Цитата(rokhan @ Dec 24 2008, 22:28) *
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 - Dec 24 2008, 20:28
Go to the top of the page
 
+Quote Post
rokhan
сообщение Dec 25 2008, 08:23
Сообщение #17


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 14-04-06
Пользователь №: 16 129



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

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

Цитата
#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[i]==inc)
if(memcmp(&USART0_InBuf[i],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[i]==inc)
if(memcmp(&USART0_InBuf[i],inb,slen)==0)
{
fndOK=i;
break;
}
i++;
}
}



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

Сообщение отредактировал rokhan - Dec 25 2008, 08:26
Go to the top of the page
 
+Quote Post
zltigo
сообщение Dec 25 2008, 08:54
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(rokhan @ Dec 25 2008, 11:23) *
думаю мои и быстрее
...
#define bool int //в зависимости от системы char|word|int|long|int64

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

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

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
rokhan
сообщение Dec 25 2008, 09:00
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 14-04-06
Пользователь №: 16 129



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


Сообщение отредактировал zltigo - Dec 25 2008, 09:50
Go to the top of the page
 
+Quote Post
chief_olimp
сообщение Dec 25 2008, 09:15
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 249
Регистрация: 31-10-05
Из: Украина Нетешин
Пользователь №: 10 344



т.е. каждый раз при очередном сравнивании данные считываются в процедуру. Моя же функция последовательно проходит по всему буферу и ищет лишь первый символ. Когда находит то проверяет остальные. Если совпадают то выход, если нет то ищет с начала искомого слова продолжая шагать по буфферу. Может что и можно сделать с помошью библиотечных функций но меня пока не убедили.
Кстати комплилятор ругается на вашу процедуру "warning: passing arg 1 of `find' discards qualifiers from pointer target type"

Сообщение отредактировал chief_olimp - Dec 25 2008, 09:17
Go to the top of the page
 
+Quote Post
zltigo
сообщение Dec 25 2008, 09:48
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(rokhan @ Dec 25 2008, 12:00) *
У автора - используется двойное копирование + двойная проверка...

А я про Вас sad.gif - просто среагировал на рекламный сологан "быстрее и веселее" и не найдя на мой взгляд ни того ни другого (совершенно обычно все) написал ремарку. Добавлю еще, что по нынешним временам библиотечные функции отличаются оптимизированностью (и ASM там не редкое явление)и "сделать" их просто так "в лоб" не получится, если только не за счет наложения дополнительных
ограничений.
Цитата(chief_olimp @ Dec 25 2008, 12:15) *
Может что и можно сделать с помошью библиотечных функций но меня пока не убедили.

А зачем Вас кому-то убеждать smile.gif? Могу сказать одно (глядя на написанное Вами), что современные библиотечные функции написаны много-мнго более оптимально и Вам следует, как минимум, для начала воспользоваться ими.
Например, та memcmp(), которой я пользовался для ARM лет пять тому назад, до тех пор, пока IAR не "сделал" и ее выпустив очередную свою версию библиотеки.
CODE

//---------------------------------------------------------------------------
// 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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 25 2008, 10:24
Сообщение #22


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(rezident @ Dec 24 2008, 22:49) *
Теоретически вы правы. На практике могут проявиться нюансы. Как-то, приведение типа указателя без операции извлечения адреса не работает. А приведение типа в данном случае необходимо, т.к. указатель и массив имеют разный тип. IAR, например, сругался бы без приведения типа. Насчет char и unsigned char нужно опять же смотреть опции компилятора. Либо твердо помнить, что в строковых переменных используем только KOI-7 и/или только латиницу.
Я хочу сказать, что при грамотном проектировании программы приводить типы проактически не требуется - это загромождает программу. У автора ошибка в проектировании он почему-то решил применять разные типы данных для сущности и передачи указателя в функцию на эту сущность. Мне это совершенно не ясно. И это при том, что сущность едина в "двух лицах" - это строка типа чар. Вся таблица ascii прекрасно ложится в тип чар (это минимум 8 бит в нынешнем понимании, а иногда и немного больше) и пусть этот чар будет хоть со знаком, хот без - это может варьироваться от системы или опций компилятора. Повторюсь ещё раз строки должны состоять из обычных чаров - всё остальное от лукавогоsmile.gif Вот мой аргумент:
Код
const char slovo[] = "slovo";
if (slovo[0]=='s')
{
}
Видите тип 's' - это char (я така понимаю). Поэтому я правомерно могу писать такой код. Комар носа не подточит.
Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Dec 25 2008, 11:14
Сообщение #23


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Цитата(demiurg_spb @ Dec 25 2008, 12:24) *
Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.

Большинство компиляторов (все, что я видел до сих пор) имеют char по умолчанию unsigned. Но именно потому, что он переключается, char, unsigned char и signed char разные типы. Полное право имеет ругаться.
Go to the top of the page
 
+Quote Post
alx2
сообщение Dec 25 2008, 11:15
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



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


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
zltigo
сообщение Dec 25 2008, 11:37
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(HARMHARM @ Dec 25 2008, 14:14) *
Большинство компиляторов (все, что я видел до сих пор) имеют char по умолчанию unsigned.

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
chief_olimp
сообщение Dec 25 2008, 11:44
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 249
Регистрация: 31-10-05
Из: Украина Нетешин
Пользователь №: 10 344



Код
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";

И еще не смотря на компактность написания мой код на две строчки длинее всего.
Может автор сможет лучше с моим кодом сравнить по объему и быстродействию. Буду очень признателен. Сам я с асма только перелез и это моя первая программа на си. Поэтому и функциями библиотечными мало пользуюсть так как мало о них знаю.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 25 2008, 12:05
Сообщение #27


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(chief_olimp @ Dec 25 2008, 13:44) *
Сам я с асма только перелез и это моя первая программа на си. Поэтому и функциями библиотечными мало пользуюсть так как мало о них знаю.
Ну так и надо начать программирование с изучения документации. С чтения 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;
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 25 2008, 12:11
Сообщение #28


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



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


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
chief_olimp
сообщение Dec 25 2008, 12:18
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 249
Регистрация: 31-10-05
Из: Украина Нетешин
Пользователь №: 10 344



Документацию я как раз читаю. Только напоминаю я на си пишу месяц с лишним. Скажите у Вас у самого код что сверху работает со словами из FLASH? Мой код у меня работает и меня лично вполне устаивает. Здесь же вместо того что бы подсказать посылают по ссылкам которые я уже читал и эти знания успешно применяю в других кусках программы. Код что выше у меня не работает, и выдает ошибку что не понимает аттрибута функции.
Go to the top of the page
 
+Quote Post
rezident
сообщение Dec 25 2008, 12:35
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(demiurg_spb @ Dec 25 2008, 15:24) *
Я хочу сказать, что при грамотном проектировании программы приводить типы проактически не требуется - это загромождает программу.
Я с вами согласен, что нужно писать так, чтобы типы приводить не приходилось. Но я-то писал в применении к конкретному коду, а не к коду "вообще" или "в принципе".
Цитата(demiurg_spb @ Dec 25 2008, 15:24) *
Вот мой аргумент:
Код
const char slovo[] = "slovo";
if (slovo[0]=='s')
{
}
Видите тип 's' - это char (я така понимаю). Поэтому я правомерно могу писать такой код. Комар носа не подточит.
Именно тут - да, можете. А что произойдет в случае сравнения на больше/меньше? Тоже будете уповать на то, что по-умолчанию char как unsigned char используется?
Цитата(demiurg_spb @ Dec 25 2008, 15:24) *
Ну а если ваш компилятор ругается на строки с символами код которых боьше 127 (gcc не ругается, bc и msvc тоже), то надо просто покопаться в опциях компилятора.
Ага! Так все-таки "стоит покопаться в опциях" wink.gif
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 17:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01506 секунд с 7
ELECTRONIX ©2004-2016