Ştiri:

Vă rugăm să citiţi Regulamentul de utilizare a forumului Scientia în secţiunea intitulată "Regulamentul de utilizare a forumului. CITEŞTE-L!".

Main Menu

Siruri de caractere

Creat de automat, Aprilie 02, 2012, 08:16:07 PM

« precedentul - următorul »

0 Membri şi 1 Vizitator vizualizează acest subiect.

automat

Salut.

Am doua intrebari si anume :
- am urmatoarele instructiuni :  i=10;
                                           buffer = (char*) malloc (i+1);
                                           printf("\n %d\n", sizeof(buffer));

Instructiunea malloc() din cate stiu aloca in memoria heap n octeti. In cazul de fata cand vreau sa afisez dimensiunea zonei de memorie alocata cred ar trebui sa imi afiseze, presupun 11 octeti. Mie imi afiseaza 4 octeti.

- Scrieti un program care ilustreaza utilizarea functiei "strstr" pentru cautarea unui subsir intr-un sir si care scrie si pozitia la care subsirul a fost gasit.

#include<stdio.h>
#include<string.h>

int main()
{
    char str[]="este";
    char string[]="Primul pas este cel mai greu";
    char *pdest;
    int result;
    printf("\n Sirul : %s\n", string);
    pdest=strstr(string, str);                                                             // pdest = "este cel mai greu"
    result=(int)(pdest-string+1);                                                        // result = 12
    if(pdest != NULL)
    printf("\n Subsirul \"%s\" s-a gasit la pozitia %d.\n", str, result);         // Subsirul "este" s-a gasit la pozitia 12.
    else
    printf("\n Subsirul \"%s\" nu a fost gasit.\n", str);
}

N-am inteles cum se calculeaza variabila result.
result = (int)(pdest-string+1)
result = (int)("este cel mai greu" - "Primul pas este cel mai greu" + 1)
result = ???


AlexandruLazar

#1
Citat din: automat din Aprilie 02, 2012, 08:16:07 PM
- am urmatoarele instructiuni :  i=10;
                                          buffer = (char*) malloc (i+1);
                                          printf("\n %d\n", sizeof(buffer));

Instructiunea malloc() din cate stiu aloca in memoria heap n octeti. In cazul de fata cand vreau sa afisez dimensiunea zonei de memorie alocata cred ar trebui sa imi afiseze, presupun 11 octeti. Mie imi afiseaza 4 octeti.

Operatorul sizeof() îţi spune într-adevăr dimensiunea argumentului. Dar în cazul de faţă argumentul este un pointer către zona de memorie alocată dinamic (nu este o variabilă alocată static). Deci e normal ce se întâmplă -- îţi întoarce doar spaţiul necesar pentru a stoca un pointer (întrucât rezultatul e 4, presupun că ai un SO pe 32 de biţi, sau oricum, spaţiul de adrese disponibil pentru fiecare proces e de 32 de biţi). Sintaxa e ce-i drept derutantă -- arată ca o funcţie, dar nu este. E un operator unar iar expresia sizeof(buffer) se evaluează la compilare.

Poţi să obţii dimensiunea zonei de memorie alocate ca (i + 1) * sizeof(char) (i.e. ai alocat spaţiu pentru i + 1 elemente de tip char).

Edit: acum pentru a doua întrebare :).

Hai să ne uităm întâi pe ce ar trebui să facă strstr:

CitatNAME
      strstr, strcasestr - locate a substring

SYNOPSIS
      #include <string.h>

      char *strstr(const char *haystack, const char *needle);

      #define _GNU_SOURCE

      #include <string.h>

      char *strcasestr(const char *haystack, const char *needle);

DESCRIPTION
      The  strstr() function finds the first occurrence of the substring nee‐
      dle in the string haystack.  The terminating '\0'  characters  are  not
      compared.

      The  strcasestr()  function  is  like strstr(), but ignores the case of
      both arguments.

RETURN VALUE
      These functions return a pointer to the beginning of the substring,  or
      NULL if the substring is not found.

Prin urmare, apelul:

pdest=strstr(string, str);

va întoarce un pointer la începutul primei apariţii a lui "este" din "Primul pas este cel mai greu".

Pe sistemul meu s-a nimerit sa iasă aşa:


(gdb) p &string[0]
$1 = 0x7fffffffe260
(gdb) p pdest
$2 = 0x7fffffffe26b


Adică: string este reţinut în memorie începând cu adresa 0x7fffffffe260 (acolo se află caracterul 'P' -- după el urmează celelalte, consecutiv), iar pdest reţine valoarea 0x7fffffffe26b, arătând astfel că prima apariţie a lui "este" începe de la acea adresă.

Acuma, scăzând din pdest adresa primului element din pstr, vom obţine numărul de caractere dintre începutul şirului şi prima apariţie a lui este.

Totuşi, două comentarii cu privire la:


(int)(pdest-string + 1)


Codul ăsta nu e bun ;D.

În primul rând, cine îl citeşte va presupune că string e un pointer spre o zonă de memorie alocată dinamic; desigur că îşi va da seama ca nu e aşa (definiţia e câteva rânduri mai sus), dar consistenţa ajută foarte mult la urmărirea codului, pentru că nu trebuie să te uiţi de fiecare dată la declaraţia  variabilelor. Chiar dacă şi aşa cum e scris acolo e corect sintactic, recomandarea mea când ai de scăzut două adrese e să arăţi asta explicit -- i.e. prin &pstring[0]. Asta funcţionează folosind operatorul & (care se evaluează la adresa argumentului său) către elementul pstring[0] -- se citeşte chiar aşa, "adresa lui pstring[0]") şi are avantajul de a arăta imediat celui care citeşte codul că scazi două adrese, dintre care a doua e către primul element al unui array alocat static.

În al doilea rând (şi de fapt de-asta codul nu e bun), codul face presupunerea implicită că o variabilă de tip char are un octet (motiv din care se presupune că dacă scazi cele două adrese şi îţi iese diferenţa în bytes, sunt exact atâtea caractere câţi bytes sunt). Tradiţional, un char chiar are 1 byte, dar standardul C nu cere lucrul ăsta în mod explicit, deci nu e bine să te bazezi pe el.

astan

#2
Intodeauna un char va ocupa 1 byte.
Prin standard:
sizeof(char) = sizeof(unsigned char) = sizeof(signed char) = 1
Acest lucru este documentat in standardul ISO/IEC 9899, sectiunea 6.5.3.4:

6.5.3.4 The sizeof operator
When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1.

AlexandruLazar

Citat din: astan din Aprilie 03, 2012, 07:24:47 PM
Intodeauna un char va ocupa 1 byte.
Prin standard:
sizeof(char) = sizeof(unsigned char) = sizeof(signed char) = 1
Acest lucru este documentat in standardul ISO/IEC 9899, sectiunea 6.5.3.4:

6.5.3.4 The sizeof operator
When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1.

Corect -- acum e prea târziu ca să mai editez şi îmi fac autocritica ;D. De fapt standardul nu garanteaza numărul de biţi dintr-un byte, sizeof x e întotdeauna 1 dacă x e de tip char.