[C] Esercizio Stringhe
Ciao a tutti
ho questo esercizio in c sulle stringhe:
"Sono date due stringhe s1 e s2. Inserire in una terza stringa u i caratteri di s1 e di s2 alternativamente; quando la stringa più breve tra s1 e s2 si è esaurita, inserire in u ogni carattere dell'altra stringa. Es. I: abc 1234 O: a1b2c34 "
Allora io ho fatto questo:
Qualcuno mi può aiutare a capire dove sbaglio?

"Sono date due stringhe s1 e s2. Inserire in una terza stringa u i caratteri di s1 e di s2 alternativamente; quando la stringa più breve tra s1 e s2 si è esaurita, inserire in u ogni carattere dell'altra stringa. Es. I: abc 1234 O: a1b2c34 "
Allora io ho fatto questo:
void ins(char *s1,char *s2,char* u) { int i; for(i=0;s1[i]!='\0'||s2!='\0';i++){ strcat(u,s1[i]); strcat(u,s2[i]); } if(i==strlen(s1)-1) { for(;s2!='\0';i++) strcat(u,s2[i]); } else if(i==strlen(s2)-1) { for(;s1!='\0';i++) strcat(u,s1[i]); } }
Qualcuno mi può aiutare a capire dove sbaglio?

Risposte
Ciao
ho la vaga impressione che tu ti sia complicato tanto la vita.
La prima cosa che noto è che hai usato delle funzioni della libreria string.h che, per quanto valide, non serve andare a scomodare.
Ti è sufficiente fare tutto con qualche simpatico puntatore
Premetto che il codice che segue è abbastanza grezzo e non include tanti controlli sulle stringhe sarebbero stati opportuni, ma in linea di massima funziona.
Che ne dici?
ho la vaga impressione che tu ti sia complicato tanto la vita.

La prima cosa che noto è che hai usato delle funzioni della libreria string.h che, per quanto valide, non serve andare a scomodare.
Ti è sufficiente fare tutto con qualche simpatico puntatore
Premetto che il codice che segue è abbastanza grezzo e non include tanti controlli sulle stringhe sarebbero stati opportuni, ma in linea di massima funziona.
void ins (char *s1, char *s2, char *u) { unsigned char s1ptr; unsigned char s2ptr; unsigned char uptr; unsigned char stop; s1ptr = 0; s2ptr = 0; uptr = 0; stop = 0; while(stop == 0) { stop = 1; //Presumo che entrambe le stringhe siano terminate. Il valore di questa variabile verrà cambiato se almeno una delle due stringe non è terminata if (s1[s1ptr] != '\0') //Se la prima stringa è terminata non la considero { stop = 0; u[uptr++] = s1[s1ptr++] ; } if (s2[s2ptr] != '\0') //Se la seconda stringa è terminata non la considero { stop = 0; u[uptr++] = s2[s2ptr++] ; } } u[uptr] = '\0'; //Chiudi la stringa di destinazione } int main (void) { char sa[6]; //Stringa in ingresso con dimensione maggiorata di uno rispetto a quella desiderata per poter includere il carattere \0 char sb[6]; //Stringa in ingresso con dimensione maggiorata di uno rispetto a quella desiderata per poter includere il carattere \0 char x[20]; //dimensione impostata volutamente molto grande per poter contenere l'unione delle due stringhe //Popolo la prima stringa sa[0] = '0'; sa[1] = '1'; sa[2] = '2'; sa[3] = '3'; sa[4] = '4'; sa[5] = '\0'; //Popolo la seconda stringa sb[0] = 'a'; sb[1] = 'b'; sb[2] = 'c'; sb[3] = 'd'; sb[4] = 'e'; sb[5] = '\0'; ins (sa, sb, x); return 0; }
Che ne dici?
grazie molto chiaro

"Summerwind78":
Ciao
ho la vaga impressione che tu ti sia complicato tanto la vita.![]()
La prima cosa che noto è che hai usato delle funzioni della libreria string.h che, per quanto valide, non serve andare a scomodare.
Ti è sufficiente fare tutto con qualche simpatico puntatore
Premetto che il codice che segue è abbastanza grezzo e non include tanti controlli sulle stringhe sarebbero stati opportuni, ma in linea di massima funziona.
void ins (char *s1, char *s2, char *u) { unsigned char s1ptr; unsigned char s2ptr; unsigned char uptr; unsigned char stop; s1ptr = 0; s2ptr = 0; uptr = 0; stop = 0; while(stop == 0) { stop = 1; //Presumo che entrambe le stringhe siano terminate. Il valore di questa variabile verrà cambiato se almeno una delle due stringe non è terminata if (s1[s1ptr] != '\0') //Se la prima stringa è terminata non la considero { stop = 0; u[uptr++] = s1[s1ptr++] ; } if (s2[s2ptr] != '\0') //Se la seconda stringa è terminata non la considero { stop = 0; u[uptr++] = s2[s2ptr++] ; } } u[uptr] = '\0'; //Chiudi la stringa di destinazione } int main (void) { char sa[6]; //Stringa in ingresso con dimensione maggiorata di uno rispetto a quella desiderata per poter includere il carattere \0 char sb[6]; //Stringa in ingresso con dimensione maggiorata di uno rispetto a quella desiderata per poter includere il carattere \0 char x[20]; //dimensione impostata volutamente molto grande per poter contenere l'unione delle due stringhe //Popolo la prima stringa sa[0] = '0'; sa[1] = '1'; sa[2] = '2'; sa[3] = '3'; sa[4] = '4'; sa[5] = '\0'; //Popolo la seconda stringa sb[0] = 'a'; sb[1] = 'b'; sb[2] = 'c'; sb[3] = 'd'; sb[4] = 'e'; sb[5] = '\0'; ins (sa, sb, x); return 0; }
Che ne dici?
Perché usi dei [inline]unsigned char[/inline] per la dimensione della stringa? Sembra una ottimizzazione, ma in realtà rende solo il codice più soggetto a problemi. Per esempio non puoi fare questa operazione su stringhe più grandi di poche centinaia di caratteri. Inoltre per ridurre l'uso di memoria è sufficiente eliminare quelle variabili e usare direttamente i puntatori per tutto. Per esempio come ho fatto qui (il codice è basato sul tuo)
void ins(const char * s1, const char * s2, char * u) { if (!u) { return; } if (!s1) { s1 = ""; } if (!s2) { s2 = ""; } while (*s1 != '\0' || *s2 != '\0') { if (*s1 != '\0') { *(u++) = *(s1++); } if (*s2 != '\0') { *(u++) = *(s2++); } } *u = '\0'; } int main(void) { const char sa[] = "01234"; const char sb[] = "abcdefghil"; char x[50] = ""; ins("", "", x); puts(x); // "" ins(NULL, NULL, x); puts(x); // "" ins(sa, "", x); puts(x); // 01234 ins("", sb, x); puts(x); // abcdefghil ins(NULL, sb, x); puts(x); // abcdefghil ins(sa, NULL, x); puts(x); // 01234 ins(sa, sb, x); puts(x); // 0a1b2c3d4efghil ins(sb, sa, x); puts(x); // a0b1c2d3e4fghil ins(sa, sa, x); puts(x); // 0011223344 ins(sb, sb, x); puts(x); // aabbccddeeffgghhiill }In questo codice ho aggiunto qualche controllo sui puntatori, ma sarebbe buona norma passare la dimensione di [inline]u[/inline] alla funzione [inline]ins[/inline].
Ciao
come ho premesso nel mio precedente messaggio, la funzione sarebbe stata molto ottimizzabile.
Il fatto che io abbia usato un unsigned char al posto di un char, deriva dal fatto che la dimensione in memoria di una variabile dipende dal compilatore.
Io, per lavoro, sono abituato a lavorare su microcontrollori il cui compilatore solitamente distingue il char dall'unsigned char solamente per l'uso del segno, ma in entrambi i casi sono variabili a 8 bit; pertanto sufficienti per contenere il valore del carattere stampabile da tabella ASCII.
come ho premesso nel mio precedente messaggio, la funzione sarebbe stata molto ottimizzabile.
Il fatto che io abbia usato un unsigned char al posto di un char, deriva dal fatto che la dimensione in memoria di una variabile dipende dal compilatore.
Io, per lavoro, sono abituato a lavorare su microcontrollori il cui compilatore solitamente distingue il char dall'unsigned char solamente per l'uso del segno, ma in entrambi i casi sono variabili a 8 bit; pertanto sufficienti per contenere il valore del carattere stampabile da tabella ASCII.
Non ho capito la connessione tra il mio commento e la tua risposta. Io mi riferivo al fatto che uptr è un unsigned char ed è usato come indice di un array. Se la stringa è più grande del massimo valore che può essere memorizzato in un unsigned char ti potresti trovare con un ciclo infinito. Lo stesso problema esiste con qualsiasi variabile di indice la cui dimensione sia minore di quella del tipo puntatore. Usare una variabile di dimensione più piccola non è necessariamente sbagliato, ma devi essere consapevole che aggiunge una precondizione ai parametri di input.
In effetti hai ragione, avevo frainteso il commento.
L'ho riletto e mi sono accorto di aver capito male io.
La prima parte della mia risposta rimane valida. Il mio codice era un'indicazione molto migliorabile, cosa che ho detto subito.
L'ho riletto e mi sono accorto di aver capito male io.
La prima parte della mia risposta rimane valida. Il mio codice era un'indicazione molto migliorabile, cosa che ho detto subito.
Sì certo, ho commentato solo perché è qualcosa che un principiante, in questo caso ilsaggio, non impari a fare. Per lo meno finché non comprende a pieno i concetti base.