Convenții de cod - C: Diferență între versiuni

De la WikiLabs
(Reguli suplimentare)
 
(Nu s-au afișat 39 de versiuni intermediare efectuate de același utilizator)
Linia 1: Linia 1:
During the DSA lab and while solving homework, you will also get points for the way the source code is paged, tabbed, the naming of the functions and variables, and the general structure of the program. The conventions that need to be followed are:
+
Acest document descrie regulile ce trebuie respectate la scrierea de programe în C, pentru materia Programarea Calculatoarelor. Nerespectarea acestor reguli poate duce la depunctarea implementării respective.
* the segments of the file should appear in the following order:
 
** header comment, describing the role of the file, author and the project it is part of;
 
** import directives;
 
** define directives;
 
** data types (new structures or typedefs);
 
** global variables (these you should avoid in most cases);
 
** function prototypes;
 
** function implementations; each implementation should have a short comment explaining the function role, the arguments and the return type;
 
** footer comment, describing the changes in the file (this may be missing if the file is not under version control - svn, git, perforce, etc.);
 
* all segments of the file are split by a comment-line which appears also between functions;
 
* the main function, if it exists, is placed first;
 
* for if / do-while / for / case constructs and for method bodies, the open curly bracket is placed on the same line with the construct / function declaration and the closed curly bracket is placed on a separate line, on the same column with first letter from the construct/ declaration;
 
* an instruction block is indented by one extra tab in respect to the previous level;
 
* new data type names (as well as structures) start with an uppercase letter;
 
* function and variable names start with a lowercase letter;
 
* global variables start with a lowercase "g": (int g_my_global_var; or int gMyGlobalVar;)
 
* constant names are written in caps, words separated by the "_" character;
 
* the naming must be as explicit as possible regarding their purpose, in order to avoid excessive comments;
 
* it is allowed to insert a blank line, if a natural segregation of elements is obtained through it.  
 
  
Notes:
+
= Identificatori =
* your code editor should be configured so that instead of a TAB character, it should insert 4 spaces;
 
* both camel case and underscore-separated words are accepted, as long as the notation is consistent throughout the program; so pick one and stick with it;
 
* always use brackets for "if" and "for" statements, even if there is only one statement in a block; the exception is for "if" when it has only one short statement in its block in which case both the if and the statement are placed on one line: if(a > b) return a;
 
  
 +
Numele de variabile urmează convenția [https://en.wikipedia.org/wiki/CamelCase CamelCase], cu excepția numelor de macrouri și constante statice care vor urma convenția [https://en.wikipedia.org/wiki/Snake_case snake_case] și care vor fi scrise exclusiv cu litere mari.
  
== Example ==
+
În același timp toți identificatorii trebuie sa aibă nume sugestive, care să descrie fără ambiguitate scopul variabilei sau funcției. Excepție o fac variabilele contor pentru bucle cu nume consacrate: <code>i</code>, <code>j</code>, <code>k</code> și variabile ce memorează coordonate într-un plan: <code>x</code>, <code>y</code>, <code>z</code>.
 +
 
 +
== Nume de variabile ==
 +
 
 +
=== Numele de variabile locale sau argumente ===
 +
 
 +
Numele de variabile locale sau argumente de funcții vor incepe cu literă mică și vor urma convenția [https://en.wikipedia.org/wiki/CamelCase CamelCase]:
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
/*******************************************************************
+
void printMyName(char name[]) {
*          Coding Conventions Style Example
+
    int variableName;
*         
+
    float floatValue;
* Author: Radu Hobincu
+
    //...
* Date: 09.03.2014
+
}
* Description: This file contains functions and variables used
+
</syntaxhighlight>
*        to exemplify the use of coding styles and how the
 
*        readability of a program improves when it is well
 
*        written.
 
******************************************************************/
 
  
#include<stdio.h>
+
=== Numele de variabile globale ===
#include<stdlib.h>
 
  
#define MAX_INT 0x7FFFFFFF
+
Numele de variabile globale trebuie să înceapă cu litera 'g' și următoarea literă mare și vor urma convenția [https://en.wikipedia.org/wiki/CamelCase CamelCase]. Litera 'g' specifică faptul că variabila este globală și nu este definită în contextul unei funcții:
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
 
  
/******************************************************************/
+
<syntaxhighlight lang="C">
typedef unsigned short Age;
+
long long gCurrentTime;
typedef char* String;
 
  
struct Person{
+
void updateCurrentTime(long interval) {
     String first_name;
+
     gCurrentTime += interval;
     String last_name;
+
}
     Age age;
+
</syntaxhighlight>
     String address;
+
 
     int weight;
+
=== Numele de macrouri, constante statice sau elemente din <code>enum</code> ===
 +
 
 +
Numele de macrouri, constante statice sau elemente din <code>enum</code>, vor urma convenția [https://en.wikipedia.org/wiki/Snake_case snake_case] și vor fi scrise exclusiv cu litere mari:
 +
 
 +
<syntaxhighlight lang="C">
 +
#define MAX_STRING_LENGTH 100
 +
#define MAX(x, y) ((x) >= (y) ? (x) : (y))
 +
 
 +
static const MAX_CLIENTS = 1000;
 +
 
 +
enum Colors {
 +
     BLACK = 0,
 +
     BLUE,
 +
     RED,
 +
     WHITE
 
};
 
};
 +
</syntaxhighlight>
  
/******************************************************************/
+
== Numele de funcții ==
struct Person *g_myself;
 
struct Person *g_yo_momma;
 
  
/******************************************************************/
+
Numele de funcții vor urma convenția [https://en.wikipedia.org/wiki/CamelCase CamelCase] și vor începe cu literă mică:
struct Person *create_person(String first_name, String last_name,
+
<syntaxhighlight lang="C">
        Age age, String address, int weight);
+
int addValues(int, int);
struct Person *find_yo_momma(struct Person **persons,
+
float convertValue(float);
        unsigned person_count);
+
void printData(struct Person person);
void delete_person(struct Person *person);
+
</syntaxhighlight>
  
/******************************************************************
+
== Numele de structuri, enumerări sau union ==
* The main function of the program.
 
* @return the error code; 0 is execution is successful.
 
*/
 
int main(){
 
    g_myself = create_person("Radu", "Hobincu", 30, "Classified",
 
        65);
 
  
    struct Person *persons[100];
+
Numele de structuri, enumerări sau union vor urma convenția [https://en.wikipedia.org/wiki/CamelCase CamelCase] și vor începe cu literă mare:
     int i;
+
<syntaxhighlight lang="C">
     for(i=0; i<100; i++){
+
struct Person {
        persons[i] = create_person("Some First Name", "Some Last Name",  
+
    char name[50];
            i, "", rand());
+
     unsigned short age;
     }
+
     char cnp[14];
 +
};
 +
 
 +
struct DataStore {
 +
    struct Person people[];
 +
    long long rsaKey;
 +
};
 +
 
 +
enum Color {
 +
    BLACK = 0,
 +
    BLUE,
 +
     WHITE
 +
};
  
     g_yo_momma = find_yo_momma(persons, 100);
+
union IntAndByte {
     if(g_yo_momma != NULL){
+
     int intValue;
        printf("Here's yo momma! It's a global variable because there's "
+
     char chars[4];
            "not enough room on the stack!\n");
+
};
    }
+
</syntaxhighlight>
  
    for(i=0; i<100; i++){
+
= Spații =
        delete_person(persons[i]);
 
    }
 
  
    delete_person(g_myself);
+
<ol>
     return 0;
+
<li>Se pun spații înainte și după operatorii binari (=, ==, !=, <, etc.):
 +
<syntaxhighlight lang="C">
 +
int result = operand1 + operand2 / operand3;
 +
</syntaxhighlight>
 +
</li>
 +
<li>'''NU''' se pun spații înainte operatorii unari (!, -, ++, --, etc.) și operand:
 +
<syntaxhighlight lang="C">
 +
int result = operand1++ + -operand2;
 +
int canUse = !isEmpty && !isFull;
 +
</syntaxhighlight>
 +
</li>
 +
<li>În cazul blocurilor <code>for</code>, <code>while</code> și <code>if</code> se pun spații înainte de parenteza deschisă și după cea închisă:
 +
<syntaxhighlight lang="C">
 +
while (true) {
 +
     //...
 
}
 
}
  
/******************************************************************
+
for (i = 0; i < n; i++) {
* Allocates memory for a person and initializes each structure member.
+
     //...
* @param first_name the first name of the person
+
}
* @param last_name the last name of the person
 
* @param age the age of the person
 
* @param address the address of the person
 
* @param weight the weight of the person (if MAX_INT, then this is yo` momma!)
 
* @return a pointer to the newly allocated and initialized person.
 
*/
 
struct Person *create_person(String first_name, String last_name,
 
        Age age, String address, int weight){
 
    struct Person *person = (struct Person*)malloc(sizeof(struct Person));
 
    person->first_name = first_name;
 
     person->last_name = last_name;
 
    person->age = age;
 
    person->address = address;
 
    person->weight = weight;
 
  
     return person;
+
if (a == b) {
 +
    //...
 +
}
 +
</syntaxhighlight>
 +
</li>
 +
<li>În cazul funcțiilor, '''NU''' se lasă spațiu între numele funcției și paranteza deschisă, dar se lasă un spațiu după cea închisă:
 +
<syntaxhighlight lang="C">
 +
int computeValue(int operand1, float operand2) {
 +
     return (int)(operand1 / operand2);
 +
}
 +
</syntaxhighlight>
 +
</li>
 +
<li>Se lasă un spațiu după separatoare (punct-și-virgulă sau virgulă):
 +
<syntaxhighlight lang="C">
 +
for (i = 0; i < n; i++, j++) {
 +
    //...
 
}
 
}
 +
</syntaxhighlight>
 +
</li>
 +
</ol>
 +
 +
= Indentare =
 +
Indentarea se realizează cu spații, nu cu caractere <code>tab</code>, iar o indentare are dimensiunea de 4 spații. Regulile de indentare sunt cele specificate în convenția [https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS 1TBS (One True Brace Style)] cu observația că acolada de la începutul unei funcții este plasată pe aceeași linie cu definiția funcției.
 +
 +
== Blocuri de instrucțiuni ==
  
/******************************************************************
+
Un bloc de instrucțiuni începe cu o acoladă deschisă care se plasează întotdeauna la sfârșitul unei liniei, iar acoloada închisă se plasează sub primul caracter de pe linia unde s-a deschis blocul de instrucțiuni. Toate instrucțiunile dintr-un bloc de instrucțiuni se aliniază cu o indentare mai mult decât cele din blocul imediat superior:
* Finds yo` momma in an array of persons.
+
<syntaxhighlight lang="C">
* @param persons the array of persons to look for yo` momma in
+
int computeSad(int vector1[], int vector2[], int vectorLength) {
* @param person_count the number of persons in the array (amazingly enough, yo`
 
*        momma still counts as one).
 
* @return a pointer to yo` momma or NULL if she couldn't be found.
 
*/
 
struct Person *find_yo_momma(struct Person **persons, unsigned person_count){
 
 
     int i;
 
     int i;
     for(i=0; i<person_count; i++){
+
    int sad = 0;
         if(persons[i]->weight == MAX_INT) return persons[i];
+
     for (i = 0; i < vectorLength; i++) {
 +
         int difference = vector1[i] - vector2[i];
 +
        if (difference < 0) {
 +
            difference = -difference;
 +
        }
 +
        sad += difference;
 +
    }
 +
    return sad;
 +
}
 +
</syntaxhighlight>
 +
 
 +
== Utilizarea blocurilor de instrucțiuni ==
 +
 
 +
Blocurile de instrucțiuni se vor folosi inclusiv pentru <code>for</code>, <code>if</code> și <code>while</code>, chiar dacă acestea au o singură instrucțiune:
 +
<syntaxhighlight lang="C">
 +
int vectorSum(int v[], int n) {
 +
    int sum = 0;
 +
    for (i = 0; i < n; i++) {
 +
        sum += v[i];
 
     }
 
     }
 +
    return sum;
 +
}
 +
</syntaxhighlight>
  
     return NULL;
+
Singura excepție o fac blocurile <code>if</code> care se pot scrie citeț pe o singură linie:
 +
<syntaxhighlight lang="C">
 +
int vectorSum(int v[], int n) {
 +
     if (n == 0) return 0;
 +
    int sum = 0;
 +
    for (i = 0; i < n; i++) {
 +
        sum += v[i];
 +
    }
 +
    return sum;
 
}
 
}
 +
</syntaxhighlight>
  
/******************************************************************
+
== Linii lungi ==
* Deletes a person and frees any allocated resource.
+
O linie care depășeșete 120 de caractere poate fi scrisă pe două sau mai multe linii, spărgând-o după oricare operator și indentând următoare secțiune din linie cu două indenturi (8 spații):
* @param person the person to delete (yo` momma might take a longer time...)
+
<syntaxhighlight lang="C">
*/
+
int computeSum(int value1, int value2, int value2, int value4, int value5, int value6, int value7,
void delete_person(struct Person *person){
+
        int value8, int value9, int value10, int value11, int value12, int value13, int value14,
     free(person);
+
        int value15) {
 +
      
 +
    return value1 + value2 +...;
 
}
 
}
 +
</syntaxhighlight>
 +
 +
== Reguli suplimentare ==
 +
 +
Variabilele se declară fiecare pe o linie diferită:
 +
<syntaxhighlight lang="C">
 +
float gMyFloatVAriable;
 +
float gSomeOtherFloatVar;
  
/******************************************************************
+
void someFunction() {
* HISTORY:
+
    int variableName;
*
+
    int someOtherVariable;
* - 9.03.2014 - added first revision of the file;
+
    int i;
* - 9.03.2014 - added yo` momma and the size of the file quadrupled
+
   
*/
+
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Versiunea curentă din 29 octombrie 2017 20:51

Acest document descrie regulile ce trebuie respectate la scrierea de programe în C, pentru materia Programarea Calculatoarelor. Nerespectarea acestor reguli poate duce la depunctarea implementării respective.

Identificatori

Numele de variabile urmează convenția CamelCase, cu excepția numelor de macrouri și constante statice care vor urma convenția snake_case și care vor fi scrise exclusiv cu litere mari.

În același timp toți identificatorii trebuie sa aibă nume sugestive, care să descrie fără ambiguitate scopul variabilei sau funcției. Excepție o fac variabilele contor pentru bucle cu nume consacrate: i, j, k și variabile ce memorează coordonate într-un plan: x, y, z.

Nume de variabile

Numele de variabile locale sau argumente

Numele de variabile locale sau argumente de funcții vor incepe cu literă mică și vor urma convenția CamelCase:

void printMyName(char name[]) {
    int variableName;
    float floatValue;
    //...
}

Numele de variabile globale

Numele de variabile globale trebuie să înceapă cu litera 'g' și următoarea literă mare și vor urma convenția CamelCase. Litera 'g' specifică faptul că variabila este globală și nu este definită în contextul unei funcții:

long long gCurrentTime;

void updateCurrentTime(long interval) {
    gCurrentTime += interval;
}

Numele de macrouri, constante statice sau elemente din enum

Numele de macrouri, constante statice sau elemente din enum, vor urma convenția snake_case și vor fi scrise exclusiv cu litere mari:

#define MAX_STRING_LENGTH 100
#define MAX(x, y) ((x) >= (y) ? (x) : (y))

static const MAX_CLIENTS = 1000;

enum Colors {
    BLACK = 0,
    BLUE,
    RED,
    WHITE
};

Numele de funcții

Numele de funcții vor urma convenția CamelCase și vor începe cu literă mică:

int addValues(int, int);
float convertValue(float);
void printData(struct Person person);

Numele de structuri, enumerări sau union

Numele de structuri, enumerări sau union vor urma convenția CamelCase și vor începe cu literă mare:

struct Person {
    char name[50];
    unsigned short age;
    char cnp[14];
};

struct DataStore {
    struct Person people[];
    long long rsaKey;
};

enum Color {
    BLACK = 0,
    BLUE,
    WHITE
};

union IntAndByte {
    int intValue;
    char chars[4];
};

Spații

  1. Se pun spații înainte și după operatorii binari (=, ==, !=, <, etc.):
    int result = operand1 + operand2 / operand3;
    
  2. NU se pun spații înainte operatorii unari (!, -, ++, --, etc.) și operand:
    int result = operand1++ + -operand2;
    int canUse = !isEmpty && !isFull;
    
  3. În cazul blocurilor for, while și if se pun spații înainte de parenteza deschisă și după cea închisă:
    while (true) {
        //...
    }
    
    for (i = 0; i < n; i++) {
        //...
    }
    
    if (a == b) {
        //...
    }
    
  4. În cazul funcțiilor, NU se lasă spațiu între numele funcției și paranteza deschisă, dar se lasă un spațiu după cea închisă:
    int computeValue(int operand1, float operand2) {
        return (int)(operand1 / operand2);
    }
    
  5. Se lasă un spațiu după separatoare (punct-și-virgulă sau virgulă):
    for (i = 0; i < n; i++, j++) {
        //...
    }
    

Indentare

Indentarea se realizează cu spații, nu cu caractere tab, iar o indentare are dimensiunea de 4 spații. Regulile de indentare sunt cele specificate în convenția 1TBS (One True Brace Style) cu observația că acolada de la începutul unei funcții este plasată pe aceeași linie cu definiția funcției.

Blocuri de instrucțiuni

Un bloc de instrucțiuni începe cu o acoladă deschisă care se plasează întotdeauna la sfârșitul unei liniei, iar acoloada închisă se plasează sub primul caracter de pe linia unde s-a deschis blocul de instrucțiuni. Toate instrucțiunile dintr-un bloc de instrucțiuni se aliniază cu o indentare mai mult decât cele din blocul imediat superior:

int computeSad(int vector1[], int vector2[], int vectorLength) {
    int i;
    int sad = 0;
    for (i = 0; i < vectorLength; i++) {
        int difference = vector1[i] - vector2[i];
        if (difference < 0) {
            difference = -difference;
        }
        sad += difference;
    }
    return sad;
}

Utilizarea blocurilor de instrucțiuni

Blocurile de instrucțiuni se vor folosi inclusiv pentru for, if și while, chiar dacă acestea au o singură instrucțiune:

int vectorSum(int v[], int n) {
    int sum = 0;
    for (i = 0; i < n; i++) {
        sum += v[i];
    }
    return sum;
}

Singura excepție o fac blocurile if care se pot scrie citeț pe o singură linie:

int vectorSum(int v[], int n) {
    if (n == 0) return 0;
    int sum = 0;
    for (i = 0; i < n; i++) {
        sum += v[i];
    }
    return sum;
}

Linii lungi

O linie care depășeșete 120 de caractere poate fi scrisă pe două sau mai multe linii, spărgând-o după oricare operator și indentând următoare secțiune din linie cu două indenturi (8 spații):

int computeSum(int value1, int value2, int value2, int value4, int value5, int value6, int value7,
        int value8, int value9, int value10, int value11, int value12, int value13, int value14,
        int value15) {
    
    return value1 + value2 +...;
}

Reguli suplimentare

Variabilele se declară fiecare pe o linie diferită:

float gMyFloatVAriable;
float gSomeOtherFloatVar;

void someFunction() {
    int variableName;
    int someOtherVariable;
    int i;
    
}