27 Sept 2012

Introducere C - pointeri

Salut,

astazi voi incerca sa lamuresc cateva aspecte legate de pointeri.
Ei bine, un pointer este practic o variabila care retine o adresa de memorie (adresa unei date, adresa unei functii, adresa unei adrese din memorie, void - adresa catre o zona necunoscuta).

Exista doi operatori esentiali pe care ii vom folosim: * (dereferentiere) si & (referentiere) si apar in fata variabilei de tip pointer.
Acum o sa ma intrebati ce inseamna derefentiere si referentiere...
Este destul de simplu, * este folosit atunci cand dorim sa aflam valoarea stocata la adresa respectiva. Atunci cand este folosit la declararea unei variabile, acesta indica prezenta unui pointer la tipul respectiv.
Cu ajutorul lui & putem afla adresa din memorie a variabilei respective (si l-am si folosit deja la functia scanf).

Trebuie sa retinem faptul ca un pointer nu este alocat la definire. Va trebui ca noi sa facem asta si vom vedea cum putin mai tarziu.

Exemple:
int *a; // pointer la int sau vector de intregi
int b = 10; // variabila de tip int
char *c; // pointer la char sau sir de caractere (vector de caractere)
void *s = NULL; // initializare la null (valoare 0)
*a = 5; // initializare gresita, a nu a fost alocat si nu indica nicio adresa
a = &b; // initializare corecta, a indica acum adresa lui b
*a = 5; // initializare corecta, echivalenta cu b = 5

Dupa cum am spus deja, declaratia int *a este echivalenta cu int a[] deci putem declara vectori cu ajutorul pointerilor, cu conditia de a face, ulterior, alocarea memoriei. Pentru ca tot veni vorba de asta, exista 2 functii de baza care ne ajuta malloc si calloc. Ele se utilizeaza in modul urmator:

int *a;
// vom aloca un vector de 100 de elemente intregi
a = (int*)malloc(100 * sizeof(int));
a = (int*)calloc(100, sizeof(int));

Diferenta dintre cele doua este ca calloc face si initializarea componentelor la zero.

Important! De fiecare data cand folosim functiile de alocare a memoriei este fundamental sa o eliberam la finalul programului. Pentru aceasta exista functie free.

Multi se sperie de pointeri si gasesc acest lucru gresit. Daca sunt folositi corect, acestia fac minuni. Este foarte adevarat ca pot aparea si efecte secundare daca doi pointeri arata catre acelasi continut de memorie (cum am vazut in exemplul de mai sus), insa intotdeauna trebuie sa folosim pointerii cu atentie.
Cineva mi-a povestit odata cum vede el un pointer si a facut o analogie cu un ogar care indica spre prada de vanatoare (asa ca in desenele animate :) ). Evident cainele este variabila de tip pointer, iar prada este continutul/adresa din memorie.

Consider ca este de ajuns pentru astazi. Data viitoare vom vedea cum se folosesc acesti pointeri in probleme cu vectori. Pana atunci eu va doresc numai bine.

25 Sept 2012

Introducere C - vectori

Salut,

astăzi, după o perioadă de inactivitate pentru care vă cer scuze, voi continua cu câteva lucruri introductive despre vectori.

Aceștia pot fi priviți ca o colecție liniară (elementele pot fi accesate dupa index) și omogenă (adică au elemente de același tip) de date. 
În C indexarea începe de la zero.

Declarația este de felul următor
<tip> <nume_vector>[<dimensiune>];
Pentru început, vom declara vectori statici, adică vom specifica dimensiunea lor ca în forma de mai sus.
Acum câteva exemple de inițializare
int a[100];
float b[50];
char s[10] = {0}; // asa se initializeaza toate elementele la valoarea zero
 
Exemplu de citire a unui vector de întregi de la tastatură

int main() {
   int a[100],n,i; // vectorul are maxim 100 de intregi

   scanf ("%d",&n); // citim nr de elemente

   for (i = 0; i < n; ++i)
      scanf("%d", &a[i]);

   for (i = 0; i < n; ++i)
      printf("%d ", a[i]);

   return 0;
}

Alte aplicații clasice cu vectori sunt căutările și sortările. În continuare vă voi da o implementare a sortării prin inserție.

#include <stdio.h>
#include <stdlib.h>

//sortare prin insertie, ca parametrii dam vectorul si dimensiunea sa
void insertie(int *v, int n){
int t, j, i;

for (i = 1;i < n; ++i){
    t = v[i];
    j = i;
    while(j > 0 && t <= v[j - 1]){
        v[j] = v[j-1];
        --j;
        }
    v[j] = t;
    }
}

int main(){
    int i;

    // declaram un vector de 10 elemente de tip int
    int v[10];   

    // citirea numerelor
    for (i = 0;i < 10;++i)
        scanf("%d", &v[i]);
 
    // sortarea
    insertie(v, 10);

    // afisarea vectorului soratat
    for (i = 0;i < 10;++i)
        printf("%d ", v[i]);

    return 0;
}


25 Aug 2012

Introducere C - despre funcții

Salutare tuturor!

Astăzi  vom vedea cum putem modulariza codul astfel încât să fie mult mai ușor de citit și de înțeles. Acest lucru se realizează, în principal, cu ajutorul funcțiilor, C-ul fiind prin excelență un limbaj procedural.
Funcțiile ne permit, totodată, să le reutilizăm după necesități. De exemplu, să presupunem că am făcut o funcție care verifică dacă un număr este prim. Dacă avem de rezolvat, o problemă mai complicată care necesită, la un moment dat, testarea unor numere pentru a vedea dacă ele sunt prime, atunci putem folosi funcția realizată anterior. Important este ca funcțiile să fie cât mai generale și să preia numai parametrii absolut necesari. Și pentru că am pomenit de parametrii, iată cum arată semnătura generică a unei funcții:

tip_rezultat nume_funcție(tip parametru1, tip parametru2, ...) {
    // declarații și instrucțiuni
 }

Apelarea se face în modul următor:

nume_funcție(lista parametri) daca tip_rezultat este void (adică nu întoarce nimic)
sau
variabila = nume_funcție(lista parametri) daca funcția întoarce ceva

Iar acum să modificăm ultimele exemple prezentate astfel încât programele să fie cu funcții.

1. Fiind date de la tastatură două numere întregi, să se afișeze cel mai mare divizor comun al lor. (Indiciu: Algoritmul lui Euclid)

#include <stdio.h>

int cmmdc (int a, int b) {
   int r;

   // testam cazul limita cand b este zero
   if (b == 0) {
       return a;
   }
   // aici ar fi mers un 'else', dar nu e nevoie datorita return-ului anterior
   // aici este algoritmul propriu-zis
   do{
       r = a % b;
       a = b;
       b = r;
   }while(r);

   // la final, cmmdc-ul este in 'a'
   return a;
}

int main(){
   // declaram variabilele; ele vor fi initializate automat la zero
   int a, b, c;

   printf("Introduceti primul numar: ");
   scanf("%d",&a);

   printf("Introduceti al doilea numar: ");
   scanf("%d",&b);
 
   c = cmmdc(a,b);
  
   printf("Cmmdc este %d\n",c);
  
   return 0; 
}


2. Să se verifice dacă un număr introdus de la tastatură este prim.

#include <stdio.h>

// functia va intoarce 0 (fals) sau 1 (adevarat) in functie de rezultatul testului
int e_prim(int nr){
   int i, prim = 1;
   /* pentru fiecare numar mai mic decat numarul nostru, verificam daca exista vreunul la care
   * acesta acesta din urma se imparte exact
   * s-a aratat ca nu e cazul sa verificam toate numerele, ci doar pe acelea mai mici decat nr/2
   */
   for (i = 2; i < nr/2; ++i) {
       if (nr % i == 0) {
           printf("Numarul nu este prim\n");
           prim = 0;
           break; // am gasit ca numarul nu este prim si iesim fortat din bucla; nu are sens sa continuam
       }
   } 
   return prim;
}

int main(){
   // vom folosi o variabila auxiliara pentru a putea afisa mesajul afirmativ de la sfarsit
   // pornim de la ideea ca numarul este prim
   int nr, i, prim = 1;

   printf("Introduceti numarul: ");
   scanf("%d",&nr);

   prim = e_prim(nr);

   if (prim) {
       printf ("Numarul este prim\n");
   }
   else {
      printf("Numarul nu este prim\n");
   }

   return 0;
}

23 Aug 2012

Introducere C - probleme rezolvate (3)

Salutare tuturor!

Astăzi o să vă prezint ultima parte a problemelor simple urmând ca, de data viitoare, să trecem la modularizare și alte lucruri interesante.
Pe ordinea de zi, avem tot două probleme, după cum urmează

1. Fiind date de la tastatură două numere întregi, să se afișeze cel mai mare divizor comun al lor. (Indiciu: Algoritmul lui Euclid)

#include <stdio.h>

int main(){
   // declaram variabilele; ele vor fi initializate automat la zero
   int a, b, r;

   printf("Introduceti primul numar: ");
   scanf("%d",&a);

   printf("Introduceti al doilea numar: ");
   scanf("%d",&b);

   // testam cazul limita cand b este zero
   if (b == 0) {
       printf("Cmmdc este %d\n",a);
       return 0;
   }
   // aici ar fi mers un 'else', dar nu e nevoie datorita return-ului anterior
   // aici este algoritmul propriu-zis
   do{
       r = a % b;
       a = b;
       b = r;
   }while(r);

   // la final, cmmdc-ul este in 'a'
   printf("Cmmdc este %d\n",a);

   return 0; 

}


2. Să se verifice dacă un număr introdus de la tastatură este prim.

#include <stdio.h>

int main(){
   // vom folosi o variabila auxiliara pentru a putea afisa mesajul afirmativ de la sfarsit
   // pornim de la ideea ca numarul este prim
   int nr, i, prim = 1;

   printf("Introduceti numarul: ");
   scanf("%d",&nr);

   /* pentru fiecare numar mai mic decat numarul nostru, verificam daca exista vreunul la care
   * acesta acesta din urma se imparte exact
   * s-a aratat ca nu e cazul sa verificam toate numerele, ci doar pe acelea mai mici decat nr/2
   */
   for (i = 2; i < nr/2; ++i) {
       if (nr % i == 0) {
           printf("Numarul nu este prim\n");
           prim = 0;
           break; // am gasit ca numarul nu este prim si iesim fortat din bucla; nu are sens sa continuam
       }
   }  
   // aici era corect si if (prim == 1)
   // in C, o structura de tipul if (ceva) este echivalenta cu if (ceva != 0)
   if (prim) {
       printf ("Numarul este prim\n");
   }
   return 0;
}

20 Aug 2012

Codepad, un instrument util

După cum v-ați seama deja, aș vrea să vă spun două vorbe despre Codepad.
Acesta este un compilator / interpretor online pe care îl puteți folosi pentru a vă testa programele. Aveți însă grijă la citirile de la tastatură, care nu vor fi efectuate - va trebui să inițializați de mână variabilele respective. În rest, este un instrument ușor de utilizat și util, zic eu. Suportă mai multe limbaje de programare și oferă programului vostru rulat un link pe care îl puteți partaja cu prietenii.
Codepad poate fi găsit aici.

Introducere C - probleme rezolvate (2)

Salutare,
astazi continuam seria problemelor rezolvate.

1. De la tastatură se introduce un număr real ce reprezintă măsura unui unghi în radiani. Să se scrie un program pentru conversia acestuia în grade, minute şi secunde sexagesimale.

#include <stdio.h>

// asa ne definim noi o constanta
#define PI 3.14159265

int main(){
   // definire variabile
   float radiani, gf, mf;
   int grade, minute, secunde;

   printf(“Introduceti numarul de radiani: “);
   scanf("%f", &radiani);

   /** aici avem valoare introdusa de la tastatura
   * mai trebuie sa facem calculele necesare conversiei
   * primele doua initializari sunt interesante intrucat, mai intai, calculam
   * valoarea reala (cu virgula) a expresiei, iar apoi obtinem si partea intreaga a rezultatului
   * in variabila de tip int
   */
   grade = gf = radiani * 180 / PI;
   minute = mf = (gf - g) * 60;
   secunde = (mf - m) * 60;

   printf("%f radiani inseamna %d grade %d minute %d secunde.\n", radiani, grade, minute, secunde);

   return 0;
}

2. Să se calculeze abaterea media patratică a unor valori rezultate în urma unui experiment. Formula de calcul poate fi găsită aici, la finalul primei secțiuni. Pentru usurință, aceasta poate fi puțin prelucrată făcând reducerile necesare și dând factor comun.

#include <stdio.h>
#include <math.h>

int main(){
   int n,i;
   double a, suma1 = 0, suma2 = 0, amp;
  
   printf("Introduceti numarul valorilor: ");
   scanf("%d",&n);

   for (i=0;i<n;i++) {
      printf("Introduceti valoarea %d: ",i+1);
      scanf("%lf",&a);
      suma1+=a*a;
      suma2+=a;
    }

    amp=sqrt((n * suma1 - suma2 * suma2) / (n * (n - 1)));
    printf("Abaterea medie patratica este %lf.\n",amp);
    return 0;
}

Pana data viitoare, eu va doresc numai bine.

19 Aug 2012

Adaptor USB bluetooth nu a fost detectat de Nokia PC Suite

ES-388

Adaptorul USB bluetooth cu seria ES-388 care foloseste driverul IVT BlueSoleil, prezinta o problema, nu este detectat de nokia pc suite si nici de ovi nokia. Aceata problema a fost prezentata de foarte multi utilizatori.
Motivul acestei probleme este dat de faptul ca de la versiunea 7.0 a programului nokia pc suite, stiva de drivere suportate de program nu suporta versiuni mai joase de 6.0 ale IVT BlueSoleil.
Modul cel mai simplu de rezolvare a acestei probleme este prin utilizarea unei versiuni mai vechi a programului nokia pc suite. Versiunea ce functioneaza destul de bine fiind  6.x.x.x. Sau achizionarea unei versiuni mai recente a softului dongle. 

Modul in care se poate verifica daca problema este de la driver este urmatoarea:
1.Deschidere nokia pc suite / ovi nokia 


2. Click HELP->About nokia pc suite...

3. Click pe Show system information dialog ( i ).

4. Daca driverul este recunoscut de program acesta ar trebui sa apara in lista din fereastra nou aparuta, exact ca in imaginea de mai jos. Daca nu apare atunci driverul nu a fost detectat de program si fie se updateatza driverul, fie se downgradeaza versiunea softului de transfer de date(acest acest nokia pc suite).