Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

String и Pointer в CCS, проблеми...
http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=420
Страница 1 от 2

Автор:  Predator_MF [ Вто Фев 22, 2005 2:07 pm ]
Заглавие:  String и Pointer в CCS, проблеми...

Проблема ми е следния:

Код:
struct DirEntry {
                 unsigned char DIR_Name[8];      //8 chars filename
                 unsigned char DIR_Ext[3];       //3 chars extension
                 unsigned char DIR_Attr;         //file attributes RSHA
                 unsigned char DIR_NTres;        //set to zero
                 unsigned char DIR_CrtTimeTenth; //creation time part in milliseconds
                 unsigned int  DIR_CrtTime;      //creation time
                 unsigned int  DIR_CrtDate;      //creation date
                 unsigned int  DIR_LastAccDate;  //last access date (no time for this !)
                 unsigned int  DIR_FstClusHI;  //first cluster high word
                 unsigned int  DIR_WrtTime;      //last write time
                 unsigned int  DIR_WrtDate;      //last write date
                 unsigned int  DIR_FstClusLO;  //first cluster low word
                 unsigned long DIR_FileSize;
                };   

void MakeNewFileEntry(char *name,char *ext,int16 clnum,int16 size)
{ struct DirEntry dir;
 
   strcpy(dir.DIR_Name,name);
   strcpy(dir.DIR_Ext,ext);
   printf("New File Created: %S %S",dir.DIR_Name,dir.DIR_Ext); 
   
}


При извикване на МакеNewFileEntry по следните начини:
Код:
MakeNewFileEntry("Errors","TXT",3,2);

Бих очаквал да ми се изпринтира "New File Created: ErrorsTXT", но компилатора казва: "Expecting variable such as LVALUE or...." и ми сочи към "Errors" стринга. Предполагам, че това не е правилния начин да си извикам процедурата, затова пробвах по втори начин:
Код:
char *fname,fext;
...
...
strcpy(fname,"Errors");
strcpy(fext,"TXT");
MakeNewFileEntry(fname,fext,3,2);

Това се компилира, обаче в резултат ми изписва само "New File Created:".
Къде бъркам? Защо не мога да извикам процедурата във вид MakeNewFileEntry("Errors","TXT",3,2) ?

Автор:  bateAz [ Вто Фев 22, 2005 3:43 pm ]
Заглавие: 

защото PIC няма указател към стринг и въобще към константа, защото той е с харвардска организация и "Errors" въобще го няма в RAM-a, та да има поинтер към него.

Автор:  Predator_MF [ Вто Фев 22, 2005 3:48 pm ]
Заглавие: 

Добре де...това:
strcpy(fname,"Errors"), не качва ли текст във fname (във RAM-а)...как тогава въобще работи strcpy(), след като е написана по следния начин:
Код:
/*    Standard template: char *strcpy(char *s1, const char *s2)
copies the string s2 including the null character to s1*/

char *strcpy(char *s1, char *s2)
{
  char *s;

  for (s = s1; *s2 != 0; s++, s2++)
     *s = *s2;
  return(s1);
}
???

Автор:  bateAz [ Вто Фев 22, 2005 4:27 pm ]
Заглавие: 

Ako си го копнал от някоя библиотека на CCS - нямам думи!
Компилирай го и виж компилаторът какъв .ASM ти е сгенерирал. Сигурно ще се натъкнеш на инструкцията RETLF или нещо подобно.

Автор:  Predator_MF [ Вто Фев 22, 2005 4:51 pm ]
Заглавие: 

Точно оттам съм го копнал (не можах да разбера това за думите :?: )... и като гледам на ASM работи с INDF-a...що не мога да схвана...по принцип трябва да работи, това си е C...егати :!:

EDIT:
Доколкото имам опит в CCS-a, знам че '*' означава "address of". T.e. ако дефинираш
Код:
#define A 0x05

и използваш А така:
Код:
*А = 0xEA;

...е същото като това:
Код:
#byte A = 0x05
...
A = 0xEA;

Автор:  danov [ Вто Фев 22, 2005 6:36 pm ]
Заглавие:  Re: String и Pointer в CCS, проблеми...

Не съм сигурен, но мисля, че оплакването идва от факта, че функцията очаква variable, а ти им подаваш константа.

При втория начин fname е указател, който не е инициализиран - класически пример за мазане някъде по паметта (а може там да няма памет). А пък fext е само един символ, а ти пишеш в него 4 (плюс нулата). Правилно е да ти даде грешка при strcpy (fext,"TXT");

Мисля, че ще имаш и друг проблем - strcpy копира докато срещне 0, но копира и 0-та. Както ти е направена структурата, копирането с strcpy на име, което е 8 символа, ще доведе до копиране на 0-та в началото на разширението. Също така и копирането на разширение от 3 символа ще доведе до копиране на 0 в следващото поле.

Автор:  Predator_MF [ Вто Фев 22, 2005 6:46 pm ]
Заглавие: 

Донякъде има логика, това за Variable-а го разбрах още като го писах...само че пак не схващам...В help-а на CCS пише следното за strcpy:
Код:
Syntax:
strcpy (dest, src)

Parameters:
dest is a pointer to a RAM array of characters.

src may be either a pointer to a RAM array of characters or it may be a constant string.

Function:
Copies a constant or RAM string to a RAM string.  Strings are terminated with a 0.

Availability:
All devices.

Requires
Nothing

Examples:
char string[10], string2[10];

...
strcpy (string, "Hi There");

strcpy(string2,string);



Значи, трябва ли да разбирам, че предварително трябва да обявявам дължината на стринга (което би било доста тъпо)...И защо във кода на strcpy е обявена променлива *s...значи то вероятно работи...но как? Тая вечер ще си поблъскам тиквата с още такива въпроси :wink:

Автор:  danov [ Вто Фев 22, 2005 7:03 pm ]
Заглавие: 

Predator_MF написа:
Донякъде има логика, това за Variable-а го разбрах още като го писах...само че пак не схващам...

По принцип константите и променливите (могат да) стоят в различни сегменти, типове памет, и ... Затова в C са дефинирани като различни. Не съм писал за PIC, но най-вероятно константните стрингове се слагат някъде след програмата във flash/eprom.

Predator_MF написа:
Значи, трябва ли да разбирам, че предварително трябва да обявявам дължината на стринга (което би било доста тъпо)...И защо във кода на strcpy е обявена променлива *s...значи то вероятно работи...но как? Тая вечер ще си поблъскам тиквата с още такива въпроси :wink:

Вариантите за работа със стрингове са два. Първия да са с предварително зададен размер, другия е да са динамично заделени с malloc. Това е възможно ако конкретната системна библиотека има поддръжка на функциите malloc/realloc/free. Ако няма, може да си ги направиш в част от RAM паметта, но ... може да се окаже, че е по-лесно да се работи с предварително зададени размери.

Автор:  danov [ Вто Фев 22, 2005 7:06 pm ]
Заглавие: 

Predator_MF написа:
...И защо във кода на strcpy е обявена променлива *s...значи то вероятно работи...но как?

А на тази променлива не се ли присвоява някаква стойност преди да се използва?
Просто char *s е указател, т.е. адреса на масив от символи, а не самия масив от символи.

Автор:  Predator_MF [ Вто Фев 22, 2005 7:12 pm ]
Заглавие: 

Хм, тогава това как работи?
Код:
/*    Standard template: char *strcpy(char *s1, const char *s2)
copies the string s2 including the null character to s1*/

char *strcpy(char *s1, char *s2)
{
  char *s;

  for (s = s1; *s2 != 0; s++, s2++)
     *s = *s2;
  return(s1);
}


Никъде не е дефинирано колко е дълъг "s"...

Автор:  danov [ Вто Фев 22, 2005 7:33 pm ]
Заглавие: 

Predator_MF написа:
Хм, тогава това как работи?
...
Никъде не е дефинирано колко е дълъг "s"...

Все пак може да погледнеш някоя книга за програмиране на C и по-конкретно за работа със стрингове и указатели. В C стринговете са поредица символи, завършваща с 0. Конкретно в тази функция се копира в s1 докато се срещне 0 в s2 (но трябва да копира и нулата, за да се получи отново валиден стринг по правилата на C).
Задължение на викащата функция е да подаде правилни входни параметри - указател s1, който сочи към достатъчно заделена памет, и указател s2, който сочи към стринг, написан по правилата на C - т.е. поредица символи, завършваща с 0.
Ако няма достатъчно място в масива, сочен от s1 (т.е. по-малко от колкото е дължината на s2), то се получава мазане в паметта след масива.

А тази функция според мен има проблем - не копира 0-та на края, защото цикъла се изпълнява докато *s2 != 0 и когато стане 0 тя не се записва в s. Искам да кажа, че ако имаш стринга "0123", то той заема 5 байта в паметта, а фунцията ще копира само 4. Последния, който е 0 няма да се копира и ще получиш стринг, който не е правилно терминиран.
И ако пуснеш нещо като:

char s1 [10], s2 [10];

memset (s1, 'a', 9);
s1 [9] = 0;
s2 [9] = 0;
strcpy (s1, "12345");
strcpy (s2, s1);
printf ("%s\n", s2);

ще видиш резултат:
12345aaaa
вместо
12345

Автор:  Predator_MF [ Вто Фев 22, 2005 7:48 pm ]
Заглавие: 

danov написа:
А тази функция според мен има проблем - не копира 0-та на края, защото цикъла се изпълнява докато *s2 != 0 и когато стане 0 тя не се записва в s. Искам да кажа, че ако имаш стринга "0123", то той заема 5 байта в паметта, а фунцията ще копира само 4. Последния, който е 0 няма да се копира и ще получиш стринг, който не е правилно терминиран.


CCS HELP написа:
...copies the string s2 including the null character to s1*/
...тука вече почвам да се бъркам здраво...довечера ще погледна малко в една книга, сигурен съм че ще измисля нещо...Благодаря за инфото :D

Автор:  danov [ Вто Фев 22, 2005 8:06 pm ]
Заглавие: 

За най-чисто ти предлагам да го изпробваш. Ще ми е интересно какъв е резултата.

Автор:  Predator_MF [ Чет Фев 24, 2005 3:47 pm ]
Заглавие: 

Така, направих няколко опита...оказва се следното:

Код:
void printshit(char *s)
             { putc(s);}
....
printshit("Predator_MF");


Тоя код ми принтира "Predator_MF"...т.е. функцията ми се извиква Length(s) пъти с параметър s++...В случая нямаше значение дали ще дефинирам дължината на s (char s[10] примерно...). Странно, това не го знаех...Следващия ми опит беше да пробвам как работи strcpy(dest,src). Пробвах с това:
Код:
strcpy(s,"Predator_MF");
          printf(s);

Тука резултат няма, нищо не се принтира!!! Ако вместо printf(s) напиша:
Код:
for (i=0;i<10;putc(s[i]);

Резултата е print на "Predator_MF"...Проблема значи функцията strcpy си работи, проблема идва в принтирането...не знам точно защо :?: . Все пак решението не ми е известно още...няма значение, ще гледам да избягвам стриговете, поне тези в CCS за PIC...то така или иначе RAM-a им си е достатъчно малък че да го тъпча с такива неща...в случая "Да живее АСЕМБЛЕР!!!" :D

Автор:  bateAz [ Чет Фев 24, 2005 9:18 pm ]
Заглавие: 

@Предатор, това за Асемблера е вярно, ама отчасти. Ако сега започваш и не възнамеряваш да програмираш непрекъснато, то асемблерът е за предпочитане - лесно се учи и лесно се ползва. Сравнително лесно се дебъгва и трасира.
Ако обаче си решил с това да си вадиш хляба- то решението е C. Просто времето за "научаване" на езика се връща многократно при по-нататъшната работа. Програмира се по-бързо, и най-важното : имаш лесна миграция от един контролер на друг. (поне теоретично е така :wink: ). Естествено, нормално е езикът и компилаторът от време на време да ти вгорчават живота с някоя полова изненада, ама приеми го философски :D .

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/