From: Jérôme Benoit Date: Mon, 27 Feb 2017 18:15:11 +0000 (+0100) Subject: Add TP 7 correction. X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=c2bc2b96a16dbea260d81c674abd5ac53687c273;p=TD_C.git Add TP 7 correction. Signed-off-by: Jérôme Benoit --- diff --git a/TP_7_C/Makefile b/TP_7_C/Makefile new file mode 100644 index 0000000..57d5b7b --- /dev/null +++ b/TP_7_C/Makefile @@ -0,0 +1,15 @@ +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 $@ + diff --git a/TP_7_C/README b/TP_7_C/README new file mode 100644 index 0000000..e452c5b --- /dev/null +++ b/TP_7_C/README @@ -0,0 +1,9 @@ +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. diff --git a/TP_7_C/exo1-base.c b/TP_7_C/exo1-base.c new file mode 100644 index 0000000..a30362c --- /dev/null +++ b/TP_7_C/exo1-base.c @@ -0,0 +1,44 @@ +#include +#include + +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); +} diff --git a/TP_7_C/exo1-extra.c b/TP_7_C/exo1-extra.c new file mode 100644 index 0000000..3d191f0 --- /dev/null +++ b/TP_7_C/exo1-extra.c @@ -0,0 +1,54 @@ +#include +#include + +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); +} diff --git a/TP_7_C/exo1-full.c b/TP_7_C/exo1-full.c new file mode 100644 index 0000000..451816b --- /dev/null +++ b/TP_7_C/exo1-full.c @@ -0,0 +1,55 @@ +#include +#include + +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); +} diff --git a/TP_7_C/exo2-base.c b/TP_7_C/exo2-base.c new file mode 100644 index 0000000..7212cfc --- /dev/null +++ b/TP_7_C/exo2-base.c @@ -0,0 +1,79 @@ +#include +#include + +/** 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); +} diff --git a/TP_7_C/exo2-extra.c b/TP_7_C/exo2-extra.c new file mode 100644 index 0000000..2250cfd --- /dev/null +++ b/TP_7_C/exo2-extra.c @@ -0,0 +1,119 @@ +#include +#include +#include + +/** 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); +} diff --git a/TP_7_C/exo2-full.c b/TP_7_C/exo2-full.c new file mode 100644 index 0000000..acbe4a3 --- /dev/null +++ b/TP_7_C/exo2-full.c @@ -0,0 +1,85 @@ +#include +#include + +/** 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); +} diff --git a/TP_7_C/exo3-base.c b/TP_7_C/exo3-base.c new file mode 100644 index 0000000..c50753c --- /dev/null +++ b/TP_7_C/exo3-base.c @@ -0,0 +1,33 @@ +#include + +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); +} diff --git a/TP_7_C/exo3-extra.c b/TP_7_C/exo3-extra.c new file mode 100644 index 0000000..36fdb64 --- /dev/null +++ b/TP_7_C/exo3-extra.c @@ -0,0 +1,60 @@ +#include +#include + +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 +} diff --git a/TP_7_C/exo3-full.c b/TP_7_C/exo3-full.c new file mode 100644 index 0000000..4f6eca0 --- /dev/null +++ b/TP_7_C/exo3-full.c @@ -0,0 +1,55 @@ +#include + +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); +}