1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <malloc.h>
static int vscanf_generic(const char *str, FILE *fd, const char *p_format, va_list arg_list){
char *nformat = strdup(p_format);
char *format = nformat;
int i;
int n=0;
int convtot=0;
int conv=EOF;
for (i=0; format[i]; i++){
if (format[i] == '%'){
if (format[i+1] == '%' || format[i+1] == '*' || format[i+1] == '\0')
i++; // pas compté comme variable à allouer, je saute
else { // c'est une variable
if (n==0) // première variable: OK
n++;
else { // deuxième variable: on coupe juste avant
char f[3];
f[1]=format[i+1]; f[2]=format[i+2];
format[i+1]='n'; format[i+2]='\0'; // %n = nombre de caractères lus dans l'entrée
void *p = va_arg(arg_list, void *);
int lu=-1,conv;
conv = (str ? sscanf(str, format, p, &lu) :
fd ? fscanf(fd, format, p, &lu) :
scanf(format, p, &lu) );
if (lu==-1){ // échec à la conversion
convtot += (conv>=0 ? conv : 0); // peut-être converti quand même une variable?
break; // mais ensuite on arrête
}
convtot++; // une variable lue
if (str)
str += lu; // avancer dans l'entrée
format[i+1]=f[1]; format[i+2]=f[2]; // rétablir la chaîne de format
format += i; i = -1; // avancer dans le format
n=0; // on repart avec 0 variable détectée dans la nouvelle chaîne
}
}
}
}
if (format[i]=='\0' && n>0) {
// on est arrivé au bout, et il reste une variable à convertir
void *p = va_arg(arg_list, void *);
int conv;
conv = (str ? sscanf(str, format, p) :
fd ? fscanf(fd, format, p) :
scanf(format, p) );
convtot += (conv>=0 ? conv : 0);
}
free(nformat);
return (convtot>0 ? convtot : conv);
}
int vsscanf(const char *str, const char *p_format, va_list arg_list){
// fonction qui curieusement n'existe pas chez Microsoft
return vscanf_generic(str, NULL, p_format, arg_list);
}
int vscanf(const char *p_format, va_list arg_list){
// fonction qui curieusement n'existe pas chez Microsoft
return vscanf_generic(NULL, NULL, p_format, arg_list);
}
int vfscanf(FILE *fd, const char *p_format, va_list arg_list){
// fonction qui curieusement n'existe pas chez Microsoft
return vscanf_generic(NULL, fd, p_format, arg_list);
} |
Partager