Sscanf

Sk_Anonymous
Ciao ragazzi dovrei estrarre un numero da una stringa...ad es: cos80.
Vorrei estrarre il numero 80...cm posso fare????Ho provato ad usare sscanf...boh?!
ps. Mi scrivereste un pezzo di codice in ANSI C....grazie mille...CIAO

Risposte
vict85
"giocala88":
Ciao ragazzi dovrei estrarre un numero da una stringa...ad es: cos80.
Vorrei estrarre il numero 80...cm posso fare????Ho provato ad usare sscanf...boh?!
ps. Mi scrivereste un pezzo di codice in ANSI C....grazie mille...CIAO


Ho messo due codici (entrambi non provati). In nessuno ho usato sscanf...

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* questo solo per il secondo */
#include <limits.h>


[...]

/* VERSIONE 1 */
char s[N], *s_f;
int i, cont_num = 0, num[M];

[...]

for (i = 0; s[i] != '\0'; ++i) {
	if (isdigit(s[i])) {
		num[cont_num] = strtol((s + i), s_f, 10);
		++cont_num;
		i += s_f - s[i+1];
	}
}

/* VERSIONE 2 */
char s[N];
int i, digit = 0, cont_num = 0, num[M];

[...]

for (i = 0; s[i] != '\0'; ++i) {
	if (isdigit(s[i])) {
		if (num < INT_MAX/10) {
			num[cont_num]*=10;
		}
		if (num < INT_MAX - s[i]) {
			num[cont_num]+=s[i];
		}
		if (!digit)
			digit = 1;
	}
	else {
		if (digit) {
			digit = 0;
			++cont_num;
			num[cont_num] = 0;
		}
	}
}

Sk_Anonymous
vict85 apprezzo l'aiuto ma io nn sn cm te...ci capisco poco se nn mi commenti quello ke fai o perlomeno nn mi fai un programma ke posso far partire...nn mi piace copiare snz capire....cmq grazie mille 6 davvero bravo cn la programmazione!!!!!...ciao

vict85
Non sono così bravo... ho solamente visto più codice...

In entrambi ti trova tutti i numeri contenuti nella stringa s[N] e li memorizza dentro l'array num[M]

Scorre tutta la stringa trattandolo come un array di char (cosa che è). Finisce quando raggiunge il terminatore di stringa '\0'

Ora i 2 algoritmi si defferenziano:
1. Trova un elemento che è una cifra (utilizzando la funzione standard isdigit contenuta in ctype.h). Chiama quindi la funzione strtol (che sta per string to long) per convertire il numero che segue. Passo (s+i) utilizzando il legame tra puntatori e array (ma potevo anche mettere &s). s_f è un puntatore in cui viene memorizzato (sempre dentro strtol) il valore del primo carattere non numerico da s. Dopo di che attraverso s_f trovo quanto era lungo il numero. In realtà avrei dovuto scrivere s_f - s - 1 ma ho messo s[i+1] perché aveva lo stesso risultato. Anche qui ho usato il legame tra array e puntatori. Il -1 è legato al fatto che il for aumenta sempre di uno e dovevo essere sicuro che s_f non puntasse a '\0'
2. è sbagliato... Asp che lo metto a posto...

vict85
Ho fatto un errore stupido...
Lo commento dentro...

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>

/* VERSIONE 2 */
char s[N];
int i, digit = 0, cont_num = 0, num[M];

[...]
/* Leggo i char contenuti nella stringa */
for (i = 0; s[i] != '\0'; ++i) {

   /* Se ho a che fare con una cifra */
	if (isdigit(s[i])) {
       /* Se moltiplicare per 10 non fa andare il numero in overflow lo moltiplico per 10 (con la prima cifra il numero che moltiplico è 0) */
		if (num < INT_MAX/10) {
			num[cont_num]*=10;
		}
       /* Se aumentare di quella cifra non manda in overflow... Il mio errore è stato non pensare al fatto che nella codifica dei char '0', '1', '2'... potrebbe non essere (e generalmente non è) 0, 1, 2, 3... anche se sono sempre numeri consecutivi.*/
		if (num < INT_MAX - (int) (s[i] - '0')) {
			num[cont_num]+= (int) (s[i] - '0');
		}
       /* Questo è un valore int usato come bool che serve per segnare se il numero precedente era numerico */
		if (!digit)
			digit = 1;
	}
	else {
       /* Se il numero precedente era numerico si sposta nell'elemento successivo di num e lo inizializza a 0 */
		if (digit) {
			digit = 0;
			++cont_num;
			num[cont_num] = 0;
		}
	}
}

vict85
"Sergio":


@vict85: non capisco le tue soluzioni. Direi che il metodo più semplice consiste nel leggere la stringa a ritroso, dall'ultimo carattere al primo. Non capisco, inoltre, quel num che è dichiarato e usato come un array, ma poi anche usato come numero in confronti del tipo "if (num < INT_MAX/10)".



Num in quella riga era un array... In quel caso era num[cont_num]. Comunque strlen è un O(n)...

Io non partivo dal presupposto che ci fosse solo un numero... quindi ho creato un array per contenerli tutti... Inoltre ho fatto un mezzo controllo per l'overflow.
Nel primo ho solo usato la funzione strtol che se gli dai un puntatore all'inizio del numero te lo converte.

In ogni caso facendo le tue assunzioni il mio codice (1) diventa così:

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

#define N 20

int main() {
	/* La stringa */
	char s[N];
	
	/* La variabile in cui memorizzo il numero (se ce n'é uno non ho bisogno di un array */
	long num;
	
	/* Variabile per il ciclo */
	int i = 0;
	int n_bool = 0;
	
	/* Salvo la stringa e la stampo a video */
	printf("Immetti una stringa che contenga un numero: ");
	fgets(s, N, stdin);
	printf("la stringa è: %s", s);
	/* N.B. leggi il nota bene di sergio */

	/* ciclo che legge e si chiude quando ha finito di leggere la stringa o ha letto il numero*/
	while (s[i] != '\n' && !n_bool) {
		/* Se il carattere che incontra è una cifra o se è un meno seguito da un numero chiama atoi per convertire la stringa in numero da quel carattere in poi. */
		if(isdigit(s[i]) || ((s[i] == '-') && isdigit(s[i+1]))) {
			num = atol(&s[i]);
			n_bool = 1;
		}
		else ++i;
	}
	
	printf("numero: %ld\n", num);
	
	system("PAUSE");
	return 0;
}


Il secondo codice semplicemente implementava strtol...

P.S: per stampare singoli caratteri è meglio putchar(*p);

vict85
Questo codice non chiama la funzione di libreria e non fa le assunzioni di Sergio come il precedente (che è il più semplice).

La stringa può avere fino a 40 caratteri (+ '\n' e '\0') e può contenere fino a 20 numeri (anche negativi, cosa che però faceva anche l'altro). Controlla inoltre l'overflow.

#include <stdio.h>
#include <ctype.h>
#include <limits.h>

#define N 42
#define M 20

int main() {
	/* La stringa, il secondo char serve per il controllo della presenza del meno */
	char s[N], meno;
	
	/* La variabile in cui memorizzo il numero (se ce n'é uno non ho bisogno di un array */
	long num[M];
	
	/* Variabili per i cicli e contatore per i numeri, m_pres è un int che serve come bool e che serve per capire se alla variabile meno è stato assegnato un valore */
	int i;
	int cont_num, m_pres = 0;
	
	/* Salvo la stringa e la stampo a video */
	printf("Immetti una stringa che contenga dei numeri: ");
	fgets(s, N, stdin);
	printf("la stringa è: %s", s);
	/* N.B. leggi il nota bene di sergio */

	/* Inizializzo le variabili */
	i = 0;
	cont_num = 0;
	/* ciclo grande che continua a cercare numeri, se ne vuoi solo uno basta levare il do all'inizio e il while alla fine, oltre che trasformare num in semplice numero */
	do {
		/* Questo ciclo elimina tutto ciò che non è numero all'inizio della stringa, i è inizializzato sopra sopra */
		for (; !isdigit(s[i]) && s[i] != '\n'; ++i);
		/* Se c'é un numero... */
		if (s[i] != '\n') {
			/* metto in num la prima cifra che incontra (legge da sinistra) */
			num[cont_num] = (long) (s[i] - '0');
			/* se i è diverso da 0 memorizza il carattere che precede il numero, per poi controllare se è un meno */
			if (i) {
				meno = s[i-1];
				m_pres = 1;
			}
			/* aumento l'indice per leggere la seconda cifra, se c'é */
			++i;
			/* finche sono cifre... */
			while (isdigit(s[i])) {
				/* se non è in overflow moltiplico per 10 il vecchio numero e aggiungo la nuova cifra */
				if (num[cont_num] < (LONG_MAX/10 - (long) (s[i] - '0'))) {
					num[cont_num] *= 10;
					num[cont_num] += (long) (s[i] - '0');
					++i;
				}
				/* altrimenti esco */
				else {
					puts("Il numero e' troppo grande\n");
					/* Questo serve su windows per tenere aperta la console */
					system("PAUSE");
					return 1;
				}
			}
			/* controllo se c'é il meno */
			if (m_pres && meno == '-') {
				num[cont_num] = -num[cont_num];
				m_pres = 0;
			}
			++cont_num;
		}
	} while (s[i] != '\n');
	
	printf("ci sono %d numeri nella stringa:", cont_num);
	for(i=0; i<cont_num; ++i) {
		printf(" %d", num[i]);
	}
	putchar('\n');
	
	/* Questo serve su windows per tenere aperta la console */
	system("PAUSE");
	return 0;
}

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