Formattazione del testo con tag HTML
Adesso pensiamo a come fare la condizione per identificare i caratteri minuscoli. Guardando la tabella ASCII notiamo che le maiuscole sono fra la rappresentazione decimale 65 e la 90. Le minuscole invece sono tra 97 e 122. Possiamo quindi sviluppare lo pseudocodice precedente così:
while (...) {
if (65 <= array[i] <= 90) {
array[i] -= 32;
} else if (97 <= array[i] <= 122) {
array[i] += 32;
}
}
Ecco il programma finale:
#include <stdio.h>
#include <assert.h>
#include <string.h>
int main(void) {
char array[100] = "thiS Is a WORD!";
int i = 0;
while (array[i] != '\0') {
if (array[i] >= 97 && array[i] <= 122) {
array[i] -= 32;
} else if (array[i] >= 65 && array[i] <= 90) {
array[i] += 32;
}
i++;
}
printf("%s\n", array);
assert(strcmp(array, "THIs iS A word!") == 0);
return 0;
}
Franco Masotti, 2023 | https://blog.franco.net.eu.org
string.h strcmp ci serve per chiamare
- Iteriamo tutta la stringa
- Troviamo le minuscole e facciamo la conversione
- Troviamo le maiuscole e facciamo la conversione
assertLa funzione permette di verificare se il nostro algoritmo funziona. Viene spesso usata in fase di debug. Se quello che si trova dentroassertè falso il programma termina immediatamente con un errore. La funzione confronta una stringa con un'altra. Se le due stringhe in input sono uguali la funzione ritorna0. Quindi, usandoassertassieme astrcmppossiamo verificare di aver fatto tutto correttamente- Per risolvere questo esercizio è anche possibile utilizzare le funzioni
isupper,islower,toupper,tolowerdefinite inctype.h.
NOTE qui sotto, anche se in C++, riporta un'altra soluzione che utilizza queste funzioni.
Approfondimento
Qui sotto trovate la soluzione in C++ usando alcune funzioni integrate. La logica è la stessa della soluzione originaria in C.
C.<iostream> #include <assert.h> int main(void) { std::string array = "thiS Is a WORD!"; int i = 0; while (array[i] != '\0') { if (isupper(array[i])) { array[i] = tolower(array[i]); } else if (islower(array[i])) { array[i] = toupper(array[i]); } i++; } std::cout << array; assert(array.compare("THIs iS A word!") == 0); return 0; } Esercizio 2 Consegna: data una stringa (tipo char *) array, invertirla e salvare il risultato in result. Data una stringa (tipo char *) array, invertirla e salvare il risultato in result. #include <stdio.h> int main(void) { char array[100] = "Questa e' una stringa di prova"; char result[100]; int i = 0; while (array[i] != '\0') { i++; } int j = 0; while (i >= 0) { result[j] = array[i]; i--; j++; } printf("%s\n", result); return 0; }
<stdio.h>
#include <stdlib.h>
int main(void) {
char array[100] = "Questa e' una stringa di prova";
char result[100];
int length = 0;
int i, j = 0;
while (array[length] != '\0') {
length++;
}
length--;
for (i = length; i >= 0; i--, j++) {
result[j] = array[i];
}
result[j] = '\0';
printf("%s\n", result);
return 0;
}
Perché:
- devo sottrarre 1 perché in C gli array partono da 0 '\0',
- devo arrivare all'indice della stringa subito prima del carattere quindi devo sottrarre 1 un'altra volta
Partendo dalla fine della stringa vado verso l'inizio e salvo carattere per carattere:
| Franco Masotti, 2023 | https://blog.franco.net.eu.org |
Aggiungo il carattere terminatore alla fine della stringa risultato.
Soluzione alternativa:
È anche possibile invertire una stringa senza calcolare a priori la lunghezza ma comunque scorrendola normalmente dall'inizio fino alla fine. Quando si è giunti alla fine si scorre al contrario salvando carattere per carattere.
#include <stdio.h>
int main(void) {
char array[100] = "Questa è una stringa di prova";
char result[100];
char i = 0, j = 0, done = 0, go_back = 0;
while (!done) {
if (array[i] == '\0') {
go_back = 1;
i--;
}
if (go_back) {
result[j] = array[i];
j++;
i--;
} else {
done = 1;
}
}
result[j] = '\0';
printf("%s\n", result);
return 0;
}
- Una volta arrivati in fondo alla stringa, si va indietro di una posizione per saltare il carattere terminatore. Setto anche il flag che dice di spostare l'indice indietro.
- Salvo un carattere per volta nella stringa result.
- Proseguo sulla casella successiva di result array e sulla casella precedente di array.
- Proseguo sulla casella successiva di array perché devo ancora arrivare alla fine della stringa.
- Setto il flag done per uscire dal ciclo. In questo modo si evita di andare in underflow array leggendo la stringa originale.
Esercizio 3
Consegna
Modificare l'esercizio precedente per fare in modo che la stringa venga letta dall'utente all'interno di un ciclo. EOF Quando l'utente inserisce la stringa il programma deve terminare e si deve il programma e'
terminato. Stampare a video strcmp, strlen, ecc...
Non è consentito usare funzioni quali
Potete usare la traccia precedente.
Soluzione
Possiamo estendere la soluzione precedente mettendola all'interno di un ciclo while, così:
while <non viene letto "EOF">
<inverti stringa>
"EOF\0"
Per sapere se l'utente ha inserito esattamente si può procedere carattere per carattere. Non sapendo a priori la lunghezza della stringa bisogna controllare di non '\0' raggiungere il carattere terminatore.
Possiamo migliorare lo pseudocodice precedente con questo:
done = false;
while (!done) {
scanf ...
if (array[0] != '\0' && array[0] == 'E' && array[1] != '\0' && array[1] == 'O' && array[2] != '\0' && array[2] == 'F' && array[3] != '\0')
done = true;
else
<inverti stringa>
}
E,
8 | Franco Masotti, 2023 | https://blog.franco.net.eu.org
per finire, ecco il codice completo:
<stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main(void) {
char array[100];
char result[100];
bool done = false;
int length = 0, i, j;
while (!done) {
length = 0;
done = false;
printf("inserire una stringa da invertire (EOF per uscire, max 99 caratteri): ");
scanf("%s", array);
if (array[0] != '\0' && array[0] == 'E' && array[1] != '\0' && array[1] == 'O' && array[2] != '\0' && array[2] == 'F' && array[3] == '\0') {
done = true;
printf("il programma e' terminato\n");
}
if (!done) {
while (array[length] != '\0') {
length++;
}
length--;
j = 0;
for (i = length; i >= 0; i--, j++) {
result[j] = array[i];
}
result[j] = '\0';
printf("risultato: %s\n", result);
}
}
return 0;
}
Franco Masotti, 2023 | https://blog.franco.net.eu.org | 9viene settato il flag② scanf
Usiamo il classico③ "EOF\0"
Controllo se l’utente ha immesso esattamente④ if
Il codice all’interno dell’ <code> </code> è uguale a quello dell’esercizio precedente.
scanf non c’è nessun controllo di overflow con la stringa!
Usando Infatti inserendo troppi caratteri si incappa in un errore di scanf %s segmentazione. Inoltre la funzione con ignora gli spazi
WARNING scanf non è una funzione
prima e dopo la stringa. In generalesicura ma è comunque adatta per spiegare questi problemiintroduttivi.
Esercizio 4
Consegna
Data una stringa controllare se è palindroma.
Una parola palindroma si legge allo stesso modo da sinistra a destra e da destra a sinistra: per esempio, è una parola palindroma.
Il programma non deve prevedere la gestione dei caratteri whitespace: per esempio onora rono non deve risultare come palindromo.
main true false
La funzione deve ritornare se è palindroma oppure se non lo è.
#include <stdio.h>
#include <stdbool.h>
int main(void) {
// La stringa è di 128 caratteri + 1 carattere terminatore di stringa.
char array[129] = "EaQDQeLCUsddXqFOUjFMcFPUxNZzdtuctIIKZzOmDyxHoNDbqtaT"
"oBAbWBCoIqDzzDqIoCBWbABoTatqbDNoHxyDmOzZKIItcutdzZNx"
"UPFcMFjUOFqXddsUCLeQDQaE";
bool palindrome;