Discussione Ufficiale Programmiamo con Inforge | Esercitazione 02 in C | Livello base

Una Discussione Ufficiale punta a raccogliere tutte le informazioni su un argomento o un fatto di attualità, con costanti aggiornamenti da parte del creatore e dei partecipanti.

Not an engineer

Moderatore
31 Ottobre 2011
2,715
100
1,204
1,091
Ultima modifica:
main.png


Programmiamo con Inforge | Presentazione

Ad oggi, sul web, si trovano moltissime guide sui vari linguaggi di programmazione e sulle loro molteplici applicazioni. Tuttavia, chi si approccia a queste risorse, non sempre riesce a mettere in pratica ciò che ha appreso. Al fine di limitare queste mancanze, nasce Programmiamo con Inforge.

In questa rubrica potrai scrivere codice per la risoluzione di alcuni problemi legati alla programmazione, mettendo in pratica quanto stai apprendendo dalla teoria oppure mostrando le tue abilità e competenze nel campo dell’informatica.


Partiamo dalle basi del C

In questa guida puoi trovare i testi per studiare e approfondire il C: I migliori libri per imparare e approfondire il C
In questa discussione puoi trovare le risposte alle domande più frequenti su come scrivere codice in C: Frequently asked questions: da dove si parte?


Esercitazione 02 in C | Livello base | [Strutture dati]

Conoscere le strutture dati e saper lavorare su di esse è un aspetto fondamentale della programmazione; con queste entità è possibile organizzare insiemi di dati e compiere una serie di operazioni su di essi.
L'esercitazione si compone di 2 esercizi nei quali ti sarà richiesto di definire una struttura dati che supporti determinate operazioni basilari (è possibile scegliere la struttura che più ti aggrada, ad esempio una lista) come l'inserimento, la ricerca e la cancellazione.



Soluzioni

Per rendere l'esercitazione più interessante, non verrà pubblicata alcuna soluzione! Spetterà a te scrivere la tua versione del codice e pubblicarla in questo thread così che possa essere valutata dai moderatori e dalla community; il modo migliore per imparare!

Conclusioni

Pubblica la soluzione ottimale per risolvere gli esercizi e ricorda che puoi confrontarti con il resto della community in questo thread, chiedere aiuto o aiutare gli altri ;)
 
Ultima modifica:
Eccomi qui con la mia versione. Ho utilizzato una lista ordinata bidirezionale.
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MODE_INSERT 0
#define MODE_FIND 1
#define MODE_REMOVE 2

struct Person
{
  char* name;
  char* last_name;
  int age;
};

struct LLNode
{
  struct Person data;
  struct LLNode *next;
  struct LLNode *prev;
};

struct LLNode *head = NULL;
int LLSize = 0;

void clean_input_buffer()
{
  char c;
  while ((c = getchar()) != '\n' && c != EOF);
}

void pause()
{
  printf("\n\nPremere un tasto per continuare.. ");
  getchar();
}

int get_int(char* message)
{
  int input = 0;

  printf("\n%s:\t", message);
  scanf("%d", &input);

  clean_input_buffer();

  return input;
}

char* get_string(char* message)
{
  char* input = (char*)malloc(1024);

  printf("\n%s:\t", message);
  scanf("%[^\n]%*c", input);

  int len = strlen(input);
  input[len] = 0;

  return (char*)realloc(input, len + 1);
}

void print_list()
{
  struct LLNode *node = head;

  printf("\n\nLISTA PERSONE (%d):", LLSize);

  while(node != NULL)
  {
    printf("\n%s\t%s\t%d", node->data.name, node->data.last_name, node->data.age);

    node = node->next;
  }
}

struct Person insert_person(char* name, char* last_name, int age)
{
  struct Person person;
  person.name = name;
  person.last_name = last_name;
  person.age = age;

  struct LLNode *new_node = (struct LLNode*)malloc(sizeof(struct LLNode));
  new_node->data = person;

  if(head == NULL)
  {
    head = new_node;
  }
  else
  {
    struct LLNode *node = head;
    int index = 0;

    while(node != NULL)
    {
      if(node->data.age < new_node->data.age)
      {
        new_node->next = node;
        node->prev = new_node;

        if(index == 0)
        {
          head = new_node;
        }

        break;
      }

      if(node->next == NULL)
      {
        node->next = new_node;
        break;
      }

      node = node->next;
      index++;
    }
  }

  LLSize++;

  return person;
}

void find_people(char* name, char* last_name)
{
  struct LLNode *node = head;

  printf("\n\nRISULTATI:");

  while(node != NULL)
  {
    if(strstr(node->data.name, name) ||
      strstr(node->data.last_name, last_name))
    {
      printf("\n%s\t%s\t%d", node->data.name, node->data.last_name, node->data.age);
    }

    node = node->next;
  }
}

struct Person* remove_person(char* name, char* last_name)
{
  struct Person *person = NULL;
  int index = 0;
  struct LLNode *node = head;

  while(node != NULL)
  {
    if(strstr(node->data.name, name) &&
      strstr(node->data.last_name, last_name))
    {
      person = &node->data;

      if(index == 0)
      {
        if(LLSize > 1)
        {
          head = node->next;
        }
        else {
          head = NULL;
        }
      }
      else
      {
        if(index < LLSize - 1)
        {
          node->prev->next = node->next;
          node->next->prev = node->prev;
        }
        else
        {
          node->prev->next = NULL;
        }
      }

      LLSize--;

      break;
    }

    node = node->next;
    index++;
  }

  return person;
}

void ask_person(int mode)
{
  char* name;
  char* last_name;
  int age;

  switch(mode)
  {
    case MODE_INSERT:
      printf("\n\nINSERIMENTO NUOVA PERSONA\n");
   
      name = get_string("DIGITARE IL NOME");
      last_name = get_string("DIGITARE IL COGNOME");
      age = get_int("DIGITARE L'ETA'");

      struct Person inserted = insert_person(name, last_name, age);

      printf("\n%s %s INSERITO!", inserted.name, inserted.last_name);

      print_list();
      break;
    case MODE_FIND:
      printf("\n\nRICERCA PERSONA\n");
   
      name = get_string("DIGITARE IL NOME");
      last_name = get_string("DIGITARE IL COGNOME");

      find_people(name, last_name);
      break;
    case MODE_REMOVE:
      printf("\n\nRIMOZIONE PERSONA\n");
   
      name = get_string("DIGITARE IL NOME");
      last_name = get_string("DIGITARE IL COGNOME");

      struct Person *removed = remove_person(name, last_name);

      if(removed == NULL)
      {
        printf("\nNESSUNA PERSONA TROVATA!");
        break;
      }

      printf("\n%s %s RIMOSSO!", removed->name, removed->last_name);

      print_list();
      break;
  }
}

int main() {
    int action;
 
    do
    {
      action = -1;
      system("clear");

      printf("__________ MENU __________\n\n");
      printf("1. Inserisci una persona\n");
      printf("2. Cerca delle persone\n");
      printf("3. Rimuovi una persona\n");
      printf("0. Esci\n");
      printf("__________________________\n");

      action = get_int("SELEZIONARE UN OPERAZIONE");

      switch(action)
      {
        case 1:
          ask_person(MODE_INSERT);
          break;
        case 2:
          ask_person(MODE_FIND);
          break;
        case 3:
          ask_person(MODE_REMOVE);
          break;
      }

      if(action < 0 || action > 3)
      {
        printf("\nOPERAZIONE NON VALIDA!");
        action = 1;
      }

      if(action != 0)
      {
        pause();
      }
    } while (action > 0);

    printf("\nADDIO!");
    return action;
}

Alcuni screenshot dell'esecuzione:

1615376215342.png
1615376257499.png
1615376286741.png

1615376315289.png
1615376599919.png
 
Pubblico la mia soluzione too (fatta un po' di fretta)

C:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SIZE 30

typedef struct Persona
{
    char name[SIZE];
    char last_name[SIZE];
    unsigned int age;

    struct Persona* next;
} Persona;


void printPersona(Persona* node)
{
    if (node == NULL)
        return;

    printf(
        "Name: %s, Last Name: %s, Age: %u\n",
        node->name,
        node->last_name,
        node->age
    );
}

void printPersonaList(Persona* head)
{
    printf("\nBEGIN LIST\n");
    while (head != NULL)
    {
        printPersona(head);
        head = head->next;
    }
    printf("END LIST\n\n");
}

void freePersona(Persona* node)
{
    free(node);
}

void freePersonaList(Persona* head)
{
    while (head != NULL)
    {
        Persona* temp = head;
        head = head->next;

        freePersona(temp);
    }
}

Persona* insert(Persona** head, char name[], char last_name[], int age)
{
    Persona* newNode = malloc(sizeof(Persona));

    strcpy(newNode->name, name);
    strcpy(newNode->last_name, last_name);
    newNode->age = age;
    newNode->next = NULL;

    // forse c'è un modo migliore per farlo ma non ho voglia di pensarci
    if (*head == NULL || (*head)->age < newNode->age)
    {
        newNode->next = *head;
        *head = newNode;
    }
    else
    {
        Persona* previous = *head;
        Persona* current = (*head)->next;

        while (current != NULL) {
            if (current->age < newNode->age) {
                previous->next = newNode;
                newNode->next = current;
                break;
            }

            previous = current;
            current = current->next;
        }

        // tail insert
        if (newNode->next == NULL)
            previous->next = newNode;
    }

    return newNode;
}

Persona* searchByName(Persona* head, char name[])
{
    while (head != NULL) {
        if (strcmp(name, head->name) == 0)
            break;

        head = head->next;
    }

    return head;
}

void deleteByName(Persona** head, char name[])
{
    if (*head == NULL)
        return;

    if (strcmp(name, (*head)->name) == 0) {
        Persona* temp = *head;
        *head = (*head)->next;

        freePersona(temp);
    } else {
        Persona* previous = *head;
        Persona* current = (*head)->next;

        while (current != NULL && strcmp(name, current->name) != 0) {
            previous = current;
            current = current->next;
        }

        if (current) {
            previous->next = current->next;
            freePersona(current);
        }
    }
}

int main()
{
    Persona* head = NULL;
    Persona* temp = NULL;

    temp = insert(&head, "nome1", "cognome1", 15);
    printPersona(temp);

    temp = insert(&head, "nome2", "cognome2", 24);
    printPersona(temp);

    temp = insert(&head, "nome3", "cognome3", 17);
    printPersona(temp);

    char nome4[] = "nome4";
    temp = insert(&head, nome4, "cognome4", 13);
    printPersona(temp);

    printPersonaList(head);

    temp = searchByName(head, "nome3");
    printPersona(temp);

    temp = searchByName(head, "nome0"); // invalid name
    printPersona(temp);

    deleteByName(&head, "nome4");
    deleteByName(&head, "nome2"); // delete HEAD
    deleteByName(&head, "nome0"); // invalid name;

    printPersonaList(head);

    freePersonaList(head);

    return 0;
}

Output:

1615384856394.png
 
Ultima modifica:
Ecco la mia follia con le linked list:
Scusate le funzioni di getString e getInt ma senza usare le STL di C++ mi viene da bestemmiare con la commandline quindi le ho abbozzate in quel brutto modo (per qualche motivo MSVC conosce solo la getline di std).
C:
#include <stdio.h>

typedef struct
{
    char* name;
    char* lastName;
    int age;
} Person;

typedef struct LinkedNode
{
    Person val;
    LinkedNode* next;
} LinkedNode, *PersonList;

char* getString(const char* prompt)
{
    if (prompt != NULL)
        printf("%s ", prompt);

    char* str = (char*)malloc(1024);
    if (str == NULL)
        return NULL;

    do
    {
        fgets(str, 1023, stdin);

    } while (str[0] == '\n');

    int len = strlen(str);
    str[len - 1] = 0;
    return (char*)realloc(str, len);
}

int getInt(const char* prompt)
{
    if (prompt != NULL)
        printf("%s ", prompt);

    int n = 0;
    scanf("%d", &n);
    return n;
}

void free_person(Person& p)
{
    if (p.name != NULL)
        free(p.name);
    if (p.lastName != NULL)
        free(p.lastName);
}

void free_node(LinkedNode* node)
{
    if (node != NULL)
    {
        free_person(node->val);
        free(node);
    }
}

void print_person(Person& p)
{
    printf("Nome: %s \tCognome: %s \tEta': %d\n", p.name, p.lastName, p.age);
}

void print_persons(PersonList& list)
{
    LinkedNode* pNode = list;
    while (pNode != NULL)
    {
        print_person(pNode->val);
        pNode = pNode->next;
    }
}

void insert_person(PersonList& list)
{
    Person p;
    p.name = getString("Inserisci nome:");
    p.lastName = getString("Inserisci cognome:");
    p.age = getInt("Inserisci eta':");

    LinkedNode* node = (LinkedNode*)malloc(sizeof(LinkedNode));
    node->val = p;
    node->next = NULL;

    // sorting by age
    LinkedNode *prevNode, *pNode = list;
    prevNode = NULL;
    while (pNode != NULL)
    {
        if (p.age > pNode->val.age)
        {
            node->next = pNode;

            if (prevNode == NULL)
                list = node;
            else
                prevNode->next = node;
        }
        else if (pNode->next == NULL)
        {
            pNode->next = node;
            break;
        }
        prevNode = pNode;
        pNode = pNode->next;
    }

    if (list == NULL)
        list = node;
}

void find_person(PersonList& list)
{
    LinkedNode* pNode = list;

    char* search = getString("Cerca per Nome o Cognome:");
    int c = 0;

    while (pNode != NULL)
    {
        if (strstr(pNode->val.name, search) != NULL
            || strstr(pNode->val.lastName, search) != NULL)
        {
            print_person(pNode->val);
            c++;
        }
        pNode = pNode->next;
    }
  
    printf("%d risultati trovati\n", c);
    free(search);
}

void delete_person(PersonList& list)
{
    LinkedNode *prevNode, *pNode = list;

    char* name = getString("Nome da eliminare:");
    char* lastName = getString("Cognome da eliminare:");
    int c = 0;

    prevNode = NULL;

    while (pNode != NULL)
    {
        if (strcmp(pNode->val.name, name) == 0
            && strcmp(pNode->val.lastName, lastName) == 0)
        {
            if (pNode == list)
            {
                list = list->next;
                free_node(pNode);
                pNode = list;
            }
            else
            {
                prevNode->next = pNode->next;
                free_node(pNode);
                pNode = prevNode;
            }

            c++;
        }
        prevNode = pNode;
        pNode = pNode->next;
    }

    printf("%d risultati eliminati\n", c);
    free(name);
    free(lastName);
}

typedef void(*cbHandler)(PersonList& list);

typedef struct
{
    const char* Description;
    cbHandler handler;
} Action;

int esercizio2_main()
{
    PersonList list = NULL;

    const Action actions[] = {
        { "Lista persone",      print_persons },
        { "Inserisci persona",  insert_person },
        { "Ricerca",            find_person },
        { "Elimina",            delete_person }
    };

    const int nActions = (sizeof(actions) / sizeof(Action));

    printf("Menu:\n");
    for (int i = 1; i <= nActions; i++)
        printf("- [%d] %s\n", i, actions[i - 1].Description);

    printf("- [0] Esci\n\n");

    int cmd = 0;

    do
    {
        cmd = getInt(">");
      
        if (cmd < 0 || cmd > nActions)
            printf("Comando non valido\n");
        else if (cmd != 0)
            actions[cmd - 1].handler(list);

    } while (cmd > 0);

    return 0;
}

sample.png
 
Ultima modifica:
Posto subito una bozza sbarbina che devo uscire per una mezz'oretta, quando torno spero ci sia già qualcuno che ha distrutto e pestato a sangue questo codice.
p.s. non ricordo come "cancellare" per bene quindi ho semplicemente cambiato in campo vuoto.

C++:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <string>

class elenco
{
        char nome[20]; //ho provato ad usare string per nome e cognome ma mi dà errore, come si può fare? in un main pulito crea e stampa senza problemi
        char cognome[20];
        short eta;
        public:
        void inserisci();
        void visualizza();
        void cancella();
};
void elenco::inserisci()
{
        printf("Inserisci nome: ");
        scanf("%s",&nome);
        printf("Inserisci cognome: ");
        scanf("%s",&cognome);
        printf("Inserisci eta': ");
        scanf("%d",&eta);
     

}
void elenco::visualizza()
{

        printf("\nNome: %s", nome);
        printf("\nCognome: %s", cognome);
        printf("\nEta'': %d", eta);
       
}

void elenco::cancella()
{
    nome"";
    cognome="";
    eta="";
}




main()
{
    elenco r[10];
    int x=-1,c=1;
    while(x!=3)
    {
    printf("1)Inserisci utente\n2)Ricerca utente\n3)Cancella\n4)Inserisci e ordina\n");
    scanf("%d",&x);
        switch(x)
        {
           case 1:
           {       
                r[c].inserisci();
                c++;
                break;
           }
           case 2:
           {
                       int cerca=0;
                       printf("\nInserisci 0>posizione>9 del contatto da cercare:");
                       scanf("%d",&cerca);               
                    r[cerca-1].visualizza();               
                    break;       
           }
           case 3:
           {
                   int num=0;              
                   printf("\nInserisci 0>posizione>9 del contatto da eliminare:");
                   scanf("%d",&num);
                   r[num-1].cancella();
                   break;
           }
           case 4:
           {
            \\questo non ho idea di come farlo, o almeno per il momento non ricordo come far interagire i parametri della funzione e lo struct (sempre se si può)
            break;
           }
        }
    }
}
 
Ultima modifica:
Pronto a sfornare ignoranza.
Dico subito che non ho la minima idea di come mettere qualcosa di lunghezza variabile in uno struct, quindi da buona capra metto array a lunghezza definita e pace.
Ovviamente continuo a scrivere in c++ essendo, come scritto prima, capra.
 
  • Mi piace
  • Love
Reazioni: Valley e Kode
@Dazorn
Ben fatto. Ma giusto per cercare il pelo nell'uovo, ti segnalo un paio di cose.
  1. Guardando il codice non mi è sembrato di aver visto l'inserimento con ordinamento
  2. Non liberi mai la memoria allocata, nè sulle stringhe nè rispetto agli elementi della lista
  3. usi system("clear"); che non è portabile (ma in effetti non ci sono molte alternative valide)


@Sax3r28
Prendendo sempre il codice che hai pubblicato ieri, questo funziona:

C++:
class elenco
{
        std::string nome;
        std::string cognome;
        short eta;
        public:
        void inserisci();
        void visualizza();
        void cancella();
};

Comunque se usi C++, puoi usarlo "fino in fondo" ;)
Quindi ad esempio scrivendo:
C++:
using namespace std;

int main()
{
string prova="ciao";
cout << prova;
}

Per il distruttore ho controllato anche delle slide mie e ho trovato qualcosa, ma così a prima vista non ci sto capendo molto(e nell'esempio la creazione del vettore è sempre a lunghezza definita, quindi non mi aiuta molto). Praticamente basta creare questo ~nomeClasse e metterci dentro delete [] nomearray;? Questo poi scala gli elementi in automatico o va fatto in seguito?

Ti faccio un esempio con una classe simile alla tua (premetto di non conoscere bene C++ e di non usarlo da qualche anno):
C++:
#include <iostream>

class Person {
    private:
        std::string name;
        std::string last_name;
        int age;
        
    public:
        Person(std::string name, std::string last_name, int age) { 
            this->name = name;
            this->last_name = last_name;
            this->age = age;
        }
    
        void printPerson() {
            std::cout << this->name << " " << this->last_name << " " << age << std::endl;
        }
};

int main() {
    Person **person = new Person*[10]; // Ho scelto 10 elementi
    
    for(int i=0; i<10; i++) {
        person[i] = new Person("Name" , "Last Name", i+1);
    }
    
    for(int i=0; i<10; i++) {
        person[i]->printPerson();
    }
    return 0;
}

Un altro esempio:
C++:
#include <iostream>

class Person {
    private:
        std::string name;
        std::string last_name;
        int age;
        
    public:
        Person() {}
        
        Person(std::string name, std::string last_name, int age) { 
            this->name = name;
            this->last_name = last_name;
            this->age = age;
        }
    
        void printPerson() {
            std::cout << this->name << " " << this->last_name << " " << age << std::endl;
        }
};

int main() {
    Person *person = new Person[10]; // Ho scelto 10 elementi
    
    for(int i=0; i<10; i++) {
        person[i] = Person("Name" , "Last Name", i+1);
    }
    
    for(int i=0; i<10; i++) {
        person[i].printPerson();
    }
    return 0;
}

Una dimensione iniziale dovrai comunque darla in quanto l'array è statico, come in C (e non solo); dovrai ridimensionarlo tu "manualmente".

Normalmente in C++ per cose come queste usi i vector, non gli array (il vector viene ridimensionato in automatico "internamente"). Quindi volendo potresti anche usare un vector; ovviamente sarebbe più semplice rispetto a una soluzione in C dove è necessario gestire anche le riallocazioni. ;)
Questo è un esempio con un vector:
C++:
#include <iostream>
#include <vector>

class Person {
    private:
        std::string name;
        std::string last_name;
        int age;
        
    public:
        Person(std::string name, std::string last_name, int age) { 
            this->name = name;
            this->last_name = last_name;
            this->age = age;
        }
    
        void printPerson() {
            std::cout << this->name << " " << this->last_name << " " << age << std::endl;
        }
};

int main() {
    std::vector<Person> person;
    
    for(int i=0; i<10; i++) {
        person.push_back(Person("Name" , "Last Name", i+1));
    }
    
    for(int i=0; i<10; i++) {
        person[i].printPerson();
    }
    return 0;
}

Ti ho fatto fare un pò di confusione io, mea culpa. Se usi un array, non puoi rimpicciolirlo eliminando un elemento.
L'operatore delete a cui fai riferimento libera (dealloca) la memoria; prima di questo però viene invocato il distruttore, se è definito (e se si tratta di una classe).

Un'altra cosa che mi è venuta in mente adesso vedendo tutti sti *, usando i puntatori non serve passare le variabili alle funzioni giusto?

Non ho capito bene che intendi...

Un while input<0 && input >x(che dovrebbe essere sì dinamico ma sto pian piano sbloccando tutti i ricordi) può bastare?

Certo ;)

In merito all'altra questione: se vuoi usare C++, allora usa direttamente vector e amen, a mio avviso è meglio se non vai a "mischiare" le cose.

@demtor
Ho guardato solo velocemente la tua soluzione (non ho più tempo), ma direi sia ben fatta. ;)



Vedo che tutti quanti avete usato bene o male una lista... nessuno ha voglia di provare altre soluzioni?
 
Ultima modifica:
Posto subito una bozza sbarbina che devo uscire per una mezz'oretta, quando torno spero ci sia già qualcuno che ha distrutto e pestato a sangue questo codice.
p.s. non ricordo come "cancellare" per bene quindi ho semplicemente cambiato il contatto in un campo vuoto.

C++:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
class elenco
{
        char nome[20];
        char cognome[20];
        short eta;
        public:
        void inserisci();
        void visualizza();
        void cancella();
};
void elenco::inserisci()
{
        printf("Inserisci nome: ");
        scanf("%s",&nome);
        printf("Inserisci cognome: ");
        scanf("%s",&cognome);
        printf("Inserisci eta': ");
        scanf("%d",&eta);
      

}
void elenco::visualizza()
{

        printf("\nNome: %s", nome);
        printf("\nCognome: %s", cognome);
        printf("\nEta'': %d", eta);
        
}

void elenco::cancella()
{
    nome"";
    cognome="";
    eta="";
}




main()
{
    elenco r[10];
    int x=-1,c=1;
    while(x!=3)
    {
    printf("1)Inserisci utente\n2)Ricerca utente\n3)Cancella\n4)Esci\n");
    scanf("%d",&x);
        switch(x)
        {
           case 1:
           {        
                r[c].inserisci();
                c++;
                break;
           }
           case 2:
           {
                       int cerca=0;
                       printf("\nInserisci posizione>0 del contatto da cercare:");
                       scanf("%d",&cerca);                
                    r[cerca-1].visualizza();                
                    break;        
           }
           case 3:
           {
                   int num=0;               
                   printf("\nInserisci posizione>0 del contatto da eliminare:");
                   scanf("%d",&num);
                   r[num-1].cancella();
                   break;
           }
           case 4:
           {           
            break;
           }
        }
    }
}
Il case 4 secondo me potrebbe anche non servire in questo caso (certamente non influenza le prestazioni dell'algoritmo). Normalmente si inserisce un controllo di questo tipo quando hai un while che circonda il tuo menù a console, in maniera tale da uscire dal while stesso solamente quando l'utente finisce di utilizzare l'applicazione.
Comunque la consegna chiedeva una sequenza di dimensione variabile e nel tuo caso mi sembra fissa a 10.

Devi implementare un struttura dati LISTA
 
  • Mi piace
Reazioni: Valley
@Sax3r28

Perchè non stai "includendo" il namespace, dovresti fare using namespace std; oppure quando definisci la stringa usare std::. Quindi ad esempio std::string nome;. ;)
In C++ per distruggere la memoria allocata esistono i distruttori. Per vedere come si utilizzano https://en.cppreference.com/w/cpp/language/destructor

Poi fai attenzione ad un'altra cosa: stai usando un array di oggetti di tipo elenco, quindi quando elimini una persona... dovresti trovare un modo per "compattare" il tuo array, così da non avere buchi.

Anche nei case 2 e 3, attenzione: dovresti verificare il valore inserito, altrimenti andresti fuori dai limiti dell'array.

Ultima cosa: l'elenco di persone non dovrebbe avere una lunghezza definita. Prova a modificare l'algoritmo così da accettare più di 10 persone. ;)

@JunkCoder
C'è poco da dire, non ho considerazioni da fare, bel lavoro.
 
  • Love
Reazioni: Not an engineer
Ultima modifica:
@Sax3r28

Perchè non stai "includendo" il namespace, dovresti fare using namespace std; oppure quando definisci la stringa usare std::. Quindi ad esempio std::string nome;. ;)
In C++ per distruggere la memoria allocata esistono i distruttori. Per vedere come si utilizzano https://en.cppreference.com/w/cpp/language/destructor
Ho provato a metterlo sia dentro lo struct che fuori, sotto gli include, ma continuava questi errori:
expected nsted-name-specifier before namespace
'string' does not name a type

Questo funziona se scritto a sé
C++:
int main()
{
    using namespace std;

    string prova="ciao";
    printf("%s",prova.c_str());
}
Crea la string, la stampa e tutto bene, nell'altro codice invece non ne voleva sapere.

Per il distruttore ho controllato anche delle slide mie e ho trovato qualcosa, ma così a prima vista non ci sto capendo molto(e nell'esempio la creazione del vettore è sempre a lunghezza definita, quindi non mi aiuta molto). Praticamente basta creare questo ~nomeClasse e metterci dentro delete [] nomearray;? Questo poi scala gli elementi in automatico o va fatto in seguito?
Un'altra cosa che mi è venuta in mente adesso vedendo tutti sti *, usando i puntatori non serve passare le variabili alle funzioni giusto?
Poi fai attenzione ad un'altra cosa: stai usando un array di oggetti di tipo elenco, quindi quando elimini una persona... dovresti trovare un modo per "compattare" il tuo array, così da non avere buchi.
Per quello ho spizzicato file che scrissi quando ancora andavo a scuola :rofl: e ho trovato questo
C++:
void azzera(int v[], int k)
{
    int *p;
    p= &v[0];
    for(int i=0;i<k;i++)
    {
        p= &v[i];
        *p=0;
    }
}
Può servirmi? O serve qualcosa che proprio pulisce dov'è stato allocato il valore e scala tutto di una posizione?
Anche nei case 2 e 3, attenzione: dovresti verificare il valore inserito, altrimenti andresti fuori dai limiti dell'array.
Un while input<0 && input >x(che dovrebbe essere sì dinamico ma sto pian piano sbloccando tutti i ricordi) può bastare?
Ultima cosa: l'elenco di persone non dovrebbe avere una lunghezza definita. Prova a modificare l'algoritmo così da accettare più di 10 persone. ;)
Sempre spulciando ho trovato questo, potrebbe andare? Ovviamente ritoccandolo per adattarlo alle richieste.
Anche se ora che lo leggo bene anche questo è a lunghezza definita. Probabilmente è pure una roba semplice da scrivere per fare sto struct dinamico, ma proprio non mi viene in mente.
C++:
struct elemento *crea_lista()
{
   struct elemento *p, *punt;
   int i, n;
   printf("\n Specificare il numero di elementi: ");
   scanf("%d", & n);
   if(n==0)
   {
   p = NULL; // lista vuota
   }
   else
   {
      /* creazione primo elemento */
    p = (struct elemento *)malloc(sizeof(struct elemento));
    printf("\nInserisci il primo valore: ");
    scanf("%d", & p->inf);
    punt = p;




// CREAZIONE ELEMENTI SUCCESSIVI
      for(i=2; i<=n; i++)
      {
         punt->pun = (struct elemento *)malloc(sizeof(struct elemento));
         punt = punt->pun;
         printf("nInserisci il %d elemento: ", i);
         scanf("%d", & punt->inf);
      } // chiudo il for
      punt->pun = NULL; // marcatore fine lista
   } // chiudo l'if-else
   return(p);
} // chiudo la funzione

Ovviamente @Not an engineer se puoi indirizzarmi pure te :frog-good:
 
  • Mi piace
Reazioni: Valley
Guardando il codice non mi è sembrato di aver visto l'inserimento con ordinamento
E' di default quando vai ad inserire una nuova persona con la funzione insert_person.
Non liberi mai la memoria allocata, nè sulle stringhe nè rispetto agli elementi della lista
Questo è vero hahaha, me ne sono proprio dimenticato :)
Messaggio unito automaticamente:

Non ho la minima idea di cos'altro si può fare e ne butto una così, una matrice? :asd:
Una cosa che mi viene in mente è un'albero binario.
 
  • Mi piace
Reazioni: Valley
Comunque vi state superando in questa esercitazione, mi avete impressionato. Ho visto soluzioni semplici ed efficace e complesse (o come dico io "risultati dello smanettare"). Continuate cosi :)
 
  • Mi piace
Reazioni: Shin Rea
Visualizza allegato 50643

Programmiamo con Inforge | Presentazione

Ad oggi, sul web, si trovano moltissime guide sui vari linguaggi di programmazione e sulle loro molteplici applicazioni. Tuttavia, chi si approccia a queste risorse, non sempre riesce a mettere in pratica ciò che ha appreso. Al fine di limitare queste mancanze, nasce Programmiamo con Inforge.

In questa rubrica potrai scrivere codice per la risoluzione di alcuni problemi legati alla programmazione, mettendo in pratica quanto stai apprendendo dalla teoria oppure mostrando le tue abilità e competenze nel campo dell’informatica.


Partiamo dalle basi del C

In questa guida puoi trovare i testi per studiare e approfondire il C: I migliori libri per imparare e approfondire il C
In questa discussione puoi trovare le risposte alle domande più frequenti su come scrivere codice in C: Frequently asked questions: da dove si parte?


Esercitazione 02 in C | Livello base | [Strutture dati]

Conoscere le strutture dati e saper lavorare su di esse è un aspetto fondamentale della programmazione; con queste entità è possibile organizzare insiemi di dati e compiere una serie di operazioni su di essi.
L'esercitazione si compone di 2 esercizi nei quali ti sarà richiesto di definire una struttura dati che supporti determinate operazioni basilari (è possibile scegliere la struttura che più ti aggrada, ad esempio una lista) come l'inserimento, la ricerca e la cancellazione.

*** Testo nascosto: non può essere aggiunto alla citazione ***



Soluzioni

Per rendere l'esercitazione più interessante, non verrà pubblicata alcuna soluzione! Spetterà a te scrivere la tua versione del codice e pubblicarla in questo thread così che possa essere valutata dai moderatori e dalla community; il modo migliore per imparare!


Conclusioni

Pubblica la soluzione ottimale per risolvere gli esercizi e ricorda che puoi confrontarti con il resto della community in questo thread, chiedere aiuto o aiutare gli altri ;)
vediamo : )
 
  • Mi piace
Reazioni: Valley