Comparsa di caratteri non voluti

di il
33 risposte

Comparsa di caratteri non voluti

Come mai nell'output ottengo dei caratteri non voluti. Questi sono "y·?" (quelli tra virgolette) ma cambiano ad ogni nuova esecuzione del programma. "xl?" etc...
Inserire un testo di massimo 500 caratteri terminate con il carattere "a capo":

Ho notato che a volte, nell'unione di due stringhe mi escono dei caratteri strani.

La lunghezza di stringa1 e': 82

Inserire un nuovo testo di massimo 500 caratteri terminate con il carattere "a capo":

Come mai succede questo?

La lunghezza di stringa2 e': 24

Ho notato che a volte, nell'unione di due stringhe mi escono dei caratteri strani.

Come mai succede questo?

Le 2 stringhe in una sono:

Ho notato che a volte, nell'unione di due stringhe mi escono dei caratteri strani. Come mai succede questo?y·

La lunghezza della stringa risultante e': 110




Vuoi procedere con l'esercizio successivo? 0 per continuare, -1 per terminare: -1


Time elapsed: 000:32:984
Press any key to continue
Riporto il codice:
#include <stdio.h>
#include <string.h>
#define DIM 500

int lunghezza(char a[]) {  // calcola la lunghezza della stringa
	int i = 0;
	for(i = 0; a[i] != '\0'; ++i);
	return i;
}

void attaccaStringhe(char a[], char b[]) {  // attacca la stringa b alla stringa a
	char unione[2 * DIM];
	int lungA = lunghezza(a);
	int lungB = lunghezza(b);
	int k = 0;
	for(int i = 0; i < lungA; ++i) {
		unione[k] = a[i];
		++k;
	}
	unione[k] = ' ';
	++k;
	for(int j = 0; j < lungB; ++j) {
		unione[k] = b[j];
		++k;
	}
	puts(unione);
	printf("\nLa lunghezza della stringa risultante e': %d\n", lunghezza(unione));
}

void sovrascrStringhe(char a[], char b[]) {  // sovrascrive la stringa b con la stringa a
	int dimA = lunghezza(a);
	for(int i = 0; i < dimA; ++i) {
		b[i] = a[i];
	}
	puts(b);
	printf("Sono stati sovrascritti in tutto %d caratteri della prima stringa nella seconda", dimA);
}

int main() {
	char stringa1[DIM];
	char stringa2[DIM];
	char stringa3[DIM];
	char stringa4[DIM];
	printf("Inserire un testo di massimo %d caratteri terminate con il carattere \"a capo\":\n\n", DIM);
	scanf(" %[^\n]", stringa1);
	puts("");
	printf("La lunghezza di stringa1 e':  %d\n\n", lunghezza(stringa1));
	printf("Inserire un nuovo testo di massimo %d caratteri terminate con il carattere \"a capo\":\n\n", DIM);
	scanf(" %[^\n]", stringa2);
	puts("");	
	printf("La lunghezza di stringa2 e':  %d\n\n", lunghezza(stringa2));
	puts(stringa1);
	puts("");
	puts(stringa2);
	puts("\nLe 2 stringhe in una sono:\n");
	attaccaStringhe(stringa1, stringa2);
	int nuovoEsercizio = 0;
	printf("\n\n\n\nVuoi procedere con l'esercizio successivo? 0 per continuare, -1 per terminare:  ");
	scanf("%d", &nuovoEsercizio);	
	if(nuovoEsercizio == 0) {
		char stringa[DIM];
		int riprova = 0;
		while(riprova != -1) {
			printf("\nInserire una stringa di massimo %d caratteri compresi gli spazi ", DIM);
			printf("e ne verra' calcolata la lunghezza\nInserisci la stringa:\n\n");
			scanf(" %[^\n]", stringa);
			int l = lunghezza(stringa);
			printf("\nLa lunghezza della stringa e':  %d", l);		
			printf("\nVuoi riprovare con un'altra stringa? 1 per riprovare, -1 per terminare:  ");
			scanf("%d", &riprova);
			while(getchar() != '\n');
		}
		printf("\n\n\n\nVuoi procedere con l'esercizio successivo? 0 per continuare, -1 per terminare:  ");
		scanf("%d", &nuovoEsercizio);		
		if(nuovoEsercizio == 0) {
			printf("\nInserire una stringa di massimo %d caratteri compresi gli spazi:\n\n", DIM);	
			scanf(" %[^\n]", stringa3);
			int l3 = lunghezza(stringa3);
			printf("\nLa lunghezza della stringa e':  %d\n", l3);		
			printf("\nInserire una stringa di massimo %d caratteri compresi gli spazi:\n\n", DIM);	
			scanf(" %[^\n]", stringa4);
			int l4 = lunghezza(stringa4);
			printf("\nLa lunghezza della stringa e':  %d\n", l4);	
			printf("\n\nLa seconda stringa sulla quale e' stata sovrascritta la prima e':\n");
			sovrascrStringhe(stringa3, stringa4);
		}
	}
	puts("\n");
	return 0;
}

// Si era commesso l'errore di non mettere lo spazio che comunque poteva essere risolto 
// pulendo il buffer con la getchar(). Comunque funziona sia con entrambe le soluzione 
// oppure solo con una o l'altra.
Grazie

33 Risposte

  • Re: Comparsa di caratteri non voluti

    Risposta breve:
    ti sei dimenticato di terminare la stringa risultante

    risposta lunga:
    oltra a non terminare la stringa risutante, che è la causa dl tuo problema hai anche scritto funzioni un po' poverelle
    per un clone della strcat() si potrebbe fare qualcosa di più

    cominciamo dalla lunghezza(), clone della strlen()
    size_t lunghezza(char * stringa)
    {
       size_t i=0;
       while(stringa[i++]);
       return i;
    }
    prova a vedere se fa giusto o se sbaglia di uno,
    che comunque la lunghezza() non è espressamente necessaria per "clonare" la strcat()
    attaccastringa(char * a, char * b)
    {
       char c[dimensionecalcolata];
       int i=0;
       int j=0;
       while(a[i])
       {
          c[j++]=a[i++];
       }
       i=0;
       c[j++]=' ';
       while(b[i])
       {
          c[j++]=b[i++];
       }
       c[j]=0;
    } 
    vedi un po' se ti ritrovi........
  • Re: Comparsa di caratteri non voluti

    size_t lunghezza(char * stringa)
    {
       size_t i=0;
       while(stringa[i++]);
       return i;
    }
    Scusa ma non manca il valore booleano??? Se non capisco questo non capisco niente del codice che hai scritto perchè lo stesso è stato fatto per attacastringhe!...P.S.scusa l'ignoranza...!
  • Re: Comparsa di caratteri non voluti

    Pensa a queste semplici domande:
    1) quanto vale successivamente I? (successivamente: passo a passo)
    2) quanto vale successivamente stringa[i++]?
    3) e quando la stringa è finita?

    e invece rispondi a queste:
    come hai studiato 'C'? autodidatta? università?, come?
    hai letto K&R?
  • Re: Comparsa di caratteri non voluti

    JackieJack1207 ha scritto:


    size_t lunghezza(char * stringa)
    {
       size_t i=0;
       while(stringa[i++]);
       return i;
    }
    Scusa ma non manca il valore booleano??? Se non capisco questo non capisco niente del codice che hai scritto perchè lo stesso è stato fatto per attacastringhe!...P.S.scusa l'ignoranza...!
    Mi aggiungo alle domande che StandardOil, giustamente, ti pone.

    In C (come in C++) c’è questa bruttissima cosa di poter convertire interi e puntatori in booleani implicitamente (anzi, il tipo _Bool comparirà solo più avanti in C e il "booleano" non è che un intero diverso da 0).
    Siccome un char non è che un tipo intero, questo è utilizzabile in aspetti booleani senza problemi. In caso di carattere di terminazione '\0', il cui valore ASCII è proprio 0, corrisponde il valore booleano false.
    La condizione esiste quindi, anche se in modo implicito; raggiunto un carattere di terminazione l’esecuzione esce dal ciclo e ritorna i nonché la lunghezza della stringa.
  • Re: Comparsa di caratteri non voluti

    Macché bruttissima cosa

    La concisione è il bello del C

    K&R lo facevano -> io lo faccio
  • Re: Comparsa di caratteri non voluti

    StandardOil ha scritto:


    Macché bruttissima cosa

    La concisione è il bello del C

    K&R lo facevano -> io lo faccio
    La mancanza di type safe è uno dei difetti del C, non a caso tutti i linguaggi la hanno superata e sono così type safe da non concedere quasi più nulla, ed è giusto così.
    Considerare un puntatore NULL (o nullptr) come falso e qualsiasi altro come vero è uno degli obbrobri che ancora affliggono C e C++, basta sicuramente farci la mano ma alla prima vista confonde sulla natura della condizione in sé.
  • Re: Comparsa di caratteri non voluti

    _Achille ha scritto:


    StandardOil ha scritto:


    Macché bruttissima cosa

    La concisione è il bello del C

    K&R lo facevano -> io lo faccio
    La mancanza di type safe è uno dei difetti del C, non a caso tutti i linguaggi la hanno superata e sono così type safe da non concedere quasi più nulla, ed è giusto così.
    Considerare un puntatore NULL (o nullptr) come falso e qualsiasi altro come vero è uno degli obbrobri che ancora affliggono C e C++, basta sicuramente farci la mano ma alla prima vista confonde sulla natura della condizione in sé.
    Guarda che il boolean non esiste: alla fine della fiera in linguaggio macchina sarà sempre qualche registro a 8, 16, 32 o 64 bit diverso oppure uguale a zero.
    E non è che la mancanza di type safety sia un obbrobrio e uno svantaggio sempre e comunque: su PC sicuramente, ma prova a programmare un DSP dove hai i microsecondi contati...
  • Re: Comparsa di caratteri non voluti

    Senza nulla togliere a nessuno

    Ma se voglio un linguaggio type safe non uso il C

    Se uso il C.....
  • Re: Comparsa di caratteri non voluti

    _Achille ha scritto:


    JackieJack1207 ha scritto:


    size_t lunghezza(char * stringa)
    {
       size_t i=0;
       while(stringa[i++]);
       return i;
    }
    Scusa ma non manca il valore booleano??? Se non capisco questo non capisco niente del codice che hai scritto perchè lo stesso è stato fatto per attacastringhe!...P.S.scusa l'ignoranza...!
    Mi aggiungo alle domande che StandardOil, giustamente, ti pone.

    In C (come in C++) c’è questa bruttissima cosa di poter convertire interi e puntatori in booleani implicitamente (anzi, il tipo _Bool comparirà solo più avanti in C e il "booleano" non è che un intero diverso da 0).
    Siccome un char non è che un tipo intero, questo è utilizzabile in aspetti booleani senza problemi. In caso di carattere di terminazione '\0', il cui valore ASCII è proprio 0, corrisponde il valore booleano false.
    La condizione esiste quindi, anche se in modo implicito; raggiunto un carattere di terminazione l’esecuzione esce dal ciclo e ritorna i nonché la lunghezza della stringa.
    OK, detto ciò, omettere il valore booleano corrisponde a "false" e nel caso delle stringhe corrisponde al raggiungere il carattere di terminazione '\0'. Giusto?

    Pensa a queste semplici domande:
    1) quanto vale successivamente I? (successivamente: passo a passo)
    2) quanto vale successivamente stringa[i++]?
    3) e quando la stringa è finita?

    RISPOSTA: i parte da 0 fuori dal ciclo while. Nel ciclo while, crescerà ogni volta che un carattere sarà diverso da quello di terminazione e varrà alla fine la dimensione della stringa occupata dai caratteri meno il carattere di terminazione, condizione che farà terminare il while in quanto stringa sarà uguale a '\0' cioè falso, dunque fine del while. Dunque otterremo la lunghezza della stringa.

    e invece rispondi a queste:
    come hai studiato 'C'? autodidatta? università?, come? RISPOSTA: Università in corso da 9 cfu totali. Non ho letto k&k ma il Deitel: "Il linguaggio C"
    hai letto K&R?

    Cmq grazie per l'annotazione sui valori booleani. Ora posso continuare con l'analisi del suggerimento ricevuto.
  • Re: Comparsa di caratteri non voluti

    StandardOil ha scritto:


    Risposta breve:
    ti sei dimenticato di terminare la stringa risultante

    risposta lunga:
    oltra a non terminare la stringa risutante, che è la causa dl tuo problema hai anche scritto funzioni un po' poverelle
    per un clone della strcat() si potrebbe fare qualcosa di più

    cominciamo dalla lunghezza(), clone della strlen()
    size_t lunghezza(char * stringa)
    {
       size_t i=0;
       while(stringa[i++]);
       return i;
    }
    prova a vedere se fa giusto o se sbaglia di uno,
    che comunque la lunghezza() non è espressamente necessaria per "clonare" la strcat()
    attaccastringa(char * a, char * b)
    {
       char c[dimensionecalcolata];
       int i=0;
       int j=0;
       while(a[i])
       {
          c[j++]=a[i++];
       }
       i=0;
       c[j++]=' ';
       while(b[i])
       {
          c[j++]=b[i++];
       }
       c[j]=0;
    } 
    vedi un po' se ti ritrovi........
    Per rispondere alla correzione breve, ho corretto così il codice:
    void attaccaStringhe(char a[], char b[]) {  // attacca la stringa b alla stringa a
    	char unione[2 * DIM];
    	int lungA = lunghezza(a);
    	int lungB = lunghezza(b);
    	int k = 0;
    	for(int i = 0; i < lungA; ++i) {
    		unione[k] = a[i];
    		++k;
    	}
    	unione[k] = ' ';
    	++k;
    	for(int j = 0; j < lungB; ++j) {
    		unione[k] = b[j];
    		++k;
    	}
    	unione[k] = '\0';
    	puts(unione);
    	printf("\nLa lunghezza della stringa risultante e': %d\n", lunghezza(unione));
    }
    aggiungendo dunque
    unione[k] = '\0';
    . Funziona e grazie!!

    Per quanto riguarda il resto dell'appunto fatto nella tua correzione devo dire che per me il modo di inserire un'istruzione dentro un array è piuttosto una sorpresa per me, dato che non l'avevo mai vista prima.
    c[j++]=a[i++];
    qui per esempio. Ne prendo nota e vado avanti Grazie comunque!
  • Re: Comparsa di caratteri non voluti

    Inserire un'istruzione dentro un array? Ma che vuol dire?
  • Re: Comparsa di caratteri non voluti

    oregon ha scritto:


    Inserire un'istruzione dentro un array? Ma che vuol dire?
    In questo caso:
    c[j++]=a[i++];
    ed in questo:
    while(stringa[i++]);
    è stata messa l'istruzione
    i += 1;
    dentro le parentesi quadre dell'array. Dunque stringa[i++] non ha solo il significato della iesima posizione nella stringa ma anche di incrementare i di 1 ad ogni ciclo. Questa sintassi non l'avevo mai vista. Mi sono spiegato?
  • Re: Comparsa di caratteri non voluti

    Non c'è sul Deitel?

    Che libro povero
  • Re: Comparsa di caratteri non voluti

    StandardOil ha scritto:


    Non c'è sul Deitel?

    Che libro povero
    costa 39 euro . Comunque che libro è il K&K?? Su internet qualcosa che gli assomiglia come nome è "Programmazione in C" di Kim N. King... ma non so se è questo quello che dite voi.
Devi accedere o registrarti per scrivere nel forum
33 risposte