Newsgroup: it.comp.lang.c
Titolo: principiante ignorante

Salve a tutti,sto cercando di imparare il linguaggio ma sono alle prime
armi,non riesco proprio a far funzionare sto miniprogrammino che dovrebbe
,inserita una parola,darmi lastessa invertita;più che la soluzione
dell'enigma volevo chedervi una curiosità,ma posso farlo senza usare i
puntatori,dato che sono all'inizio volevo incominciare per gradi,grazie
1000000!!!!!!!
#include <string.h>
#include <stdio.h>
int main()
{
char a[10];
char vettuscita[10];
int i;
int j;
int k;
printf("Inserisci una parola : ");
scanf("%c",a);
il vettore di input a
 for(i=0;   (a[i]=getchar())!='\n';  ++i)
  for(j = 9 ; j>=0 ;--j);
  for(k = 0 ; k<=10; ++k)
    vettuscita[k] = a[j];
printf("La parola scritta al contrario e': \n");
scanf("%c",vettuscita[k]);
return 0;
}

 1000000!!!!!!!
Guarda, sono agli inizi proprio come te. Ho scritto questo, anche se non so
se sia proprio la cosa che stavi cercando, cmq un poco di allenamento non mi
farà male:
// Inizio codice
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void);
void main(void)
{
  char parola[100];
  printf("Inserisci parola: ");
  //scanf("%s", parola);
  gets(parola);
  int len = (strlen(parola) - 1);
  for (int i = len; i >= 0; i--)
  {
    printf("%c", parola[i]);
  }
  getch();
}
// Fine codice
e, compilato con Borland C++ 5 funziona. Chiaramente come vedi la parola non
può avere più di 100 caratteri, ma se è per quello può anche essere una
frase, infatti lo spazio non è che un normale carattere ascii come gli
altri. Se vuoi inserire qualcosa si più lungo basta modificare l'indice
dell'array. Non ho usato alcun puntatore come non lo hai fatto neanche tu,
solo array (almeno che tu non ti sia confuso tra i due). Non ho letto il tuo
codice, ma magari lo farò.
Ti saluto e spero che sia quello che stavi cercando.
---
Ramses
---
icq:39860665
http://knowledgeparty.cjb.net
http://evilz0ne.cjb.net

    vettuscita[k] = a[j];
Volevi usare un doppio ciclo for, ma è inutilmente complicato! ;-)
E' molto più semplice così:
for(i = 0; i < MAX - 2; i++)
  vettuscita[i] == vettuscita[MAX - 2 - i];
In pratica usi lo stesso indice, invece di un doppio ciclo for
(sbagliato tra l'altro, perché fa assumere alla stessa lettera via via
tutti i valori della stringa di destinazione, e alla fine dovresti
trovarti una stringa composta di soli caratteri '\0' (l'ultimo
carattere della stringa).

carattere della stringa).
Piccolo svarione, sorry! Volevo dire che fa assumere a ciascuna
lettera del vettore vettuscita tutti i valori degli elementi del
vettore a, fino a raggiungerne la fine.
Poi il ciclo si ripete fino alla ultima lettera di vettuscita.
Alla fine avrai una bella stringa di caratteri uguali (qualunque sia
questo carattere)... :-)
C'é un altro piccolo difetto nel tuo programma. Tu assumi a priori che
la stringa occupi tutto lo spazio disponibile, e non metti il
carattere terminatore '\0', né ti preoccupi di saltarlo all'inizio.
Se hai definito, per esempio, char a[100], ma ricevi in input una
parola di sole 10 lettere, scrivendo un ciclo for senza verificare
l'effettiva lunghezza ti porta a leggere 89 caratteri che non hai
avuto in input, e che potrebbero avere qualsiasi strano valore.
Devi usare la strlen (o scrivere una semplice funzione che conta i
caratteri prima di '\0') per misurare la lunghezza della stringa e
limitarti solamente a quei primi caratteri. La parte che si trova
oltre '\0' non ha alcun interesse per te,.
Ho riscritto il tuo programma in modo che funzioni, usando la strlen
(per usarla devi includere string.h, come puoi vedere).
Una soluzione ancora migliore e' di stampare semplicemente la stringa,
senza memorizzarla in un vettore apposito (vettuscita). Questo
permette di risparmiare memoria.
Se invece fosse proprio necessario invertire la stringa, puoi
invertirla su se stessa, senza chiedere altra memoria al sistema. 
Usando la fgets (come ho fatto sotto) viene sprecato un carattere
(quello che precede il terminatore di stringa '\0'). Puoi usare quel
carattere come elemento temporaneo per scambiare ciascun elemento con
il suo simmetrico rispetto alla metà della stringa..
/* inversione di una stringa */
#include <stdio.h>
#include <string.h>
#define MAX 100
void main(void)
{
  int i, lunghezza;
  char a[MAX], vettuscita[MAX];
  printf("\n\n\tInserisci la stringa da invertire:\n\t");
  fgets(a, MAX, stdin);
  lunghezza = strlen(a) - 2; 
/* prende la lunghezza della stringa, - 1 per escludere il carattere
terminatore '\0', e un altro - 1 per eliminare anche il new line
('\n'). Se non escludessi '\0', lo troverei proprio all'inizio della
stringa, e ovviamente la printf non stamperebbe nulla (stamperebbe
'\0' ovvero nulla) */
  for(i = 0; i < lunghezza; i++)
    vettuscita[i] = a[lunghezza - 1 - i];
  /* scorre vettuscita da sinistra a destra, e contemporaneamente
lunghezza da destra a sinistra */
  vettuscita[i] = '\0';
  /* aggiunge il carattere '\0' per terminare la stringa */
  printf("\n\n\tLa stringa invertita è:\n\t%s", vettuscita);
/* stampa il risultato */
}

Beh... già che c'ero... ;-)
Eccoti anche la versione con una stringa sola. Come puoi vedere, tolti
i commenti, è veramente un programma ridotto.
#include <stdio.h>
#include <string.h>
#define MAX 100
void main(void)
{
  int i, lunghezza;
  char a[MAX];
  printf("\n\n\tInserisci la stringa da invertire:\n\t");
  fgets(a, MAX, stdin);
  /* prende in input una stringa di lunghezza massima MAX */
  lunghezza = strlen(a) - 1;
  /* memorizza la lunghezza della stringa esclusi i caratteri '\n' e
'\0' */
  while (getchar() != '\n');
  /* svuota il buffer di tastiera, per darti il tempo di leggere con
il getchar alla fine (puoi toglierlo, e il programma funziona
ugualmente) */
  for(i = 0; i < lunghezza / 2; i++)
  {
    a[lunghezza] = a[i];
    a[i] = a[lunghezza - i - 1];
    a[lunghezza - i - 1] = a[lunghezza];
    /* inverte ogni elemento della stringa con il proprio simmetrico
rispetto alla meta' della dimensione della stringa effettivamente
utilizzata. Come elemento temporaneo per lo scambio utilizza
a[lunghezza], che non ci serve, visto che e' quello usato dalla fgets
per mettere il newline */
  }
  a[lunghezza] = '\0';
  /* termina la stringa per permettere la stampa formattata con la
printf */
  printf("\n\n\tLa stringa invertita è:\n\t%s", a);
  /* stampa il risultato */
  getchar();
  /* chiede la pressione di enter per evitare che la finestra possa
sparire subito se stai usando il run dell'ambiente di sviluppo (puoi
toglierlo e il programma funziona ugualmente) */
}

#define MAX 100
allora è molto meglio:
enum { MAX = 100 };
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

Grazie mille ragazzi,stanotte mi applico!!!!Ciaoooo e Grazieeeee

 enum { MAX = 100 };
   Definire e` umano, enumerare diabolico. ;)
	const int MAX=100;
   Le classi di memorizzazione, queste sconosciute.
--
Alla prossima,
Marco

   Le classi di memorizzazione, queste sconosciute.
appunto; cosa sono?


   Le classi di memorizzazione, queste sconosciute.
In effetti... ;-) Io sono abituato ad usare "#define", ma mi sembrano
plausibili anche le altre due soluzioni. Circa l'uso del const, sono un
po' restio: non vorrei mai che qualche compilatore trattasse MAX come
una variabile, ossia che allocasse memoria (magari anche di sola
lettura, ma non č questo il punto) per scriverci dentro "100".
Ma a parte questo, nel caso in esame quali svantaggi presenta l'uso del
#define, rispetto alle altre due soluzioni?
Direi che l'uso di const č il piů elegante, ma c'č altro?
-- 
Saluti,
    Mardy
http://www.interlingua.com

 tutto è risolto a compile time. O sbaglio?
giusto, o perlomeno al 50%.
una variabile const occupa spazio in memoria dati, tanti byte per
quanto e' la dim della variabile stessa, una #define o il valore di un
enum sono dei valori immediati, occuperanno spazio nel "codice", a
seconda di come li ottimizza il compilatore/cpu.
Nel caso const var per leggere il valore di MAX la cpu deve comunque
leggere in memoria, nel caso di define/enum ha il valore che fa parte
dell'istruzione assembly, quindi il caso const e' anche piu lento
della #define.
ciao
donCiccio


I'm not prejudiced, I hate everyone equally.

 #define, rispetto alle altre due soluzioni?
   Sia l'enumerazione che la costante occupano spazio in memoria: per 
quel che riguarda il codice macchina sono entrambe un mucchietto di byte 
allocati nel segmento dati costanti del programma.
   L'unica differenza tra i due costrutti e` che l'enumerazione, 
generalmente, contiene, anche se non necessariamente, piu` elementi, 
preferibilmente ordinati e contigui, e puo` sembrare curioso utilizzarla 
per un solo termine.
   Inoltre, questa similitudine esiste solo in questo caso particolare, 
nel quale l'oggetto /MAX/ e` di tipo /int/: i termini di un'enumerazione 
possono solo essere interi, mentre oggetti di qualsiasi tipo possono 
essere dichiarati costanti.
   L'uso del costrutto /#define/, invece, era molto utilizzato prima 
della seconda versione dello standard (che ha inserito la classe di 
memorizzazione /const/). Io lo eviterei: e` pur sempre una delega che tu 
dai ad un programma, il pre-processore, che non e` il compilatore e dal 
quale, quindi, non puoi pretendere lo stesso comportamento.
--
Alla prossima,
Marco


la mia opinione e' che per definire valori costanti la direttiva #define e'
piu' che corretta.
const va usata solo se ti serve che ci sia un'area di memoria da non
modificare.
la differenza e' tutta li:
#define MAX 100     // e' una costante, cioe' valore immediato
const int MAX=100;  // e' una zona di memoria (come una variabile), il cui
valore non puo' essere cambiato
nel secondo caso posso fare:
const int * p=&MAX;
nel primo no.
ciao
donCiccio

 donCiccio


#define, rispetto alle altre due soluzioni?
solitamente č meglio evitare le macro, in quanto modificano la
semantica del linguaggio; inoltre se sbagli e la usi in un contesto
non appropriato per il compilatore č piů facile produrre un messaggio
di errore comprensibile se usi enum. inoltre l'uso di enum al posto di
#define č consigliato da Kernighan e Pike in "Programmazione nella
pratica".


 di memoria di MAX?
si
ciao
donCiccio

 pratica".
si ma non per
#define MAX 100
da sostituire con
enum { MAX=100 };
daiiiiii!!
prova ad aprire un .h standard e guarda quante #define dipo MAX ci sono, a
cominciare da NULL (la piu' usata), come mai non sono tutti enum?
ciao
donCiccio

della #define.
immaginavo; cmq ci tengo a precisare che in C++ questo non succede, in
quanto il compilatore č autorizzato ad ottimizzare anche in questo
caso: quindi se ci riesce puņ sostituire direttamente il valore della
costante.


allocati nel segmento dati costanti del programma.
per quel che ne so io non è vero che l'enum occupa spazio in memoria,
è una semplice costante letterale.


costante.
Credo (ma non ho nessun testo sacro da citare) che sia la stessa
identica cosa anche in C.
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

enum { MAX=100 };
"[...] i programmatori C utilizzano tradizionalmente #define [...].
Purtroppo il preprocessoro C è uno strumento potente ma ottuso e le
macro rappresentano un modo pericoloso di programmare [...]. Lasciate
che sia il linguaggio a fare il lavoro. In C e in C++ le costanti
intere possono essere definite con l'istruzione enum."
					(B.W. Kernighan / R. Pike, Programmazione nella pratica)
poi ognuno fa quello che vuole; ma io sono portato a fidarmi di gente
come loro...
Ciao Anto 



ciao Andrea, ti ricordi di me?
come la mettiamo con i miei compilatori della Canistracci Inc, che non
vogliono compilare il seguente codice?
const int MAX=100;
char array[MAX];
int main ( void )
...
ciao
donCiccio


e perche' non ti fidi di chi ha scritto
#define NULL (void*)0
(punto di domanda)?
per me la definizione simbolica di *una* costante non ha molto senso fatta
con un enum.
Ti do ragione invece per le definizioni di piu' costanti logicamente
collegate, dove poi pero' usi variabili di tipo enum, altrimenti che
controlli in piu' puo' fare il compilatore? (anzi che controlli dovrebbe
fare? vedi dopo)
E ti do ancora ragione per le macro, cioe' espressioni celate dietro un
simbolo, da evitare il piu' possibile.
un esempio (poco attendibile perche' fatto con i miei compilatori della
Canistracci Inc):
ne borlandc++5.0 ne vc++5.0 si lamentano in un codice come questo:
enum pippo { AA,BB,CC };
enum pluto { XX,YY,ZZ };
enum pippo p;
int main ( void )
{
  p=Z;     // p e' di tipo pippo ma gli assegno un valore di tipo pluto
  p=1000;  // pippo ha valori solo da 0 a 2
  return 0;
}
a fronte di cio' perche' enum e' meglio di #define?
ciao
donCiccio
PS

1> // Inizio codice
2> #include <stdio.h>
3> #include <conio.h>
4> #include <string.h>
5>
6> void main(void); /* <-------------- */
7>
8> void main(void)
9> {
Guarda che non è necessario mettere il prototipo della funzione main
(riga 6)...
Ciao ciao
--
Vale
[ 
vdu...@galactica.it
 ]
"Non esistono domande sceme ma solo risposte sceme" - Einstein
"Non dormire non sempre significa essere svegli"

identica cosa anche in C.
tempo fa ho avuto una discussione su questo argomento su una ML.
Putroppo non avevamo nessun "testo sacro" da controllare, ma ci siamo
limitati a scrivere dei semplici prog e controllare il codice
assembler prodotto da gcc. E' risultato che in questo caso:
const int a=3;
int main() {
	return a;
}
Il compilatore C allocava memoria, mentre il compilatore C++
ottimizzava; già che ci sono ne approffitto per una domanda: le
costanti (come quella sopra) in C++ hanno di default linkage interno:
in C?


 in C?
intendi dire che sono locali al file, tipo variabili statiche?
in C no.
puoi benissimo scrivere cose del tipo
extern const int MAX;
ciao
donCiccio

extern const int MAX;
Non c'entra l'uso di extern, si parla di linkage di default.
--
CyberWalkie - walkietalkie(at)
libero.it

(riga 6)...
Oltretutto main DEVE restituire int e non void.
--
CyberWalkie - walkietalkie(at)
libero.it

 CyberWalkie - walkietalkie(at)
libero.it
oh, ciao Laforgia, un'altro nick?!
cmq, la risposta giusta qual'e'? (alla domanda di Cuni intendo)
e cosa vuol dire linkage? (che io ho erroneamente associato al linker)
ciao
donCiccio

a fronte di cio' perche' enum e' meglio di #define?
più che altro sono questioni di diagnostica: le enum vengono
considerate dal compilatore, non dal preprocessore: quindi in caso di
uso sbagliato o di errore per il compilatore è più facile generare un
errore più comprensibile.
Cmq è solo questione di gusti.


a fronte di cio' perche' enum e' meglio di #define?
Bisogna staccarsi il piu' possibile da cio' che non e' codice
masticato dal compilatore (e quindi NON soggetto a controlli).
L'uso delle direttive del preprocessore va ridotto al minimo.
--
CyberWalkie - walkietalkie(at)
libero.it

 Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it
donCiccio
--
Francesco Mirabella, 34 anni, programmatore (mi piace darmi delle arie)
13 anni di esperienza nell'automazione industriale.
cazziato *piu' volte* dai grandi di questo NG.  :o(

 L'uso delle direttive del preprocessore va ridotto al minimo.
Antonio Cuni dice: "Cmq č solo questione di gusti."
io la penso come lui.
ciao
donCiccio

extern const int MAX;
anche in C++ puoi farlo; perņ in C++ la scrittura:
const int a=3;
equivale a:
static const int a=3;
A quanto ho capito il C si comporta diversamente, vero?


 A quanto ho capito il C si comporta diversamente, vero?
si infatti, non sono static.
ma toglimi una curiosita':
se in un modulo C++ scrivo
const int a=3
e in un altro, sempre C++ scrivo
extern const int a;
come faccio a linkarli insieme se 'a' nel primo modulo e' static?
avro' un 'unresolved external' durante il link, quindi che senso ha
dichiarare extern la costante 'a', se non puo' essere vista aldifuori
del modulo dove la dichiaro?
sicuramente mi sfugge qualcosa.
ciao
donCiccio

io la penso come lui.
E' una questione di stile di programmazione, e' leggermente
diverso.
--
CyberWalkie - walkietalkie(at)
libero.it

> Guarda che non è necessario mettere il prototipo della funzione main
Si, lo so, solo che sono abituato a farlo, tanto che quando scrivo il
programma dall'inizio ormai lo scrivo senza pensarci. Grazie.


 Oltretutto main DEVE restituire int e non void.
Perchč? Io non voglio che ritorni nulla. A me basta che faccia quello che
gli ho scritto. Non č cosě che si fa?
--


gli ho scritto. Non č cosě che si fa?
No. main DEVE restituire un valore intero, che in caso di
successo e' 0.
--
CyberWalkie - walkietalkie(at)
libero.it

 successo e' 0.
Ah si, forse una volta lo avevo letto. Perchč lo zero serve a dire al
sistema operativo che tutto si č svolto senza errori avevo letto, giusto? Ma
llora return solo a cosa serve?


successo e' 0.
Perche' mai voler restituire un valore a tutti i costi anche quando
non ti serve ? Cioe' nel 99% dei casi !
Allora void non avrebbe senso, si potrebbe ad esempio obbligare a
restuire sempre qualcosa, MA A CHE PRO ?
Se non ti interessa utilizzare il valore di ritorno del programma non
lo usi e basta, ti ritroverai un valore casuale, ma che importa ?
ciao, acc.   
a...@libero.it

lo usi e basta, ti ritroverai un valore casuale, ma che importa ?
Errato.  
Leggi la documentazione in proposito (standard + FAQ di
comp.lang.c).
--
CyberWalkie - walkietalkie(at)
libero.it

sicuramente mi sfugge qualcosa.
quello che dici tu è giusto. Per far si che una costante abbia linkage
esterno devi preporre extern anche alla definizione:
extern const int a = 3; // definizione
extern const int a; // dichiarazione



ecco cosa mi sfuggiva, grazie!
ciao
donCiccio


mi potresti rispondere riguardo ai maggiori controlli fatti dal
compilatore in caso di enum, dando un'occhiata al codice che ho
postato qualche mex fa in questo thread? te ne sarei molto grato.
ciao
donCiccio

non ti serve ? Cioe' nel 99% dei casi !
be, ad esempio perché lo richiede lo standard...


be, ad esempio perché lo richiede lo standard...
...e se lo standard lo richiede non e' per puro piacere, ma
perche' ci sono motivi pratici alla base.
--
CyberWalkie - walkietalkie(at)
libero.it