Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless
Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless
MSI FORGE GK600 TKL WIRELESS: switch lineari hot-swap, tripla connettività, display LCD e 5 strati di fonoassorbimento. Ottima in gaming, a 79,99 euro
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici
DJI porta un importante aggiornamento alla sua linea di gimbal camera tascabili con Osmo Pocket 4: sensore CMOS da 1 pollice rinnovato, gamma dinamica a 14 stop, profilo colore D-Log a 10 bit, slow motion a 4K/240fps e 107 GB di archiviazione integrata. Un prodotto pensato per i creator avanzati, ma che convince anche per l'uso quotidiano
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori
Il primo headset open-back della linea INZONE arriva a 200 euro con driver derivati dalle cuffie da studio MDR-MV1 e un peso record di soli 199 grammi
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 10-07-2010, 17:34   #1
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
[C] Vettore di puntatori

Devo fare un programma che creato un array di puntatori, ad ogni indice, inserisco una stringa di testo ( di lunghezza indefinita ).
Siccome quando è stato assegnato l'esercizio, non ci era dato sapere come si allocava dinamicamente la memoria, deduco che il vettore avrà una lunghezza massima specificata ( quindi x puntatori ).
Il mio problema ora è capire come caricare le stringhe in ogni indice dell'array.

Sui libri che ho, dando uno sguardo, utilizzano tutti il malloc per fare ciò... Vorrei capire se è possibile farlo senza specificare la lunghezza massima di ogni stringa ( penso di si visto che comunque ogni indice punta ad un indirizzo ).

Ho provato una cosa del genere:
Codice:
/*
 Write a C function that takes an array of pointers to strings as an argument and sorts the array in ascending length order.
 Write also a main that tests the function by sorting a sequence of words read from keyboard.
 Hint: For the main, you can re-use the functions of the stringsort.c program.
 For the sort function, you can modify the sort function in the stringsort.c program.
 
*/
#include <stdio.h>
#define MAX 10 //Maximum number of strings

char *sarray[MAX];

void string_sort (void);
void get_size_sarray( int *n);
void get_strings(int *n);
void get_lenght(void);

int main (void)
{
	int n; //How many string we want to enter
	
	printf("Enter how many strings you want to enter\n");
	printf("This program can hold a maximum of %d strings\n", MAX);
	get_size_sarray(&n);
	get_strings(&n);
	
	return 0;
}

void get_size_sarray(int *n)
{
	scanf("%d", n);
	while( *n <= 0 || *n > MAX)
	{
		printf("Invalid number entered, try again\n");
		scanf("%d\n", n);
	}
	
}

void get_strings(int *n)
{
	int i;
	
	for ( i=0; i < *n; i++)
		scanf("%s", sarray[i]);
}
Però va in crash il programma, come devo fare?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 10-07-2010, 18:18   #2
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
void get_strings(int *n)

Qui non ha senso fare il passaggio per indirizzo.

Chiaro che tu abbia problemi, non essendo stato allocato sarray[i].
L'unico modo è allocare staticamente il vettore di stringhe:

char sarray[SMAX][MAX];

Consiglio: non usare mai variabili globali. Prendila come regola
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 10-07-2010, 18:55   #3
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
void get_strings(int *n)

Qui non ha senso fare il passaggio per indirizzo.

Chiaro che tu abbia problemi, non essendo stato allocato sarray[i].
L'unico modo è allocare staticamente il vettore di stringhe:

char sarray[SMAX][MAX];

Consiglio: non usare mai variabili globali. Prendila come regola
Ho pensato di farlo per indirizzo perchè sarebbe poi magari sarebbe tornato utile poterlo modificarlo globalmente, non si sa mai.
Per la variabile globale, so che non è buona abitudine usarle, ma ho avuto due professori durante il corso di programmazione: il primo si sarebbe fatto fucilare prima di usare una variabile globale, l'altro era solito impostare alcune variabili come globali ( quelle che quasi sicuramente vengono chiamate in ogni funzione del programma ). Mi pare una buona idea fare così per questo tipo di variabili, invece che chiamarle ogni volta... Alla fine chiamarle in ogni funzione e avere la memoria allocata per queste variabili durante tutta l'esecuzione del programma è pressochè uguale no?

Comunque per il vettore di puntatori: scritto come hai detto tu, vado a porre un limite al numero massimo di caratteri di ogni stringa, o sbaglio?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 10-07-2010, 19:07   #4
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da kwb Guarda i messaggi
Ho pensato di farlo per indirizzo perchè sarebbe poi magari sarebbe tornato utile poterlo modificarlo globalmente, non si sa mai.
Se non lo cambi dentro la funzione, passarlo per indirizzo non serve a niente, anche se lo vai a modificare globalmente.
Quote:
Originariamente inviato da kwb Guarda i messaggi
Alla fine chiamarle in ogni funzione e avere la memoria allocata per queste variabili durante tutta l'esecuzione del programma è pressochè uguale no?
E' una questione diversa. Comode lo sono sicuramente, ma programmando in modo ben strutturato le variabili globali tendono a rendere meno leggibile una funzione. Questo perché non si capisce subito a colpo d'occhio da quali parametri questa funzione dipende.
Metti caso volessi spostare la funzione in un altro modulo... Ti toccherebbe usare extern in ogni modulo in cui usi quella variabile globale.
Quote:
Originariamente inviato da kwb Guarda i messaggi
Comunque per il vettore di puntatori: scritto come hai detto tu, vado a porre un limite al numero massimo di caratteri di ogni stringa, o sbaglio?
Certo, ma se non usi l'allocazione dinamica non puoi fare altrimenti.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 10:38   #5
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
Se non lo cambi dentro la funzione, passarlo per indirizzo non serve a niente, anche se lo vai a modificare globalmente.
Intendi dire, se non lo cambi dopo avergli già assegnato un valore.

Quote:
Originariamente inviato da cionci Guarda i messaggi
E' una questione diversa. Comode lo sono sicuramente, ma programmando in modo ben strutturato le variabili globali tendono a rendere meno leggibile una funzione. Questo perché non si capisce subito a colpo d'occhio da quali parametri questa funzione dipende.
Metti caso volessi spostare la funzione in un altro modulo... Ti toccherebbe usare extern in ogni modulo in cui usi quella variabile globale.
Uhm intuisco il problema di fondo, anche se non sono giunto ancora fino a questo "livello" di programmazione

Quote:
Originariamente inviato da cionci Guarda i messaggi
Certo, ma se non usi l'allocazione dinamica non puoi fare altrimenti.
Ma scrivere *sarray[MAX] e sarray[][MAX] non è la stessa cosa?
Se io lo pongo come argomento di funzione la sintassi è corretta...
Quando lavoravo con le matrici, negli argomenti definivo solo l'ultima dimensione.
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 11:02   #6
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da kwb Guarda i messaggi
Intendi dire, se non lo cambi dopo avergli già assegnato un valore.
Non ti seguo...
Quello che sto dicendo è che se il valore non viene modificato all'interno della funzione, non ha senso passare un argomento per puntatore.
Quote:
Originariamente inviato da kwb Guarda i messaggi
Ma scrivere *sarray[MAX] e sarray[][MAX] non è la stessa cosa?
Se io lo pongo come argomento di funzione la sintassi è corretta...
Quando lavoravo con le matrici, negli argomenti definivo solo l'ultima dimensione.
Solo quando lo passi come argomento di una funzione. Questo perché gli array vengono passati tramite il puntatore. Non è quindi necessario conoscere la dimensione di ogni singolo vettore, ma basta il puntatore al primo elemento.

Però la memoria per contenere gli elementi di ogni singolo vettore deve essere allocata. Quindi l'unico modo che attualmente conosci è quello di creare una matrice di caratteri.
Così come per allocare una stringa usi:

char s[MAX];

così per allocare un vettore di stringhe dovrai usare

char v[MAX][N];
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 11:23   #7
tuccio`
Senior Member
 
Iscritto dal: Apr 2010
Città: Frosinone
Messaggi: 416
Quote:
Originariamente inviato da kwb Guarda i messaggi
Intendi dire, se non lo cambi dopo avergli già assegnato un valore.
se la funzione avesse un prototipo

void get_size_sarray(int n):

invece di

void get_size_sarray(int *n);

daresti la garanzia che il valore di n non viene modificato (perché eventuali modifiche non si ripercuoterebbero sul chiamante).. e funzionerebbe comunque

quello che ti sta dicendo è che se non serve realmente a qualcosa scriverci (ad esempio potresti avere due valori da ritornare, quindi uno lo ritorni e uno lo scrivi in una variabile di cui ti sei fatto passare il puntatore) è bene che tu garantisca che non ci scrivi passando per valore

a volte ti può anche capitare di dover necessariamente passare un puntatore (come per le stringhe e gli array) anche se non devi modificare niente, se ci fai caso, in questi casi, le funzioni della standard library che usano le stringhe e che non le modificano, come strcmp o printf, prendono un const char * proprio per garantire che non vengano modificate, quindi tu, dopo averle chiamate, sei certo che siano rimaste uguali a quelle di prima.. quello che sto cercando di dire in questo italiano stentato è che è bene fornire una garanzia che le variabili nel main rimangano invariate se non è necessario
tuccio` è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 15:15   #8
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
Non ti seguo...
Quello che sto dicendo è che se il valore non viene modificato all'interno della funzione, non ha senso passare un argomento per puntatore.
Quote:
Originariamente inviato da tuccio` Guarda i messaggi
se la funzione avesse un prototipo

void get_size_sarray(int n):

invece di

void get_size_sarray(int *n);

daresti la garanzia che il valore di n non viene modificato (perché eventuali modifiche non si ripercuoterebbero sul chiamante).. e funzionerebbe comunque

quello che ti sta dicendo è che se non serve realmente a qualcosa scriverci (ad esempio potresti avere due valori da ritornare, quindi uno lo ritorni e uno lo scrivi in una variabile di cui ti sei fatto passare il puntatore) è bene che tu garantisca che non ci scrivi passando per valore

a volte ti può anche capitare di dover necessariamente passare un puntatore (come per le stringhe e gli array) anche se non devi modificare niente, se ci fai caso, in questi casi, le funzioni della standard library che usano le stringhe e che non le modificano, come strcmp o printf, prendono un const char * proprio per garantire che non vengano modificate, quindi tu, dopo averle chiamate, sei certo che siano rimaste uguali a quelle di prima.. quello che sto cercando di dire in questo italiano stentato è che è bene fornire una garanzia che le variabili nel main rimangano invariate se non è necessario
Si, era quello che intendevo dire.


Quote:
Originariamente inviato da cionci Guarda i messaggi
Solo quando lo passi come argomento di una funzione. Questo perché gli array vengono passati tramite il puntatore. Non è quindi necessario conoscere la dimensione di ogni singolo vettore, ma basta il puntatore al primo elemento.

Però la memoria per contenere gli elementi di ogni singolo vettore deve essere allocata. Quindi l'unico modo che attualmente conosci è quello di creare una matrice di caratteri.
Così come per allocare una stringa usi:

char s[MAX];

così per allocare un vettore di stringhe dovrai usare

char v[MAX][N];
Quindi in realtà io non sto creando un vettore di puntatori, ma un semplice array bidimensionale, giusto?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 11-07-2010, 15:25   #9
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da kwb Guarda i messaggi
Si, era quello che intendevo dire.


Quindi in realtà io non sto creando un vettore di puntatori, ma un semplice array bidimensionale, giusto?
Come un stringa è un array monodimensionale, allora un array di stringhe è un array bidimensionale
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2010, 11:44   #10
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Riesumo il topic.
Ho reiniziato con un programma semplificato, cercando prima di fare in modo che mi ordini le parole contenute in un file, ecco ciò che ho scritto ( non è tutto di mio pugno, ho preso un po' dal libro cercando di capire esattamente cosa facesse ogni comando ):
Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MWORDLENGHT 30 //We need to define a maximum word lenght since we must know what's the lenght of each string
#define MSTRING 10 //Maximum number of strings in array of pointers

void error_calloc (void); //Memory allocation failed, error!
void error_string(void); //The string is too long ( too many words ), error!
void error_word(void); //The word is too long, error! 

void word_sort (char *w[], int n);
void swap(char **p, char **q );
void write_words(char *w[], int n);

int main (void)
{
	char word[MWORDLENGHT]; //Stores single words
	char *w[MSTRING]; //Stores strings ( Array of pointers )
	int n; //Stores how many words we have to sort
	int i;
	
	for (i=0; scanf("%s", word) == 1; i++) //This stops when scanf cannot read anymore char
	{
		if ( i >= MSTRING )
			error_string();
		if ( strlen(word) >= MWORDLENGHT )
			error_word();
		
		w[i] = calloc(strlen(word)+1, sizeof(char)); //Memory allocation, we add +1 to have space for \0
		if ( w[i] == NULL )
			error_calloc();
		strcpy ( w[i], word );
	}
	n = i; //Now we now how many words we must sort
	word_sort( w, n); //Sort words
	write_words( w, n); //Write words
	
	return 0;
}

void error_calloc (void)
{
	printf("%s", "ERROR: Failed in using calloc(), cannot allocate requested memory \n QUIT\n");
	exit(1); //Exit the whole program
}

void error_string (void)
{
	printf("ERROR: you are trying to sort more than %d words, that's not allowed\n QUIT", MSTRING);
	exit(1);
}

void error_word(void)
{
	printf("%s%d%s", "ERROR: You entered a word with lenght greater than ", MWORDLENGHT, "\n QUIT\n");
	exit(1);
}

void word_sort ( char *w[], int n)
{
	int i, j;
	for (i=0; i < n; i++)
		for (j=0; j<n; j++)
			if ( strcmp(w[i], w[j]) > 0 )
				swap ( &w[i], &w[j]);
}

void swap ( char **p, char **q )
{
	char *tmp; //Temporary stores address of pointer
	
	tmp = *p;
	*p = *q;
	*q = tmp;
}

void write_words(char *w[], int n)
{
	int i;
	for ( i=0; i < n; i++)
		printf("%s\n", w[i]);
}
A parte il puntatore di puntatore ( usato nella funzione swap, per scambiare le parole ) che non ho mai utilizzato, cmq sia mi pare di capire che l'esempio del libro voglia scambiare gli indirizzi all'interno del vettore e non le parole stesse, corretto? Detto questo, il programma non funziona perchè non riesco a fermare lo scanf prima che oltrepassi le dieci parole... Perchè?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2010, 12:25   #11
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Per fermare la scanf:

for (i=0; scanf("%s", word) == 1 && i < MSTRING; i++)

Esatto, lo swap scambia i puntatori
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2010, 15:08   #12
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
Per fermare la scanf:

for (i=0; scanf("%s", word) == 1 && i < MSTRING; i++)

Esatto, lo swap scambia i puntatori
Perchè mai scambiare i puntatori? Non è più semplice cambiare la posizione delle stringhe?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2010, 16:59   #13
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da kwb Guarda i messaggi
Perchè mai scambiare i puntatori? Non è più semplice cambiare la posizione delle stringhe?
No, al contrario, scambiando i puntatori non devi ricopiare le stringhe.
Parlando in termini di byte, supponendo 4 la dimensione di un puntatore, swappare i puntatori comporta la lettura e la scrittura di 3*4 byte (swap = a, a = b, b = swap).
Scambiare due stringhe significa leggere e scrivere strlen(a) + strlen(b) + strlen(b oppure a) byte.
Senza contare che quando non si ha un limite superiore sulla dimensione della stringa siamo costretti anche a fare l'allocazione dinamica delle stringa che deve contenere lo swap.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2010, 18:35   #14
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
No, al contrario, scambiando i puntatori non devi ricopiare le stringhe.
Parlando in termini di byte, supponendo 4 la dimensione di un puntatore, swappare i puntatori comporta la lettura e la scrittura di 3*4 byte (swap = a, a = b, b = swap).
Scambiare due stringhe significa leggere e scrivere strlen(a) + strlen(b) + strlen(b oppure a) byte.
Senza contare che quando non si ha un limite superiore sulla dimensione della stringa siamo costretti anche a fare l'allocazione dinamica delle stringa che deve contenere lo swap.
Ah ho capito, insomma è più conveniente in termini di prestazioni
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 22-08-2010, 09:51   #15
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Devo veramente capire come si fa sto esercizio. Sono giunto alla conclusione che per ordinare una stringa si intende ordinare una serie di parole date in input.
Quindi, ho pensato a come operare:.

1. CARICAMENTO:
- Inserisco la stringa
- Ad ogni spazio carico la parola nel vettore di puntatori
- Alloco spazio sufficiente per la parola dentro il vettore di puntatori
- Torno indietro di uno, sostituisco lo spazio con \0
- Calcolo la lunghezza della parola
- Ciclo finchè non ho terminato la stringa

2. ORDINAMENTO
- Uso funzione strcmp
...

Per l'ordinamento devo ancora pensarci, però per caricare le parole mi pare possa funzionare la cosa.
Quello che non capisco è perchè sui vari libri viene imposta una costante per la lunghezza massima della stringa e della singola parola, quando secondo me è superfluo visto che si potrebbe ( credo ) allocare lo spazio.

Siccome mi rendo conto che le parole possono essere di lunghezza diversa, e quindi immagino occupino spazio differente, non potrei utilizzare la funzione realloc qualora lo spazio precedentemente allocato non sia sufficiente?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505

Ultima modifica di kwb : 22-08-2010 alle 09:54.
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 22-08-2010, 10:31   #16
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Esatto, per la lettura ve bene così.
A cose normali la lunghezza massima della parola serve comunque, il buffer su cui la parola viene riversata temporaneamente è comunque un buffer di dimensione finita.
Anche se si possono attuare varie soluzioni per togliere queste limitazioni. Tra l'altro potrebbe essere un ottimo esercizio. Tu pensa che fgets permette di specificare la dimensione del buffer, quindi può terminare la lettura anche in caso di raggiungimento della massima dimensione, pur lasciando altri caratteri nell'input (in questo caso l'ultimo carattere non è '\n'): http://www.cplusplus.com/reference/c.../cstdio/fgets/
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 23-08-2010, 15:41   #17
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Ho fatto così per la lettura ma ho alcuni problemi, infatti non riesco a caricare dentro l'array di puntatori...
Codice:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define WORD_MAX 40
#define STRING_MAX 300
 
int main (void)
{
	char **pstring, input_string[STRING_MAX], word[WORD_MAX];
	int i=0, word_counter=0, slen=0, j=0;
	int actual_index=0;
	
	printf("Insert a string to be sorted\n");
	if ((fgets(input_string, WORD_MAX, stdin))==NULL)
	{
		printf("Read line error, QUIT\n");
		exit(1);
	}
	slen = strlen(input_string);
	for ( i=0; i < slen; i++)
	{	
		if ( isspace(input_string[i]))
			word_counter++; // How many words we have in the string? So we know how much memory to allocate
		
	}
	if ((pstring = calloc(word_counter, sizeof(char *)))==NULL)
	{
		printf("Memory row allocation error, QUIT\n");
		exit(1);
	}
	
	for ( i=0; i < slen; i++)
	{
		if ( isspace(input_string[i]))
		{	
			strncpy ( word, input_string, i);
			for ( j = 0; j < word_counter; j++)
				if ((pstring[i] = calloc(strlen(word), sizeof(char)))==NULL)
				{	
					printf("Memory columns allocation error, QUIT\n");
					exit(1);
				}
			actual_index=i+1;
			input_string += actual_index;
		}
	}
	for (i =0; i < word_counter; i++)
		fputs(pstring[i], stdout);
    return 0;
}
Mi pare l'allocazione sia corretta, inoltre non riesco a far andare ad un altro indirizzo il vettore in cui carico la stringa, così da poter eliminare la parola caricata dentro il vettore word...
So che il programma è ben poco ottimizzato e ci sono risoluzioni migliori, però il mio scopo ora è quello di riuscire a fargli stampare ste stringhe...
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 24-08-2010, 08:36   #18
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
http://www.cplusplus.com/reference/c...tring/strncpy/

No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.

Devi aggiungere \0 in fondo alla stringa.

Codice:
if ( isspace(input_string[i]))
		{	
			strncpy ( word, input_string, i);
			word[i] = '\0';
Inoltre non capisco a cosa ti serve questo:

actual_index=i+1;
input_string += actual_index;

Se fai così dovresti anche azzerare nuovamente i.
Senza contare che non puoi cambiare l'indirizzo a cui punta input_string, visto che allocata staticamente.
Dovresti usare una variabile per contare il numero dei caratteri da copiare in word.
Inoltre in pstring[i] non copi alcuna stringa e la dimensione di pstring[i] dovrebbe essere pari a strlen(word) + 1, perché deve contenere anche il carattere di fine stringa.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 24-08-2010, 16:05   #19
kwb
Senior Member
 
L'Avatar di kwb
 
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
Quote:
Originariamente inviato da cionci Guarda i messaggi
http://www.cplusplus.com/reference/c...tring/strncpy/

No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.

Devi aggiungere \0 in fondo alla stringa.

Codice:
if ( isspace(input_string[i]))
		{	
			strncpy ( word, input_string, i);
			word[i] = '\0';
A parte che il vettore parte di default riempito di \0, quindi è superfluo farlo... Inoltre non ne capisco l'utilità...

Quote:
Originariamente inviato da cionci Guarda i messaggi
Inoltre non capisco a cosa ti serve questo:

actual_index=i+1;
input_string += actual_index;

Se fai così dovresti anche azzerare nuovamente i.
Senza contare che non puoi cambiare l'indirizzo a cui punta input_string, visto che allocata staticamente.
Dovresti usare una variabile per contare il numero dei caratteri da copiare in word.
Inoltre in pstring[i] non copi alcuna stringa e la dimensione di pstring[i] dovrebbe essere pari a strlen(word) + 1, perché deve contenere anche il carattere di fine stringa.
Questo mi serve per eliminare ciò che ho caricato dentro input_string, così da poter mettere in word sempre l'ultima parola.
Il fatto è che cercavo di spostarmi tra gli indirizzi perchè lo avevo già fatto in un altro programma, e aveva funzionato, solo che li l'array veniva passato ad una funzione come argomento, sebbene fosse allocato in modo statico ( grandezza predefinita ).

EDIT: Ne sono venuto a capo, ora le stringhe vengono caricate dentro il vettore di puntatori correttamente, così:
Codice:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define WORD_MAX 40
#define STRING_MAX 300
 
int main (void)
{
	char **pstring, input_string[STRING_MAX], word[WORD_MAX];
	int i=0, word_counter=0, slen=0, j=0;
	int iactual_index=0, jactual_index=0;
	
	printf("Insert a string to be sorted\n");
	if ((fgets(input_string, WORD_MAX, stdin))==NULL)
	{
		printf("Read line error, QUIT\n");
		exit(1);
	}
	slen = strlen(input_string);
	for ( i=0; i < slen; i++)
	{	
		if ( isspace(input_string[i]))
			word_counter++; // How many words we have in the string? So we know how much memory to allocate
		
	}
	if ((pstring = calloc(word_counter, sizeof(char *)))==NULL)
	{
		printf("Memory row allocation error, QUIT\n");
		exit(1);
	}
	
	for ( i=0; i < slen; i++)
	{
		if ( isspace(input_string[i]))
		{	
			strncpy ( word, input_string + iactual_index, i);
			iactual_index += i+1;
			for ( j = jactual_index; j < word_counter; j++)
			{	if ((pstring[j] = calloc(strlen(word)+1, sizeof(char)))==NULL)
				{	
					printf("Memory columns allocation error, QUIT\n");
					exit(1);
				}
				strcpy(pstring[j], word);
			}
			jactual_index++;
		}
	}
	for (i =0; i < word_counter; i++)
	{	
		fputs(pstring[i], stdout);
		printf("\n");
	}
    return 0;
}
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505

Ultima modifica di kwb : 24-08-2010 alle 16:18.
kwb è offline   Rispondi citando il messaggio o parte di esso
Old 25-08-2010, 08:09   #20
cionci
Senior Member
 
L'Avatar di cionci
 
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
Quote:
Originariamente inviato da kwb Guarda i messaggi
A parte che il vettore parte di default riempito di \0, quindi è superfluo farlo... Inoltre non ne capisco l'utilità...
E' un vettore allocato staticamente. Tu non devi supporre quale sarà il suo contenuto dopo la creazione.
Ma anche supponendo che sia inizializzato con 0, il contenuto cambia...
Se io la prima volta ci copio dentro "abcdef" e la seconda volta "abcd", la strlen ritornerà nuovamente 6. Questo perché strncpy non aggiunge automaticamente '\0'.
Quote:
Originariamente inviato da kwb Guarda i messaggi
Questo mi serve per eliminare ciò che ho caricato dentro input_string, così da poter mettere in word sempre l'ultima parola.
Questo lo avevo capito, comunque non sarebbe funzionato anche se il vettore invece di essere statico fosse stato un puntatore.
Quote:
Originariamente inviato da kwb Guarda i messaggi
Il fatto è che cercavo di spostarmi tra gli indirizzi perchè lo avevo già fatto in un altro programma, e aveva funzionato, solo che li l'array veniva passato ad una funzione come argomento, sebbene fosse allocato in modo statico ( grandezza predefinita ).
Probabilmente in quel caso lo passavi come puntatore. Quando passi un vettore per puntatore non fai altro che passare l'indirizzo al primo elemento del vettore. Quindi puoi usare l'aritmetica degli indirizzi sul parametro della funzione.

Nel codice sopra continui a fare lo stesso errore concettuale di prima (supponiamo che tu aggiunga il carattere di fine stringa dopo strncpy, altrimenti non se ne esce):
strncpy ( word, input_string + iactual_index, i);
iactual_index += i+1;

Supponiamo che la stringa sia:

"nel mezzo del cammin"

Quando i == 2 c'è la prima iterazione:
- strncpy(word, input_string + 0, 3);
- word è "Nel "
- iactual_index = 4;

Quando i == 9 c'è la seconda iterazione:
- strncpy(word, input_string + 4, 9);
- word è "mezzo del "
- iactual_index = 4 + 10 = 14;

Quando i == 9 c'è la seconda iterazione:
- strncpy(word, input_string + 4, 9);
- word è "mezzo del "
- iactual_index = 4 + 10 = 14;

Quando i == 13 c'è la seconda iterazione:
- strncpy(word, input_string + 14, 13);
- ovvio che tu abbia un overflow

Inoltre perché allochi ogni volta i vettori che vanno da jactual_index a word_counter ?
Non serve quel for lì dentro: per ogni parola trovata devi allocare un solo elemento di pstring.

Suggerimento: dato un puntatore a char, scrivi una funzione che ti ritorna la lunghezza della PRIMA parola incontrata.

Altro suggerimento: avendo come parametro un puntatore alla stringa contente i dati, devi usare la funzione sopra, allocare lo spazio necessario e copia la parola trovata con la funzione sopra nella nuova stringa allocata. La funzione ritorna il puntatore alla memoria allocata.

Ultimo suggerimento: avendo la funzione del suggerimento precedente, usa l'aritmetica dei puntatori per dare in pasto una stringa contente molte parole alla funzione sopra.
cionci è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Tastiera gaming MSI GK600 TKL: switch hot-swap, display LCD e tre modalità wireless Tastiera gaming MSI GK600 TKL: switch hot-swap, ...
DJI Osmo Pocket 4: la gimbal camera tascabile cresce e ha nuovi controlli fisici DJI Osmo Pocket 4: la gimbal camera tascabile cr...
Sony INZONE H6 Air: il primo headset open-back di Sony per giocatori Sony INZONE H6 Air: il primo headset open-back d...
Nutanix cambia pelle: dall’iperconvergenza alla piattaforma full stack per cloud ibrido e IA Nutanix cambia pelle: dall’iperconvergenza alla ...
Recensione Xiaomi Pad 8 Pro: potenza bruta e HyperOS 3 per sfidare la fascia alta Recensione Xiaomi Pad 8 Pro: potenza bruta e Hyp...
Xbox Game Pass cambierà: tra le n...
I nuovi Surface Pro e Laptop sono vicini...
OnePlus ci riprova con la fascia bassa: ...
La Top 10 delle offerte Amazon del weeke...
XGIMI MoGo 2 Pro a 339€: Google TV con N...
Forum IT & Intelligence 2026: dall'A...
iPhone 16e per la prima volta a meno di ...
Stop Killing Games: Ross Scott convince ...
Annunciata la tuta di volo di Vast che s...
Vast presenta il nuovo Large Docking Ada...
Una denuncia getta ombre sulle batterie ...
DJI Avata 2 Fly Smart Combo a 526€: il d...
Alla guida della nuova auto elettrica ci...
GeForce RTX 3060 12 GB a giugno di nuovo...
Apple Music sarà sponsor ufficiale di Po...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 10:26.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v