DOMANDA Linguaggio C Stringhe Con Lunghezza Variabile

steferro97

Nuovo Utente
131
14
CPU
Intel i5-6600k @3.5Ghz
Dissipatore
Enermax Liqtech 240
Scheda Madre
Asus Z170 Pro Gaming
HDD
Seagate Barracuda 1TB 7200rpm
RAM
HyperX Savage DDR4 2400Mhz 2*4GB
GPU
Gigabyte GTX 970 G1 Gaming
Audio
Integrata
Monitor
Haier TV-Monitor 32"
PSU
Antec VPF-550W
Case
Zalman Z11 Neo
Periferiche
Steelseries Apex[RAW] - Mouse Roccat Kova RGB - Tritton AX720 - Neewer NW700
OS
Windows 10 Pro 64-bit
Ciao a tutti, avevo una curiosità, esiste in C un modo per leggere una stringa di caratteri qualsiasi, senza prima specificare quanto sia la sua lunghezza massima? Su stack overflow avevo trovato una discussione che parlava di array flessibili, ma non ho capito come si usano e se possono essere utili per quello che voglio fare.
In pratica vorrei scrivere un programma che chiede all'utente di inserire una parola e la memorizza e stampa la lunghezza.
Avevo pensato di farlo anche con una lista a puntatori ma ciò richiederebbe l'inserimento di un carattere alla volta e non è quello che volevo, sapete darmi una mano?
 

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
In C una stringa è un array di char. Se è una stringa ben codificata, il carattere successivo all'ultimo carattere effettivo è un terminatore che si distingue da tutti gli altri.
Ciò significa che tu puoi recuperare la lunghezza della stringa contando tutti i caratteri non terminatori partendo dal primo, o più semplicemente con la funzione strlen (string.h se non erro).
 

steferro97

Nuovo Utente
131
14
CPU
Intel i5-6600k @3.5Ghz
Dissipatore
Enermax Liqtech 240
Scheda Madre
Asus Z170 Pro Gaming
HDD
Seagate Barracuda 1TB 7200rpm
RAM
HyperX Savage DDR4 2400Mhz 2*4GB
GPU
Gigabyte GTX 970 G1 Gaming
Audio
Integrata
Monitor
Haier TV-Monitor 32"
PSU
Antec VPF-550W
Case
Zalman Z11 Neo
Periferiche
Steelseries Apex[RAW] - Mouse Roccat Kova RGB - Tritton AX720 - Neewer NW700
OS
Windows 10 Pro 64-bit
In C una stringa è un array di char. Se è una stringa ben codificata, il carattere successivo all'ultimo carattere effettivo è un terminatore che si distingue da tutti gli altri.
Ciò significa che tu puoi recuperare la lunghezza della stringa contando tutti i caratteri non terminatori partendo dal primo, o più semplicemente con la funzione strlen (string.h se non erro).
Ciao, grazie per la risposta, ma non è quello che intendevo, conosco il carattere terminatore \0 e la funzione strlen() ,ma io chiedevo se fosse possibile leggere una stringa di caratteri senza dover inizializzare un array con una lunghezza massima predefinita. Cioè vorrei che sia il programma a dare la lunghezza all'array DOPO che la parola è stata inserita, a seconda della sua lunghezza.
 

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
In questo caso allora no, l'unica "soluzione" è scendere a compromessi con l'utente, per esempio imponendo una lunghezza massima per l'input.
 
  • Mi piace
Reazioni: crsn

Bonfi97

Nuovo Utente
41
6
È possibile leggere una stringa da input di lunghezza ignota allocando memoria dinamicamente.
In particolare è necessario leggere ogni singolo carattere ricevuto da tastiera fino all'inserimento di un carattere che indicherà il termine della stringa (in questo caso il carattere "a capo": '\n'): ad ogni carattere inserito si allocherà nuova memoria per inserire il carattere successivo il terminatore '\0' al termine della stringa.
Per allocare nuova memoria è possibile usare sia una malloc di una stringa di dimensione +1 rispetto alla precedente, copiare il contenuto della prima stringa nella seconda, aggiungere il nuovo carattere e liberare lo spazio della stringa precedente oppure sfruttare la funzione "realloc" che permette di aumentare la dimensione di una parte di memoria già allocata.
Inoltre non è necessario scrivere un carattere alla volta, ma, dato il funzionamento della funzione scanf, è possibile scrivere un'intera stringa seguita da un carattere '\n': chiamando la scanf (impostando la formattazione con "%c") essa leggerà un solo carattere alla volta della stringa precedente per ogni volta che verrà richiamata, senza dover aspettare la pressione del pulsate invio ad ogni richiamo poiché non ha ancora raggiunto il termine di stdin.
Codice:
#include <stdio.h>
#include <stdlib.h>

#define STOP '\n'


int main(int argc, char *argv[]) {
  int i;
  char c,*s;
 
  if(s=malloc(sizeof(char))) {
     scanf("%c",&c);
     for(i=0;c!=STOP;i++) {
       s[i]=c;
       if(!(s=realloc(s,(i+2)*sizeof(char)))) {
           printf("Errore nell\'allocazione della memoria");
           return EXIT_FAILURE;
       }
       scanf("%c",&c);
     }
     s[i]='\0';
   
     /*operazioni su s*/
   
     free(s);
   }
   else {
       printf("Errore nell\'allocazione della memoria");
       return EXIT_FAILURE;
   }
 
  return EXIT_SUCCESS;
}
 
Ultima modifica:

steferro97

Nuovo Utente
131
14
CPU
Intel i5-6600k @3.5Ghz
Dissipatore
Enermax Liqtech 240
Scheda Madre
Asus Z170 Pro Gaming
HDD
Seagate Barracuda 1TB 7200rpm
RAM
HyperX Savage DDR4 2400Mhz 2*4GB
GPU
Gigabyte GTX 970 G1 Gaming
Audio
Integrata
Monitor
Haier TV-Monitor 32"
PSU
Antec VPF-550W
Case
Zalman Z11 Neo
Periferiche
Steelseries Apex[RAW] - Mouse Roccat Kova RGB - Tritton AX720 - Neewer NW700
OS
Windows 10 Pro 64-bit
È possibile leggere una stringa da input di lunghezza ignota allocando memoria dinamicamente.
In particolare è necessario leggere ogni singolo carattere ricevuto da tastiera fino all'inserimento di un carattere che indicherà il termine della stringa (in questo caso il carattere "a capo": '\n'): ad ogni carattere inserito si allocherà nuova memoria per inserire il carattere successivo il terminatore '\0' al termine della stringa.
Per allocare nuova memoria è possibile usare sia una malloc di una stringa di dimensione +1 rispetto alla precedente, copiare il contenuto della prima stringa nella seconda, aggiungere il nuovo carattere e liberare lo spazio della stringa precedente oppure sfruttare la funzione "realloc" che permette di aumentare la dimensione di una parte di memoria già allocata.
Inoltre non è necessario scrivere un carattere alla volta, ma, dato il funzionamento della funzione scanf, è possibile scrivere un'intera stringa seguita da un carattere '\n': chiamando la scanf (impostando la formattazione con "%c") essa leggerà un solo carattere alla volta della stringa precedente per ogni volta che verrà richiamata, senza dover aspettare la pressione del pulsate invio ad ogni richiamo poiché non ha ancora raggiunto il termine di stdin.
Codice:
#include <stdio.h>
#include <stdlib.h>

#define STOP '\n'


int main(int argc, char *argv[]) {
  int i;
  char c,*s;
 
  if(s=malloc(sizeof(char))) {
     scanf("%c",&c);
     for(i=0;c!=STOP;i++) {
       s[i]=c;
       if(!(s=realloc(s,(i+1)*sizeof(char)))) {
           printf("Errore nell\'allocazione della memoria");
           return EXIT_FAILURE;
       }
       scanf("%c",&c);
     }
     s[i]='\0';
   
     /*operazioni su s*/
   
     free(s);
   }
   else {
       printf("Errore nell\'allocazione della memoria");
       return EXIT_FAILURE;
   }
 
  return EXIT_SUCCESS;
}

Grazie mille! Era quello che cercavo, grazie per la spiegazione e per aver scritto anche tutto il codice. La funzione "realloc" non l'avevo mai usata ne studiata, domani provo a testare il codice e vedere se riesco a farlo funzionare
 

Bonfi97

Nuovo Utente
41
6
Piccolo aggiornamento: avevo sbagliato a contare la lunghezza dell'array riallocato. In particolare ho modificato il codice da
Codice:
s=realloc(s,(i+1)*sizeof(char))
a
Codice:
s=realloc(s,(i+2)*sizeof(char))
 
  • Mi piace
Reazioni: steferro97

movlw

Nuovo Utente
32
6
CPU
AMD A4 5300
Dissipatore
Default
Scheda Madre
AsRock DG3+
HDD
Toshiba 500GB
RAM
Kingstone 8GB DDR3
GPU
APU HD7480D
Monitor
Benq FP71G+
PSU
ITEK
OS
Windows 10 64bit
realloc è una funzione che va evitata come la peste, soprattutto dai principianti. È una funzione mal progettata che fa mille cose e fatte male: alloca memoria, libera memoria e ridimensiona blocchi di memoria; il tutto in contrasto col principio secondo cui una funzione deve fare una cosa e farla bene. Inoltre invocare realloc per ogni carattere in input è come cambiare casa ogni volta che si ha un ospite a pranzo. I calcolatori sono soggetti a limiti e pertanto bisogna accettare il fatto che bisogna preallocare la memoria necessaria a leggere una stringa e porre dei limiti all'utente. Usa un array statico di char come buffer e leggi la stringa con fgets.
 
Ultima modifica:

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!