Skip to content

Instantly share code, notes, and snippets.

@becheru
Last active March 1, 2018 08:35
Show Gist options
  • Save becheru/6dee29605c8347196b685f8404435a78 to your computer and use it in GitHub Desktop.
Save becheru/6dee29605c8347196b685f8404435a78 to your computer and use it in GitHub Desktop.
Acest document se doreste a fii un indreptar al stilului de scriere a programelor in limbajul C

Indreptar de scriere a programelor in limbajul C

Reguli generale

Cu exceptii rare, nici o linie de cod nu trebuie sa fie mai lunga de 80 de caractere, numarad atat spatiile si tab-urile. Astfel, se evita scrierea unor linii de cod alambicate si ne asiguram ca un potential cititor nu este nevoit sa faca scroll orizontal.

Pentru identarea la dreapta se va folosii tab-ul, indiferent de sistemul de operare.

Dupa caracterul de sfirsit de linie ;, nu se va mai scrie nimic, nici macar comentarii.

Ne vom folosii de acolade {} ori de cate ori putem, spre a delimita clar blocurile de cod logice.

Variabile

Conform regulilor limbajului C numele variabilelor se scriu cu caractere alfa numerice [a-z][A-Z][0-9] si/sau cu underscore _. Denumirea unei variabile nu poate incepe cu caractere numerice.

Urmatoarele denumiri de variabile sunt corect scrise:

a
_A
_9v
_greutate_in_10_masini

Urmatoarele denumiri de variabile sunt incorect scrise:

9b
%a
$_V
5pisici

Ca regula de stil, se va utiliza underscore _ pentru despartirea in cuvinte a variabilelor, e.g.: greutatea_rotilor_de_tren, inaltime_om_cm. Altfel, se va evita folosirea underscore. Exemplu de utilizare gresita _greutate, numar_ul_de_mere. A se evita folosirea unor variabile cu denumiri lungi si foarte lungi, mai mult de 4/8 cuvinte. Cu toate acestea, in proiectele foarte mari sau in cazul in care este necesara o mai buna dizambiguizare a variabilelor, este permisa utilizarea unor denumiri lungi.

Exemplu de utilizare a unor variabile lungi in mod corect:

doctor_qualification_name_simplified_chinese
doctor_qualification_name_old_chinese
doctor_qualification_name_english

In exemplul de mai sus, este necesara folosirea unor denumiri lungi pentru a dizambiguiza variabilele. Insa, mai jos aveti un exemplu de denumiri de variabile incorecte, lungite fara sens:

the_length_of_the_car_in_cm
\\ putem redenumii variabila car_legth_cm
average_distance_from_the_sun_outer_shell_to_earth_atmosphere
\\ variabila de mai sus poate redenumita astronomical_unit

Ca regula de stil, se va evita utilizarea prepozitiilor in numele variabilelor. Acesta nu aduc nici un aport semnificativ in dezambiguizarea numelor, ba chiar obliga programatorul sa scrie mai mult.


Ca regula de stil, se vor utiliza cifrele/numerele in denumirile variabilelor doar in cazurile rare cand denumirile obiectelor/persoanelor/institutiilor reprezentate prin variabile le contin.

Exemple de utilizari corecte a cifrelor/numerelor in variabile:

nume_real_2pac \\ variabila ce va retine numele cantaretului 2pac
web_address_cloud9 \\ variabile ce va retine adresa web a site-ului cloud9

Exemple de utilizari incorecte a cifrelor/numerelor in variabile:

al_9_om
6_cai_frumosi
x2
var4

Ca regula de stil, limba de scriere a numelor variabilelor este limba Engleza, astfel codul dumnevoastra devine inteligibil pentru un segment semnificativ de programatori (la nivel global).


In cazul variabilelor ce reprezinta ce reprezinta unitati masurabile in sistemul international, se va adauga la denumirea acestora (la sfirsit) simbolul unitatii de masura folosit. A se vedea exemplele de mai jos:

height_in \\ variabila ce exprima inaltimea unui obiect in inch
weight_kg \\ variabila ce exprima greutate unui obiect in kilograme
volume_m3 \\ variabila ce exprima volumul unui obiect in metri cubi

Ca regula de stil, utilizarea de cuvinte prescurtate este permisa doar in cazul prescurtarilor universal cunoscute, e.g.: nr, kg, aux, max, avg. A nu se utiliza prescurtari de circulatie restranta sau gresite, e.g.:

nanog \\ pentru nanograme
it \\ pentru iterator
wa \\ pentru web address

Ca regula generala, denumirea variabilelor trebuie sa fie dezambiguitoare si nu viceversa. Un nume de variabila trebuie sa ofere informatii despre obiect/persoana/institutia ce este reprezentata de aceasta precum si asupra caracteristiciilor ce sunt referite de catre variabila in cauza.

Exemplu de nume de variabile corecte:

bar_length_m
car_color_rgb
doctor_name
palace_street_name

Exemplu de nume de variabile incorecte, datorita ambiguitatii numelor:

length \\ lungimea cui?
x \\ nu este clar ce reprezinta aceasta variabila
vector \\ vector continand ce tip informatie ?
nr \\ numara ceva, dar ce?

Ca regula de stil, denumirea variabilelor trebuie sa urmareasca schema obiect_atribut. Unde obiect poate fii un obiect, fiinta, institutie iar atribut este o caracterstica a obiectului. Exemple de folosire corecta a schemei:

person_age
boat_max_speed
police_department_location

Urmatoarele exemple arata folosirea incorecta a schemei de denumire a variabilelor:

age_of_person
max_speed_boat
location_department_police

Ca regula de stil pentru variabilele statice, cele a caror valoarea nu mai poate fii modificata dupa atribuirea initiala, numele acestora va fii scris doar cu litere mari. De altfel, este si singurul caz in care este permisa utilizarea litelor mari (capslock).

Exemplu de utilizare corecta a variabilelor cu litere mari:

const float PI = 3.14;
float circle_radius = 2.3;
float circle_area;
circle_area = PI * pow(circle_radius,2);

Ca regula de stil pentru variabilele globale, cele definie in afara oricarei functii, se va adauga la inceputul numelui variabilei sintagma g_, e.g.: g_program_name, G_PI.

Ca si regula de stil fiecare variabila va fii declarata pe cate un rand, astfel variabilele vor fii usor de indetificat iar atribuirea ulterioara a unei valori initiale se va face cu usurinta.

Exemplu de declarare corecta a variabilelor:

int car_manufacturing_year = 2007;
int car_color;
int car_registration_code = 1001;
float car_price_eur = 10512.24;

Exemplu de declarare incorecta a variabilelor:

int car_manufacturing_year = 2007, car_color, car_registration_code = 1001;
float car_price_eur = 10512.24;

Variabila car_color este mai usor de indetificat in primul exemplu, chiar si pentru acest exemplu cu 4 variabile, imaginati-va insa cazul (extrem de probabil) in care sunt peste 20 de variabile de tip int.

Ca si regula de stil este de augur gruparea declararilor de variabile dupa tip, obiect, sau ambele. Pentru ca gruparile sa fie usor observabile se vor introduce randuri libere intre grupari.

Exemplu de grupare a variabilelor dupa tipul acestora:

bool car_in_use = TRUE;
bool aux = FALSE;

char car_manufacturer_first_letter = 'M';
char driver_name_initial = 'Z';

int car_registration_code;
int driver_age = 23;

float car_price_eur;
float driver_salary_eur = 5000.99;

double car_full_stop_time_at_60_Mph;

Exemplu de grupare a variabilelor dupa obiecte:

bool aux = FALSE;

char driver_name_initial = 'Z';
int driver_age = 23;
float driver_salary_eur = 5000.99;

bool car_in_use = TRUE;
char car_manufacturer_first_letter = 'M';
float car_price_eur;
double car_full_stop_time_at_60_Mph;

Este indicata folosirea plurarului in denumirea unei variabile atunci cand aceasta se refera la tablouri (vector, matrice) sau liste (simplu sau multiplu inlatuite).

Exemplu de folosire corecta a plurarului in denumirea variabilelor.

int ages = {1,2,3} 
float salaries = {100.23, 505.60}
bool coolness_of_students = {{TRUE, FALSE}, {FALSE, FALSE}}

Exemplu de folosire incorecta a plurarului in denumirea variabilelor.

int ages = 3 
float salaries = 100.23
bool coolness_of_students = TRUE

In cazul pointerilor steluta specifica acestuia si specificatorul de adresa & va fii scrisa alipita de numele pointerului *nume_pointer. Altfel, specificatorul * poate fii usor confundat cu operatia de inmultire.

Exemplu de folosire corecta a pointerilor.

int *pointer
float *salaries = &pointer;
bool *is_rich = malloc( 10 * sizeof(bool) )

Exemplu de folosire incorecta a pointerilor.

int * pointer
float* salaries = &pointer;
bool * is_rich = malloc( 10 * sizeof(bool) )

Operatori

Operatori unari

Un operator unar, e.g., ++, --; va fii atasat variabilei/expresiei asupra caruia opereaza.

Exemplu de spatiere corecta a operatorilor unari:

a++ 
a--
++a
!a

Exemplu de spatiere incorecta a operatorilor unari:

a+ + 
a  --
+ + a
! a

Operatori binari

Un operator binar, e.g., +, -; va fii intotdeanuna precedat si urmat de un spatiu. Astfel, acesti operatori vor fii mai usor de observat.

Exemplu de spatiere corecta a operatorilor binari:

a + b
a / b
a - b
a += 2
a ^ b
a >> 2

Exemplu de spatiere incorecta a operatorilor binari:

a +b
a/b
a -   b
a +=2
a^ b 
a > > 2

Operatori ternari

Pentru operatorul ternar, se vor adaugate cate un spatiu inainte si dupa fiecare simbol constituent.

Exemplu de spatiere corecta a operatorilor ternari:

( a > b ) ? a++ : b--;

Exemplu de spatiere corecta a operatorilor ternari:

( a > b ) ? a++ :b--;
( a > b )?a++: b--;
(a>b)?a++:b--;

Expresii

TBD

Instructiuni

If Else

Structura generala a instructiunii:

if ( conditie ){
    .....   
    .... 
}else if ( conditie2 ){  
    ....
    ....
}else{
    ....
    ....
}

Exemplu de stilizare corecta a instructiunii if else:

if ( car_age < car_max_allowed_age ){
    printf("You can still drive your car.\n");   
    aux = car_max_allowed_age - car_age;
    printf("You car should be good for the next %d years.\n", aux); 
}else if ( car_age == car_max_allowed_age ){  
    printf("You can still drive your car till the end of the current year.\n");
    printf("Consider buyng another car\n"); 
}else{
    printf("You can not drive your car anymore.\n");

}

Switch Case

Structura generala a instructiunii:

switch ( expresie ){
    case value: 
        ....
        ....
    case value_1: 
        ....
        ....
    case value_n: 
        ....
        ....
    default: 
        ....
        ....
}

Exemplu de stilizare corecta a instructiunii switch case:

switch ( car_age ){
    case 0: 
        printf("You've got a new car.\n"); 
        break;
    case 1: 
        printf("Please change the oil.\n");
        break;
    case 2: 
        printf("A revision is mandatory.\n");
        break;
    case 3: 
        printf("Please change the battery.\n");
        break;
    default: 
        printf("You can not drive your car anymore.\n");
}

While

Structura generala a instructiunii:

while ( conditie ){
    ....
    ....
}

Exemplu de stilizare corecta a instructiunii while:

while ( car_age < car_max_allowed_age  ){
    printf("You can still drive your car.\n");
    aux = car_max_allowed_age - car_age;
    printf("You car should be good for the next %d years.\n", aux);
}

Do While

Structura generala a instructiunii:

do{
    ....
    ....
}while ( conditie );

Exemplu de stilizare corecta a instructiunii do while:

do{
    printf("You can still drive your car.\n");
    aux = car_max_allowed_age - car_age;
    printf("You car should be good for the next %d years.\n", aux);
}while ( car_age < car_max_allowed_age );

For

Structura generala a instructiunii:

for ( initializare; conditie; incrementare ){
    ....
    ....
}

Exemplu de stilizare corecta a instructiunii for:

for ( car_age = 0; car_age < car_max_allowed_age; car_age++ ){
    printf("You can still drive your car.\n");
    aux = car_max_allowed_age - car_age;
    printf("You car should be good for the next %d years.\n", aux);
}

Functii

Schema generala a unei functii este:

tip_date_returnat nume( date_de_intrare ){
    ....
    ....
    return var; //in cazul in care functia returneaza o valoare
}

Primul rand tip_date_returnat nume( date_de_intrare ){ se numeste antetul functiei iar restul fac randurilor fac parte din corpul functiei.

Antetul

Denumirea unei functii

Numele unei functii trebui sa respecte schema [actiune]_[obiectul-actiunii]_[obiect-asupra-caruia-se-rasfrange-actiunea]. Schema poate fii exprimata si sub forma verb_obiect.

Exemplu de denumire corecta a unor functii

sum_two_integers
add_money_bank
print_car_name
print_matrix
print_1st_diagonal_matrix
max_age_dogs
avg_height_humans

Exemplu de denumire incorecta a unor functii

sum // suma a ce? 
add_money // unde se adauga valoarea monetara
printcarname // greu de citit
matrix_print // verbul trebuie sa fie primul
print_diagonal_matrix // care diagonala?
max // maximul a ce?
avg_height // inaltime medie a cui?

Spatierea antetului

Nu se vor adauga spatii intre denumirea functie si secventa de declarare a datelor de intrare nume_functie(, precum nu se va adauga nici intre secventa de declarare si acolada de deschide a functiei ){.

Posterior parantezei unde sunt precizate datele de intrare ( si anterior parantezei ce inchide declararea datelor de intrare ) se vor adauga spatii.

Exemplu de spatiere corecta a antetului:

void max_salary_ceo(){
int avg_distance( int dinstance_1, int distance_2 ){
float compute_salary( float base_salary, float salary_bonus ){

Exemplu de spatiere incorecta a antetului:

void max_salary_ceo () {
int avg_distance(int dinstance_1,int distance_2){
float compute_salary(float base_salary, float salary_bonus){

Corpul unei functii

Liniile de cod ce compun corpul unei functii pot fii grupate in blocuri logice cu ajutorul unor linii lasate libere. Ca regula de stil, o linie libera va fii lasata dupa declararea variabilelor locale si inaintea instructiunii return (in cazul in care aceasta este necesara).

Schema generala a unui corp de functie este:

bloc declarare variabile
bloc declarare variabile
bloc declarare variabile

bloc intructiuni 1
bloc intructiuni 1
bloc intructiuni 1

bloc intructiuni n
bloc intructiuni n
bloc intructiuni n

return

Exemplu de functie al carui corp este stilizat corect:

float compute_salary( float income ){
    float country_tax_percentage = 17.5;
    float city_tax_percentage = 18.0;
    float total_tax_percentage;
    float salary;
    
    total_tax_percentage = city_tax_percentage + country_tax_percentage; 
    salary = ( ( 100 - total_tax_percentage) / 100 ) * income;

    return salary;
}

Exemplu de functie al carui corp este stilizat incorect:

float compute_salary( float income ){
    float country_tax_percentage = 17.5;
    float city_tax_percentage = 18.0;
    float total_tax_percentage;
    float salary;
    total_tax_percentage = city_tax_percentage + country_tax_percentage; 
    salary = (100 - total_tax_percentage) * income;
    return salary;
}

Comentarii aduse functiilor

Conform unui principiu enutat adesea de catre Linus Torvalds, codul scris si stilizat corect nu are nevoie de comentarii. Insa, apar cazuri cand comentariile sunt imperios necesare, mai ales pentru a descrie pe scurt actiuniile unei functii. Aceste comentarii se vor scrie pe prima linie dupa antetul functiilor si sunt urmate de o linie libera, e.g.:

float compute_salary( float income ){
    //compute and return salary from income by deducting taxes
    
    float country_tax_percentage = 17.5;
    float city_tax_percentage = 18.0;
    float total_tax_percentage;
    float salary;
    
    total_tax_percentage = city_tax_percentage + country_tax_percentage; 
    salary = (100 - total_tax_percentage) * income;

    return salary;
}

Apelul functiilor

Desi functiile pot fi apelate in cadrul altor functii, acesta facilitate trebuie utlizata cu precautie din 2 motive practice:

  • liniile de cod tind sa devina foarte lungi si greu de inteles
  • o eroare generata pe o linie de cod cu foarte multe apeluri este exponential mai greu de identificat si reparat.

Acesta este un exemplu de stilizare incorecta a apelurilor de functii.

salary = get_income_from_db() * ( 100 - ( get_country_tax_percentage() + get_city_tax_percentage ) ) )

Exemplul de mai sus poate fii stilizat corect astfel:

income = get_income_from_db();
country_tax = get_country_tax_percentage();
city_tax = get_get_city_tax_percentage();
total_tax = country_tax + get_city_tax;
salary = income * ( ( 100 - total_tax_percentage ) / 100 ) );

Structura unui program

Structura generala a unui program poate fii exprimata astfel:

//instructiuni de preprocesare
#include
#include
#define
#define


//variabile globale
bool 
int 
float
double


//functii
f1


f2


f3


//functia main
int main(){

    return 0;
}

Ca regula de stil, intre functii se vor introduce doua linii goale. Astfel, separarea intre functii va fii clara.

Exemplu de program c stilizat corect:

#include <stdio.h>
#define G_MATRIX_MAX_ROW 3;

int const G_MATRIX_MAX_COL = 3;
int g_matrix[G_MATRIX_MAX_ROW][G_MATRIX_MAX_COL] = {
        {1,2,3},
        {4,5,6},
        {7,8,9}
};
int *g_pointer_to_matrix = &g_matrix;


void print_matrix_addreses(){
    int iter_row;
    int iter_col;

    for( iter_row = 0; iter_row < G_MATRIX_MAX_ROW; iter_row++ ){
        for( iter_col = 0; iter_col < G_MATRIX_MAX_COL; iter_col++ ){
            printf( "%x ", &g_matrix[iter_row][iter_col] );
        }
        printf("\n");
    }
}


int get_matrix_value(int line, int col){
    //return the value in the matrix at line line and column col
    
    int shift;
    int *address;
    
    shift = line * G_MATRIX_MAX_ROW + col;
    address = g_pointer_to_matrix + shift;

    return *address;
}


int main(){
    print_matrix_addreses();
    printf(" %d ", get_matrix_value(1,1));
    
    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment