Fråga om Strängar.

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
SeniorLemuren
Inlägg: 8371
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Fråga om Strängar.

Inlägg av SeniorLemuren »

Jag har ju hållit på nu ett par år med PIC och C. Hittills har jag lyckats undgå att lära mig något om stränghantering, men nu är det dags.

Jag vill göra en rutin som läser igenom en textsträng och skriver ut dem ett och ett på en display. När den hittar tecknet ÅÄÖåäö så skall ascii-värdet bytas ut mot ett som svarar för mina egendefinierade tecken.

Utskriften är inga problem. Problemet är att jag har otroligt svårt att fatta detta med C-strängar, Det finns massor av förklaringar men ingen som biter på mig. Jag har fattat fundamentalt fel någonstans.. :shock:

Just nu står jag här och stampar.

Kod: Markera allt

char *text = "                    ";

void main() {
.
.
text = "min text här!" ;
Lcd_Out(4,1,&text[0]) ; // skriver ut hela strängen från pos 0
.
.
Är ovanstående helt fel och hur får jag tag i de enskilda tecknen i denna textsträng?

F..n vad jag längtar efter Pascal. :(
gkar
Inlägg: 1576
Blev medlem: 31 oktober 2011, 15:28:29
Ort: Linköping

Re: Fråga om Strängar.

Inlägg av gkar »

Du har inga strängar egentligen i C, allt är en helt vanlig array, av char. Denna termineras av tecknet med asciikod 0 (null).

Lcd_Out(4,1,&text[0]); // detta är samma som:
Lcd_Out(4,1,text)



char *text = " ";
chat temp = 0;
void main() {
.
.
text = "min text här!" ;
Lcd_Out(4,1,&text[0]) ; // skriver ut hela strängen från pos 0
temp = text[2]; // temp innehåller nu 'n'

n är ingen Csträng utan ett tecken, dvs det finns ingen nolla efter det.
Du bör skriva ut det med en rutin som bara tar emot ett tecken ,inte en sträng.

Lcd_Out(4,1,&text[4]) ; // skriver ut hela strängen från pos 0
Nu får du bara texten "text här!" utskriven.


text[3] = 0;
Lcd_Out(4,1,text) ; // skriver ut hela strängen från pos 0
Blir bara de 3 första tecknen i strängen, eftesom det nu finns en 0 tecken som terminerar den sedan.
Användarvisningsbild
SeniorLemuren
Inlägg: 8371
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Fråga om Strängar.

Inlägg av SeniorLemuren »

Tack! Mycket lättfattlig och bra beskrivning. Nu funkar det och jag glad igen. :D
Nerre
Inlägg: 27168
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Fråga om Strängar.

Inlägg av Nerre »

Man kan säga att en sträng är en array av char vars aktuella längd enkelt definieras av att den avslutas med 0x00.

Vore det en "vanlig" array skulle du behöva en extra variabel för att tala om hur lång den är. Så funkar det i vissa språk, där är första byten i strängen ett tal som talar om hur lång den är, strängen kan då max vara 255 tecken (eftersom en byte bara kan gå från 0-255). Undrar om inte Pascal funkar så?
sodjan
EF Sponsor
Inlägg: 43241
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om Strängar.

Inlägg av sodjan »

Behöer inte vara en enstaka byte, så klart.
Och det behöver inte heller ligga "i strängen".
Nerre
Inlägg: 27168
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Fråga om Strängar.

Inlägg av Nerre »

Nej, det var ju ett exempel jag tog, inget generellt. Ser att det kan tolkas generellt.

Men det måste ju vara definierat i förhand så att säga.

Och det är ju bara för att olika strängfunktioner ska kunna hantera strängar som strängar som man gör så, själva processorn vet ju inte om en array är en sträng eller inte, det är ändå bara en radda med tal.
sodjan
EF Sponsor
Inlägg: 43241
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om Strängar.

Inlägg av sodjan »

Att ha en mer genomtängt stränghantering har sina fördelar som t.ex ett
bättre gränssnitt mot programmeraren och att undvika "buffer overflow"
(en stor orsak till många "expliots").
Nerre
Inlägg: 27168
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Fråga om Strängar.

Inlägg av Nerre »

C-strängar har ju "nackdelen" att man inte kan lagra 0x00 som ett tecken. Det kan man väl i Pascal-strängar såvitt jag förstått?

Men när det gäller overflow så är väl inte strängar besvärligare än andra arrays? Det spelar väl ingen roll om det är text i form av ascii eller oktetter för IP-adresser som "svämmar över" en buffert?
sodjan
EF Sponsor
Inlägg: 43241
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om Strängar.

Inlägg av sodjan »

Problemet är att förlita sig på att det *måste* finnas ett null på slutet.
Och problemet med expoits är till största delen med areor för strängar
som t.ex URL'er eller liknande, där för långa strängar skriver över
det som ligger efter, så att säga.

Men visst finns det andra problem, som att kod ligger i minnessegment
med "write, execute", d.v.s att man över huvudtaget kan modifera kod
och köra den.
Användarvisningsbild
Icecap
Inlägg: 26621
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Fråga om Strängar.

Inlägg av Icecap »

Senior: om du anger en sträng som:
const char* Text = "Hej o hå!";
kommer 'å' ju inte att passa enl. dina hemlagade tecken.

Men om du skriver (vi låtsas att 'å' är 0x03):
const char* Text = "Hej o h\x03!";
behöver du inte göra om tecknen on-the-fly.

Alternativt kan man skriva:
const char* Text = "Hej o h" \x03 "!";
som ger samma resultat.
Nerre
Inlägg: 27168
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Fråga om Strängar.

Inlägg av Nerre »

Men är det inte så att när man deklarerar en sträng i C så blir längden "+1" så det alltid ligger en "uppfångningsnolla" på slutet?

Pascal-strängar är ju inte bättre, om du deklarerar en sträng på 10 tecken så finns det inget som hindrar att du skriver 40 i första byten och därmed hamnar långt utanför strängen.

För att klara sig undan såna grejer så måste man förutom att hålla reda på strängens nuvarande längd även hålla reda på den max tillåtna, och då börjar vi får lite avancerade strängstrukturer:)
Användarvisningsbild
Icecap
Inlägg: 26621
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Fråga om Strängar.

Inlägg av Icecap »

Nerre: om man deklarerar en C-sträng buffer som varande 10 bytes stor betyder det att det finns plats för 9 tecken + EOL.
Användarvisningsbild
SeniorLemuren
Inlägg: 8371
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Fråga om Strängar.

Inlägg av SeniorLemuren »

Så här blev det till slut. Nu kan jag skriva ÅÄÖåäö i mina texter till LCD utan att krångla. :)

Kod: Markera allt

//**************** generate char **********************
const char character_zero[] = {4,0,14,1,15,17,15,0};    //char å
const char character_one[] = {10,0,14,1,15,17,15,0};    //char ä
const char character_two[] = {10,0,14,17,17,17,14,0};   //char ö
const char character_three[] = {4,14,17,17,31,17,17,0}; //char Å
const char character_four[] = {10,14,17,17,31,17,17,0}; //char Ä
const char character_five[] = {10,14,17,17,17,17,14,0}; //char Ö
const char character_six[] = {0,14,21,27,31,17,14,0};   // gubbe
const char character_seven[] = {4,14,21,4,4,4,4,0};     //uppåtpil

void load_char() {  // Load char to LCD CGRAM
  char i;
    Lcd_Cmd(64);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_zero[i]);
    Lcd_Cmd(72);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_one[i]);
    Lcd_Cmd(80);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_two[i]);
    Lcd_Cmd(88);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_three[i]);
    Lcd_Cmd(96);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_four[i]);
    Lcd_Cmd(104);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_five[i]);
    Lcd_Cmd(112);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_six[i]);
    Lcd_Cmd(120);
    for (i = 0; i<=7; i++) Lcd_Chr_CP(character_seven[i]);
}
//**************** END generate char **********************

char temp = 0;
int i,antchar ;



void skriv_LCD(int rad, int col, char *text ){
   i=0 ;
   antChar = strlen(text);
   if (rad == 1) rad = 128 ;
   if (rad == 2) rad = 192 ;
   if (rad == 3) rad = 148 ;
   if (rad == 4) rad = 212 ;
   rad = rad + col - 1 ;
   LCD_CMD(rad); // startrsd och startkolumn
do {
   temp = text[i];
   if (temp =='ä') temp = 1;
   if (temp =='å') temp = 0;
   if (temp =='ö') temp = 2;
   if (temp =='Å') temp = 3;
   if (temp =='Ä') temp = 4;
   if (temp =='Ö') temp = 5;
   Lcd_Chr_Cp(temp) ;
   i++ ;
   }while(i < antChar);
   }
   
void main() {
   TRISA  =  0b00000000;
   TRISB  =  0b00000000;
   TRISC  =  0b00000000;
   TRISD  =  0b00000000;
   TRISE  =  0b00000111;
   Lcd_Init();
   load_char(); // load custom char.
   Lcd_Cmd(_LCD_CLEAR);               // Clear display
   Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
   
   skriv_LCD(1,1,"Å Ä Ö och å ä ö yes!") ;  // rad 1 kolumn 1 + texten

}
sodjan
EF Sponsor
Inlägg: 43241
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om Strängar.

Inlägg av sodjan »

De flesta språk har kontroller vid runtime så att deklarerade storlekar inte överskrids.
Jag är rellativt övertygad om att Pascal har det. Sen så bör man ju även ha olika
minnestyper som "read/write", "readonly", "no-executre" o.s.v så att man t.ex inte
kan exekvera data på heap eller stack som kod.
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Re: Fråga om Strängar.

Inlägg av kimmen »

Blir inte det där fel om strängen är tom (med endast NUL i alltså)?

Borde det inte vara

Kod: Markera allt

while(i < antChar)
{
  skicka tecken;
  i++;
}
eller för tydlighetens skull kanske

Kod: Markera allt

for(i=0; i < antChar; i++)
{
  skicka tecken;
}
Skriv svar