ANSI C

Tags:    c

<< < 12 > >>
Hej,

har følgende koder der afvikles i en Engine der kun håndterer Ansi C.
Er der nogle der kan optimer dette lidt, eller er det bare som det skal være ?


Opgaven er at finde en tal værdi en en char streng hvor opbygningen er fast. Men længden vil varierer. F.eks. @MAIN_2560_1024.PROCESSPICTURE_1:F1_1_OPERATING . Her skal det første 1 tal findes.

// Find Picture number and X pos
//Get testStr pos
while(z < (strlen(PicPath)))
{
strncpy(PictureNr, PicPath+z, 1);
if (strcmp(PictureNr,testStr)==0) { break; }
z++;
}
//Get numper i path
strncpy(PictureNr, PicPath, z);
strncpy(PictureNr, PictureNr+z-1, z-1);

//Adjust X pos
switch(atoi(PictureNr))
{
case 1:
X = X;
break;
case 2:
X = X+1280;
break;
}
//End



11 svar postet i denne tråd vises herunder
2 indlæg har modtaget i alt 10 karma
Sorter efter stemmer Sorter efter dato
Sørens kode burde virke, men det finder ikke det første 1-tal i strengen. Men det er måske det tal, som Karsten mente?

Du behøver ikke at kopiere den substreng, som indeholder tallet, for 'atoi()' stopper med at parse tal, når det når til en ASCII værdi udenfor talrækken...altså:

Fold kodeboks ind/udKode 

...vil returnere tallet '123'.

Som Gustav siger, så kan 'strtok()' bruges til at finde en substreng, men 'strchr()' er muligvis bedre i dette tilfælde, for den leder efter et enkelt tegn. Det er bedst at bruge disse standard funktioner, for dem kender compileren i visse tilfælde og kan optimere dem smart. Det bliver sværere for compileren at optimere, når vi selv skriver noget tilsvarende.

Er du i tvivl, så kig i den genererede assembly kode.

Her er mit bud:
Fold kodeboks ind/udC kode 


Og det ser ud til at virke:
Fold kodeboks ind/udKode 




Indlæg senest redigeret d. 01.11.2012 09:41 af Bruger #2695
Fold kodeboks ind/udC kode 

Her tager du 1 tegn ad gangen fra PicPath og smider over i PictureNr. Siden PicPath efter al sandsynlighed er større end 1 bliver der ikke indsat nogen nul-byte (se dokumentation for strncpy), hvilket kan give problemer. Så sammenligner du om PictureNr hvilket er en helt tilfældig streng siden vi ikke ved hvornår den slutter, med testStr. Men testStr kan kun være en enkelt streng så du kan umuligt finde flere forskellige strenge, hvilket du jo leder efter (de forskellige tal der kan være i strengen).

Fold kodeboks ind/udC kode 

Her går den også galt. Lad os sige du finder dit tal på indeks, nr 5. Så vil z=5. Så tager du de første 5 tegn i PicPath og kopierer ind i PictureNr. Det du gør bagefter er sådan set at beholde indeks 4..7 hvilket virker lidt tilfældigt. Du bryder også funktionens betingelser hvilket er at destination og source ikke må være det samme.

http://www.cplusplus.com/reference/clibrary/cstring/strncpy/

Kan godt være jeg har misset noget - kender heller ikke startværdien for z og testStr.

Som Gustav siger findes der ikke noget regex i ANSI C som standard. Du kan dog finde biblioteker. Men lad os lige prøve en simplere struktureret tilgang først:

Du siger opbygningen er ens. Nu ved jeg ikke hvilke dele er ens, men jeg antager at det er ':' i:

@MAIN_2560_1024.PROCESSPICTURE_1:F1_1_OPERATING

Så den overordnende tilgang er følgende:
1. Find kolonnet. Tallet vi leder efter er lige før.
2. Gå tilbage indtil vi møder noget andet end tal.
3. Træk tallet ud.

Det kan godt være der er nogen syntaksfejl der måske skal rettes.

Fold kodeboks ind/udC kode 




Indlæg senest redigeret d. 31.10.2012 20:30 af Bruger #14645
Jeg tror desværre du får svært ved at finde folk der er bedre end dig til ANSI C herinde. Du vil nok have større held på et forum ala StackOverflow - de har et lidt bredere publikum :-)

Men jeg vil da alligevel forsøge mig med lidt feedback. Jeg antager at "PROCESSPICTURE_1" er den spændende del.

Efter lidt google-søgning må jeg konstatere at det ser ud til at ANSI C ikke har noget lignende regex. Et alternativ i dit tilfælde kan være strtok(). Den deler en string op i tokens på baggrund af en seperator. Fx:

Fold kodeboks ind/udC kode 


Jeg har INGEN idé om det her virker - det ser lidt hacky ud - og jeg har aldrig kodet C :-) Men strtok() ser ud til at fungere som i andre sprog...

ref: http://www.java2s.com/Code/C/String/Truncatestringbydelimiterhowtousestrtok.htm

P.s. Håber ikke jeg bliver totalt til grin nu :-)




Indlæg senest redigeret d. 31.10.2012 19:57 af Bruger #17015
Hej alle,
tak for alle jeres input. Tror lige mit indlæg kræver lidt mere forklaring, det gik måske lidt for stærkt i går.

Det jeg i virkeligheden vil finde er tallet der står foran | : | i teksten @MAIN_2560_1024.PROCESSPICTURE_1:F1_1_OPERATING

Jeg ved at der altid startes med |@| og at der optræder et | . | og | : |
Antal karakter mellem de tre tegn kender jeg ikke. Tallet foran | : | vil typisk være mellem 1 og 4, begge inkl. og fortæller på hvilken skærm min mus har trykket på et symbol.

Derfor finder jeg positionen for : og trækker en fra(Derfor Break, jeg er ligeglad med resten). Der efter kopierer jeg tallet som på det tidspunkt er en karakter. Og konverterer det til et tal. Som så bruges til noget offset beregning.

Dette :
//Get number in path
strncpy(PictureNr, PicPath, z);
strncpy(PictureNr, PictureNr+z-1, z-1);

har jeg ændret til :
//Get number in path
strncpy(PictureNr, PicPath+z-1, 1);

//Adjust X pos
switch(atoi(PictureNr))

Der var ingen grund til at kopierer to gange.



Indlæg senest redigeret d. 01.11.2012 11:58 af Bruger #9875
Prøv mit bette program...det gør ca. det samme som Sørens (bare lidt smartere imho).
Altså leder efter ':', søger derfra baglæns efter første ikke-nummeriske ascii tegn og returnerer derefter 'atoi()' på tallet.

Du har slet ikke brug for at kopiere strengen rundt.



Fik lige læst jeres indlæg igennem en gang mere, og fandt et gulkorn i Roberts indlæg. Faktisk kan strtok() + en strlen() afløse mit loop.
Og vil tro disse to funktioner afvikles hurtigere end mit loop, om ikke andet kan det hele udføres i én linje. Det skal jeg nok få ros for af min ikke C kyndige kolleger ;o)

Men tak for alle jeres indlæg. (har så lige en række scripts rundt om i mit program der skal optimeres ud fra denne nye viden).

//Get numper i path
strncpy(PictureNr, PicPath+strlen(strtok(PicPath, ":" ))-1, 1);
//printf ("PictureNr = %i \r\n",atoi(PictureNr));
//Adjust X pos
switch(atoi(PictureNr))



Jeg forstår stadig ikke hvorfor du kopierer teksten. Det er ikke nødvendigt.

strchr(PicPath, ':') gør det samme som strtok(PicPath, ":") men er hurtigere.




Det er nok fordi jeg ikke har forstået strchr(PicPath, ':') , kopierer den teksten frem til | : | eller fotæller den pos for | : | ? .

Prøver lige igen.



strchr(str, ':') finder kun første position i strengen, hvor ':' findes, men du har jo ikke brug for at kopiere noget. Du ville have fat i tallet før ':', og derfor finder vi dens position.
I linje 11 i min version har jeg positionen for dette tal og derfor "konverterer" jeg det bare til en integer på linje 11, som jeg så returnerer på linje 13.
Jeg kopierer på intet tidspunkt dele af strengen, for det er ikke nødvendigt. 'atoi()' funktionen kan sagtens arbejde med strengen som den er.



En lille simpel test.

char * PictureNr_1;
char *PictureNr_2;

//Get numper i path
PictureNr_1 = strtok(PicPath,":");
PictureNr_2 = strchr(PicPath,':');

printf ("PictureNr_1 = %s \r\n",(PictureNr_1));
printf ("PictureNr_2 = %s \r\n",(PictureNr_2));

Og output

PictureNr_1 = @MAIN_2560_1024.PROCESSPICTURE_1
PictureNr_2 = (null)

Men måske mig der har misforstået et eller andet. Og er blevet lidt stædig ;o)



<< < 12 > >>
t