--- /dev/null
+*.static
+*.dynamic
+# for cygwin
+*.exe
+
+*.o
+
+*.so
+*.a
+
+# editor trash
+*.swp
+*~
+
+.build
+
+thumbs.db
+*.DS_Store
--- /dev/null
+Introduction:
+-------------
+
+The whole purpose of the current C code is to solve the
+Polytech'Marseille C tutorial exercices.
+
+The repositories organisation is pretty straightforward:
+TP_#/exo?, where # is a digit representing the TP number and
+? is a digit representing the exercice number, is the repository
+where lies the solution to exercice ? TP #.
+
+Building the solution:
+-----------------------
+
+ cd TP_#/exo? && make
+
+Cleaning the solution:
+-----------------------
+
+ cd TP_#/exo? && make clean
+
+Running the solution:
+----------------------
+
+ cd TP_#/exo? && ./exo?
+
+Exercice skeleton:
+------------------
+
+It's the directory exo_skel with a basic Makefile inside
+
+To use it:
+ $ cp -a exo_skel TP_#/exo? (where # and ? are digits)
+ $ cd TP_#/exo? && cp exo_skel.c exo?.c
+ Edit the Makefile to change the TARGET variable to the
+ exercice name desired
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo1
+LIBOBJS=clist.o # object to put in the library
+LIBRARY_NAME=libtpC
+#LDLIBS=-L. -ltpC
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME) $(BINARY_NAME).dynamic $(BINARY_NAME).staticlocal
+
+CC=gcc
+LD=gcc
+AR=ar
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+#FIXME: Add a way to better control the library build
+CFLAGS := -fPIC $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+LIBLDFLAGS := -shared $(LDFLAGS)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+OBJSLIB=$(addprefix $(OBJDIR)/,$(LIBOBJS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(LIBRARY_NAME).a: $(OBJSLIB)
+ @echo "[AR StO] $@"
+ @$(AR) rcs $@ $^
+
+$(LIBRARY_NAME).so: $(OBJSLIB)
+ @echo "[LD ShO] $@"
+ @$(LD) $(CFLAGS) $(LIBLDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+LOCALLDLIBS=-L. -ltpC
+$(BINARY_NAME).staticlocal: $(OBJDIR)/$(BINARY_NAME).o $(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LOCALLDLIBS) $(LDLIBS) -o $@
+
+$(BINARY_NAME).dynamic: $(OBJDIR)/$(BINARY_NAME).o $(LIBRARY_NAME).so
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LOCALLDLIBS) $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+ -@rm $(BINARY_NAME).staticlocal
+ -@rm $(BINARY_NAME).dynamic
+ -@rm $(LIBRARY_NAME).so
+ -@rm $(LIBRARY_NAME).a
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "clist.h"
+
+link_t* list_new(int value) {
+ link_t* link_new;
+ link_new = malloc(sizeof(link_t));
+ link_new->value = value;
+ link_new->next = NULL;
+ return link_new;
+}
+
+link_t* list_append(link_t* head, int value) {
+
+ if (head == NULL) {
+ return head = list_new(value);
+ } else {
+ link_t* head_first = head;
+ while (head->next != NULL) {
+ head = head->next;
+ }
+ head->next = list_new(value);
+ return head_first;
+ }
+}
+
+link_t* list_prepend(link_t* head, int value) {
+ link_t* first_link = list_new(value);
+
+ first_link->next = head;
+ return first_link;
+}
+
+link_t* list_insert(link_t* head, unsigned index, int value) {
+
+ if (index == 0) {
+ return list_prepend(head, value);
+ } else if (index == list_count(head)) {
+ return list_append(head, value);
+ } else {
+ link_t* link_insrt = list_new(value);
+ link_t* head_first = head;
+ link_t* head_next = NULL;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_next = head->next;
+ head->next = link_insrt;
+ head = link_insrt;
+ head->next = head_next;
+ return head_first;
+ }
+}
+
+link_t* list_delete(link_t* head, unsigned index) {
+ link_t* head_prev = NULL;
+ link_t* head_next = NULL;
+ link_t* head_ret = NULL;
+
+ if (head == NULL) {
+ return NULL;
+ } else if (index == 0) {
+ head_next = head->next;
+ free(head);
+ head = head_next;
+ head_ret = head;
+ } else {
+ link_t* head_first = head;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_prev = head;
+ head = head->next;
+ head_next = head->next;
+ free(head);
+ head = head_prev;
+ head->next = head_next;
+ head_ret = head_first;
+ }
+ if (head_ret != NULL) {
+ return head_ret;
+ } else {
+ return NULL;
+ }
+}
+
+link_t* list_concat(link_t* first, link_t* second) {
+ link_t* head_first = first;
+
+ while (first->next != NULL) {
+ first = first->next;
+ }
+ first->next = second;
+ return head_first;
+}
+
+link_t* list_sort(link_t* head) {
+ int tmp;
+ bool isswaped;
+ link_t* head_first = head;
+
+ do {
+ isswaped = false;
+ while (head->next != NULL) {
+ if (head->value > head->next->value) {
+ tmp = head->value;
+ head->value = head->next->value;
+ head->next->value = tmp;
+ isswaped = true;
+ }
+ head = head->next;
+ }
+ /* Reloop at the beginning of the list until there's values swaped */
+ head = head_first;
+ } while (isswaped);
+ return head_first;
+}
+
+static link_t* _list_merge_sort(link_t* head1, link_t* head2) {
+ link_t* head_result = NULL;
+
+ if (head1 == NULL) {
+ return head2;
+ }
+ if (head2 == NULL) {
+ return head1;
+ }
+ if (head1->value < head2->value) {
+ head_result = head1;
+ head_result->next = _list_merge_sort(head1->next, head2);
+ } else {
+ head_result = head2;
+ head_result->next = _list_merge_sort(head1, head2->next);
+ }
+ return head_result;
+}
+
+link_t* list_merge_sort(link_t* head) {
+ link_t* head1;
+ link_t* head2;
+
+ if (head == NULL || head->next == NULL) {
+ return head;
+ }
+
+ head1 = head;
+ head2 = head->next;
+ while (head2 != NULL && head2->next != NULL) {
+ head = head->next;
+ head2 = head->next->next;
+ }
+ head2 = head->next;
+ head->next = NULL;
+
+ head1 = list_merge_sort(head1);
+ head2 = list_merge_sort(head2);
+ return _list_merge_sort(head1, head2);
+}
+
+unsigned list_count(link_t* head) {
+ unsigned count = 0;
+
+ while (head != NULL) {
+ ++count;
+ head = head->next;
+ }
+ return count;
+}
+
+void list_set(link_t* head, unsigned index, int value) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) { head->value = value; }
+}
+
+int list_get(link_t* head, unsigned index) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) {
+ return head->value;
+ } else {
+ return -1;
+ }
+}
+
+void list_clear(link_t* head) {
+ link_t* next_link = NULL;
+
+ while (head != NULL) {
+ next_link = head->next;
+ free(head);
+ head = next_link;
+ }
+}
+
+void list_display_values(link_t* head) {
+ unsigned i = 0;
+
+ printf("------Begin------\n");
+ while (head != NULL) {
+ printf("value at [%d]=%d\n", i, head->value);
+ head = head->next;
+ i++;
+ }
+ printf("------End------\n");
+}
--- /dev/null
+#ifndef CLIST_H
+#define CLIST_H
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value);
+link_t* list_append(link_t* head, int value);
+link_t* list_prepend(link_t* head, int value);
+link_t* list_insert(link_t* head, unsigned index, int value);
+link_t* list_delete(link_t* head, unsigned index);
+link_t* list_concat(link_t* first, link_t* second);
+link_t* list_sort(link_t* head);
+link_t* list_merge_sort(link_t* head);
+unsigned list_count(link_t* head);
+void list_set(link_t* head, unsigned index, int value);
+int list_get(link_t* head, unsigned index);
+void list_clear(link_t* head);
+void list_display_values(link_t* head);
+
+#endif /* CLIST_H */
--- /dev/null
+#include <stdio.h>
+
+#include "clist.h"
+
+int main() {
+ link_t* head1 = NULL;
+ link_t* head2 = NULL;
+ link_t* head = NULL;
+
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ head1 = list_append(head1, 1);
+ head1 = list_append(head1, 2);
+ head1 = list_append(head1, 3);
+ head1 = list_append(head1, 4);
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ list_display_values(head1);
+ head1 = list_prepend(head1, 5);
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ list_display_values(head1);
+ list_set(head1, 0, 78);
+ list_display_values(head1);
+ head1 = list_insert(head1, 2, 7);
+ list_display_values(head1);
+ head1 = list_delete(head1, 3);
+ list_display_values(head1);
+ head1 = list_append(head1, 5);
+ head1 = list_append(head1, 12);
+ head1 = list_append(head1, 65);
+ head1 = list_append(head1, 21);
+ head1 = list_sort(head1);
+ list_display_values(head1);
+ head2 = list_insert(head2, 0, 8);
+ head2 = list_append(head2, 6);
+ head2 = list_prepend(head2, 5);
+ list_display_values(head2);
+ head = list_concat(head1, head2);
+ list_display_values(head);
+ head = list_merge_sort(head);
+ //head = list_sort(head);
+ list_display_values(head);
+ //list_clear(head1);
+ //list_clear(head2);
+ list_clear(head);
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# $(SRC_PATH) directory.
+#
+# This Makefile expect all embedded library source files (.c) to be at the same level, in the
+# $(LIBRARY_PATH) directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name linked against the library if necessary.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set LIBRARY_NAME to the name of the library file to build.
+# The default path for the library code and object is lib.
+# By default the linker will look for $(BINARY_NAME) library name.
+# Set BUILD_TYPE to either debug or release.
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo2
+SRC_PATH:=src
+LIBRARY_NAME=libexo2
+LIBRARY_PATH:=lib
+BUILD_TYPE=debug
+#BUILD_TYPE=release
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME) $(BINARY_NAME).dynamic $(BINARY_NAME).static
+
+CC=gcc
+LD=gcc
+AR=ar
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+UNAME := $(shell uname -o)
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+endif
+
+ifeq ($(UNAME),Cygwin)
+GOLD_SUPPORT = no
+endif
+
+ifeq ($(LTO_SUPPORT),yes)
+CFLAGS_LTO = -flto -ffat-lto-objects
+LDFLAGS_LTO = -fuse-linker-plugin -flto
+endif
+
+ifeq ($(GOLD_SUPPORT),yes)
+LDFLAGS_GOLD = -fuse-ld=gold
+endif
+
+# Putting header files in the source directory is not the purpose of this INCLUDES variable
+INCLUDES := $(INCLUDES) -I$(LIBRARY_PATH)
+CFLAGS := $(CFLAGS) $(CFLAGS_LTO) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG) $(INCLUDES)
+LIBCFLAGS := -fPIC $(CFLAGS)
+LDFLAGS := $(LDFLAGS) $(LDFLAGS_LTO) $(LDFLAGS_GOLD) $(STRIP_FLAG)
+LIBLDFLAGS := -shared $(LDFLAGS)
+STATICLIBLDFLAGS := -static $(LDFLAGS)
+LDLIBS := $(LDLIBS) -L$(LIBRARY_PATH) -l$(BINARY_NAME)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard $(SRC_PATH)/*.c)
+LIBSRCS=$(wildcard $(LIBRARY_PATH)/*.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRCS)))
+LIBOBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(LIBSRCS)))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$(notdir $*).Td
+POSTCOMPILE = mv -f $(DEPDIR)/$(notdir $*).Td $(DEPDIR)/$(notdir $*).d
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).a: $(LIBOBJS)
+ @echo "[AR StO] $@"
+ @$(AR) rcs $@ $^
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).so: $(LIBOBJS)
+ @echo "[LD ShO] $@"
+ @$(LD) $(LIBCFLAGS) $(LIBLDFLAGS) $^ -o $@
+
+#$(BINARY_NAME): $(OBJS) $(LIBOBJS)
+# @echo "[LD ] $@"
+# @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME): $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).static: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(STATICLIBLDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).dynamic: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: $(SRC_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+$(OBJDIR)/%.o: $(LIBRARY_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(LIBCFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(LIBSRCS))))
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+#FIXME: add an install target
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+ -@rm $(BINARY_NAME).static
+ -@rm $(BINARY_NAME).dynamic
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "clist.h"
+
+link_t* list_new(int value) {
+ link_t* link_new;
+ link_new = malloc(sizeof(link_t));
+ link_new->value = value;
+ link_new->next = NULL;
+ return link_new;
+}
+
+link_t* list_append(link_t* head, int value) {
+
+ if (head == NULL) {
+ return head = list_new(value);
+ } else {
+ link_t* head_first = head;
+ while (head->next != NULL) {
+ head = head->next;
+ }
+ head->next = list_new(value);
+ return head_first;
+ }
+}
+
+link_t* list_prepend(link_t* head, int value) {
+ link_t* first_link = list_new(value);
+
+ first_link->next = head;
+ return first_link;
+}
+
+link_t* list_insert(link_t* head, unsigned index, int value) {
+ unsigned max_index = list_count(head);
+
+ if (index == 0) {
+ return list_prepend(head, value);
+ } else if (index == max_index) {
+ return list_append(head, value);
+ } else {
+ link_t* link_insrt = list_new(value);
+ link_t* head_first = head;
+ link_t* head_next = NULL;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_next = head->next;
+ head->next = link_insrt;
+ head = link_insrt;
+ head->next = head_next;
+ return head_first;
+ }
+}
+
+link_t* list_delete(link_t* head, unsigned index) {
+ link_t* head_prev = NULL;
+ link_t* head_next = NULL;
+ link_t* head_ret = NULL;
+
+ if (head == NULL) {
+ return NULL;
+ } else if (index == 0) {
+ head_next = head->next;
+ free(head);
+ head = head_next;
+ head_ret = head;
+ } else {
+ link_t* head_first = head;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_prev = head;
+ head = head->next;
+ head_next = head->next;
+ free(head);
+ head = head_prev;
+ head->next = head_next;
+ head_ret = head_first;
+ }
+ if (head_ret != NULL) {
+ return head_ret;
+ } else {
+ return NULL;
+ }
+}
+
+link_t* list_concat(link_t* first, link_t* second) {
+ link_t* head_first = first;
+
+ while (first->next != NULL) {
+ first = first->next;
+ }
+ first->next = second;
+ return head_first;
+}
+
+link_t* list_sort(link_t* head) {
+ int tmp;
+ bool isswaped;
+ link_t* head_first = head;
+
+ do {
+ isswaped = false;
+ while (head->next != NULL) {
+ if (head->value > head->next->value) {
+ tmp = head->value;
+ head->value = head->next->value;
+ head->next->value = tmp;
+ isswaped = true;
+ }
+ head = head->next;
+ }
+ /* Reloop at the beginning of the list until there's values swaped */
+ head = head_first;
+ } while (isswaped);
+ return head_first;
+}
+
+static link_t* _list_merge_sort(link_t* head1, link_t* head2) {
+ link_t* head_result = NULL;
+
+ if (head1 == NULL) {
+ return head2;
+ }
+ if (head2 == NULL) {
+ return head1;
+ }
+ if (head1->value < head2->value) {
+ head_result = head1;
+ head_result->next = _list_merge_sort(head1->next, head2);
+ } else {
+ head_result = head2;
+ head_result->next = _list_merge_sort(head1, head2->next);
+ }
+ return head_result;
+}
+
+link_t* list_merge_sort(link_t* head) {
+ link_t* head1;
+ link_t* head2;
+
+ if (head == NULL || head->next == NULL) {
+ return head;
+ }
+
+ head1 = head;
+ head2 = head->next;
+ while (head2 != NULL && head2->next != NULL) {
+ head = head->next;
+ head2 = head->next->next;
+ }
+ head2 = head->next;
+ head->next = NULL;
+
+ head1 = list_merge_sort(head1);
+ head2 = list_merge_sort(head2);
+ return _list_merge_sort(head1, head2);
+}
+
+unsigned list_count(link_t* head) {
+ unsigned count = 0;
+
+ while (head != NULL) {
+ ++count;
+ head = head->next;
+ }
+ return count;
+}
+
+void list_set(link_t* head, unsigned index, int value) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) { head->value = value; }
+}
+
+int list_get(link_t* head, unsigned index) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) {
+ return head->value;
+ } else {
+ return -1;
+ }
+}
+
+void list_clear(link_t* head) {
+ link_t* next_link = NULL;
+
+ while (head != NULL) {
+ next_link = head->next;
+ free(head);
+ head = next_link;
+ }
+}
+
+void list_display_values(link_t* head) {
+ unsigned i = 0;
+
+ printf("------Begin------\n");
+ while (head != NULL) {
+ printf("value at [%d]=%d\n", i, head->value);
+ head = head->next;
+ i++;
+ }
+ printf("------End------\n");
+}
--- /dev/null
+#ifndef CLIST_H
+#define CLIST_H
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value);
+link_t* list_append(link_t* head, int value);
+link_t* list_prepend(link_t* head, int value);
+link_t* list_insert(link_t* head, unsigned index, int value);
+link_t* list_delete(link_t* head, unsigned index);
+link_t* list_concat(link_t* first, link_t* second);
+link_t* list_sort(link_t* head);
+link_t* list_merge_sort(link_t* head);
+unsigned list_count(link_t* head);
+void list_set(link_t* head, unsigned index, int value);
+int list_get(link_t* head, unsigned index);
+void list_clear(link_t* head);
+void list_display_values(link_t* head);
+
+#endif /* CLIST_H */
--- /dev/null
+#include <stdio.h>
+
+#include "ui.h"
+
+int promptValue(const char* msg, int* result) {
+ puts(msg);
+ int retVal = scanf("%d", result);
+ return (retVal == 1) ? 0 : 1;
+}
+
+void displayArray(const int array[], unsigned length) {
+ printf("--Begin--\n");
+ for (unsigned i = 0; i < length; i++) {
+ printf("array[%d]=%d\n", i, array[i]);
+ }
+ printf("--End--\n");
+}
+
+void displayList(link_t* head) {
+ printf("--Begin--\n");
+ for (unsigned i = 0, length = list_count(head); i < length; i++) {
+ printf("value at [%d]=%d\n", i, list_get(head, i));
+ }
+ printf("--End--\n");
+}
--- /dev/null
+#ifndef UI_H
+#define UI_H
+
+#include "clist.h"
+
+int promptValue(const char* msg, int* result);
+void displayArray(const int array[], unsigned length);
+void displayList(link_t* head);
+
+#endif /* UI_H */
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "ui.h"
+
+int main() {
+ link_t* head = NULL;
+ unsigned counter = 0;
+ int value = 0;
+ int promptrtVal = 0;
+ int* array = NULL;
+
+ while (true) {
+ promptrtVal = promptValue("Saisir une valeur:", &value);
+ if (promptrtVal != 0)
+ break;
+ head = list_append(head, value);
+ counter++;
+ }
+ printf("Liste:\n");
+ displayList(head);
+ array = malloc(counter*sizeof(int));
+ array[0] = list_get(head, 0);
+ for (unsigned i = 1; i < counter; i++) {
+ array[i] = array[i-1] + list_get(head, i);
+ }
+ printf("Tableau des sommes:\n");
+ displayArray(array, counter);
+ list_clear(head);
+ free(array);
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo3
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+ printf("argc=%d\n", argc);
+ for (int i = 0; i < argc; i++) {
+ printf("argv[%d]=\"%s\"\n", i, argv[i]);
+ }
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo1
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+typedef bool(*compare_cb)(int a, int b);
+
+bool ascending(int a, int b) {
+ return a > b;
+}
+
+bool descending(int a, int b) {
+ return a < b;
+}
+
+void swap(int* v1, int* v2) {
+ int tmp = *v1;
+ *v1 = *v2;
+ *v2 = tmp;
+}
+
+void displayArray(int* array, int count) {
+ for (int i = 0; i < count; i++) {
+ printf("Value in array at index[%d]= %d\n", i, array[i]);
+ }
+}
+
+bool sortFirst(int* array, int length, compare_cb compare) {
+ bool rt = false;
+ for (int i = 0; i < length-1; i++) {
+ if (compare(array[i], array[i+1])) {
+ swap(&array[i], &array[i+1]);
+ if (!rt) { rt = true; };
+ }
+ }
+ return rt;
+}
+
+void sortArray(int* array, int length, compare_cb compare) {
+ bool rt;
+ do {
+ rt = sortFirst(array, length, compare);
+ } while (rt);
+}
+
+int main() {
+ const int tab_size = 10;
+ int tab[10] = {4, 6, 2, 9, 5, 7, 1, 3, 8, 0};
+
+ printf("\nView array content unsorted:\n");
+ displayArray(tab, tab_size);
+ printf("\nNow, sorting the array ascending...\n");
+ sortArray(tab, tab_size, ascending);
+ printf("\nView array content sorted:\n");
+ displayArray(tab, tab_size);
+ printf("\nNow, sorting the array descending...\n");
+ sortArray(tab, tab_size, descending);
+ printf("\nView array content sorted:\n");
+ displayArray(tab, tab_size);
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo2
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ char ch;
+ char* fname;
+ FILE* fp;
+
+ printf("Enter the name of the file you wish to see\n");
+ scanf("%s", fname);
+
+ fp = fopen(fname, "r"); /* read mode */
+ if (fp == NULL) {
+ perror("Error while opening the file.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("The content of %s file is :\n", fname);
+
+ while((ch = fgetc(fp)) != EOF)
+ printf("%c", ch);
+
+ fclose(fp);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+Bonjour,
+
+Je suis un fichier texte de test, ouvrez moi, demonter moi.
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo3
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char** argv) {
+ char* fnamesrc = (char*)argv[1], fnamedest = (char*)argv[2];
+ FILE* fpsrc, fpdest;
+
+ if (argc < 3) {
+ puts("Please enter two arguments separated by a space: file_name_src file_name_dest");
+ exit(EXIT_FAILURE);
+ }
+
+ fpsrc = fopen(fnamesrc, "r"); /* read mode */
+ if (fpsrc == NULL) {
+ perror("Error while opening the source file.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(fpsrc);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# $(SRC_PATH) directory.
+#
+# This Makefile expect all embedded library source files (.c) to be at the same level, in the
+# $(LIBRARY_PATH) directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name linked against the library if necessary.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set LIBRARY_NAME to the name of the library file to build.
+# The default path for the library code and object is lib.
+# By default the linker will look for $(BINARY_NAME) library name.
+# Set BUILD_TYPE to either debug or release.
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo1
+SRC_PATH:=src
+LIBRARY_NAME=libexo1
+LIBRARY_PATH:=lib
+BUILD_TYPE=debug
+#BUILD_TYPE=release
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME) $(BINARY_NAME).dynamic $(BINARY_NAME).static
+
+CC=gcc
+LD=gcc
+AR=ar
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+UNAME := $(shell uname -o)
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+endif
+
+ifeq ($(UNAME),Cygwin)
+GOLD_SUPPORT = no
+endif
+
+ifeq ($(LTO_SUPPORT),yes)
+CFLAGS_LTO = -flto -ffat-lto-objects
+LDFLAGS_LTO = -fuse-linker-plugin -flto
+endif
+
+ifeq ($(GOLD_SUPPORT),yes)
+LDFLAGS_GOLD = -fuse-ld=gold
+endif
+
+# Putting header files in the source directory is not the purpose of this INCLUDES variable
+INCLUDES := $(INCLUDES) -I$(LIBRARY_PATH)
+CFLAGS := $(CFLAGS) $(CFLAGS_LTO) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG) $(INCLUDES)
+LIBCFLAGS := -fPIC $(CFLAGS)
+LDFLAGS := $(LDFLAGS) $(LDFLAGS_LTO) $(LDFLAGS_GOLD) $(STRIP_FLAG)
+LIBLDFLAGS := -shared $(LDFLAGS)
+STATICLIBLDFLAGS := -static $(LDFLAGS)
+LDLIBS := $(LDLIBS) -L$(LIBRARY_PATH) -l$(BINARY_NAME)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard $(SRC_PATH)/*.c)
+LIBSRCS=$(wildcard $(LIBRARY_PATH)/*.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRCS)))
+LIBOBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(LIBSRCS)))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$(notdir $*).Td
+POSTCOMPILE = mv -f $(DEPDIR)/$(notdir $*).Td $(DEPDIR)/$(notdir $*).d
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).a: $(LIBOBJS)
+ @echo "[AR StO] $@"
+ @$(AR) rcs $@ $^
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).so: $(LIBOBJS)
+ @echo "[LD ShO] $@"
+ @$(LD) $(LIBCFLAGS) $(LIBLDFLAGS) $^ -o $@
+
+#$(BINARY_NAME): $(OBJS) $(LIBOBJS)
+# @echo "[LD ] $@"
+# @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME): $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).static: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(STATICLIBLDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).dynamic: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: $(SRC_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+$(OBJDIR)/%.o: $(LIBRARY_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(LIBCFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(LIBSRCS))))
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+#FIXME: add an install target
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+ -@rm $(BINARY_NAME).static
+ -@rm $(BINARY_NAME).dynamic
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "array.h"
+
+int* create_tab(int tab[], unsigned tab_size) {
+ tab = malloc(sizeof(int) * tab_size);
+ if (tab != NULL) {
+ /* initialize to zero the integer array */
+ for (unsigned i = 0; i < tab_size; i++) {
+ tab[i] = 0;
+ }
+ }
+ return tab;
+}
+
+void free_tab(int tab[]) {
+ free(tab);
+}
+
+/* we suppose both tabs are already created */
+static void copy_tab(int src_tab[], int dest_tab[], unsigned src_tab_size, unsigned index_offset) {
+ /* FIXME: I think it's worth doing some sanity checks on the array size:
+ * dest_tab_size >= src_tab_size */
+ if (src_tab == NULL || dest_tab == NULL) {
+ printf("please ensure you have created both arrays beforehand\n");
+ return;
+ }
+ for (unsigned i = 0; i < src_tab_size; i++) {
+ dest_tab[i + index_offset] = src_tab[i];
+ }
+}
+
+/* one must free the two source tabs in case they will be unused after to concatenation */
+int* concat_tab(int tab1[], unsigned tab_size1, int tab2[], unsigned tab_size2) {
+ int* tab_dest = NULL;
+ tab_dest = create_tab(tab_dest, tab_size1 + tab_size2);
+
+ copy_tab(tab1, tab_dest, tab_size1, 0);
+ copy_tab(tab2, tab_dest, tab_size2, tab_size1);
+ return tab_dest;
+}
+
+int* resize_tab(int tab[], unsigned old_tab_size, unsigned new_tab_size) {
+ tab = realloc(tab, sizeof(int) * new_tab_size);
+ if (old_tab_size < new_tab_size) {
+ for (unsigned i = old_tab_size; i < new_tab_size; i++) {
+ tab[i] = 0;
+ }
+ }
+ return tab;
+}
+
+/* number of occurences of an element in an unsorted array */
+unsigned count_tab_element(int tab[], unsigned tab_size, int element) {
+ unsigned el_count = 0;
+
+ for (unsigned i = 0; i < tab_size; i++) {
+ if (tab[i] == element) {
+ el_count++;
+ }
+ }
+ return el_count;
+}
+
+unsigned count_tab_criteria(int tab[], unsigned tab_size, c_criteria_cb c_criteria) {
+ unsigned cr_count = 0;
+
+ for (unsigned i = 0; i < tab_size; i++) {
+ if (c_criteria(tab[i])) {
+ cr_count++;
+ }
+ }
+ return cr_count;
+}
+
+bool is_even(int a) {
+ return (a % 2 == 0);
+}
+
+bool is_odd(int a) {
+ return (a % 2 != 0);
+
+}
+
+void sort_tab(int tab[], unsigned tab_size, s_criteria_cb sort_criteria) {
+ sort_bubble_array(tab, tab_size, sort_criteria);
+}
--- /dev/null
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <stdbool.h>
+
+#include "sort.h"
+
+typedef bool(*c_criteria_cb)(int a);
+
+bool is_even(int a);
+bool is_odd(int a);
+
+int* create_tab(int tab[], unsigned tab_size);
+void free_tab(int tab[]);
+int* concat_tab(int tab1[], unsigned tab_size1, int tab2[], unsigned tab_size2);
+int* resize_tab(int tab[], unsigned old_tab_size, unsigned new_tab_size);
+unsigned count_tab_element(int tab[], unsigned tab_size, int element);
+unsigned count_tab_criteria(int tab[], unsigned tab_size, c_criteria_cb c_criteria);
+void sort_tab(int tab[], unsigned tab_size, s_criteria_cb sort_criteria);
+
+#endif /* ARRAY_H */
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "io.h"
+#include "array.h"
+
+int prompt_value(const char* msg, int* result) {
+ puts(msg);
+ int retVal = scanf("%d", result);
+ return (retVal == 1) ? 0 : 1;
+}
+
+int* prompt_array(int array[], unsigned* size) {
+ int errno = prompt_value("Taille du tableau?", (int*)size);
+ array = create_tab(array, *size);
+ for (unsigned i = 0; i < *size; i++) {
+ errno += prompt_value("Valeur?", &array[i]);
+ }
+ /* error might have occured */
+ handle_prompt_error(errno);
+ return array;
+}
+
+void display_choice_menu() {
+ printf("\n=== Menu ===\n\n");
+ printf("1) Saisir puis concatener un autre tableau.\n");
+ printf("2) Trier le tableau.\n");
+ printf("3) Afficher le tableau.\n");
+ printf("4) Compter le nombre d'occurence d'un entier dans le tableau.\n");
+ printf("5) Compter le nombre d'entiers pairs dans le tableau.\n");
+ printf("6) Compter le nombre d'entiers impairs dans le tableau.\n");
+ printf("7) Redimensionner le tableau.\n");
+ printf("8) Quitter.\n");
+}
+
+int* do_concat(int array[], unsigned* size) {
+ int* tab_to_concat = NULL;
+ unsigned tab_to_concat_size = 0;
+ printf("\n=== Saisie d'un tableau ===\n\n");
+ tab_to_concat = prompt_array(tab_to_concat, &tab_to_concat_size);
+ int* tab_concat = concat_tab(array, *size, tab_to_concat, tab_to_concat_size);
+ *size += tab_to_concat_size;
+ free_tab(array);
+ free_tab(tab_to_concat);
+ return tab_concat;
+}
+
+void do_sort(int array[], unsigned size) {
+ int errno = 0;
+ int choice = 0;
+ bool done = false;
+ s_criteria_cb sort_criteria;
+
+ printf("\n=== Menu de tri ===\n\n");
+ printf("1) Croissant.\n");
+ printf("2) Decroissant.\n");
+ printf("3) Croissant pairs en premier.\n");
+ printf("4) Croissant impairs en premier.\n");
+ do {
+ errno = prompt_value("Choix?", &choice);
+ handle_prompt_error(errno);
+ done = true;
+ if (1 > choice || 4 < choice) {
+ printf("\nFaire un choix compris entre 1 et 4\n");
+ done = false;
+ }
+ } while (!done);
+ switch (choice) {
+ case 1:
+ sort_criteria = ascending;
+ break;
+ case 2:
+ sort_criteria = descending;
+ break;
+ case 3:
+ sort_criteria = ascending_and_even;
+ break;
+ case 4:
+ sort_criteria = ascending_and_odd;
+ break;
+ default:
+ /* sort ascending by default, unused code path */
+ sort_criteria = ascending;
+ break;
+ }
+ sort_tab(array, size, sort_criteria);
+}
+
+void do_count(int array[], unsigned size) {
+ int errno = 0;
+ int search_value = 0;
+
+ errno = prompt_value("\nValeur a chercher?", &search_value);
+ handle_prompt_error(errno);
+ printf("La valeur %d est presente %d fois dans le tableau\n", search_value, count_tab_element(array, size, search_value));
+}
+
+void do_resize(int array[], unsigned* old_size) {
+ int errno = 0;
+ unsigned new_size = 0;
+
+ errno = prompt_value("\nNouvelle taille?", (int*)&new_size);
+ handle_prompt_error(errno);
+ /* FIXME: one should able the set the array new content if new_size > *old_size
+ * for now, new values are zeroed */
+ array = resize_tab(array, *old_size, new_size);
+ *old_size = new_size;
+}
+
+void handle_prompt_error(int errno) {
+ if (errno != 0) {
+ printf("\nMerci de saisir un nombre entier, exiting\n");
+ /* it's somewhat violent but better than looping forever */
+ exit(EXIT_FAILURE);
+ }
+}
+
+void display_array(int array[], unsigned size) {
+ if (array != NULL) {
+ printf("\n--array begin--\n");
+ for (unsigned i = 0; i < size; i++) {
+ printf("value in array at index[%d]=%d\n", i, array[i]);
+ }
+ printf("--array end--\n");
+ } else {
+ printf("\n--array NULL--\n");
+ }
+}
--- /dev/null
+#ifndef IO_H
+#define IO_H
+
+int prompt_value(const char* msg, int* result);
+int* prompt_array(int array[], unsigned* size);
+void handle_prompt_error(int errno);
+
+void display_choice_menu();
+
+int* do_concat(int array[], unsigned* size);
+void do_sort(int array[], unsigned size);
+void do_count(int array[], unsigned size);
+void do_resize(int array[], unsigned* size);
+
+void display_array(int array[], unsigned size);
+
+#endif /* IO_H */
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: macros.h
+ *
+ * Description: Some useful macros
+ *
+ * Version: 1.0
+ * Created: 09/03/2017 15:28:46
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#ifndef MACROS_H
+#define MACROS_H
+
+#include <stdlib.h>
+
+/* definition to expand macro then apply to pragma message */
+#define VALUE_TO_STRING(x) #x
+#define VALUE(x) VALUE_TO_STRING(x)
+#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
+
+/* FIXME: ensure we manipulate real array */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+#endif /* MACROS_H */
--- /dev/null
+#include "utils.h"
+#include "sort.h"
+
+bool ascending(int a, int b) {
+ return a > b;
+}
+
+bool descending(int a, int b) {
+ return a < b;
+}
+
+bool ascending_and_even(int a, int b) {
+ return (((a % 2 != 0) && (b % 2 == 0)) || ((a % 2 == 0) && (b % 2 == 0) && ascending(a, b)) \
+ || ((a % 2 != 0) && (b % 2 != 0) && ascending(a, b)));
+}
+
+bool ascending_and_odd(int a, int b) {
+ return (((a % 2 == 0) && (b % 2 != 0)) || ((a % 2 == 0) && (b % 2 == 0) && ascending(a, b)) \
+ || ((a % 2 != 0) && (b % 2 != 0) && ascending(a, b)));
+}
+
+static bool sort_first(int* array, unsigned length, s_criteria_cb sort_criteria) {
+ bool rt = false;
+ for (unsigned i = 0; i < length-1; i++) {
+ if (sort_criteria(array[i], array[i+1])) {
+ swap_int(&array[i], &array[i+1]);
+ rt = true;
+ }
+ }
+ return rt;
+}
+
+/* the feature of this function is awaited in the array.c file */
+void sort_bubble_array(int* array, unsigned length, s_criteria_cb sort_criteria) {
+ bool rt;
+ do {
+ rt = sort_first(array, length, sort_criteria);
+ } while (rt);
+}
--- /dev/null
+#ifndef SORT_H
+#define SORT_H
+
+#include <stdbool.h>
+
+typedef bool(*s_criteria_cb)(int a, int b);
+
+/* sort criteria */
+bool ascending(int a, int b);
+bool descending(int a, int b);
+bool ascending_and_even(int a, int b);
+bool ascending_and_odd(int a, int b);
+
+void sort_bubble_array(int* array, unsigned length, s_criteria_cb sort_criteria);
+
+#endif /* SORT_H */
--- /dev/null
+#include <stdio.h>
+
+#include "utils.h"
+
+void swap_int(int* v1, int* v2) {
+ int tmp = *v1;
+ *v1 = *v2;
+ *v2 = tmp;
+}
+
+void swap_ptr(void* v1, void* v2) {
+ void* tmp = v1;
+ v1 = v2;
+ v2 = tmp;
+}
--- /dev/null
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "macros.h"
+
+void swap_int(int* v1, int* v2);
+void swap_ptr(void* v1, void* v2);
+
+#endif /* UTILS_H */
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "array.h"
+#include "utils.h"
+#include "io.h"
+
+int main() {
+ int* tab = NULL;
+ unsigned tab_size = 0;
+ int errno = 0;
+ int choice = 0;
+
+ printf("=== Saisie initiale ===\n\n");
+ tab = prompt_array(tab, &tab_size);
+
+ do {
+ display_choice_menu();
+ errno = prompt_value("Choix?", &choice);
+ handle_prompt_error(errno);
+ if (1 > choice || 8 < choice) {
+ printf("\nFaire un choix compris entre 1 et 8\n");
+ continue;
+ }
+ switch (choice) {
+ case 1:
+ tab = do_concat(tab, &tab_size);
+ break;
+ case 2:
+ do_sort(tab, tab_size);
+ break;
+ case 3:
+ display_array(tab, tab_size);
+ break;
+ case 4:
+ do_count(tab, tab_size);
+ break;
+ case 5:
+ printf("\nLe nombre d'entiers pairs dans le tableau est %d\n", count_tab_criteria(tab, tab_size, is_even));
+ break;
+ case 6:
+ printf("\nLe nombre d'entiers impairs dans le tableau est %d\n", count_tab_criteria(tab, tab_size, is_odd));
+ break;
+ case 7:
+ do_resize(tab, &tab_size);
+ break;
+ default:
+ /* do nothing, unused code path */
+ break;
+ }
+ } while (choice != 8);
+
+ free_tab(tab);
+ exit(EXIT_SUCCESS);
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# $(SRC_PATH) directory.
+#
+# This Makefile expect all embedded library source files (.c) to be at the same level, in the
+# $(LIBRARY_PATH) directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name linked against the library if necessary.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set LIBRARY_NAME to the name of the library file to build.
+# The default path for the library code and object is lib.
+# By default the linker will look for $(BINARY_NAME) library name.
+# Set BUILD_TYPE to either debug or release.
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo2
+SRC_PATH:=src
+LIBRARY_NAME=libexo2
+LIBRARY_PATH:=lib
+LDLIBS=-lncurses -ltinfo
+BUILD_TYPE=debug
+#BUILD_TYPE=release
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME) $(BINARY_NAME).dynamic $(BINARY_NAME).static
+
+CC=gcc
+LD=gcc
+AR=ar
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+UNAME := $(shell uname -o)
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+LTO_SUPPORT = yes
+GOLD_SUPPORT = yes
+endif
+
+ifeq ($(UNAME),Cygwin)
+GOLD_SUPPORT = no
+endif
+
+ifeq ($(LTO_SUPPORT),yes)
+CFLAGS_LTO = -flto -ffat-lto-objects
+LDFLAGS_LTO = -fuse-linker-plugin -flto
+endif
+
+ifeq ($(GOLD_SUPPORT),yes)
+LDFLAGS_GOLD = -fuse-ld=gold
+endif
+
+# Putting header files in the source directory is not the purpose of this INCLUDES variable
+INCLUDES := $(INCLUDES) -I$(LIBRARY_PATH)
+CFLAGS := $(CFLAGS) $(CFLAGS_LTO) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG) $(INCLUDES)
+LIBCFLAGS := -fPIC $(CFLAGS)
+LDFLAGS := $(LDFLAGS) $(LDFLAGS_LTO) $(LDFLAGS_GOLD) $(STRIP_FLAG)
+LIBLDFLAGS := -shared $(LDFLAGS)
+STATICLIBLDFLAGS := -static $(LDFLAGS)
+LDLIBS := $(LDLIBS) -L$(LIBRARY_PATH) -l$(BINARY_NAME)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard $(SRC_PATH)/*.c)
+LIBSRCS=$(wildcard $(LIBRARY_PATH)/*.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRCS)))
+LIBOBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(LIBSRCS)))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$(notdir $*).Td
+POSTCOMPILE = mv -f $(DEPDIR)/$(notdir $*).Td $(DEPDIR)/$(notdir $*).d
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).a: $(LIBOBJS)
+ @echo "[AR StO] $@"
+ @$(AR) rcs $@ $^
+
+$(LIBRARY_PATH)/$(LIBRARY_NAME).so: $(LIBOBJS)
+ @echo "[LD ShO] $@"
+ @$(LD) $(LIBCFLAGS) $(LIBLDFLAGS) $^ -o $@
+
+#$(BINARY_NAME): $(OBJS) $(LIBOBJS)
+# @echo "[LD ] $@"
+# @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME): $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).static: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(STATICLIBLDFLAGS) $^ $(LDLIBS) -o $@
+
+$(BINARY_NAME).dynamic: $(OBJS) $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: $(SRC_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+$(OBJDIR)/%.o: $(LIBRARY_PATH)/%.c $(DEPDIR)/%.d
+ @echo "[C ] $(notdir $*)"
+ @$(CC) $(DEPFLAGS) $(LIBCFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(LIBSRCS))))
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+#FIXME: add an install target
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+ -@rm $(BINARY_NAME).static
+ -@rm $(BINARY_NAME).dynamic
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).a
+ -@rm $(LIBRARY_PATH)/$(LIBRARY_NAME).so
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+Tic-tac-toe
+-----------
+
+Touches correspondantes au case de la grille:
+
+a|z|e
+-+-+-
+q|s|d
+-+-+-
+w|x|c
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: coordinates.c
+ *
+ * Description: Data definition and functions to manipulate elements in the grid
+ *
+ * Version: 1.0
+ * Created: 16/03/2017 19:05:02
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#include "coordinates.h"
+
+void init_coordinates(coordinates_t* coordinates_array) {
+ for (unsigned i = 0; i < MAX_COORDINATES; i++) {
+ coordinates_array[i] = set_coordinates(0, 0, 0);
+ }
+}
+
+coordinates_t set_coordinates(int y, int x, unsigned type) {
+ coordinates_t new_coordinates;
+
+ new_coordinates.y = y;
+ new_coordinates.x = x;
+ new_coordinates.type = type;
+ return new_coordinates;
+}
+
+/* the function do a lot of sanity checks before adding new board elements,
+ * hence the loop. moving the checks in the main loop is also possible */
+unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round) {
+ /* valid coordinates are in the [1-3] range */
+ if (new_coordinates.y < 1 || new_coordinates.y > 3 || new_coordinates.x < 1 || new_coordinates.x > 3) {
+ return 3; /* error value for invalid coordinates */
+ } else if (round == MAX_COORDINATES + 1) {
+ return 1; /* error value for full array */
+ }
+
+ for (unsigned i = 0; i < MAX_COORDINATES; i++) {
+ /* check if already entered */
+ if (new_coordinates.y == (coordinates_array + i)->y && new_coordinates.x == (coordinates_array + i)->x) {
+ return 2; /* error value for duplicates */
+ } else if ((coordinates_array + i)->y == 0 && (coordinates_array + i)->x == 0) {
+ coordinates_array[i] = new_coordinates;
+ return 0; /* error value when everything if fine */
+ }
+ }
+ return 4; /* error value for unknown error case - should never happen - */
+}
+
+bool chk_win_conditions(coordinates_t* coordinates_array) {
+ for (unsigned i = 0; i < MAX_COORDINATES; i++) {
+
+ }
+ return false;
+}
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: coordinates.h
+ *
+ * Description: Header for data definition and functions to manipulate elements in the grid
+ *
+ * Version: 1.0
+ * Created: 16/03/2017 19:06:16
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#ifndef COORDINATES_H
+#define COORDINATES_H
+
+#include <stdbool.h>
+
+/* we only have nine elements in the grid */
+#define MAX_COORDINATES 9
+
+typedef struct coordinates_s {
+ int y;
+ int x;
+ unsigned type; /* 0 = O, 1 = X */
+} coordinates_t;
+
+void init_coordinates(coordinates_t* coordinates_array);
+coordinates_t set_coordinates(int y, int x, unsigned type);
+unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round);
+bool chk_win_conditions(coordinates_t* coordinates_array);
+
+#endif /* COORDINATES_H */
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: display.c
+ *
+ * Description: Routines to handle the display
+ *
+ * Version: 1.0
+ * Created: 15/03/2017 20:06:11
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#include <ncurses.h>
+
+#include "display.h"
+
+/* in all print routine, y and x are the coordinates of the first character of the shape
+ * which can be a space ' ' */
+
+void print_board(int y, int x) {
+ mvprintw(y, x, " | |");
+ mvprintw(y+1, x, " | |");
+ mvprintw(y+2, x, "----+----+----");
+ mvprintw(y+3, x, " | |");
+ mvprintw(y+4, x, " | |");
+ mvprintw(y+5, x, "----+----+----");
+ mvprintw(y+6, x, " | |");
+ mvprintw(y+7, x, " | |");
+}
+
+/* there's only nine valid (y, x) 2-uplets for this two shapes
+ * that are : - base_y, base_x +1
+ * - base_y, base_x + 6
+ * - base_y, base_x + 11
+ * - base_y + 3, base_x + 1
+ * - base_y + 6, base_x + 1
+ * - base_y + 3, base_x + 6
+ * - base_y + 3, base_x + 11
+ * - base_y + 6, base_x + 6
+ * - base_y + 6, base_x + 11
+ * The added (y, x) couple values can be {0, 3, 6}x{1, 6, 11}
+ */
+
+void print_x(int y, int x) {
+ mvprintw(y, x, "\\/");
+ mvprintw(y+1, x,"/\\");
+}
+
+void print_o(int y, int x) {
+ mvprintw(y, x, "/\\");
+ mvprintw(y+1, x, "\\/");
+}
+
+/* y: 1 -> +0 x: 1 -> +1
+ * 2 -> +3 2 -> +6
+ * 3 -> +6 3 -> +11 */
+static int remap_y(int y) {
+ if (y == 1) {
+ return 0;
+ } else if (y == 2) {
+ return 3;
+ } else {
+ return 6;
+ }
+}
+
+static int remap_x(int x) {
+ if (x == 1) {
+ return 1;
+ } else if (x == 2) {
+ return 6;
+ } else {
+ return 11;
+ }
+}
+
+void print_coordinates(coordinates_t coordinates_array[], int base_y, int base_x) {
+ unsigned i = 0;
+ while ((coordinates_array + i)->y != 0 && (coordinates_array + i)->x != 0) {
+ if ((coordinates_array + i)->type == 0) {
+ print_o(base_y + remap_y((coordinates_array + i)->y), base_x + remap_x((coordinates_array + i)->x));
+ } else {
+ print_x(base_y + remap_y((coordinates_array + i)->y), base_x + remap_x((coordinates_array + i)->x));
+ }
+ i++;
+ }
+}
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: display.h
+ *
+ * Description: Headers for display routines
+ *
+ * Version: 1.0
+ * Created: 15/03/2017 20:07:12
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#include "coordinates.h"
+
+void print_board(int y, int x);
+void print_x(int y, int x);
+void print_o(int y, int x);
+void print_coordinates(coordinates_t coordinates_array[], int base_y, int base_x);
+
+#endif /* DISPLAY_H */
--- /dev/null
+/*
+ * =====================================================================================
+ *
+ * Filename: macros.h
+ *
+ * Description: Some useful macros
+ *
+ * Version: 1.0
+ * Created: 09/03/2017 15:28:46
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
+ * Organization: Piment Noir
+ *
+ * =====================================================================================
+ */
+
+#ifndef MACROS_H
+#define MACROS_H
+
+#include <stdlib.h>
+
+/* definition to expand macro then apply to pragma message */
+#define VALUE_TO_STRING(x) #x
+#define VALUE(x) VALUE_TO_STRING(x)
+#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
+
+/* FIXME: ensure we manipulate real array */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+#endif /* MACROS_H */
--- /dev/null
+#include "utils.h"
+
+void swap_int(int* v1, int* v2) {
+ int tmp = *v1;
+ *v1 = *v2;
+ *v2 = tmp;
+}
+
+void swap_ptr(void* v1, void* v2) {
+ void* tmp = v1;
+ v1 = v2;
+ v2 = tmp;
+}
--- /dev/null
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "macros.h"
+
+void swap_int(int* v1, int* v2);
+void swap_ptr(void* v1, void* v2);
+
+#endif /* UTILS_H */
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ncurses.h>
+
+#include "display.h"
+#include "coordinates.h"
+
+int main() {
+ int row, col, errno = 0, round = 0, player = 0, key_pressed;
+ const int str_max_length = 255;
+ char* top_msg = malloc(str_max_length * sizeof(char));
+ char* back_msg = malloc(str_max_length * sizeof(char));
+
+ initscr();
+ getmaxyx(stdscr, row, col);
+ noecho();
+ curs_set(0);
+
+ /* array of the active coordinates in the entered order */
+ coordinates_t coordinates_array[MAX_COORDINATES];
+ init_coordinates(coordinates_array);
+ coordinates_t new_coordinates = {0, 0, 0};
+
+ /* center base coordinates for the board */
+ int base_y = row/2 - 4;
+ int base_x = col/2 - 7;
+
+ print_board(base_y, base_x);
+
+ do {
+ if (errno == 0) round++;
+
+ if (round % 2 == 0) {
+ player = 1;
+ top_msg = "Joueur 2 joue";
+ } else {
+ player = 0;
+ top_msg = "Joueur 1 joue";
+ }
+
+ mvprintw(base_y - 2, (base_x + 7 - strlen(top_msg)/2), top_msg);
+
+ print_coordinates(coordinates_array, base_y, base_x);
+
+ /* getch() is blocking */
+ key_pressed = getch();
+ switch (key_pressed) {
+ case 'a':
+ new_coordinates = set_coordinates(1, 1, player);
+ break;
+ case 'z':
+ new_coordinates = set_coordinates(1, 2, player);
+ break;
+ case 'e':
+ new_coordinates = set_coordinates(1, 3, player);
+ break;
+ case 'q':
+ new_coordinates = set_coordinates(2, 1, player);
+ break;
+ case 's':
+ new_coordinates = set_coordinates(2, 2, player);
+ break;
+ case 'd':
+ new_coordinates = set_coordinates(2, 3, player);
+ break;
+ case 'w':
+ new_coordinates = set_coordinates(3, 1, player);
+ break;
+ case 'x':
+ new_coordinates = set_coordinates(3, 2, player);
+ break;
+ case 'c':
+ new_coordinates = set_coordinates(3, 3, player);
+ break;
+ default:
+ /* set invalid coordinates */
+ new_coordinates = set_coordinates(0, 0, player);
+ break;
+ }
+
+ errno = add_coordinates(new_coordinates, coordinates_array, round);
+
+ if (errno == 2) {
+ back_msg = "Choisir une case vide";
+ } else if (errno == 3) {
+ back_msg = "Coordonnees invalides";
+ } else if (errno == 1) {
+ back_msg = "Tableau rempli sans gagnant: egalite";
+ } else if (errno == 4) {
+ back_msg = "Erreur inconnue";
+ } else if (errno == 0) {
+ /* FIXME: properly zero the string */
+ back_msg = "";
+ }
+
+ mvprintw(base_y + 10, (base_x + 7 - strlen(back_msg)/2), back_msg);
+
+ refresh();
+
+ } while (errno != 1);
+
+ if (!top_msg)
+ free(top_msg);
+ if (!back_msg)
+ free(back_msg);
+
+ endwin();
+
+ exit(EXIT_SUCCESS);
+}
--- /dev/null
+TARGET = exo1
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall
+LDFLAGS = -g -Wall
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+//FIXME: Comment the code !!!
+
+void promptValue(int* addr) {
+ scanf("%d", addr);
+}
+
+// The efficiency of this swap alternative is debatable ..
+void xorSwap (int *v1, int *v2) {
+ if (v1 != v2) {
+ *v1 ^= *v2;
+ *v2 ^= *v1;
+ *v1 ^= *v2;
+ }
+}
+
+void swap(int* v1, int* v2) {
+ int tmp = *v1;
+ *v1 = *v2;
+ *v2 = tmp;
+}
+
+void displayArray(int* array, int count) {
+ for (int i = 0; i < count; i++) {
+ printf("Value in array at index[%d]= %d\n", i, array[i]);
+ }
+}
+
+bool sortFirst(int* array, int length) {
+ bool rt = false;
+ // This loop could probably be replaced by a while loop with conditions
+ // on the array values permutation AND the iteration value, later ...
+ for (int i = 0; i < length-1; i++) {
+ if (array[i] > array[i+1]) {
+ swap(&array[i], &array[i+1]);
+ //xorSwap(&array[i], &array[i+1]);
+ if (!rt) { rt = true; };
+ }
+ }
+ return rt;
+}
+
+void sortArray(int* array, int length) {
+ bool rt;
+ do {
+ rt = sortFirst(array, length);
+ } while (rt);
+}
+
+int main() {
+ int tab_length = 10;
+ int tab[tab_length];
+ for (int i = 0; i < tab_length; i++) {
+ tab[i] = 0;
+ }
+
+ for (int i = 0; i < tab_length; i++) {
+ printf("Enter integer value at array's index[%d]? ", i);
+ /* En langage C, une ligne doit être terminée par le caractère '\n'. Tant que */
+ /* la ligne n'est pas terminée et que le tampon associé au fichier n'est pas plein, */
+ /* les caractères transmis ne seront pas effectivement écrits mais tout simplement */
+ /* placés dans le tampon. On peut cependant forcer le vidage de ce tampon à l'aide */
+ /* de la fonction fflush. */
+ fflush(stdout);
+ promptValue(&tab[i]);
+ }
+
+ printf("\nView array content unsorted:\n");
+ displayArray(tab, tab_length);
+ printf("\nNow, sorting the array...\n");
+ sortArray(tab, tab_length);
+ printf("\nView array content sorted:\n");
+ displayArray(tab, tab_length);
+
+ return 0;
+}
--- /dev/null
+TARGET = exo2
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall
+LDFLAGS = -g -Wall
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+//FIXME: Comment the code !!!
+
+void displayMenuEntry(int num, const char* option) {
+ printf("%d - %s\n", num, option);
+}
+
+void displayMenu() {
+ displayMenuEntry(1, "Addition");
+ displayMenuEntry(2, "Soustraction");
+ displayMenuEntry(3, "Multiplication");
+ displayMenuEntry(4, "Division");
+ displayMenuEntry(5, "Puissance");
+ displayMenuEntry(6, "Quitter");
+}
+
+int promptValue(const char* invite) {
+ int value = 0;
+ puts(invite);
+ scanf("%d", &value);
+ return value;
+}
+
+int promptOperation() {
+ displayMenu();
+ return promptValue("Veuillez choisir une operation ?");
+}
+
+int doAddition(int val1, int val2) {
+ return val1 + val2;
+}
+
+int doSubstraction(int val1, int val2) {
+ return val1 - val2;
+}
+
+int doMultiplication(int val1, int val2) {
+ return val1 * val2;
+}
+
+int doDivision(int val1, int val2) {
+ //FIXME: Useless code path given the exit main loop condition
+ if (val2 == 0) {
+ printf("Division par zero !\n");
+ // FIXME: I'm not very fond of this convention ...
+ return 0;
+ } else {
+ return val1 / val2;
+ }
+}
+
+int doPuissance(int base, int expo) {
+ int power;
+ if ( expo == 1) {
+ power = base;
+ } else if ( expo % 2 == 0 ) {
+ power = doPuissance(base*base, expo/2);
+ } else {
+ power = base*doPuissance(base*base,(expo-1)/2);
+ }
+ return power;
+}
+
+int doOperation(int selection, int val1, int val2) {
+ int op_result;
+ switch (selection) {
+ case 1:
+ op_result = doAddition(val1, val2);
+ break;
+ case 2:
+ op_result = doSubstraction(val1, val2);
+ break;
+ case 3:
+ op_result = doMultiplication(val1, val2);
+ break;
+ case 4:
+ op_result = doDivision(val1, val2);
+ break;
+ case 5:
+ op_result = doPuissance(val1, val2);
+ break;
+ case 6:
+ break;
+ default:
+ puts("Faire un choix compris entre 1 et 6");
+ }
+ return op_result;
+}
+
+int main() {
+ int choice = promptOperation();
+ int value1 = promptValue("Veuillez saisir une valeur entiere initiale ?");
+ int value2 = 0, result = 0;
+ bool first_loop = true;
+
+ for (;;) {
+ if (choice == 6) break;
+ if (first_loop) {
+ value2 = promptValue("Veuillez saisir une valeur entiere avec laquelle l'operation sera effectuee ?");
+ if (value2 == 0) break;
+ result = doOperation(choice, value1, value2);
+ first_loop = false;
+ } else {
+ value2 = promptValue("Veuillez saisir la prochaine valeur entiere avec laquelle l'operation sera effectuee sur l'ancien resultat ?");
+ if (value2 == 0) break;
+ result = doOperation(choice, result, value2);
+ }
+ printf("Le resultat de l'operation choisie est %d\n\n", result);
+ }
+
+ return 0;
+}
--- /dev/null
+TARGET = exo3
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall
+LDFLAGS = -g -Wall
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <ctype.h>
+
+//FIXME: Comment the code !!!
+
+void swap(char* v1, char* v2) {
+ if (v1 != v2) {
+ char tmp = *v1;
+ *v1 = *v2;
+ *v2 = tmp;
+ }
+}
+
+int stringLength(const char* str) {
+ int length;
+
+ for(length = 0; str[length] != '\0'; ++length);
+ return length;
+}
+
+// FIXME: this function have issues with non english characters
+void reverseString(char* str) {
+ int length = stringLength(str);
+
+ for (int i = length - 1; i >= length/2; --i) {
+ swap(&str[i], &str[(length - 1) - i]);
+ }
+}
+
+// FIXME: this function have issues with non english characters
+void permAlphaChar(char* str, int key) {
+ char alphabet[26] = "abcdefghijklmnopqrstuvwxyz";
+ int str_length = stringLength(str);
+
+ for (int i = 0; i < str_length; i++) {
+ //if (str[i] == ' ') continue;
+ for (int j = 0; j < 26; j++) {
+ if (str[i] == alphabet[j]) {
+ str[i] = alphabet[(j+key) % 26];
+ break;
+ } else if (str[i] == toupper(alphabet[j])) {
+ str[i] = toupper(alphabet[(j+key) % 26]);
+ break;
+ }
+ }
+ }
+}
+
+int main() {
+ char rev_msg[] = "Bonjour le monde";
+ int rev_length = stringLength(rev_msg);
+ char perm_msg[] = "Bonjour a tous et toutes";
+ int perm_length = stringLength(perm_msg);
+
+ printf("La chaine de caracteres a inverser est \"%s\" et a pour longueur %d caractere(s)\n", rev_msg, rev_length);
+ reverseString(rev_msg);
+ printf("La chaine inversee de caracteres est \"%s\"\n", rev_msg);
+
+ printf("\n");
+
+ printf("La chaine de caracteres a permuter est \"%s\" et a pour longueur %d caractere(s)\n", perm_msg, perm_length);
+ permAlphaChar(perm_msg, 13);
+ printf("La chaine permutee de caracteres est \"%s\"\n", perm_msg);
+
+ return 0;
+}
--- /dev/null
+all: \
+ exo1-base \
+ exo1-full \
+ exo1-extra \
+ exo2-base \
+ exo2-full \
+ exo2-extra \
+ exo3-base \
+ exo3-full \
+ exo3-extra \
+
+
+%:%.c
+ gcc $< -std=c99 -Wall -g -o $@
+
+clean:
+ @rm -f \
+ exo1-base \
+ exo1-full \
+ exo1-extra \
+ exo2-base \
+ exo2-full \
+ exo2-extra \
+ exo3-base \
+ exo3-full \
+ exo3-extra \
+
--- /dev/null
+Correction du TP noté de C
+
+Pour compiler, utiliser make directement:
+
+$ make
+
+Les fichiers -base contiennent l'exercice de base, les fichiers -full contiennent les points optionels.
+
+Les fichiers -extra contiennent une version alternative. Cette version n'est pas nécessairement plus efficace (voir elle est parfois moins efficace!) et n'est pas non plus aussi lisible; de manière générale les "astuces" utilisées ne sont pas conseillées quand elles réduisent la lisibilité sans apporter d'avantage réel.
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+void swap(int* v1, int* v2) {
+ int tempValue = *v1;
+ *v1 = *v2;
+ *v2 = tempValue;
+}
+
+/** Display the array on standard output. */
+void displayArray(int* array, int count) {
+ for (int tabIndex = 0; tabIndex < count; ++tabIndex) {
+ printf("array[%d] = %d\n", tabIndex, array[tabIndex]);
+ }
+}
+
+/** Perform one swap on the first two values not in increasing order.
+ *
+ * @return true if a swap was performed, false if the whole array is ordered.
+ */
+bool sortFirst(int* array, int length) {
+ for (int tabIndex = 0; tabIndex < (length - 1); ++tabIndex) {
+ if (array[tabIndex] > array[tabIndex + 1]) {
+ swap(&array[tabIndex], &array[tabIndex + 1]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void sortArray(int* array, int length) {
+ bool swappedValues;
+
+ do {
+ swappedValues = sortFirst(array, length);
+ } while (swappedValues);
+}
+
+int main() {
+ int arr[10] = {23, 2, 0, 4, 56, 3, 7, 8, 98, 1};
+ sortArray(arr, 10);
+ displayArray(arr, 10);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+void swap(int* v1, int* v2) {
+ int tempValue = *v1;
+ *v1 = *v2;
+ *v2 = tempValue;
+}
+
+/** Display the array on standard output. */
+void displayArray(int* array, int count) {
+ for (int tabIndex = 0; tabIndex < count; ++tabIndex) {
+ printf("array[%d] = %d\n", tabIndex, *(array++));
+ }
+}
+
+/** Swap every out-of-order cells at most once.
+ *
+ * @return true if a swap was performed, false if the whole array is ordered.
+ */
+bool sortFirst(int* array, int length) {
+ bool swappedValues = false;
+ int* cursor = array;
+
+ while (--length) {
+ if (*cursor > *(cursor + 1)) {
+ swap(cursor, cursor + 1);
+ swappedValues = true;
+ }
+
+ ++cursor;
+ }
+
+ return swappedValues;
+}
+
+void sortArray(int* array, int length) {
+ while (sortFirst(array, length));
+}
+
+/** Fill the array with user input. */
+void promptArray(int* array, int length) {
+ for (int tabIndex = 0; tabIndex < length; ++tabIndex) {
+ printf("Enter value for index %d:\n", tabIndex);
+ scanf("%d", array++);
+ }
+}
+
+int main() {
+ int arr[10];
+ promptArray(arr, 10);
+ sortArray(arr, 10);
+ displayArray(arr, 10);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+void swap(int* v1, int* v2) {
+ int tempValue = *v1;
+ *v1 = *v2;
+ *v2 = tempValue;
+}
+
+/** Display the array on standard output. */
+void displayArray(int* array, int count) {
+ for (int tabIndex = 0; tabIndex < count; ++tabIndex) {
+ printf("array[%d] = %d\n", tabIndex, array[tabIndex]);
+ }
+}
+
+/** Swap every out-of-order cells at most once.
+ *
+ * @return true if a swap was performed, false if the whole array is ordered.
+ */
+bool sortFirst(int* array, int length) {
+ bool swappedValues = false;
+
+ for (int tabIndex = 0; tabIndex < (length - 1); ++tabIndex) {
+ if (array[tabIndex] > array[tabIndex + 1]) {
+ swap(&array[tabIndex], &array[tabIndex + 1]);
+ swappedValues = true;
+ }
+ }
+
+ return swappedValues;
+}
+
+void sortArray(int* array, int length) {
+ bool swappedValues;
+
+ do {
+ swappedValues = sortFirst(array, length);
+ } while (swappedValues);
+}
+
+/** Fill the array with user input. */
+void promptArray(int* array, int length) {
+ for (int tabIndex = 0; tabIndex < length; ++tabIndex) {
+ printf("Enter value for index %d:\n", tabIndex);
+ scanf("%d", &array[tabIndex]);
+ }
+}
+
+int main() {
+ int arr[10];
+ promptArray(arr, 10);
+ sortArray(arr, 10);
+ displayArray(arr, 10);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+/** Display a prompt to the user then wait for an integer input. */
+int promptValue(const char* prompt) {
+ printf("%s:\n", prompt);
+ int result;
+ scanf("%d", &result);
+ return result;
+}
+
+void displayMenuEntry(int index, const char* label) {
+ printf("%d | %s\n", index, label);
+}
+
+void displayMenu() {
+ displayMenuEntry(1, "Addition");
+ displayMenuEntry(2, "Substraction");
+ displayMenuEntry(3, "Multiplication");
+ displayMenuEntry(4, "Exit");
+}
+
+/** Prompt the user for his operation choice.
+ *
+ * @return The selected operation. No invalid value can be returned.
+ */
+int promptOperation() {
+ displayMenu();
+ int result;
+
+ do {
+ result = promptValue("Choose an option");
+
+ if (result >= 1 && result <= 4) {
+ break;
+ }
+
+ puts("Please choose a valid option (1-4)");
+ } while (true);
+
+ return result;
+}
+
+int main() {
+ int operation = promptOperation();
+
+ if (operation == 4) {
+ return 0;
+ }
+
+ int initialValue = promptValue("Initial value");
+
+ do {
+ int nextValue = promptValue("Next value");
+
+ if (nextValue == 0) {
+ break;
+ }
+
+ switch (operation) {
+ // Addition
+ case 1:
+ initialValue += nextValue;
+ break;
+
+ // Substraction
+ case 2:
+ initialValue -= nextValue;
+ break;
+
+ // Multiplication
+ case 3:
+ initialValue *= nextValue;
+ break;
+ }
+
+ printf("Result: %d\n", initialValue);
+ } while (true);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/** Pointer to a function with this profile */
+typedef int(*operation_cb)(int v1, int v2);
+
+/** Describe a single operation */
+typedef struct {
+ const char* label;
+ operation_cb cb;
+} operation_t;
+
+int doAddition(int v1, int v2);
+int doSubstraction(int v1, int v2);
+int doMultiplication(int v1, int v2);
+int doXOR(int v1, int v2);
+
+/** All available operations */
+operation_t operations[4] = {
+ {
+ "Addition",
+ doAddition
+ },
+ {
+ "Substraction",
+ doSubstraction
+ },
+ {
+ "Multiplication",
+ doMultiplication
+ },
+ {
+ "XOR",
+ doXOR
+ }
+};
+#define operations_count ((int) (sizeof(operations) / sizeof(operations[0])))
+
+/** Display a prompt to the user then wait for an integer input. */
+void promptValue(const char* prompt, int* value) {
+ printf("%s:\n", prompt);
+ scanf("%d", value);
+}
+
+void displayMenuEntry(int index, const char* label) {
+ printf("%d | %s\n", index, label);
+}
+
+/** Display all available operations and an EXIT option. */
+void displayMenu() {
+ for (int menuIndex = 0; menuIndex < operations_count; ++menuIndex) {
+ displayMenuEntry(menuIndex + 1, operations[menuIndex].label);
+ }
+
+ displayMenuEntry(operations_count + 1, "Exit");
+}
+
+/** Prompt the user for his operation choice.
+ *
+ * @return The selected operation. If the exit option is chosen, return NULL
+ */
+operation_t* promptOperation() {
+ displayMenu();
+
+ do {
+ int result;
+ promptValue("Choose an option", &result);
+
+ if (result == (operations_count + 1)) {
+ return NULL;
+ }
+
+ if (result >= 1 && result <= operations_count) {
+ return &operations[result - 1];
+ }
+
+ printf("Please choose a valid option (1-%d)\n", operations_count);
+ } while (true);
+}
+
+int doAddition(int v1, int v2) {
+ return v1 + v2;
+}
+
+int doSubstraction(int v1, int v2) {
+ return v1 - v2;
+}
+
+int doMultiplication(int v1, int v2) {
+ return v1 * v2;
+}
+
+int doXOR(int v1, int v2) {
+ return v1 ^ v2;
+}
+
+int main() {
+ operation_t* operation = promptOperation();
+
+ if (operation == NULL) {
+ return 0;
+ }
+
+ int initialValue;
+ promptValue("Initial value", &initialValue);
+
+ do {
+ int nextValue;
+ promptValue("Next value", &nextValue);
+
+ if (nextValue == 0) {
+ break;
+ }
+
+ initialValue = operation->cb(initialValue, nextValue);
+ printf("Result: %d\n", initialValue);
+ } while (true);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdbool.h>
+
+/** Display a prompt to the user then wait for an integer input. */
+int promptValue(const char* prompt) {
+ printf("%s:\n", prompt);
+ int result;
+ scanf("%d", &result);
+ return result;
+}
+
+void displayMenuEntry(int index, const char* label) {
+ printf("%d | %s\n", index, label);
+}
+
+void displayMenu() {
+ displayMenuEntry(1, "Addition");
+ displayMenuEntry(2, "Substraction");
+ displayMenuEntry(3, "Multiplication");
+ displayMenuEntry(4, "XOR");
+ displayMenuEntry(5, "Exit");
+}
+
+/** Prompt the user for his operation choice.
+ *
+ * @return The selected operation. No invalid value can be returned.
+ */
+int promptOperation() {
+ displayMenu();
+ int result;
+
+ do {
+ result = promptValue("Choose an option");
+
+ if (result >= 1 && result <= 5) {
+ break;
+ }
+
+ puts("Please choose a valid option (1-5)");
+ } while (true);
+
+ return result;
+}
+
+int main() {
+ int operation = promptOperation();
+
+ if (operation == 5) {
+ return 0;
+ }
+
+ int initialValue = promptValue("Initial value");
+
+ do {
+ int nextValue = promptValue("Next value");
+
+ if (nextValue == 0) {
+ break;
+ }
+
+ switch (operation) {
+ // Addition
+ case 1:
+ initialValue += nextValue;
+ break;
+
+ // Substraction
+ case 2:
+ initialValue -= nextValue;
+ break;
+
+ // Multiplication
+ case 3:
+ initialValue *= nextValue;
+ break;
+
+ // XOR
+ case 4:
+ initialValue ^= nextValue;
+ break;
+ }
+
+ printf("Result: %d\n", initialValue);
+ } while (true);
+}
--- /dev/null
+#include <stdio.h>
+
+int stringLength(const char* str) {
+ int result = 0;
+
+ while (str[result] != '\0') {
+ ++result;
+ }
+
+ return result;
+}
+
+void swap(char* v1, char* v2) {
+ char temp = *v1;
+ *v1 = *v2;
+ *v2 = temp;
+}
+
+void reverseString(char* str) {
+ int length = stringLength(str);
+ int halfLength = length / 2;
+
+ for (int charId = 0; charId < halfLength; ++charId) {
+ swap(&str[charId], &str[length - charId - 1]);
+ }
+}
+
+int main() {
+ char msg[] = "Votre message";
+ printf("Initial value: \"%s\"\n", msg);
+ reverseString(msg);
+ printf("Reversed : \"%s\"\n", msg);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int stringLength(const char* str) {
+ int result = 0;
+
+ for (; str[result]; ++result);
+
+ return result;
+}
+
+void swap(char* v1, char* v2) {
+ char temp = *v1;
+ *v1 = *v2;
+ *v2 = temp;
+}
+
+void reverseString(char* str) {
+ char* begin = str;
+ char* end = str + stringLength(str) - 1;
+
+ while (begin < end) {
+ swap(begin++, end--);
+ }
+}
+
+/** Perform a classical ROT13 permutation in-place */
+void rot13(char* str) {
+ char* cursor = str;
+ char* end = str + stringLength(str);
+
+ while (cursor < end) {
+ if (*cursor >= 'a' && *cursor <= 'z') {
+ *cursor = (*cursor - 'a' + 13) % 26 + 'a';
+ } else if (*cursor >= 'A' && *cursor <= 'Z') {
+ *cursor = (*cursor - 'A' + 13) % 26 + 'A';
+ }
+
+ ++cursor;
+ }
+}
+
+int main() {
+ char* msg;
+ puts("Enter your message:");
+ int readValue = scanf("%ms", &msg);
+
+ if (readValue == 0) {
+ puts("oops");
+ return 0;
+ }
+
+ printf("Initial value: \"%s\"\n", msg);
+ reverseString(msg);
+ printf("Reversed : \"%s\"\n", msg);
+ reverseString(msg); // Restore the original message
+ rot13(msg);
+ printf("ROT13 : \"%s\"\n", msg);
+ free(msg); // scanf("%ms") allocate dynamic memory
+}
--- /dev/null
+#include <stdio.h>
+
+int stringLength(const char* str) {
+ int result = 0;
+
+ while (str[result] != '\0') {
+ ++result;
+ }
+
+ return result;
+}
+
+void swap(char* v1, char* v2) {
+ char temp = *v1;
+ *v1 = *v2;
+ *v2 = temp;
+}
+
+void reverseString(char* str) {
+ int length = stringLength(str);
+ int halfLength = length / 2;
+
+ for (int charId = 0; charId < halfLength; ++charId) {
+ swap(&str[charId], &str[length - charId - 1]);
+ }
+}
+
+/** Perform a classical ROT13 permutation in-place */
+void rot13(char* str) {
+ int length = stringLength(str);
+
+ for (int charId = 0; charId < length; ++charId) {
+ char chrValue = str[charId];
+
+ if (chrValue >= 'a' && chrValue <= 'z') {
+ str[charId] =
+ (chrValue - 'a' // Translate chrValue from 'a'-'z' to 0-25
+ + 13) // Add 13
+ % 26 // Rotate in 0-25
+ + 'a'; // Translate the value from 0-25 to 'a'-'z'
+ } else if (chrValue >= 'A' && chrValue <= 'Z') {
+ str[charId] = (chrValue - 'A' + 13) % 26 + 'A';
+ }
+ }
+}
+
+int main() {
+ char msg[] = "Votre message";
+ printf("Initial value: \"%s\"\n", msg);
+ reverseString(msg);
+ printf("Reversed : \"%s\"\n", msg);
+ reverseString(msg); // Restore the original message
+ rot13(msg);
+ printf("ROT13 : \"%s\"\n", msg);
+}
--- /dev/null
+TARGET = exo1
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall -Wextra
+LDFLAGS = -g -Wall -Wextra
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int promptValue() {
+ int value;
+ scanf("%d", &value);
+ return value;
+}
+
+int main() {
+ int* arr;
+ printf("Longeur?\n");
+ int size = promptValue();
+ //arr[size];
+ //arr = malloc(sizeof(arr));
+ arr = malloc(sizeof(int)*size);
+
+ for (int i = 0; i < size; i++) {
+ printf("Valeur?\n");
+ arr[i] = promptValue();
+ }
+
+ printf("Sortie:\n");
+ int sum = 0;
+ for (int i = 0; i < size; i++) {
+ printf("%d (%d)\n", arr[i], sum += arr[i]);
+ }
+
+ free(arr);
+
+ return 0;
+}
--- /dev/null
+TARGET = exo2
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall -Wextra
+LDFLAGS = -g -Wall -Wextra
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+/** Display a prompt to the user then wait for an integer input. */
+int promptValue(const char* prompt) {
+ printf("%s:\n", prompt);
+ int result;
+ scanf("%d", &result);
+ return result;
+}
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value) {
+ link_t* link_t_new;
+ link_t_new = malloc(sizeof(link_t));
+ link_t_new->value = value;
+ link_t_new->next = NULL;
+ return link_t_new;
+}
+
+void list_clear(link_t* link) {
+ free(link);
+}
+
+int main() {
+ link_t* head;
+ int value = promptValue("Entrer l'entier a mettre dans un maillon");
+ head = list_new(value);
+ printf("Valeur entiere dans le maillon: %d\n", head->value);
+ list_clear(head);
+
+ return 0;
+}
--- /dev/null
+TARGET = exo3
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall -Wextra
+LDFLAGS = -g -Wall -Wextra
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+/** Display a prompt to the user then wait for an integer input. */
+int promptValue(const char* prompt) {
+ printf("%s:\n", prompt);
+ int result;
+ scanf("%d", &result);
+ return result;
+}
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value) {
+ link_t* link_t_new;
+ link_t_new = malloc(sizeof(link_t));
+ link_t_new->value = value;
+ link_t_new->next = NULL;
+ return link_t_new;
+}
+
+void list_append(link_t* head, int value) {
+
+ while (head->next != NULL) {
+ head = head->next;
+ }
+ head->next = list_new(value);
+}
+
+unsigned list_count(link_t* head) {
+ // And if head is not defined?
+ int count = 1;
+
+ while (head->next != NULL) {
+ ++count;
+ head = head->next;
+ }
+ return count;
+}
+
+int list_get(link_t* head, unsigned index) {
+
+ if (index < list_count(head)) {
+ for (unsigned i = 0; i < index; i++) {
+ head = head->next;
+ }
+ return head->value;
+ } else {
+ return -1;
+ }
+}
+
+void list_clear(link_t* link) {
+
+ while (link != NULL) {
+ link_t* next_link = link->next;
+ free(link);
+ link = next_link;
+ }
+}
+
+int main() {
+ link_t* head = list_new(1);
+ printf("Longueur de la liste: %d\n", list_count(head));
+ list_append(head, 2);
+ list_append(head, 3);
+ list_append(head, 4);
+ printf("Longueur de la liste: %d\n", list_count(head));
+ printf("Valeur a index %d: %d\n", 2, list_get(head, 2));
+ printf("Valeur a index %d: %d\n", 3, list_get(head, 3));
+ printf("Valeur a index %d: %d\n", 4, list_get(head, 4));
+ list_clear(head);
+
+ return 0;
+}
--- /dev/null
+TARGET = exo1
+LIBS =
+CC = gcc
+# Enforce C11 ISO standard for now
+CFLAGS = -std=c11 -g -Wall -Wextra
+LDFLAGS = -g -Wall -Wextra
+
+.PHONY: default all clean
+
+default: $(TARGET)
+all: default
+
+OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
+HEADERS = $(wildcard *.h)
+
+%.o: %.c $(HEADERS)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.PRECIOUS: $(TARGET) $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) $(LIBS) -o $@
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS)
+
+disassemble: $(TARGET)
+ objdump -d $< | less
+
+symbols: $(TARGET)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdlib.h>
+
+#include "clist.h"
+
+link_t* list_new(int value) {
+ link_t* link_t_new;
+ link_t_new = malloc(sizeof(link_t));
+ link_t_new->value = value;
+ link_t_new->next = NULL;
+ return link_t_new;
+}
+
+void list_append(link_t* head, int value) {
+
+ while (head->next != NULL) {
+ head = head->next;
+ }
+ head->next = list_new(value);
+}
+
+unsigned list_count(link_t* head) {
+ // And if head is not defined?
+ int count = 1;
+
+ while (head->next != NULL) {
+ ++count;
+ head = head->next;
+ }
+ return count;
+}
+
+int list_get(link_t* head, unsigned index) {
+
+ if (index < list_count(head)) {
+ for (unsigned i = 0; i < index; i++) {
+ head = head->next;
+ }
+ return head->value;
+ } else {
+ return -1;
+ }
+}
+
+void list_clear(link_t* link) {
+
+ while (link != NULL) {
+ link_t* next_link = link->next;
+ free(link);
+ link = next_link;
+ }
+}
--- /dev/null
+#ifndef CLIST_H
+#define CLIST_H
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value);
+void list_append(link_t* head, int value);
+unsigned list_count(link_t* head);
+int list_get(link_t* head, unsigned index);
+void list_clear(link_t* link);
+
+#endif /* CLIST_H */
--- /dev/null
+#include <stdio.h>
+
+#include "clist.h"
+
+int main() {
+ link_t* head = list_new(1);
+ printf("Longueur de la liste: %d\n", list_count(head));
+ list_append(head, 2);
+ list_append(head, 3);
+ list_append(head, 4);
+ printf("Longueur de la liste: %d\n", list_count(head));
+ printf("Valeur a index %d: %d\n", 2, list_get(head, 2));
+ printf("Valeur a index %d: %d\n", 3, list_get(head, 3));
+ printf("Valeur a index %d: %d\n", 4, list_get(head, 4));
+ list_clear(head);
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo2
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c99
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "clist.h"
+
+link_t* list_new(int value) {
+ link_t* link_new;
+ link_new = malloc(sizeof(link_t));
+ link_new->value = value;
+ link_new->next = NULL;
+ return link_new;
+}
+
+link_t* list_append(link_t* head, int value) {
+
+ if (head == NULL) {
+ return head = list_new(value);
+ } else {
+ link_t* head_first = head;
+ while (head->next != NULL) {
+ head = head->next;
+ }
+ head->next = list_new(value);
+ return head_first;
+ }
+}
+
+link_t* list_prepend(link_t* head, int value) {
+ link_t* first_link = list_new(value);
+
+ first_link->next = head;
+ return first_link;
+}
+
+link_t* list_insert(link_t* head, unsigned index, int value) {
+
+ if (index == 0) {
+ return list_prepend(head, value);
+ } else if (index == list_count(head)) {
+ return list_append(head, value);
+ } else {
+ link_t* link_insrt = list_new(value);
+ link_t* head_first = head;
+ link_t* head_next = NULL;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_next = head->next;
+ head->next = link_insrt;
+ head = link_insrt;
+ head->next = head_next;
+ return head_first;
+ }
+}
+
+link_t* list_delete(link_t* head, unsigned index) {
+ link_t* head_prev = NULL;
+ link_t* head_next = NULL;
+ link_t* head_ret = NULL;
+
+ if (head == NULL) {
+ return NULL;
+ } else if (index == 0) {
+ head_next = head->next;
+ free(head);
+ head = head_next;
+ head_ret = head;
+ } else {
+ link_t* head_first = head;
+ for (unsigned i = 0; i < index-1; i++) {
+ head = head->next;
+ }
+ head_prev = head;
+ head = head->next;
+ head_next = head->next;
+ free(head);
+ head = head_prev;
+ head->next = head_next;
+ head_ret = head_first;
+ }
+ if (head_ret != NULL) {
+ return head_ret;
+ } else {
+ return NULL;
+ }
+}
+
+link_t* list_concat(link_t* first, link_t* second) {
+ link_t* head_first = first;
+
+ while (first->next != NULL) {
+ first = first->next;
+ }
+ first->next = second;
+ return head_first;
+}
+
+link_t* list_sort(link_t* head) {
+ int tmp;
+ bool isswaped;
+ link_t* head_first = head;
+
+ do {
+ isswaped = false;
+ while (head->next != NULL) {
+ if (head->value > head->next->value) {
+ tmp = head->value;
+ head->value = head->next->value;
+ head->next->value = tmp;
+ isswaped = true;
+ }
+ head = head->next;
+ }
+ /* Reloop at the beginning of the list until there's values swaped */
+ head = head_first;
+ } while (isswaped);
+ return head_first;
+}
+
+static link_t* _list_merge_sort(link_t* head1, link_t* head2) {
+ link_t* head_result = NULL;
+
+ if (head1 == NULL) {
+ return head2;
+ }
+ if (head2 == NULL) {
+ return head1;
+ }
+ if (head1->value < head2->value) {
+ head_result = head1;
+ head_result->next = _list_merge_sort(head1->next, head2);
+ } else {
+ head_result = head2;
+ head_result->next = _list_merge_sort(head1, head2->next);
+ }
+ return head_result;
+}
+
+link_t* list_merge_sort(link_t* head) {
+ link_t* head1;
+ link_t* head2;
+
+ if (head == NULL || head->next == NULL) {
+ return head;
+ }
+
+ head1 = head;
+ head2 = head->next;
+ while (head2 != NULL && head2->next != NULL) {
+ head = head->next;
+ head2 = head->next->next;
+ }
+ head2 = head->next;
+ head->next = NULL;
+
+ head1 = list_merge_sort(head1);
+ head2 = list_merge_sort(head2);
+ return _list_merge_sort(head1, head2);
+}
+
+unsigned list_count(link_t* head) {
+ unsigned count = 0;
+
+ while (head != NULL) {
+ ++count;
+ head = head->next;
+ }
+ return count;
+}
+
+void list_set(link_t* head, unsigned index, int value) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) { head->value = value; }
+}
+
+int list_get(link_t* head, unsigned index) {
+ unsigned count = 0;
+
+ while (head != NULL && count < index) {
+ ++count;
+ head = head->next;
+ }
+ if (head != NULL) {
+ return head->value;
+ } else {
+ return -1;
+ }
+}
+
+void list_clear(link_t* head) {
+ link_t* next_link = NULL;
+
+ while (head != NULL) {
+ next_link = head->next;
+ free(head);
+ head = next_link;
+ }
+}
+
+void list_display_values(link_t* head) {
+ unsigned i = 0;
+
+ printf("------Begin------\n");
+ while (head != NULL) {
+ printf("value at [%d]=%d\n", i, head->value);
+ head = head->next;
+ i++;
+ }
+ printf("------End------\n");
+}
--- /dev/null
+#ifndef CLIST_H
+#define CLIST_H
+
+/** Linked list of int */
+typedef struct link_s {
+ int value;
+ struct link_s* next;
+} link_t;
+
+link_t* list_new(int value);
+link_t* list_append(link_t* head, int value);
+link_t* list_prepend(link_t* head, int value);
+link_t* list_insert(link_t* head, unsigned index, int value);
+link_t* list_delete(link_t* head, unsigned index);
+link_t* list_concat(link_t* first, link_t* second);
+link_t* list_sort(link_t* head);
+link_t* list_merge_sort(link_t* head);
+unsigned list_count(link_t* head);
+void list_set(link_t* head, unsigned index, int value);
+int list_get(link_t* head, unsigned index);
+void list_clear(link_t* head);
+void list_display_values(link_t* head);
+
+#endif /* CLIST_H */
--- /dev/null
+#include <stdio.h>
+
+#include "clist.h"
+
+int main() {
+ link_t* head1 = NULL;
+ link_t* head2 = NULL;
+ link_t* head = NULL;
+
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ head1 = list_append(head1, 1);
+ head1 = list_append(head1, 2);
+ head1 = list_append(head1, 3);
+ head1 = list_append(head1, 4);
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ list_display_values(head1);
+ head1 = list_prepend(head1, 5);
+ printf("Longueur de la liste: %d\n", list_count(head1));
+ list_display_values(head1);
+ list_set(head1, 0, 78);
+ list_display_values(head1);
+ head1 = list_insert(head1, 2, 7);
+ list_display_values(head1);
+ head1 = list_delete(head1, 3);
+ list_display_values(head1);
+ head1 = list_append(head1, 5);
+ head1 = list_append(head1, 12);
+ head1 = list_append(head1, 65);
+ head1 = list_append(head1, 21);
+ head1 = list_sort(head1);
+ list_display_values(head1);
+ head2 = list_insert(head2, 0, 8);
+ head2 = list_append(head2, 6);
+ head2 = list_prepend(head2, 5);
+ list_display_values(head2);
+ head = list_concat(head1, head2);
+ list_display_values(head);
+ head = list_merge_sort(head);
+ //head = list_sort(head);
+ list_display_values(head);
+ //list_clear(head1);
+ //list_clear(head2);
+ list_clear(head);
+
+ return 0;
+}
--- /dev/null
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo_skel
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+ @echo "[LD ] $@"
+ @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+ @echo "[C ] $*"
+ @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+ @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+ @echo "[CLN]"
+ -@rm -r $(BUILDDIR)
+ -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+ objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+ objdump -t $< | sort | less
--- /dev/null
+#include <stdio.h>
+
+int main() {
+
+ return 0;
+}