Vágásfüggvény a C

Idiomatikus trim funkciót próbálok C-be írni. Hogyan néz ki ez? Inkább össze kellene állítanom az új karakterláncot, és vissza kell adnom?

void trim(const char *input, char *result) { int i, j = 0; for (i = 0; input[i] != "\0"; i++) { if (!isspace(input[i])) { result[j++] = input[i]; } } } 

Megjegyzések

  • Ott ‘ a kód hibáinak száma, ‘ kiszolgáltatott a puffertúlcsordulási támadásoknak, és nem ‘ t csináld, amit egy tipikus ” trim ” függvény csinál. A vágás eltávolítja a vezető és a záró szóközt. Ez kicsúsztatja őket.
  • Köszönöm. Tudna részletesen bemutatni egy puffertúlcsordulási támadás kezelését?
  • Soha nem szabad vakon másolnia az adatokat valamilyen pufferbe, ha nem tudja, hogy ‘ mennyi hely van kiosztva. rá, hogy ‘ csak problémát kér. Egyszerű tennivaló lenne egy olyan paraméter hozzáadása, amely befogadja a puffer méretét. Így ‘ a hívó félnek elmondani, hogy valójában mekkora. Ezután ‘ rajtad múlik, hogy soha ne próbálj meg olvasni / írni a megadott hosszon túl. Természetesen ‘ nem bolond bizonyíték, a hívó fél hamis hosszúságot adhat meg, de ez nem a tiéd, hanem a végük problémája lenne.

Válasz

Mint @JeffMercado rámutatott, ez eltávolítja a szóközöket a vezető és a záró szóközök levágása helyett. Feltéve, hogy meg akarja tartani a jelenlegi funkcionalitást, hívjuk “div div = = 7c4491d7a8”>

-nek.

Itt nagyon finom hiba van:

... isspace(input[i]) ... 

isspace egy előjel nélküli karakter vagy EOF. A rendszerint aláírt char átadása meghatározatlan viselkedést eredményez. Ehelyett mondja ki:

... isspace((unsigned char) input[i]) ... 

Egy másik hiba: nem ad ki NUL terminátort, vagyis a hívónak nincs módja tudni, hogy a karakterlánc milyen hosszú ( hacsak nem nullázta le a puffert a függvény meghívása előtt).

Ezen hibák kijavításával kapunk:

void remove_spaces(const char *input, char *result) { int i, j = 0; for (i = 0; input[i] != "\0"; i++) { if (!isspace((unsigned char) input[i])) { result[j++] = input[i]; } } result[j] = "\0"; } 

@JeffMercado is ezt a függvényt mondta érzékeny a puffertúlcsordulásra. Bizonyos értelemben ez nem igaz, feltéve, hogy a hívó tudja, hogy legalább strlen(input) + 1 puffert rendeljen hozzá. De a hívó fél lusta lehet, és csak azt mondja, hogy char result[100]. Kimeneti pufferméret-paraméter hozzáadása valószínűleg megvéd az ilyen hibáktól:

void remove_spaces(const char *input, char *output, size_t output_size); 

Nézze meg, megvalósíthatja-e ezt Néhány szem előtt tartandó dolog:

  • A kimeneti puffer méretének ellenőrzésénél ne felejtsd el a NUL terminátort.

  • Ne legyen olyan, mint strncpy , és hagyja ki a NUL terminátort, amikor meg kell csonkolnia a karakterláncot, mivel ez finom hibákhoz vezethet.

  • Ha a int elemet használja a i és a j és size_t output_size esetén kapjon fordítói figyelmeztetéseket az aláírt és az aláíratlan összehasonlításáról. Ha nem, akkor kapcsolja be a fordító figyelmeztetéseit. Ha a GCC-t a parancssorból használja, akkor szokjon gépelni gcc -Wall -W.

Megjegyzések

  • strncpy() nem string függvény, még bár egyesek feltételezik. Tehát a karakterlánc eredménye egyébként is történés lenne. Ami az analógiát legjobb esetben is vázlatosá teszi.

Válasz

Tudjuk, hogy egy mutatót előre és hátra mozgathatunk , és azt is tudjuk, hogy balról levághatunk egy húrt. Ha növekszünk a mutatóval, és csökkentjük a mutatót a jobb oldalról történő vágáshoz, akkor két while hurok elegendő. Észre fogja venni, hogy a jobb séta száma kisebb, mint a bal séta száma.

Jobbra szabott kód:

#include <stdio.h> #include <ctype.h> void trim_both(char *, char *); int main (void) { char title[100] = " My long string "; char title_t[100] = ""; (void) printf("String before left trim is:[%s]\n", title); trim_both(title, title_t); (void) printf("String after left trim is:[%s]\n", title_t); } // trim spaces from left void trim_both(char *title_p, char *title_tp) { int flag = 0; // from left while(*title_p) { if(!isspace((unsigned char) *title_p) && flag == 0) { *title_tp++ = *title_p; flag = 1; } title_p++; if(flag == 1) { *title_tp++ = *title_p; } } // from right while(1) { title_tp--; if(!isspace((unsigned char) *title_tp) && flag == 0) { break; } flag = 0; *title_tp = "\0"; } } 

Válasz

Legegyszerűbb mód (csak a szóközök eltávolítása):

Trim.Start:

  1. A karakterek összehasonlítása a karakterlánc elején " " (szóköz vagy más karakterek, például \n vagy \t) és növekményes temp (i) változó.
  2. Mutató mozgatása a i (str+=i). Most a karakterlánc olyan karakterből indul, amely nem szóköz (vagy bármely más fehér karakter).

Trim.End:

  1. Tegye ugyanazt, amit a Trim.Start esetében, de a karakterlánc végétől kezdve.
  2. Állítsa be az utolsó karaktert (utolsó szóköz) \0.

Az a fontos, hogy a függvény a mutatót mutatóra (húrra) vigye.Figyelje a függvényhívást: StringTrim(&p2);

char * StringTrim(char * *pointerToString) { u8 start=0, length=0; // Trim.Start: length = strlen(*pointerToString); while ((*pointerToString)[start]==" ") start++; (*pointerToString) += start; if (start < length) // Required for empty (ex. " ") input { // Trim.End: u8 end = strlen(*pointerToString)-1; // Get string length again (after Trim.Start) while ((*pointerToString)[end]==" ") end--; (*pointerToString)[end+1] = 0; } return *pointerToString; } 

Használat:

 char str1[] = " test1 "; char * p1 = str1; Debug("1. before trim: [%s]", p1); StringTrim(&p1); Debug("1. after trim [%s]", p1); char str2[] = " test2"; char * p2 = str2; Debug("2. before trim: [%s]", p2); StringTrim(&p2); Debug("2. after trim [%s]", p2); char str3[] = "test3 "; char * p3 = str3; Debug("3. before trim: [%s]", p3); StringTrim(&p3); Debug("3. after trim [%s]", p3); char str4[] = " "; char * p4 = str4; Debug("4. before trim: [%s]", p4); StringTrim(&p4); Debug("4. after trim [%s]", p4); char str5[] = ""; char * p5 = str5; Debug("5. before trim: [%s]", p5); StringTrim(&p5); Debug("5. after trim [%s]", p5);  

Eredmény :

 1. before trim: [ test1 ] 1. after trim [test1] 2. before trim: [ test2] 2. after trim [test2] 3. before trim: [test3 ] 3. after trim [test3] 4. before trim: [ ] 4. after trim [] 5. before trim: [] 5. after trim []  

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük