Newsgroup: it.comp.lang.c
Titolo: scanf, ma come funziona?

Ho una stringa (char *) che contiene
"pippo=10"
e voglio una sscanf che mi restituisca "pippo" e "10" in due diverse
stringhe: come posso fare?
Ho provato con
char *s = "pippo=10";
char a[64], b[64];
sscanf(s, "%[^=]s%s", a, b);
e ottengo che a contiene "pippo, ma b rimane vuota.
Ho provato varie robe al posto del secondo %s, tipo:
sscanf(s, "%[^=]s=%s", a, b);
sscanf(s, "%[^=]s%[=]s%s", a, scarto,b);        // char scarto[64];
sscanf(s, "%[^=]s%c%s", a, &c, b);                // char c;
e altri che non ricordo, ma sempre senza esiti, b rimane vuota...
TIA
bp
P.S.:
lo so, posso evitare di usare la sscanf e scrivere quialche riga di codice
che mi fa il parse e mi restituisce quanto voglio... ma mi piacerebbe sapere
se usando
la sscanf riesco a risolvere il problema. Giusto per curiosita', anche
perche' io non
ne sono venuto a capo.

 sscanf(s, "%[^=]s%s", a, b);
Prova con
	sscanf(s, "%[^=]=%s", a, b);
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

	sscanf(s, "%[^=]=%s", a, b);
Mi sfugge una cosa : com'e' che il C capisce che ho due stringhe
considerando che c'e' solo una 's' ?
In quest'altro caso :
    char *s = "pippo=10";
    char b[64];
    int i = 0;
    sscanf(s, "%[^=]=%d", b, &i);
com'e' che capisce che la prima variabile e' una stringa ?
grazie
ciao

         sscanf(s, "%[^=]=%s", a, b);
Non finisco mai di sorprendermi della potenza della scanf()...
EMG

com'e' che capisce che la prima variabile e' una stringa ?
Dall'help del C++ Builder, a proposito dei set di scanf :
Search Set Conversion (%[search_set])
-------------------------------------
The set of characters surrounded by brackets can be substituted for
the s-type character.
The address argument is a pointer to an array of characters (char
arg[]).
These brackets surround a set of characters that define a search set
of possible characters making up the string (the input field).
If the first character in the brackets is a caret (^), the search set
is inverted to include all ASCII characters except those between the
brackets.
(Normally, a caret will be included in the inverted search set unless
explicitly listed somewhere after the first caret.)
The input field is a string not delimited by whitespace. ...scanf
reads the corresponding input field up to the first character it
reaches that does not appear in the search set (or in the inverted
search set).

Prova con


>> sscanf(s, "%[^=]=%s", a, b);
funziona, ma non riesco a capire una cosa: se scrivo
sscanf(s, "%[^=]s=%s", a, b);    // uno dei miei tentativi
la prima s (quella dopo la ]) che senso ha? perche' non funziona piu?
Ne deduco che scrivere "%[a-z]" e scrivere "%[a-z]s" NON e' la stessa cosa,
e quindi per leggere tutta na riga fino alla fine e' corretto "%[^\n]",
mentre e' sbagliato scrivere "%[^\n]s" (che funziona comunque perche' ???)
Grazie per la risposta, se puoi, e scusate per il lungo post.
bp

 dalla quale ho preso spunto)
scusate, ma perche' per leggere intere linee non usate fgets (che e'
stato creato apposta), invece che cose contro natura come scanf?
personalmente, per _qualunque_ uso che 1) non sia banale e 2) voglia
tener conto in maniera esauriente dei casi in cui chi fornisce l'input
possa scrivere scemate arbitrarie, uso _sempre_ fgets e mi faccio il
parsing dell'input.
per il parsing ci sono utensili leggeri come strtok e strtol, e truppe
corazzate come lex e yacc.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

stato creato apposta), invece che cose contro natura come scanf?
Concordo.


[SNIP]
Era solo un esempio, e la citazione riguardava un tread dal quale ho preso
spunto.
Anche in un post piu' sopra, ho detto che potevo sempre risolvere il mio
problema scrivendo una routine che fa il parse.
Comunque, la scanf esiste, e questo e' per me motivo sufficiente per capirne
il funzionamento.
Poi posso decidere di usarla o meno...
Inoltre il mio problema originale non c'entrava nulla con la lettura di una
riga intera,
vedi il mio post.
Ciao
bp

mentre e' sbagliato scrivere "%[^\n]s" (che funziona comunque perche' ???)
's' non va specificato dopo le parentesi !
O le parentesi, o 's'.
scanf("%[^\n]",buffer);
e' la versione corretta.
Nel nostro caso, invece, bisogna delimitare l'input, cioe' stabilire
quando l'uno finisce e l'altro inizia.
sscanf(s, "%[^=]=%s", a, b);
significa, leggi da s in a tutti i caratteri diversi da = (e per
questo si usa %[^=]) sino al primo uguale che incontri (il segno =
successivo), leggi l'uguale e tutti i restanti caratteri mettili in b
(%s).
Se io scrivo:
sscanf(s, "%[^=]s=%s", a, b) ;
sto invece scrivendo uno schema con cui e' impossibile trovare
corrispondenza, in quanto con %[^=] sto comunicando al sistema di
leggere tutti i caratteri diversi da = e di metterli in a, poi il
sistema (avendo escluso l'uguale) se lo trova come prossimo carattere,
ma io invece gli ho detto che il prossimo carattere deve essere una
's'. Essendo 's' == '=' sempre falso, la funzione si ferma.
E' per questo che bisogna usare 
sscanf(s, "%[^=]=%s", a, b) ;
In quanto in questo modo, dopo le parentesi, la funzione trovera' che 
'=' == '=' e continuera' la scansione.
scanf() e' una funzione il cui comportamento e' molto subdolo. 
Cerca di evitarla, usando fgets(), oppure cerca di passare al C++ :)

the s-type character.
bah, per me chi ha progettato la sscanf era malato ....
ciao


sara' anche subdola, ma risolve un sacco di problemi!
Nel caso specifico, sto programmando per dei terminali industriali
con prcessore toshiba, e l'unica roba che ho a disposizione e'
il compilatore C (neppure tanto std), e non posso passare al c++.
By the way, mentre la nostra ormai famosa
    char *s = "pippo=10";
    sscanf(s, "%[^=]=%s", a, b);
funziona egregiamente sul PC (compilatore MS VC++ 6.0),
col compilatore del terminale non funziona piu' (recupera
solo la parte a sx dell'=): sono a questo punto certo
che e' un baco del compilatore che uso... tant'e', mi sono
scritto io una funzione per fare il parse. Un po' di
esercizio non guasta ;)
Un saluto a tutti
bp

bah, per me chi ha progettato la sscanf era malato ....
Non penso proprio !
Le espressioni regolari sono una gran cosa.
Bisogna soltanto imparare ad usarle.

col compilatore del terminale non funziona piu' (recupera
Prova :
    sscanf(s, "%[^=]=%[0-9]", a, b) ;
Domanda fatidica : hai allocato memoria sia per a che per b ?

Bisogna soltanto imparare ad usarle.
Allora diciamo che era una mente cosi' eccelsa che ha fatto una cosa
cosi' potente che pochi arrivano a sfruttare e capire completamente
:-)
E questo lo vedi anche dai commenti che hanno fatto nei vari messaggi.
Commenti come :
"Non finisco mai di sorprendermi della potenza della scanf()..."
"cose contro natura come scanf?"
"scanf() e' una funzione il cui comportamento e' molto subdolo."
A me, personalmente, non sembra normale che una funzione abbia un
comportamento subdolo.
ciao
p.s. Onde evitare malintesi : non c'e' polemica da parte mia, e' solo
uno scambio d'opinioni

comportamento subdolo.
Certo che e' normale. Non e' normale che non si impari a *dominare* i
comportamenti subdoli.

Non e' normale che non si impari a *dominare* i comportamenti subdoli.
Non ti rimane un po' la paura di qualche comportamento imprevisto ?
ciao

 Quanto si scrivono programmi a linea di comando e cioč molto poco.
Forse su piattafore windows e' cosi', ma su piattaforme unix la riga di
comando va ancora
per la maggiore.
Ivan Molella

ambienti la stdlib c'e` e si usa.
Che c'entra la stdlib ? :)
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------
#exclude <windows.h>

 comando va ancora per la maggiore.
Quando comincerň a vedere in giro utenti che usano programmi a linea di
comando ne riparleremo. :-)
EMG

Quanto si scrivono programmi a linea di comando e cioč molto poco.
ehm... e tutto il mondo gnu ?
( fermo restando che provo una profonda antipatia per cin e cout, ma
riconosco che e' un mio limite !! )

 Che c'entra la stdlib ? :)
  La libreria standard contiene anche "le funzioni di I/O classico": non
eri tu che sostenevi che "alla fine non val piu' la pena neanche
studiarne il funzionamento"? :)
	Alla prossima,
		Marco

studiarne il funzionamento"? :)
Io mi riferivo a quelle contenute in stdio (STanDard I/O), non estendo
il discorso a tutta la stdlib.



Naturalmente si! (Nel post ho di molto semplificato per puntare l'attenzione
sul problema).
Buona programmazione a tutti
bp

stringhe (tipo "PIPPO=Magazzino")
sscanf(s, "%[^=]=%[A-Za-z0-9]", a, b) ;
Se neanche questa ti funziona, e' davvero colpa del compilatore.


Se neanche questa ti funziona, e' davvero colpa del compilatore.
...e difatti: e' propio il coimpilatore bacato.
Ma non mi meraviglio piu' di tanto, e' un "vecchio" compilatore della
toshiba del 1994, o forse ancora piu' vecchio.
Non credo esistano versioni piu' recenti, e questo non e' l'unico baco.
Un giorno o l'altro mi prendero' la briga di "ricostruire" un po' delle
funzioni della stdlib. Magari usando i source del caro djpp...
Comunque grazie.
bp

 <snip>
Dando una occhiata, con semantica 'strict', alla definizione
dell'input specifier della scanf, non ho trovato da nessuna parte che
l'elenco dei caratteri all'interno delle [] si possa esprimere come
una RE.
Una implementazione che interpreta il carattere '-' esattamente come
carattere '-' e non come operatore di lista di valori, puo' essere a
questo punto valida.
Bye, Andrea
-- 
 _     /°#     ----------------+-------------------------
°  \  /        Andrea          | arimicci @@
   |++~|            Rimicci    |         aritaly. com
    \ /  --------- OS/2 V5 "Phoenix" --------------------
     |   The MIDI JukeBox:
    _|_                  
http://www.aritaly.com/eng/midi/
---------------------------------------------------------
MOVIMENTO NAZIONALE UTENTI INTERNET 
http://www.notut.org/
---------------------------------------------------------

questo punto valida.
Ti sbagli.
Quella a cui hai dato un'occhiata, e' un'implementazione non conforme
allo standard. La scanf() e' in grado di interpretare A-Z esattamente
come la lista dei valori contenuti tra A e Z, estremi compresi e cosi'
anche per tutti i set seguenti.


 Ti sbagli. <snip>
Puo' essere che abbia letto un riferimento sbagliato...
avevo letto il K&R, second edition, pag.246 (Table B-2. Scanf
Conversions).
Li' c'e' scritto che tra i [] c'e' un 'set', e non si parla da
nessuna parte del poter usare RE. C'e' solo una nota sul come
inserire il carattere ']'.
Dove hai letto che si possono usare le RE ?


Dove hai letto che si possono usare le RE ?
Hai frainteso.
Non ho detto che si possono usare le RE, ma che la sintassi della
scanf() e' *basata* sulle RE, cioe' ne trae spunto.


 comando ne riparleremo. :-)
Se Intendi utenti Unix, buona parte di quelli che conosco lavorano su riga di
comando
e il 100% dei sistemisti anche :):)
Ivan Molella
Ivan Molella

 Hai frainteso. <snip>
Uffff... prima sbaglio, poi fraintendo...
Forse devo guardare il NG prima di bere, non dopo... LOL
;) Andrea


 e il 100% dei sistemisti anche :):)
Sto parlando degli utenti normali, quelli che trovi negli uffici che
hanno difficoltà perfino a fare il doppio click con il minimo di
precisione necessaria. :-)
EMG

importante...).
[SNIP]
Quello che dici e' vero, ma secondo me e' limitato all'I/O interattivo
con gli utenti.
Ma la scanf (e' una funzione di I/O classico, vero?), ha delle varianti
che si adattano benissimo anche ad altri contesti. Ad esempio, se devo
leggere un file testo che e' stato prodotto da un altro prg ed quindi
ha, con ragionevole certezza, le righe composte con un formato "fisso"...
Oppure un .ini vecchio stile, oppure interpretare stringhe di una
qualche comunicazione.
E questi utilizzi sono indipendenti dall'ambiente specifico.
Quindi, io penso che studiaree capire bene il funzionamento di
funzioni come printf, scanf, e affini sia fondamentale per
ogni programmatore C, indipendentemente dalla piattaforma
e/o dal S.O. utilizzati.
bp

 precisione necessaria. :-)
Quelli sono "uTONTI" e non utenti :-)
--
 Ciao, Bianco.
 Reply to 
luca....@tiscalinet.it