Vettori di stringhe

streghettaalice
Devo svolgere un esercizio che chiede dopo aver inserito delle parole(che termineranno quando premo invio senza inserire parola) allora le stamperò.
Ora per prima cosa vorrei chiedere cosa non va nel mio codice :
Sto memorizzando le stringhe in un vettore
#include
#include

#define MAX_STR 10
#define msg_str 20

int leggi_line(char str[],int n);


int main(void)
{
int j=0;


char *astr[MAX_STR]=(char *)malloc(2+strlen(msg_str)+1);
char str[msg_str];

for(;;)
{
printf("Inserisci parola:");

leggi_line(str,msg_str);/*legge stringa*/

strcpy( astr[j] ,msg_str);

j=j+1;
}




return 0;
}

int leggi_line(char str[],int n)
{
int ch,i =0;
while((ch=getchar())!= '\n')
{

if(i str[i++]=ch;
}
str='\0';
return i;
}


Come faccio a fermare le parole quanto inserisco invio?

Risposte
vict85
Non ho ancora controllato tutto ma:

cos'é questo mostro?
char *astr[MAX_STR] = (char *) malloc(2 + strlen(msg_str) + 1);


Anche perché msg_str non è neanche una stringa. Ma ti compila?

Più avanti scrivi:
strcpy(astr[j], msg_str);

e anche qui msg_str è un numero. Non stai copiando nulla.

Sinceramente prima di preoccuparsi di come far finire il ciclo proverei con un ciclo di lunghezza fissa per vedere se funziona tutto.


P.S: perché mescoli italiano ed inglese nei nomi?

streghettaalice
scusami cosa intendi al "primo mostro"? sbaglierò ma ho allocato dinamicamente l'array di stringhe in modo da poter più avanti modificare in caso le stringhe.Cosa c'è di sbagliato?
Scusa ma non capisco perchè msg_str è int.

vict85
La definizione è questa:
#define msg_str 20

Questo codice significa che ogni volta che il compilatore trovera scritto msg_str lo muterà in un 20.

In altre parole è come se il tuo codice dicesse:
char *astr[10] = (char *) malloc (2+strlen(20)+1); 

come minimo il tuo compilatore ti darà un warning.

Non ti sembrano comunque pochi 20 caratteri per una linea? Io ne metterei almeno 100.

Non hai comunque bisogno che astr sia un array di puntatori a char... Puoi mettere tutto in un grande array. Tra l'altro stai usando un solo malloc per tutto l'array e non sono completamente sicuro su cosa ne viene fuori. L'unica cosa che ti serve al massimo e di aggiungere un "\n" alla fine della linea. Bisogna comunque dire che esiste una funzione standard che ti fa tutto in automatico "fgets".

Di seguito ti metto una soluzione del tuo esercizio che usa le funzioni presenti nello standard e ti invito a fare un'altra, con astr creato dinamicamente ed eventualmente estendibile e che non usa fgets. Tra l'altro puoi usare calloc per creare array dinamici.

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

int main(void)
{
	size_t const msg_str = 100;
	size_t const max_line_num = 20;
	char str[msg_str];
	char astr[max_line_num*msg_str+1] = "";

	size_t line_lenght = 0;
	unsigned int line_count = 0;

	do 
	{
		fputs("Inserisci la linea: ", stdout);
		fgets(str, msg_str, stdin);
		line_lenght = strlen(str);
		strcat(astr, str);
		++line_count;
	} while((line_lenght > 1)&&(line_count < max_line_num));

	fputs("\n", stdout);
	fputs(astr, stdout);

	return 0;
}

streghettaalice
Vorrei sapere cosa sbaglio io però..
Ho rifatto un pò l'esercizio ma c'è ancora qualcosa che non va:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STR 10
#define msg_str 20


int read_line(char str[],int n);


int main(void)
{
int j=0;
int i=0;
int k=0;

char *astr[MAX_STR];
char str[msg_str];                   
char *tmp=(char *) malloc(200);

for(;;)
{
printf("Inserisci parola:");

read_line(str,msg_str);
if(strcmp(str,"")==0)
break;
astr[j]=malloc(200);
strcpy(astr[j],str);

k=k+1;
}

for(i=0;i<k;i++)
{
 for(j=i+1;j<k;j++)
 {
  if(strcmp(astr[i],astr[j])>0)
    {
	astr[i]=malloc(200);
	astr[j]=malloc(200);
    strcpy(tmp,astr[i]);
	strcpy(astr[i],astr[j]);
	strcpy(astr[j],tmp);
	}
 }
}

for(i=0;i<k;i++)
printf("%s",astr[i]);

free(tmp);

return 0;
}

int read_line(char str[],int n)
{
int ch,i =0;
while((ch=getchar())!= '\n')
{

if(i<n)
 str[i++]=ch;
 }
str[i]='\0';
return i;
}

vict85
Fino al ciclo nulla di sbagliato, al massimo io avrei definito astr come un array dinamico unico invece che come un array di puntatori, al massimo lo avrei ingrandito se serviva.

Per quanto riguarda il primo ciclo direi che j non cambia, mentre aumenti k. Non ha alcun senso considerando che j è l'indice in cui scrivi su astr. Tra l'altro manca la condizione j
for (;j<MAX_STR; ++j) /* ho aggiunto la condizione e l'aumento delle variabili */
{   
	printf("Inserisci parola:");

	read_line(str, msg_str);
	if (strcmp(str, "") == 0)
		break;
	astr[j] = malloc(,msg_str); /* è inutile che astr[j] sia più grande str */
	strcpy(astr[j], str);
}


Il secondo ciclo non ha alcun senso secondo me e lo dovresti levare. Non hai inoltre liberato la memoria di astr.

Veniamo ora a read_line. Direi in generale che è abbastanza giusta. L'unica pecca è che str[msg_str] non è definito. Quindi dovresti mettere n-1 al posto di n. Inoltre dovresti smettere di leggere quando arrivi a n in modo tale da mettere il resto su una nuova riga.

Quindi lo riscriverei così:
int read_line(char str[], int n)
{
	int ch, i = 0;
	while ( (i<n-1) && ((ch = getchar()) != '\n') )
		str[i++] = ch;
	str[i] = '\0';
	return i;
}


In sostanza lo correggerei così:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STR 10
#define msg_str 20

int read_line(char str[], int n);

int main(void)
{
	int i = 0;
	int k = 0;

	char *astr[MAX_STR];
	char str[msg_str];

	for (; k<MAX_STR; k = k+1)
	{
		printf("Inserisci parola: ");
		read_line(str, msg_str);
		if (strcmp(str, "") == 0)
			break;
		astr[k] = malloc(msg_str); /* è inutile che astr[j] sia più grande str */
		strcpy(astr[k], str);
	}

	if(k == MAX_STR)
		printf("SPAZIO IN MEMORIA FINITO.\n Ogni nuovo carattere verra' ignorato.");

	printf("\n");

	for (i = 0; i < k; i++)
	{
		printf("%s", astr[i]);
		free(astr[i]);
	}

	return 0;
}

int read_line(char str[], int n)
{
	int ch, i = 0;
	while ( (i<n-1) && ((ch = getchar()) != '\n') )
		str[i++] = ch;
	str[i] = '\0';
	return i;
}


Anche se sinceramente trovo che possa essere migliorato qua e là.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.