C: funzione "consecutivi"

matteomors
Ciao a tutti!E' il mio primo post in questa sezione scusatemi per eventuali errori...

Ho creato una funzione in C che conta quante volte i parametri "k" e "l" sono presenti CONSECUTIVAMENTE in "p"(stringa).

Il codice è questo :

#include
#include
int consecutivi(char p[],char k,char l){
int i=0;
int cont=0;
while (p!='\0'){
if ((p==k)&&(p[i+1]==l) || (p==l)&&(p[i+1]==k))
cont++;
i++;}
return cont;}


int main(int argc, char *argv[])
{

char p[21];
char m,n;
int d;
printf("inserisci la stringa\n");
scanf("%s",p);
printf("inserisci k\n");
scanf("%1s",&m);
printf("icnserisci l\n");
scanf("%1s",&n);
d=consecutivi(p,m,n);
printf("%d",d);

system("PAUSE");
return 0;
}


E il problema è che mi ritorna sempre 0 come risultato,qualsiasi combinazione di parametri passo...perchè?grazie:)!

Risposte
Rggb1
"matteomors":
E il problema è che mi ritorna sempre 0 come risultato,qualsiasi combinazione di parametri passo...perchè?grazie:)!


Un consiglio: invece sempre di chiedere "come mai questo codice non funziona bla bla..." seguito da un listato completo (ho visto spesso in vari forum, anche qui, post interminabili con centinaia di righe, oltre a essere illeggibili erano senza commento), puoi cercare sempre di arrivare da solo al problema:
- usi un debugger
- non sei un progammatore e/o non hai tempo/voglia di usare strumenti di debug: aggiungi linee di codice di controllo.

Nel tuo caso, prova a far stampare i tuoi parametri di input dopo averli letti (va benissimo una printf); se sono corretti, prova a stampare un messaggio all'interno del ciclo di controllo...

Se poi non ne vieni ancora a capo, fammi sapere. Buon lavoro ;)

apatriarca
Ci sono alcuni gravi errori nella lettura dei valori:
1. Un singolo carattere NON è una stringa di dimensione uno in quanto una stringa in C deve sempre terminare con il carattere '\n'. %s serve per leggere una stringa (ed è tra i peggiori metodi per farlo) e non per leggere un singolo carattere come è stato fatto nel tuo codice.
2. Il secondo problema è che scanf("%s", p) non effettua alcun controllo sulla dimensione dell'input.

Il metodo più semplice per risolvere il problema di lettura è quello di modificare un po' il codice (anche se non so quanto tu possa farlo). La lettura di singolo caratteri presenta infatti diversi problemi ed è quindi più conveniente usare due stringhe, nella prima memorizzi la frase e nella seconda i caratteri:
int main()
{
    char testo[21];
    char lettere[3];

    puts("Scrivi il testo (MAX 20 caratteri).");
    fgets(testo, 21, stdin);
    puts("Inserisci k e l consecutivamente e premi invio.");
    fgets(lettere, 3, stdin);
    
    d = consecutivi(testo, lettere[0], lettere[1]);
    printf("%d\n", d);

    return 0;
}

puts è una funzione che visualizza una stringa su console e va a capo subito dopo, mentre fgets è una funzione che legge una riga dalla console (fino a riempire il buffer).

Utilizza il tag code per inserire il testo e cerca di formattare il codice in modo appropriato in modo da rendere la lettura più agevole. Il resto del codice mi sembra corretto e quindi dovrebbe funzionare.

Rggb1
Credevo la mia risposta venisse meglio vagliata... Comunque a parte le considerazioni su cosa è meglio e cosa no in fatto di scrittura in linguaggio C, sulle quali discuterei ad ore - anche io ho delle belle fisse - devo dire che alcune cose a volte mi lasciano basito.
"apatriarca":
1. Un singolo carattere NON è una stringa di dimensione uno in quanto una stringa in C deve sempre terminare con il carattere '\n'. %s serve per leggere una stringa (ed è tra i peggiori metodi per farlo) e non per leggere un singolo carattere come è stato fatto nel tuo codice.
2. Il secondo problema è che scanf("%s", p) non effettua alcun controllo sulla dimensione dell'input.

- una stringa in C deve terminare con newline... sei sicuro? Io ero rimasto allo zero (0x0, byte zero, NULL, chiamalo come vuoi)
- per quale motivo un carattere non può essere considerato una "stringa di dimensione uno" se si intende che si ferma la sua scansione dopo un solo carattere (ie. senza attendere il byte zero finale), oppure se ci si assicura che sia zero-terminata?

Ma poi... il codice funziona? Sicuro? Hai provato? ;-)

apatriarca
Comunque a parte le considerazioni su cosa è meglio e cosa no in fatto di scrittura in linguaggio C, sulle quali discuterei ad ore - anche io ho delle belle fisse - devo dire che alcune cose a volte mi lasciano basito.

L'uso di scanf per la lettura di stringhe è fortemente sconsigliato da chiunque. Puoi pensarla come vuoi, ma è un metodo inefficiente e poco sicuro perché non verifica le dimensioni dell'array. Non si tratta di una "fissa". L'altro è invece proprio un errore.

una stringa in C deve terminare con newline... sei sicuro? Io ero rimasto allo zero (0x0, byte zero, NULL, chiamalo come vuoi)

Ho inserito il carattere sbagliato nel post. Termina con '\0'.

per quale motivo un carattere non può essere considerato una "stringa di dimensione uno" se si intende che si ferma la sua scansione dopo un solo carattere (ie. senza attendere il byte zero finale), oppure se ci si assicura che sia zero-terminata?

Non può essere considerata una stringa di dimensione uno perché il tipo è diverso. In un caso hai un array di due elementi di cui il secondo è '\0' mentre nell'altro hai un singolo carattere. Utilizzando scanf("%1s", &k) per leggere un singolo carattere scrivi sia su k che sul byte successivo corrompendo lo stack, scanf aggiunge infatti sempre il terminatore di stringa. L'affermazione è comunque valida anche nel caso in cui venga usata una notazione diversa per le stringhe e questa differenza esiste in credo qualsiasi linguaggio di programmazione.

A parte essermi dimenticato di dichiarare d, il codice viene compilato correttamente e restituisce il risultato corretto sul mio PC. In realtà, a parte un errore alla chiusura dell'applicazione in cui vengo informato che lo stack è corrotto, anche il codice postato ha sempre restituito il risultato corretto nelle poche prove che ho fatto.

Che compilatore utilizzi? Che cosa inserisci in input?

matteomors
Infatti gli input me li prende tutti...
allora inserisco ad esempio "ciccione","c","i" e il risultato dovrebbe essere 3!

Allora dici che è un errore del compilatore?
Come faccio a capire quale utilizzo ?thks!

Umby2
"matteomors":
Infatti gli input me li prende tutti...
allora inserisco ad esempio "ciccione","c","i" e il risultato dovrebbe essere 3!

Allora dici che è un errore del compilatore?
Come faccio a capire quale utilizzo ?thks!


perchè 3?
devi contare i caratteri oppure la "massima consecutività" ?

AABBBCBBCCABABABACCCCCRTRIUJKMJNCCCOOOLLLACPPPPQQQQ

In questo caso, ad esempio, vuoi che il programma ti restituisca 5 ? Ovvero la massima consecutività del carattere C ?

matteomors
No no quante volte appaiono consecutivamente i due caratteri inseriti nella stringa.
se ci fai caso in "ciccione" con input "c" e "i" il risultato dovrebbe essere 3:ciccione -> CIccione+cICcione+cicCIone :)

Infatti mi han detto che funziona anche se non ho scritto bene...sarà il mio compilatore che fa schifo...dove lo vedo qual'è?

Umby2
Ora mi è chiaro, cosa ti interessa. :wink:

matteomors
:) sai dirmi come faccio a sapere qual'è il mio compilatore?e se è il caso che lo cambi visto che ad altri funziona e a me no?

apatriarca
Infatti gli input me li prende tutti...

Lo fa, ma corrompe lo stack. Se proprio vuoi leggere in quel modo i caratteri definiscili come stringhe di due caratteri e poi passa il primo carattere delle due stringhe alla funzione.

allora inserisco ad esempio "ciccione","c","i" e il risultato dovrebbe essere 3!

A me con "ciccione" e "ci" funziona correttamente, quindi il problema è in effetti probabilmente nel tuo computer. Se non conosci il tuo compilatore, probabilmente stai utilizzando un qualche IDE, cosa utilizzi per scrivere e lanciare il codice? Scommetto che si tratta di DevC++. Su che sistema operativo stai lavorando?

matteomors
esatto è DevC++, e il sistema operativo è vista :(!

apatriarca
Dev-C++ è un progetto abbandonato da anni e ha grosse incompatibilità con Windows Vista mai risolte. Sei quindi costretto a passare ad un qualche altro ambiente di sviluppo. Io utilizzo Visual Studio della Microsoft (del quale esiste una versione gratuita), ma ci sono molte altre alternative. Per esempio CodeBlocks se vuoi rimanere su software open source.

Rggb1
L'uso di scanf per la lettura di stringhe è fortemente sconsigliato da chiunque. Puoi pensarla come vuoi, ma è un metodo inefficiente e poco sicuro perché non verifica le dimensioni dell'array. Non si tratta di una "fissa". L'altro è invece proprio un errore.

Difatti, non intendevo che tu avessi delle fisse, semmai che ce le ho io :D
Ho inserito il carattere sbagliato nel post. Termina con '\0'.

Ne ero sicuro, un "lapsus tastiera"
Non può essere considerata una stringa di dimensione uno perché il tipo è diverso. In un caso hai un array di due elementi di cui il secondo è '\0' mentre nell'altro hai un singolo carattere.

Hmm, forse hai le idee un po' confuse. Non esiste un tipo stringa in C, semplicemente si definisce stringa una sequenza di caratteri che termina con zero. Dal "punto di vista" del compilatore/macchina nemmeno array è un tipo, difatti puoi benissimo avere il codice
char a[100];
char *b;
/* ... */
b[25]=a+30;

ma qui vale anche come sei abituato, ovvero se preferisci "distinguere" fra array e puntatori (le virgolette sono d'obbligo).

Riassumo comunque il senso del mio intervento: se c'è un "non funziona please help" esiste un vecchio trucco, quello di aggiungere codice aka "parlante" per fare dei controlli, cosa che fra l'altro serve ANCHE per vedere se è il compilatore che sbaglia (capita, eccome se capita).

apatriarca

[quote]Non può essere considerata una stringa di dimensione uno perché il tipo è diverso. In un caso hai un array di due elementi di cui il secondo è '\0' mentre nell'altro hai un singolo carattere.

Hmm, forse hai le idee un po' confuse. Non esiste un tipo stringa in C, semplicemente si definisce stringa una sequenza di caratteri che termina con zero. Dal "punto di vista" del compilatore/macchina nemmeno array è un tipo, difatti puoi benissimo avere il codice
char a[100];
char *b;
/* ... */
b[25]=a+30;

ma qui vale anche come sei abituato, ovvero se preferisci "distinguere" fra array e puntatori (le virgolette sono d'obbligo).[/quote]
È vero che nel linguaggio C non esiste un tipo stringa, ma tutte le librerie standard del C utilizzano una rappresentazione comune delle stringhe e, siccome stavamo parlando di lettura da stdin usando le funzioni standard, ho ritenuto sensato parlare di "stringhe del C". La differenza tra un singolo carattere e una stringa esiste comunque anche a livello di codice macchina. Una stringa deve infatti in qualche modo codificare la sua dimensione, in modo esplicito con un numero o implicito come nel C, e quindi non si limita ad un singolo byte come il carattere singolo.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.