Consiglio piccolo programmino in c

di il
17 risposte

Consiglio piccolo programmino in c

Salve ragazzi ho scritto un piccolo programma in c che deve leggere un intero N, leggere N stringhe e stampare in ordine di input prima le palindrome e dopo le restanti. non mi da errori a tempo di compilazione e al momento dell esecuzione mi da diversi risultati:
1) inanzitutto quando io ho inserito un intero mi stampa due volte la stessa cosa, così:"inserire una stringa...inserire una stringa", solo per la prima stringa che andrò ad inserire però! boooo;
2)se inserisco solo stringhe palindrome il programma funziona correttamente
3)se però come stringa inserisco "itopinonavevanonipoti " c'è l'errore segmentation fault(core dump);
4)se inserisco una stringa non palindroma, il programma si blocca immediatamente con l errore segmentation fault(core dump)
ho usato il debugger e dice che l'errore sta nella funzione AddPali, nella riga in cui nel while faccio "curr=curr->next" (solo nel case 3) però), sennò l'errore è nella funzione AddNorm quando faccio "prec->succ=newNorm".
qualcuno mi spiega cosa cè che non va?? Grazie.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
    char s[41];
    struct pali *next;
}pali;
typedef struct{
    char s[41];
    struct norm *succ;
}norm;
typedef struct pali* listaP;
typedef struct norm* listaN;
void StampaListaN(listaN);
void StampaListaP(listaP);
int palindroma(char*);
pali* creaPali(char*);
norm* creaNorm(char*);
listaP AddPali(listaP, char*);
listaN AddNorm(listaN, char*);
int main()
{
    printf("inserire intero...");
    int n=0;
    scanf("%d", &n);
    listaP P;
    listaN N;
    for(int i=0;i<n;i++){
        char str[41];
        printf("inserire stringa...");
        fgets(str,41,stdin);
        if(palindroma(str)==0){
            AddPali(P,str);
        }else{
            AddNorm(N,str);
        }
    }
    StampaListaN(N);
    StampaListaP(P);
    return 0;
}
int palindroma(char *s1){
    int l=strlen(s1);
    char *s2=malloc(sizeof(char *)*l);
    strcpy(s2,s1);
    int j=l-2;
    int i=0;
    while(s1[i]!='\0'&&j>=0){
        if(s1[i]!=s2[j]) {   //usare funziona compare string
        return 1;
        }
        j--;
        i++;
    }
    return 0;
}

pali * creaPali(char * s1){
    pali *ok=malloc(sizeof(pali *));
    for(int i=0;s1[i]!='\0';i++){
        ok->s[i]=s1[i];
    }
    ok->next=NULL;
    return ok;
}
norm * creaNorm(char * s1){
    norm *ok=malloc(sizeof(pali *));
    for(int i=0;s1[i]!='\0';i++){
        ok->s[i]=s1[i];
    }
    ok->succ=NULL;
    return ok;
}


listaP AddPali(listaP lista, char *str){
   pali *newPali, *prec, *curr;
   curr=lista;
   while(curr!=NULL){
        prec=curr;
        if(curr){
        curr=curr->next;
        }
   }
   newPali=creaPali(str);
   prec->next=newPali;
   return lista;
}

listaN AddNorm(listaN lista, char *str){
    norm * curr, *prec, *newNorm;
    curr=lista;
    while(curr!=NULL){
        prec=curr;
        if(curr) curr=curr->succ;
    }
    newNorm=creaNorm(str);
    prec->succ=newNorm;
    return lista;
}

void StampaListaP(listaP list){
    pali *p=list;
    while(p!=NULL){
        printf("%s", p->s);
        p=p->next;
    }

}
void StampaListaN(listaN list){
    norm *p=list;
    while(p!=NULL){
        printf("%s", p->s);
        p=p->succ;
    }

}

17 Risposte

  • Re: Consiglio piccolo programmino in c

    1) inanzitutto quando io ho inserito un intero mi stampa due volte la stessa cosa, così:"inserire una stringa...inserire una stringa", solo per la prima stringa che andrò ad inserire però! boooo;
    Questo si risolve con un input di n diverso. In pratica quando vai a leggere la prima stringa leggi come carattere il \n dovuto all'inserimento della variabile n.

    Gli altri punti li risolvi rivendo le liste.

    In realtà duplichi il codice delle liste, praticamente identico per entrambe. Chiedo: non è più elegante scrivere un ADT lista che fa quel lavoro?
  • Re: Consiglio piccolo programmino in c

    Ciao per quanto riguarda il \n, ho capito qual è il problema, ma come faccio a non far leggere al programma il carattere \n? ho provato con scanf("%[^\n]", &m) ma non è cambiato niente. poi per gli errori sulle liste mi potresti spiegare meglio? perchè io non vedo l'errore nel fare curr=curr->next visto che curr è una variabile puntatore della mia struct e anche curr->next è definito allo stesso modo..
  • Re: Consiglio piccolo programmino in c

    Così è possibile fare la lettura dell'intero:
    fgets(str,41,stdin);
        n = atoi(str);
    
    Poi le liste dovresti organizzarle così;
    if(palindroma(str)==0) {
                P=AddPali(P,str);
            } else {
                N=AddNorm(N,str);
            }
    E ovviamente devi modificare il corpo delle AddPali e AddNorm.

    Fai attenzione ad una cosa: tu hai detto che non hai errori di compilazione, forse è vero ma dovresti per forza avere dei warning; ecco, questi vanno corretti. Un programma deve avere zero errori e zero warning.
  • Re: Consiglio piccolo programmino in c

    Ciao, sono sempre lucadd94, hai ragione in effetti ho dei warning e per eliminarli devo per forza correggere addpali e addnorm, sapresti darmi qualche suggerimento su come corregerle? grazie mille
  • Re: Consiglio piccolo programmino in c

    Le funzioni in questione ricercano l'ultimo elemento e inseriscono in coda, trovo sia da correggere questo. Prova a debaggare la tua funzione e modificarla opportunamente, sono sicuro che con un po' di prove ci riesci.
    Comunque la ricerca dell'ultimo nodo della lista ha un costo lineare, ovvero devi scorrere l'intera lista per fare ciò, io avrei sacrificato una piccola struct con il puntatore al primo elemento della lista e uno all'ultimo elemento della lista per rendere l'inserimento O(1).

    Poi ritengo sia inutile avere una parte di programma clonato con nomi diversi, puoi implementare una serie di funzioni che gestiscono la lista e utilizzare quelle per le due differenti liste.
  • Re: Consiglio piccolo programmino in c

    listaP AddPali(listaP head, char *str){
            pali *newElem=malloc(sizeof(pali));
            for(int i=0;str[i]!='\0';i++){
                newElem->s[i]=str[i];
            }
            newElem->next=head;  //qui ricevo il warning
            head=newElem;//anche qui
            return head;
    }
    
    ho modificato la funzione in questo modo, cosicchè ho sempre un puntatore al primo elemento, ma ricevo ancora dei warning
  • Re: Consiglio piccolo programmino in c

    Che cosa dice il warning?
  • Re: Consiglio piccolo programmino in c

    Warning: assignment from incompatible pointer type [enabled by default]

    lo ricevo solo alla riga head=newElem;
  • Re: Consiglio piccolo programmino in c

    Ti stai chiedendo che cosa significa?
  • Re: Consiglio piccolo programmino in c

    Siiii ma non capisco :S listaP è un tipo puntatore alla struttura pali, head è un listaP, newElem è un puntatore a pali, quindi head e listaP sono dello stesso tipo?? ma comunque anche se non uso listaP ma solo pali non cambia niente.
  • Re: Consiglio piccolo programmino in c

    Prova a sostituire queste righe vedi se va a posto:

    pali *newElem=malloc(sizeof(pali));

    listaP newElem = malloc(sizeof(*newElem));
  • Re: Consiglio piccolo programmino in c

    Non ho capito perchè fai sizeof(*newElem), cmq no non va.. anzi adesso da proprio errore
  • Re: Consiglio piccolo programmino in c

    Pali * è dello stesso tipo di listaP ?
  • Re: Consiglio piccolo programmino in c

    Sisi ho usato typedef struct pali* listaP
Devi accedere o registrarti per scrivere nel forum
17 risposte