C Cheatsheet Basic type formatting Type Format int unsigned long unsigned long double char string pointer size_t %d %u %ld %lu %<length>.<decimal length>lf %c %s %p %zu Macros #define N 5 #define SUM(a,b) (a+b) #define PRODUIT(a,b) (a*b) Switch They only work with int values int main(){ int x=3; switch(x){ default : puts("+++++"); case 4 : puts("++++"); case 3 : puts("+++"); case 2 : puts("++"); case 1 : puts("+"); case 0: ; } return EXIT_SUCCESS; } Arrays Syntax int tab[5]; The number has to be a constant in order to follow G99 We can also know the length of an array with: 1 sizeof(tab)/sizeof(tab[0]) Fast initialisation: unsigned tab[5]={1,2,3,4,5}; Work A function can modify an array: unsigned f(unsigned x[]){ x[0]+=10; return x[0]; } int main () { unsigned a[1]={2}; unsigned b=f(a); printf("a[0] vaut %u et b vaut %u\n",a[0],b); //a[0] = 12 and b = 12 } Attention You have to specify the size of the sub-arrays: void affiche(int t[][2],size_t t1,size_t t2){ for(size_t i=0;i<t1;++i){ for(size_t j=0;j<t2;++j){ printf("%d ",t[i][j]); } printf("\n"); } } Structures Two “good” ways of defining them struct point{ int x; int y; }; typedef struct point point; and typedef int int } point struct point{ x; y; ; 2 Enums enum couleur {RED=10, BLUE=2, YELLOW, GREEN} ; Pointers Syntax Creation unsigned x = 5 ; unsigned *p = &x ; unsigned **p2=&p ; Example void swap (unsigned *p1,unsigned *p2){ unsigned tmp=*p1; *p1=*p2; *p2=tmp; } int main(){ unsigned x=5; unsigned y=10; swap(&x,&y); printf("x = %u \n",x); // x = 10 printf("y = %u \n",y); // y = 5 } Passing arguments Syntax: int main(int argc, char *argv[]){ //... } Void pointers They can point to any type of data void *p; In order to use them, we have to cast them: int x=5; void *p=&x; printf("%d\n",*(int*)p); // 5 3 another example: typedef struct { int x, y; } pair; void print(pair *p) { printf("x=%d, y=%d\n", p->x, p->y); } int main() { int a = 69; void *pt = &a; printf("a = %d\n", a); *(int *)pt = 42; printf("a = %d\n", a); *(int *)pt = *((int *)pt) * *(int *)pt; printf("a = %d\n", a); } pair b = {1, 1}; pt = &b; print(&b); ((pair *)pt)->y++; print(&b); File manipulation Functions Flux manipulation • FILE *fopen(const char * restrict path, const char * restrict mode), opens a file • int fclose(FILE *stream). closes a file Reading • int fgetc(FILE *stream), reads a character • char *fgets(char * restrict str, int size, FILE * restrict stream), reads a line and stores it in str Writing 4 • int fputc(int c, FILE *stream), writes a character • int fputs(const char * restrict str, FILE * restrict stream), writes a line • int fprintf(FILE * restrict stream, const char * restrict format, ...) writes a formatted string Cursor manipulation • int fseek(FILE *stream, long offset, int whence), moves the cursor. The cursor is moved by offset bytes from the position whence (SEEK_SET, SEEK_CUR, SEEK_END). They represent the beginning, the current position and the end of the file respectively. Binary manipulation • size_t fread(void * restrict ptr, size_t size, size_t nitems, FILE * restrict stream), reads nitems elements of size size from stream and stores them in ptr • size_t fwrite(const void * restrict ptr, size_t size, size_t nitems, FILE * restrict stream), writes nitems elements of size size from ptr to stream Opening modes Mode Description r w a r+ w+ a+ Opens a file for reading. The file must exist. Opens a file for writing. If the file exists, it is truncated to zero length Opens a file for writing at the end of the file (appending) Opens a file for both reading and writing. The file must exist. Opens a file for both reading and writing. If the file exists, it is truncated to zero length Opens a file for both reading and writing at the end of the file (appending). Examples Reading With fgetc: int main(){ FILE *f=fopen("test.txt","r"); if(f==NULL){ perror("fopen"); return EXIT_FAILURE; } int c; while((c=fgetc(f))!=EOF){ 5 } printf("%c",c); } fclose(f); return EXIT_SUCCESS; and with fgets: #define BUFSIZ 1024 int main(){ FILE *f=fopen("test.txt","r"); if(f==NULL){ perror("fopen"); return EXIT_FAILURE; } char buf[BUFSIZ]; while(fgets(buf,BUFSIZ,f)!=NULL){ printf("%s",buf); } fclose(f); return EXIT_SUCCESS; } Writing With fputc: int main(){ FILE *f=fopen("test.txt","w"); if(f==NULL){ perror("fopen"); return EXIT_FAILURE; } for(int i=0;i<10;++i){ fputc('a'+i,f); } fclose(f); return EXIT_SUCCESS; } and with fputs: int main(){ FILE *f=fopen("test.txt","w"); if(f==NULL){ perror("fopen"); return EXIT_FAILURE; } for(int i=0;i<10;++i){ fputs("Hello world\n",f); 6 } } fclose(f); return EXIT_SUCCESS; Cursor manipulation int main(){ FILE *flux=fopen("fichier-test9.txt","w+"); if(flux==NULL){ perror("Probleme ouverture de fichier"); exit(EXIT_FAILURE); } int r=0; r=fputs("Une phrase plus longue 1234455454.\n",flux); assert(r!=EOF); r=fseek(flux,0,SEEK_SET); assert(r==0); r=fputs("ABC",flux); assert(r!=EOF); r=fseek(flux,0,SEEK_END); assert(r==0); r=fputs("Fin\n",flux); r=fseek(flux,0,SEEK_SET); assert(r==0); int c=fgetc(flux); if(c!=EOF){ printf("Lu %c\n",c); } r=fclose(flux); if(r!=0){ perror("Probleme fermeture de fichier"); } } end result: ABC phrase plus longue 1234455454. Fin Common functions Memory manipulation • void *calloc(size_t count, size_t size), malloc mais en initialisation des elements à 0. • void *realloc(void *ptr, size_t size), reallocates memory. It frees if necessary the old zone 7 • void *memmove(void *dst, const void *src,size_t len), copies memory zones • void *memcpy(void *dst, const void *src,size_t len), equivalent to memmove but the two zone must not overlap Character manipulation • • • • • isalpha iscntrl islower isprint isupper Characters A-Z, a-z ASCII 65-90, 97-122 ASCII 0 -31, 127 Characters a-z ASCII 97-122 Characters A-Z, a-z, 0 - 9, punctuation, space ASCII 32-126 Characters A-Z ASCII 65-90 String manipulation • char *strcat(char *restrict s1, const char *restrict s2) string concatenation, it assumes that they both end in \0 • char *strncat(char *restrict s1, const char *restrict s2, size_t n) equivalent to strcat with a limit • char *strcpy(char *dst, const char *src) copies a string • isalnum Characters 0 - 9, A-Z, a-z ASCII 48-57, 65-90, 97-122 • char *strncpy(char * dst, const char * src, size_t len) equivalent to strcopy but with a limit • int strcmp(const char *s1, const char *s2) compares to strings s1 > s2 => strcmp(s1,s2) > 0 • char * strchr(const char *s, int c) returns a pointer to the first occurrence of c, NULL if c is not present • char * strrchr(const char *s, int c) returns a pointer to the last occurrence of c, NULL if c is not present • char * strstr(const char *haystack, const char *needle) search needle dans haystack Type conversion • int atoi(const char *str) str -> int • char * itoa(int n); int -> str Split code into files Header files A header file is a file containing C declarations and macro definitions (see Macros) to be shared between several source files. You request the use of a header file in your program by including it, with the C preprocessing directive #include. #include "path_to_file" this will copy the content of the file path_to_file in the current file. 8 Header guards Header guards are used to avoid multiple inclusion of the same header file. It is a simple #ifndef #define #endif block. #ifndef HEADER_FILE #define HEADER_FILE // code #endif Compilation To compile a program with multiple files, you can use the following command: gcc -o program file1.c file2.c ... Extern keyword The extern keyword is used to declare a global variable or function in another file. In file1.h: extern int a; In file1.c: int a=10; In file2.c: #include "file1.h" int main(){ printf("%d\n",a); // prints 10 } Static keyword The static keyword is used to declare a global variable or function that can only be accessed by functions in the same file. static int a=10; Makefile A makefile is a file containing a set of directives used by a make build automation tool to generate a target/goal. Basic makefile all : prog prog : prog.c 9 gcc -Wall -o prog prog.c clean : rm -rf prog Variables CC=gcc CFLAGS=-Wall all : prog prog : prog.c $(CC) $(CFLAGS) -o prog prog.c clean : rm -rf prog Automatic variables prog : prog.c $(CC) $(CFLAGS) -o $@ $< • • • • • $@ is the name of the target (prog) $< is the name of the first prerequisite (prog.c) $ˆ: list of all the prerequisites $? : list of all the prerequisites that are newer than the target $\* name of the target without the extension Pattern rules all : prog prog : prog.o $(CC) $(CFLAGS) -o $@ $< %.o : %.c $(CC) $(CFLAGS) -c $< clean : rm -rf prog *.o This will compile all the .c files in the current directory. Phony targets They are targets that are not files. They are used to avoid conflicts with files with the same name. .PHONY: all clean all : prog prog : prog.o $(CC) $(CFLAGS) -o $@ $< %.o : %.c $(CC) $(CFLAGS) -c $< 10 clean : rm -rf prog *.o Examples (made by Yago) Reading a file With getline #define _GNU_SOURCE int parse_file(const char *path) { FILE *file = open_file(path, "r"); if (file == NULL) { return FATAL_ERROR; } char *line = NULL; size_t len = 0; ssize_t read; while ((read = getline(&line, &len, file)) != -1) { // do something with line free(line); } } free(line); fclose(file); return exit_code; Without getline Credit: StackOverflow For every line do this: int CUR_MAX = 4095; char *buffer = (char*) malloc(sizeof(char) * CUR_MAX); // allocate buffer. int length = 0; while ( (ch != '\n') && (ch != EOF) ) { if(length ==CUR_MAX) { // time to expand ? CUR_MAX *= 2; // expand to double the current size of anything similar. buffer = realloc(buffer, CUR_MAX); // re allocate memory. } ch = getc(file); // read from stream. buffer[length] = ch; // stuff in buffer. length++; 11 } . . free(buffer); Creating an structure typedef struct test_info { int passed; int failed; int total; double time; } test_info; test_info *create_test_info() { test_info *info = malloc(sizeof(test_info)); assert(info != NULL); info->passed = 0; info->failed = 0; info->total = 0; info->time = 0; } return info; Creation of empty freed strings static command *string_to_command(const char *name) { char **args = malloc(sizeof(char *)); args[0] = malloc(sizeof(char) * (strlen(name) + 1)); strcpy(args[0], name); char *cmd_name = malloc(sizeof(char) * 6); strcpy(cmd_name, "mkdir"); } command *cmd = create_command(cmd_name, 1, args); return cmd; String iterator typedef struct string_iterator { char *string; 12 int index; char delimiter; } string_iterator; string_iterator *create_string_iterator(char *string, char delimiter) { string_iterator *iterator = malloc(sizeof(string_iterator)); assert(iterator != NULL); iterator->string = string; iterator->index = 0; iterator->delimiter = delimiter; update_index_to_next_word(iterator); return iterator; } bool has_next_word(const string_iterator *iterator) { return iterator->string[iterator->inde char *next_word(string_iterator *iterator) { if (!has_next_word(iterator)) { return NULL; } // We iterate through the string until we find a delimiter, in order to skip the word int start = iterator->index; while (iterator->string[iterator->index] != '\0' && iterator->string[iterator->index] != { iterator->index++; } int end = iterator->index; update_index_to_next_word(iterator); int length = end - start; char *result = malloc(sizeof(char) * (length + 1)); assert(result != NULL); result = memmove(result, iterator->string + start, length); assert(result != NULL); result[length] = '\0'; } return result; static void update_index_to_next_word(string_iterator *iterator) { while (iterator->string[iterator->index] != '\0' && iterator->string[iterator->index] == 13 { } } iterator->index++; String strip void strip_newline(char *str) void strip_newline(char *str, char c) { assert(str != NULL); } int i, j; int len = strlen(str); for (i = j = 0; i < len; i++) { if (str[i] != c) { str[j] = str[i]; j++; } } str[j] = '\0'; String starts with bool starts_with(const char *str, const char *prefix) { if (str == NULL || prefix == NULL) { return false; } unsigned len_str = strlen(str); unsigned len_prefix = strlen(prefix); if (len_str < len_prefix) { return false; } for (unsigned i = 0; i < len_prefix; ++i) { if (str[i] != prefix[i]) { 14 return false; } } return true; } 15