Saturday, November 14, 2015

Limbajul C. Alte doua probleme simple. Conversie la binar si permutari. Simularea citirii numerelor intregi

La un moment dat, oricine codeaza se va lovi de problema permutarilor, fie ele circulare sau nu. Codul de mai jos rezolva doua chestiuni: conversia la binar a unui numar pe pozitiv pe 8 biti si permutarea circulara, de un numar de ori, a celor 8 biti.

Enuntul problemei figureaza in lista exercitiilor de la jumatatea materiei de C procedural predata in cursul de la University College Cork. Rezolvarea propusa este oarecum inaintea materiei, pentru ca foloseste vectori. Desi este posibila rezolvarea fara a apela la vectori (tablouri), a fost aleasa varianta cu tablouri, intre altele si pentru ca in practica o variabila modificata este, in general, stocata pana la finalul executiei codului.


// Scrierea binara a unui nr. de 8 biti fara semn, adica
// un intreg intre 0 si 255 inclusiv.
// Permutarea circulara a unui astfel de numar

#include <stdio.h>

// Cea mai simpla rezolvare implica tablouri si pointeri

void PermCircLeft(int *p, int n)
{
     int i, temp = p[n - 1];
     for(i = n - 1; i >= 1; i--) p[i] = p[i - 1];
     p[0] = temp;
}

void AfisezVector(int *p, int n)
{
     int i;
     for(i = n - 1; i >= 0; i--) printf("%d", p[i]);
     printf("\n");
}
   

int main()
{
    int b[8], i, c;
    unsigned n, circle;
    puts("\nEnter an integer value between 0 and 255:");
    scanf("%u", &n);
    _flushall();
    if(n >= 256 || n < 0)
    {
         printf("\nErroneus input!");
         return 1;
    }
    c = n;
    for(i = 0; i < 8; i++)
    {
       b[i] = c%2;
       c /= 2;
    }
    AfisezVector(b, 8);
    puts("\nHow many circular left shifts do you want?");
    scanf("%u", &circle);
    for(i = 1; i <= circle;)
    {
          PermCircLeft(b, 8);
          i++;
    }
    AfisezVector(b, 8);
    return 0;
}

Screenul executiei:



Urmatoarea problema nu prezinta o utilitate practica evidenta imediat dar este interesanta din punct de vedere al implementarii ramurilor de decizie if/else si din punct de vedere al conversiilor char 2 int si viceversa. Enuntul cere citirea unui intreg de la tastatura fara a apela functia scanf().

Emularea functiei corespunzatoare apeleaza in schimb functia getchar(), pe baza observatiei ca a citi digitii unui numar scris in baza 10 poate insemna si citirea simbolurilor (caracterelor) corespunzatoare cifrelor arabe si conversia codurilor ASCII astfel incat input-ul si output-ul sa coincida.

Rezolvarea propusa are, totusi, limite pentru ca rezultatele obtinute de apelul functiei getchar() in bucla while nu se stocheaza, ci doar se afiseaza imediat. Un test de eroare care impiedica introducerea unei secvente de tip -01 (zero dupa semn) sau -+12 (semn dupa semn) este prevazut in cod. Totusi, utilizatorul poate introduce o succesiune eronata precum 11-3 fara sa fie penalizat. De asemenea, poate incepe numarul cu cifra 0 fara sa primeasca mesaj de eroare.

Problema figureaza, de asemenea, in lista exercitiilor din cursul C predat la Colegiul universitar Cork din Irlanda.

//Reading a number without using scanf()

#include <stdio.h>

// Functia int getchar() intoarce codul ASCII al caracterului citit si EOF in caz de eroare
// Intrucat tipul returnat este un intreg pozitiv nenul (caracterele printabile incep cu space, cod ASCII 32)
// sau EOF (care este negativ!) rezultatul returnat poate fi folosit pentru validare intr-o bucla

int main()
{
puts("\nEnter a positive or negative number and hit CR!");
char c = '\0';
char d = '\0';
while ((c = getchar()) != EOF)
{
          if(c == 10) break; // daca c = LF opreste bucla
          // Sub Windows, secventa CR + LF echivaleaza CR sub Unix/Linux
          else if(c == 43 || c == 45) // daca un caracter citit este semn
          {
               d = getchar();
               if( d > 48 && d <= 57) printf("%c%d", c, d - 48);
               else return 2;
          }
          else if(c >= 48 && c <= 57) printf("%d", c - 48);
          else {
                printf("\nInput error!");
                return 1;
                }
    }  
return 0;
}

Screen-ul executiei:


No comments:

Post a Comment