Progetti di Programmazione II
Università di Torino 1
Indice
Prog1 · Conversione di una stringa in intero in base b 3
Prog2 · Confronto di contatti 5
Prog3 · Coda di char con array circolare dinamico 12
Prog4 · Coda di char con lista concatenata 15
Prog5 · Insieme ordinato di interi con lista concatenata 17
Prog6 · Allocatore di memoria RAM con il metodo buddy 23
SQR · Quadrato di un numero da riga di comando 32
2
Prog1 · Conversione di una stringa in intero in base b
Consegna
Implementare la funzione stoib(s, b, &r;): converte la stringa s in un intero in base b (da 2 a 36). Ignora gli
spazi iniziali e riconosce il segno; si ferma al primo carattere non valido e restituisce il numero di caratteri
letti (0 se non c'è alcun numero valido). Il file main.c contiene cinque test.
File di input
Nessun file di input.
Soluzione
main.c
#include <stdlib.h>
#include <stdio.h>
#include "stoib.h"
const char *TEST_FAILED_LABEL = "TEST FAILED\n";
const char *TEST_PASSED_LABEL = "TEST PASSED\n";
int main() {
int value = 0;
int result = 0;
// Test 1: Controllo parametro della base
result = stoib("10", 1, &value);
if (result != 0) {
fprintf(stderr, "Test1 | Res=%d (Ex %d) - Value=%d", result, 0, value);
printf("%s", TEST_FAILED_LABEL);
return 0;
}
// Test 2: Controllo valore con segno positivo in base 16
result = stoib("A4", 16, &value);
if (result != 2 || value != 164) {
fprintf(stderr, "Test2 | Res=%d (Ex %d) - Value=%d", result, 2, value);
printf("%s", TEST_FAILED_LABEL);
return 0;
}
// Test 3: Controllo valore con segno negativo in base 16
result = stoib(" -A4", 16, &value);
if (result != 5 || value != -164) {
fprintf(stderr, "Test3 | Res=%d (Ex %d) - Value=%d", result, 5, value);
printf("%s", TEST_FAILED_LABEL);
return 0;
}
// Test 4: Controllo valore dei caratteri non validi per la base
result = stoib("125a", 10, &value);
if (result != 3 || value != 125) {
fprintf(stderr, "Test4 | Res=%d (Ex %d) - Value=%d", result, 3, value);
printf("%s", TEST_FAILED_LABEL);
return 0;
}
// Test 5: Controllo valore con caratteri non validi
result = stoib(" +", 10, &value);
if (result != 0) {
fprintf(stderr, "Test5 | Res=%d (Ex %d) - Value=%d", result, 0, value);
printf("%s", TEST_FAILED_LABEL);
return 0;
}
printf("%s", TEST_PASSED_LABEL);
return 0;
}
stoib.c
#include <stdlib.h>
int stoib(char *s, unsigned short b, int *r) {
int charsRead = 0;
// Controllo dei parametri 3
_Bool isBaseCorrect = b >= 2 && b <= 36;
if (s == NULL || !isBaseCorrect || r == NULL) {
return charsRead;
}
int i = 0;
int sign = 1; // Default = +
int result = -1; // -1 = nessun carattere ancora converito
// ignora gli eventuali spazi vuoti all'inizio di s
while (s[i] == ' ' || s[i] == '\n' || s[i] == '\t') {
i++;
charsRead++;
}
// Controllo se il carattere letto è un segno
if (s[i] == '+' || s[i] == '-')
{ if (s[i] == '-') { sign = -1; }
charsRead++;
i++;
}
int convertedChar = -1; // Se uguale a -1, carattere non valido
while (s[i] != '\0')
{ // Converto il carattere nel relativo numero
convertedChar = -1;
if (s[i] >= '0' && s[i] <= '9')
convertedChar = s[i] - '0';
if (s[i] >= 'A' && s[i] <= 'Z')
convertedChar = s[i] - 'A' + 10;
// Se il carattere è valido e lo anche per la base, lo aggiungo al risultato
if (convertedChar != -1 && convertedChar < b) {
if (result == -1) {
result = 0;
}
result = result * b + convertedChar;
charsRead++;
i++;
continue;
}
break;
}
if (result == -1) {
charsRead = 0;
result = 0;
}
*r = sign * result;
return charsRead;
}
stoib.h
int stoib(char *s, unsigned short b, int *r); 4
Prog2 · Confronto di contatti
Consegna
Implementare il confronto tra contatti basato su nome e cognome, senza distinguere maiuscole e
minuscole: contactEq e contactEqEff verificano l'uguaglianza, contactCmp e contactCmpEff ordinano per
cognome e, a parità di cognome, per nome. Se un nome o un cognome è NULL restituiscono -99. Il file
main.c lancia i test.
File di input
Nessun file di input.
Soluzione
main.c
#include <stdlib.h>
#include "contact.h"
int main() {
runTests();
}
contact.c
#include <stdio.h>
#include <string.h>
#include "contact.h"
/* INSERIRE QUI EVENTUALI ALTRI #include <...> */
/* INSERT HERE MORE #include <...> IF NEEDED */
#include <ctype.h>
/* INSERIRE QUI EVENTUALI FUNZIONI AUSILIARIE */
/* INSERT HERE AUXILIARY FUNCTIONS IF NEEDED */
const char *TEST_FAILED_LABEL = "TEST FAILED\n";
const char *TEST_PASSED_LABEL = "TEST PASSED\n";
/**
* @brief Compara due stringhe tra di loro (senza distinzioni sulle minuscole e maiuscole).
* @param s1 La prima stringa.
* @param s2 La seconda stringa.
* @return Ritorna 0 se sono uguali, -1 se s1 < s2 altrimenti 1 se s1 > s2.
*/
int compare_str(const char *s1, const char *s2) {
int i = 0;
while (s1[i] != '\0' && s2[i] != '\0') {
int c1 = toupper(s1[i]);
int c2 = toupper(s2[i]);
if (c1 < c2) {
return -1;
}
if (c1 > c2) {
return 1;
}
i++;
}
int c1 = toupper(s1[i]);
int c2 = toupper(s2[i]);
if (c1 < c2) {
return -1;
}
if (c1 > c2) {
return 1;
}
return 0;
}
/**
* @brief Controlla se due contatti hanno lo stesso nome e cognome.
*
* Restituisce:
* - 1 se i due contatti sono uguali, 0 se sono diversi, -99 se qualche name o surname è NULL 5
*
* @param c1 primo contatto.
* @param c2 secondo contatto.
* @return 1, 0, o -99.
*
* <ENGLISH VERSION>
*
* @brief Checks is two contacts have same name and surname.
*
* Returns:
* - 1 if the contacts are equal, 0 is they are different, -99 is some name o surname is NULL
*
* @param c1 first contact.
* @param c2 second contact.
* @return 1, 0, o -99 (see above).
*/
int contactEq(Contact c1, Contact c2) {
// Controllo del name e surname del primo contatto
if (c1.name == NULL || c1.surname == NULL) {
return -99;
}
// Controllo del name e surname del secondo contatto
if (c2.name == NULL || c2.surname == NULL) {
return -99;
}
// Confronto dei due nomi
_Bool sameName = compare_str(c1.name, c2.name) == 0;
if (!sameName) {
return 0;
}
// Confronto dei due cognomi
_Bool sameSurname = compare_str(c1.surname, c2.surname) == 0;
if (!sameSurname) {
return 0;
}
return 1;
}
/**
* Invoca la funzione contactEq su uno o più casi a scelta, controllando che
* il suo effetto come risultato e argomenti rispetti la specifica corretta.
* Può essere sufficiente anche un unico caso, se sufficientemente generale per
* individuare quali programmi sono corretti e quali no.
* Se la funzione è corretta, come ultima cosa deve stampare "TEST PASSED\n".
* Se invece la funzione non risulta corretta, deve stampare "TEST FAILED\n".
*
* NOTA: questa funzione compare negli errori di compilazione come "student_main"
*
* <ENGLISH VERSION>
*
* Invokes the contactEq function on one or more selected test cases, checking
* that its effect as result and arguments respects the correct specification.
* A single test case may be enough, if it sufficiently general to single out
* which programs are correct and which are not.
* If the function is correct, as the final step it must print "TEST PASSED\n".
* If instead the function is not correct, it must print "TEST FAILED\n".
*
* NOTE: this function appears in compilation errors as "student_main"
*/
int test_contactEq() {
Contact c1;
Contact c2;
c1.name = NULL;
c1.surname = "Rossi";
c2.name = "Giovanni";
c2.surname = NULL;
if (contactEq(c1, c2) != -99) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Verdi";
if (contactEq(c1, c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0; 6
}
c1.name = "Luca";
c1.surname = "Verdi";
c2.name = "Mario";
c2.surname = "Verdi";
if (contactEq(c1, c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Marion";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactEq(c1, c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactEq(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c2.name = "MARIO";
c2.surname = "ROSSI";
if (contactEq(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "";
c1.surname = "";
c2.name = "";
c2.surname = "";
if (contactEq(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
printf("%s", TEST_PASSED_LABEL);
return 0;
}
// come per contactEq
// same as for contactEq
int contactEqEff(const Contact *pc1, const Contact *pc2) {
// Controllo del name e surname del primo contatto
if (pc1->name == NULL || pc1->surname == NULL) {
return -99;
}
// Controllo del name e surname del secondo contatto
if (pc2->name == NULL || pc2->surname == NULL) {
return -99;
}
// Confronto dei due nomi
_Bool sameName = compare_str(pc1->name, pc2->name) == 0;
if (!sameName) {
return 0;
}
// Confronto dei due cognomi
_Bool sameSurname = compare_str(pc1->surname, pc2->surname) == 0;
if (!sameSurname) {
return 0;
}
return 1;
}
// come per test_contactEq
// same as for test_contactEq
int test_contactEqEff() {
Contact c1;
Contact c2; 7
c1.name = NULL;
c1.surname = "Rossi";
c2.name = "Giovanni";
c2.surname = NULL;
if (contactEqEff(&c1, &c2) != -99) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Verdi";
if (contactEqEff(&c1, &c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Luca";
c1.surname = "Verdi";
c2.name = "Mario";
c2.surname = "Verdi";
if (contactEqEff(&c1, &c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Marion";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactEqEff(&c1, &c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactEqEff(&c1, &c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c2.name = "MARIO";
c2.surname = "ROSSI";
if (contactEqEff(&c1, &c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "";
c1.surname = "";
c2.name = "";
c2.surname = "";
if (contactEqEff(&c1, &c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
printf("%s", TEST_PASSED_LABEL);
return 0;
}
// come per contactEq
// same as for contactEq
int contactCmp(Contact c1, Contact c2) {
// Controllo del name e surname del primo contatto
if (c1.name == NULL || c1.surname == NULL) {
return -99;
}
// Controllo del name e surname del secondo contatto
if (c2.name == NULL || c2.surname == NULL) {
return -99;
}
// Confronto dei due cognomi
int surnameCompare = compare_str(c1.surname, c2.surname);
if (surnameCompare != 0) { 8
return surnameCompare;
}
// Confronto dei due nomi
int nameCompare = compare_str(c1.name, c2.name);
if (nameCompare != 0) {
return nameCompare;
}
return 0;
}
// come per test_contactEq
// same as for test_contactEq
int test_contactCmp() {
Contact c1;
Contact c2;
c1.name = NULL;
c1.surname = "Rossi";
c2.name = "Giovanni";
c2.surname = NULL;
if (contactCmp(c1, c2) != -99) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Giovanni";
c2.surname = "Verdi";
if (contactCmp(c1, c2) != -1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactCmp(c1, c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "MARIO";
c1.surname = "ROSSI";
c2.name = "mario";
c2.surname = "rossi";
if (contactCmp(c1, c2) != 0) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mario";
c2.surname = "Arancio";
if (contactCmp(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Zaira";
c1.surname = "Rossi";
c2.name = "Alberto";
c2.surname = "Rossi";
if (contactCmp(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Alberto";
c1.surname = "Rossi";
c2.name = "Zaira";
c2.surname = "Rossi";
if (contactCmp(c1, c2) != -1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
} 9
c1.name = "Mario";
c1.surname = "Ros";
c2.name = "Mario";
c2.surname = "Rossi";
if (contactCmp(c1, c2) != -1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
c1.name = "Mario";
c1.surname = "Rossi";
c2.name = "Mari";
c2.surname = "Rossi";
if (contactCmp(c1, c2) != 1) {
printf("%s", TEST_FAILED_LABEL);
return 0;
}
printf("%s", TEST_PASSED_LABEL);
return 0;
}
// come per test_contactEq
// same as for test_contactEq
int contactCmpEff(const Contact *pc1, const Contact *pc2) {
// Controllo del name e surname del primo contatto
if (pc1->name == NULL || pc1->surname == NULL) {
return -99;
}
// Controllo del name e surname del secondo contatto
if (pc2->name == NULL || pc2->surname == NULL) {
return -99;
}
// Confronto dei due cognomi
int surnameCompare = compare_str(pc1->surname, pc2->surname);
if (surnameCompare != 0) {
return surnameCompare;
}
// Confronto dei due nomi
int nameCompare = compare_str(pc1->name, pc2->name);
if (nameCompare != 0) {
return nameCompare;
}
return 0;
}
// come per test_contactEq
// same as for test_contactEq
int test_contactCmpEff() {
Contact c1;
Contact c2;
<Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.