Strukt problem

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Strukt problem

Inlägg av dangraf »

Jag har läst i en tidigare tråd att man kan definiera upp en strukt med pekare till "strings" för att definiera en tabell som är assymetrisk. Ett exempel på strukten har jag här nedanför.

Kod: Markera allt

const struct  {
  const char *s;
} errorTBL[] = {
  " "
  "*Writing I2C", 		//1
  "*Reading I2C",
  "*Low PPO2",
  "*High PPO2",
  "*O2 Sensor fail",	//5
  "* <10% mem left"
};

Nu vill jag göra ungefär likadant, fast av typen "int" istället för med "char" eftersom jag har en gigantisk tabell jag vill lägga in i en mikroprocessor med minne som jag vill använda till annat.

jag vill ha en tabell som ser ut ung:

Kod: Markera allt

int tabell = { {1,2,3,4,5,3,4,5,4,3,2},
                   {1,2},
                   {1} };

Men jag lyckas inte med att definiera upp den utan att kompilatorn skriker.

Det jag har testat var först att ändra från char till int enligt:

Kod: Markera allt

const struct  {
  const int *s;
} tb[] = {
  {1,2,3,4,5,3,4,5,4,3,2},
                   {1,2},
                   {1} }
};
Därefter testade jag även den ursprungliga, fast på ett annat sätt för att testa om klammerna över huvud taget fungerar

Kod: Markera allt

const struct  {
  const char *s;
} tb[] = {
  {'a','v','t'},
  "*Writing I2C", 		//1
  "*Reading I2C",
  "*Low PPO2",
  "*High PPO2",
  "*O2 Sensor fail",	//5
  "* <10% mem left"
};
varningsmeddelandet jag fick var:

DiveTbl.c:6: warning: initialization makes pointer from integer without a cast
DiveTbl.c:6: warning: excess elements in struct initializer
DiveTbl.c:6: warning: (near initialization for `tb[0]')
DiveTbl.c:6: warning: excess elements in struct initializer
DiveTbl.c:6: warning: (near initialization for `tb[0]')

För mig verkar det som att det blir fel på adresserna till mina vektorer.
Hur definerar jag upp min assymetriska tabell? Någon som vet??.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Du gör inte det!

Alla C arrays är symmetriska efter vad jag vet, yttermera anger du en 2-dimensionell array med en 1-dimensions prototyp och det fungerar inte heller.
const struct tb[] = {{1,2,3,4,5,3,4,5,4,3,2},{1,2},{1}}};
ska ju egentligen vara:
const struct tb[3][] = {{1,2,3,4,5,3,4,5,4,3,2},{1,2},{1}}};
eller hur? :wink:
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Men om alla C arrays är symetriska, hur förklarar du då den första strukten, för den är vad jag föstått inte symetrisk :roll:

Jag fattade som att den lade upp stängarna efter varandra i minntet
ung som
*Writing I2C'\0'*Reading I2C'\0'*Low PPO2'\0'...
och därefter sparade adresserna till början på varje sträng.
Så om * börjar på adressen 0x10, så innehåller
tb[0] = 0x10,
tb[1] = 0x10+längden på sträng1
tb[2] = 0x10+lengh(string1),+length(string2)

Eller har jag missuppfattat alltihop?
för det är så jag skulle vilja göra iaf. lägga upp alla mina rader med siffror och har en vektor med adresser till vart varje rad börjar. (varje rad skall givet vis ha ett sluttecken).

Man skulle kunna göra det hela manuellt, men det hade varit så mycket enklare om man skrivit det på ett smidigt sätt så kompilatorn fattar vad jag menar utan att behöva räkna en halv dag :P
macgyver
Inlägg: 321
Blev medlem: 8 juni 2005, 00:24:09
Ort: Göteborg
Kontakt:

Inlägg av macgyver »

hmm klurigt, bästa sättet jag kan komma på är:

const int nr_array0[] = {1,2,3,4,5,6};
const int nr_array1[] = {1,2,3};
const int nr_array2[] = {1,2,3,5,6};

osv.. sen skriva:
const int * nr_array_vectors[] = {nr_array0, nr_array1, nr_array2};

för att t.e.x komma åt nummret i rad 2, position 1 använder du:
x = nr_array_vectors[2][1];
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Jo, jag var nog otydlig.....kompilern antingen gnäller över att det är för få variabler eller fyller upp varje array med resterande nollor. Får skylla på trötthet.

Ska du göra ett array med olika långa texter är det en helt annan sak:

Kod: Markera allt

const char * Meddelanden[] = {
 "Olika",
  "långa",
  "meddelanden",
  "som",
  "sparas i",
  "en array",
  "av pointer's"};

alternativt:
const char * Meddelande1 = "Hej, jag är glad";
const char * Meddelande2 = " och full också!";
const char * Meddelande3 = "Kan det bli bättre?";
osv.
Sen kan du göra en array:
const char * Meddelanden[] = {Meddelanden1, Meddelanden2, Meddelanden3};
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Anledningen att det funkar så lätt med textsträngar är helt enkelt att den skapar en symmetrisk array med pekare till vardera textsträng, och i sin tur givetvis har varierande längd. Även {'a','v','t'} läggs förmodligen ihop likt en textsträng utan 0-slut. Däremot är det nog bäst att hålla koll på sizen själv (sizeof).

Det går som sagt inte att göra osymmetriska strukturer, utan man får fuska genom att ange ett maxvärde i structen:

Kod: Markera allt

struct teststruct {
   int values[15];
};

struct teststruct testarray[] = {
   {1,2,3,4,5},
   {5,4,3}
};
Men då fylls, som sagts tidigare, resten ut med det som är i minnet för stunden. :)

Nu kanske jag bara förklarade det som redan framgick?

Mvh
speakman
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Okej, Men hur förklarar ni skillnaden i initieringen mellan

Kod: Markera allt

char str1[] = "hej";
och
char str1[] = {'h','e','j','\0'};
För mig får variablerna exakt samma värden.

Men det går som sagt att skriva

Kod: Markera allt

const struct  {
  const char *s;
} errorTBL[] = {
  "hejsan",
  "hej"
}; 

men inte:

const struct  {
  const char *s;
} errorTBL[] = {
{'h' ,'e' ,'j' ,'s' ,'a' ,'n' ,'\0' },
{','h' ,'e' ,'j' ,'\0' }
}; 
Vilket jag tycker är väldigt märkligt..
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Vid att ha komma mellan anger du att det är olika värden, att de inte hör ihop, därför fungerar det inte. Man kan fint ange:
char * EnTextStreng = "Ska bara" " pröva " "såhär";
men
char * EnTextStreng = "Ska bara"," pröva ","såhär";
ger fel.
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg av JJ »

Jag tror du kan ha missförstått en grej; en sträng blir inte "en massa tecken på rad" utan "en pekare på en massat tecken på rad".
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Jag vet att det blir en pekare
Det blir det även om det är en vektor av typen int eller float.

så om jag skriver

Kod: Markera allt

char str1[] = "hej"; 
och 
char str2[] = {'h','e','j','\0'}; 

så är både 
str1 == &str1[0]
samt
str2 == &str[2]


likadant med int,

int vec[] = {1,2,3,4,5};

vec == &vec[0];
men men. Jag har löst det på mitt sätt..
jag har gjort allt som en enda sträng

Kod: Markera allt

int vec[]=
{1,2,3,4,5,
2,2,3,4,
1
2,4,5,6};

int vecindex[]  = {0,5,9,10};
så får jag använda vec[vecindex[2]] för att komma åt första elementet i rad 2.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Det var då det krångligaste sättet jag har sett på länge.

Har du en text och vill "snåla" på minneär det effektivaste sättet nog:
const char * Text1 = "Meddelandet 1 om en viss sak";
const char * Text2 = "Ganska kort";
const char * Text3 = "Kort!";
(osv)
och vill man sedan indexera i en tabell som följd av felkoder eller så:
const char * Tabell[] = {Text1, Text2,Text3 (, osv)};
Dessa texter kan sedan indexeras med Tabell[] och vill man åt enstaka tecken kan man köra med Tabell[][]. På detta vis ligger strängerna direkt efter varandra och fyller minimalt.

Jag förstår inte dit trång till att måste ange enkelkaraktärer med ett komma mellan, om man måste ange specialtecken med t.ex. en escape-kod är det lika bra med:
const char * Textgudvetvad = "Visas en specialare: \x12extra besvärlig";
i min kompiler gnälls över att den hexadecimala escape-sekvens är för lång ("\x12e"), det löser jag vid att göra:
const char * Textgudvetvad = "Visas en specialare: \x12" "extra besvärlig";
OBS: inget jävla komma! Det är ju samma sträng, komma delar variabler ju.
macgyver
Inlägg: 321
Blev medlem: 8 juni 2005, 00:24:09
Ort: Göteborg
Kontakt:

Inlägg av macgyver »

men han vill ju inte lagra textsträngar, bara integers, då blir det ju väldig jobbigt att hålla på att skriva "\x1" "\x2 "\x3 .. osv"

ditt sista förslag dangraf är nog lättast ifall du bara vill lagra tal

edit: såg nu att du använde

Kod: Markera allt

vec[vecindex[2]]
 
vilket känns lite omständigt

lättare är väl:

Kod: Markera allt

   const int nv1[] = {0,1,2,3,4, 5},
   nv2[] = {0,1,2,3},
   nv3[] = {0,1};

   const int *nrvv[] = {nv1, nv2, nv3};

sen skriva nvv[y][x] för att komma åt rad/kolumn
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

I vilken miljö är det du skriver i?
Är det en större miljö (ARM el. dyl) så hade jag nog använt mig av länkad lista, framförallt om det är väldigt varierande textlängder. Det tillkommer dock en pekarstorlek för varje text, men det kan vara försvinnande lite i många fall.

Mvh
speakman
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

>>speakman
Länkade listor använder man väl vid dynamisk minneshantering då man inte riktigt vet textlängden och när det lätt kan tillkomma/ försvinna objekt??

Jag har mina osymetriska tabeller, som alltid är konstanta. Så jag tror jag kör på mitt system eller på systemet här nedanför som "macgyver" och "icecap" föreslog.

jag har dock ytterligare en fråga i ert exempel:-)

Kod: Markera allt

   const int nv1[] = {0,1,2,3,4, 5}, 
   nv2[] = {0,1,2,3}, 
   nv3[] = {0,1}; 

   const int *nrvv[] = {nv1, nv2, nv3}; 

Hur fungerar det rent kompileringsmässigt??
Jag får ju ett gäng variabler som heter t.ex nv1, nv2 osv som jag aldrig använder förutom i initieringen. Tar de någon extra plats i processorn?
Det är nog ifs försvinnande lite. Men det hade varit intresasnt och veta lite hur det fungerar.

Tack så väldigt mycket för era svar!!!
macgyver
Inlägg: 321
Blev medlem: 8 juni 2005, 00:24:09
Ort: Göteborg
Kontakt:

Inlägg av macgyver »

nope det tar ingen extra plats, nv1,nv2,nv3 är bara namn på fasta pekare som kompilatorn använder för att adressera arrayerna som ligger lagrade som konstanter i minnet, d.v.s. enda platsen dessa pekare ligger lagrade på är i arrayen, nrvv[] alltså tas inget RAM minne upp
Skriv svar