Newsgroup: it.comp.lang.c
Titolo: Stringhe e puntatori a stringe

Ciao a tutti!
Sto cercando la differenza tra associare una stringa ad un vettore di char
o ad un puntatore a char.
In particolare, vorrei valutare quest'ultima situazione.
Ho provato a scrivere questo codice:
int main()
{
  char *reference_2 = "stringa senza indirizzo";
  printf("Stringa: %s", *reference_2);
  system("PAUSE");	
  return 0;
}
Ma appena lo eseguo, la console di DOS si chiude generando un errore. Cosa
non va?
Ho letto poi da qualche parte della possibilità di usare stringhe, con il
C, di lunghezza variabile, senza essere obbligati a dichiarare per forza
una lunghezza stabilita con un vettore: è possibile? Come si fa?
Se ho:
int main()
{
  char string1[] = "Vettore_1";
  char *reference_1;
  char nuovo;
  reference_1 = string1;
  printf("Ecco il contenuto di string1: %s \n", string1);
  printf("Inserisci ora il nuovo contenuto che vuoi dare a string1\n");
  scanf("%s", reference_1);
  getchar();
  system("PAUSE");	
  return 0;
}
E inserisco supercalifragilistichespiralitoso per memorizzarlo in string1,
lui lo memorizza e lo mostra nella printf, termina il programma scrivendo
"Premere un tasto per continuare", ma quando lo premo la console di DOS
genera un errore anziché chiudersi regolarmente.
Ho fatto qualche operazione non consentita?
Grazie in ogni caso per la vostra attenzione,
Rocky3
-- 
"Il sapere e la ragione parlano, l'ignoranza ed il torto urlano".
Arturo Graf / Indro Montanelli / Anonimo

   scanf("%s", reference_1);
Non č corretto: stai sovrascrivendo il contenuto di string1 (perché
assegni a reference_1 il valore di string1, array decaduto in puntatore al
primo elemento). Oltretutto, la scanf() non ha controlli di lunghezza,
quindi rischi facilmente di sforare la memoria allocata. Un metodo piů
sicuro per leggere l'input č il seguente (vado al volo, senza compilare):
char string1[100];
printf("Inserisci ora il nuovo contenuto che vuoi dare a string1: ");
fgets(string1, sizeof string1, stdin);
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 Ho fatto qualche operazione non consentita?
beh, "supercali..." è più lunga di "string_1", visto che non hai 
allocato memoria sufficiente, è chiaro che fai casini.
Per utilizzare stringhe di lunghezza variabile devi allocare quantità 
variabili e adeguate di memoria per contenerle!
Ciao,
Giuseppe

 
Bruttina perň l'allocazione statica. Ti suggerisco l'allocazione della 
memoria fatta cosě:
char* string1 = (char)malloc(sizeof(char)*len+1;
dove len č la lunghezza richiesta per la stringa, e il + 1 c'č per il 
tappo (\0).
Cosě sě che avresti una stringa di lunghezza massima decisa a runtime, 
(magari poi potresti aggiungere altre furbate per farla crescere a 
piacimento).
Ciao,
Giuseppe

char* string1 = (char)malloc(sizeof(char)*len+1;
Grazie del suggerimento, ma questa allocazione è errata e presenta
caratteristiche inutili in C. E' errata perché il cast sul valore di
malloc() dovrebbe essere (char*). Il cast, in C, è inutile, includendo
stdlib.h, perché la trasformazione da void* a qualsiasi T* è
automatica. Inoltre sizeof(char) è uguale a 1 su tutte le piattaforme.
La tua allocazione si tradurrebbe (a meno di includere stdlib.h) in:
char *string1 = malloc(len+1);
Ma non ha ugualmente senso se quel len è conosciuto a priori; tanto
vale allocare staticamente e dimenticarsi una free().

 sicuro per leggere l'input č il seguente (vado al volo, senza compilare):
Sě, sono certo che sia piů sicuro e non dia problemi, ma io vorrei proprio
poter allocare dinamicamente spazio per la nuova stringa che voglio
inserire, che sia piů grande o piů piccola di quella che vado a
sovrascrivere. Una cosa simile a quella che fa giuseppe, insomma. Come si
puň fare?
Grazie per il tuo aiuto


 char *string1 = malloc(len+1);
Ok, questo intendevo con l'ultimo post. Len non è conosciuto a priori!
Come posso determinarlo run-time?


"Andrea Laforgia" <x...@xx.xx> ha scritto nel messaggio
news:fie9ed$lvj$1...@news.newsland.it...

char string1[] č modificabile,
"Vettore_1" non lo č.
Cioč
reference_1 = "Vettore_1";
non funzionerebbe, ma l'esempio postato sě (se si rientra nei limiti
naturalmente).
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 vale allocare staticamente e dimenticarsi una free().
beh, questo non è quello che c'è scritto nel post originale. Si chiedeva 
di utilizzare stringhe di lunghezza variabile.
Saluti,
Giuseppe

 
Sinceramente non capisco. Malloc prende il numero di byte da allocare e 
ti restituisce il puntatore al primo elemento dell'area allocata, sta a 
te stabilire qunato deve essere ampia.
Saluti,
Giuseppe

 di utilizzare stringhe di lunghezza variabile.
Mi sembrava che fosse una semplice alternativa. L'alternativa è usare
malloc()/free(), ovviamente.


 char string1[] è modificabile,
Mai detto che non lo sia.


 Mai detto che non lo sia.
Allora qual'è il senso del seguente commento al codice del post ?
"Non è corretto: stai sovrascrivendo il contenuto di string1 (perché
assegni a reference_1 il valore di string1, array decaduto in puntatore al
primo elemento)."
Sembra che il "non è corretto" si riferisca alla "sovrascrittura".
Andrebbe quanto meno scritto diversamente, per evitare ambiguità.
Anche perché è del tutto evidente che l'intento era di sovrascrivere
string1.
Il problema è semmai lo spazio (dinamico o no).
Ma andava focalizzato ulteriormente.
Secondo me ... ovvio.


 sovrascrivere.
Devi decidere comunque tu, a priori, quanto spazio allocare.
Se invece vuoi allocare spazio per tutto ciò che scrive l'utente,
allora devi fare un ciclo di fgets() leggendo una stringa di
dimensioni statiche e, di volta in volta, agganciare la stringa appena
letta al resto, andando a botte di realloc(). Vado al volo (testa se
va bene):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int tryRealloc(void **p, size_t newSize) {
    void *newp = realloc(*p, newSize);
    if (!newp)
      return 0;
    *p=newp;
    return 1;
}
char *getString() {
     char buf[10] = {0};
     char *res = 0;
     size_t rlen = 0;
     int stop = 0;
     while (!stop && fgets(buf, sizeof buf, stdin)) {
           size_t len = strlen(buf);
           if (buf[len-1] == '\n') {
              buf[len-1] = '\0';
              stop = 1; /* lettura line-buffered */
           }
           if (tryRealloc((void**)&res, rlen+len+1)) {
             if (rlen)
               strcat(res, buf);
             else
               strcpy(res, buf);
             rlen += len;
           }
     }
     return res;
}
int main()
{
    char *s;
    printf("inserisci una stringa: ");
    s = getString();
    printf("stringa inserita: \"%s\"\n", s);
    free(s);
    system("pause");
    return 0;
}

 Allora qual'è il senso del seguente commento al codice del post ?
Il senso è che, siccome l'input sovrascrive una zona di memoria
preallocata in maniera presumibilmente insufficiente, il codice si rivela
scorretto, a livello generale. Non ho detto che string1 non si possa
sovrascrivere, ma che non si debba sovrascrivere, a meno che la
sovrascrittura non sia controllata.


            }
Cioè se alla fine della stringa ho premuto invio, esco dal while.
Mi dispiace avere tutti questi dubbi e non poter usare il codice che, con
pazienza e disponibilità, hai scritto. Forse necessitavo di una cosa più
semplice, che gestisse una sola stringa.
Grazie infinite comunque!


 te stabilire qunato deve essere ampia.
Sģ, ok, ma se io scrivo una stringa lunga 15 caratteri, lui deve allocare
memoria per 16. Se č lunga 10, deve allocarla per 11. Come fa il programma
a determinare ogni volta il valore di leght? Esiste una funzione apposita
che conta il numero di caratteri nel buffer di tastiera?
Grazie


 che conta il numero di caratteri nel buffer di tastiera?
Potrei usare strlen(), come fa Andrea nel suo programma...?


>            size_t len = strlen(buf);
Perché usi size_t e non int?


Il Mon, 3 Dec 2007 11:26:29 +0100, Rocky3 ha scritto:
Ho fatto, molto semplicemente
#include <stdio.h>
#include <stdlib.h>
int main()
{
  char *string;
  int size;
  size=3;
  printf("Inserisci la stringa che vuoi memorizzare, non legge piu' di 3
caratteri\n");
  fgets(string, size, stdin);
  printf("La stringa e' %s", *string);
 
  system("PAUSE");	
  return 0;
}
Cosa non funziona...? Dopo aver inserito 3 caratteri, il programma si
chiude bruscamente.
Forse devo inizializzare string? O che altro?


semplice, che gestisse una sola stringa.
Quello che io ho scritto gestisce una sola stringa, a meno di
intendersi su che cosa voglia dire "stringa" per te. Il testo "Quel
ramo del lago di Como" è una stringa esattamente come lo è "pippo".

Perché usi size_t e non int?
Perché size_t è un tipo intero senza segno, valido per rappresentare
le "size" su qualunque piattaforma.

  fgets(string, size, stdin);
Non hai allocato spazio per string. Ti consiglio di procurarti un buon
manuale sul linguaggio, purtroppo ti mancano le basi.

a determinare ogni volta il valore di leght?
Studia il codice che ti ho postato: fa esattamente quello che cerchi.