scanf.c (2554B)
1#include <stdint.h> 2#include <stdio.h> 3#include <stdarg.h> 4#include <ctype.h> 5 6static unsigned char scan_skip(char *s, unsigned char i) 7{ 8oncemore: 9 while(isspace(s[i])) 10 i++; 11 if(s[i] == 0) { 12 gets(s); 13 i = 0; 14 goto oncemore; 15 } 16 return i; 17} 18 19static unsigned char scan_int(char *s, unsigned char i, unsigned char base, char *nb) 20{ 21 char n = 0; 22 unsigned char j, sign = 0; 23 24 switch(s[i]) 25 { 26 case '-': 27 sign++; 28 /* and fall through */ 29 case '+': 30 ++i; 31 break; 32 } 33 while(1) { 34 if(isdigit(s[i])) 35 j = s[i] - '0'; 36 else if(isalpha(s[i])) 37 j = toupper(s[i]) - 'A' + 10; 38 else 39 break; 40 if(j >= base) 41 break; 42 n = base * n + j; 43 i++; 44 } 45 *nb = (sign == 0 ? n : -n); 46 return i; 47} 48 49static unsigned char scan_long(char *s, unsigned char i, unsigned char base, int *nb) 50{ 51 int n = 0; 52 unsigned char j, sign = 0; 53 54 switch(s[i]) 55 { 56 case '-': 57 sign++; 58 /* and fall through */ 59 case '+': 60 ++i; 61 break; 62 } 63 while(1) { 64 if(isdigit(s[i])) 65 j = s[i] - '0'; 66 else if(isalpha(s[i])) 67 j = toupper(s[i]) - 'A' + 10; 68 else 69 break; 70 if(j >= base) 71 break; 72 n = base * n + j; 73 i++; 74 } 75 *nb = (sign == 0 ? n : -n); 76 return i; 77} 78 79char scanf(char *fmt, ...) 80{ 81 va_list ap; 82 char s[64]; 83 unsigned char i = 0; 84 char nb = 0; 85 86 gets(s); 87 va_start(ap, fmt); 88 for(; *fmt; fmt++) { 89 if(isspace(*fmt)) 90 continue; 91 i = scan_skip(s, i); 92 if(*fmt == '%') { 93 switch(*++fmt) { 94 case 'c': 95 /* char */ 96 *va_arg(ap, char *) = s[i++]; 97 break; 98 case 'd': 99 /* decimal int */ 100 case 'u': 101 /* unsigned int */ 102 i = scan_int(s, i, 10, va_arg(ap, char *)); 103 break; 104 case 'o': 105 /* octal int */ 106 i = scan_int(s, i, 8, va_arg(ap, char *)); 107 break; 108 case 'x': 109 /* hexadecimal int */ 110 i = scan_int(s, i, 16, va_arg(ap, char *)); 111 break; 112 case 's': 113 /* string */ 114 { 115 char j = 0; 116 char *d = va_arg(ap, char *); 117 while((d[j++] = s[i++]) != 0) 118 ; 119 } 120 break; 121 case 'l': 122 /* long */ 123 switch(*++fmt) { 124 case 'd': 125 /* decimal long */ 126 case 'u': 127 /* unsigned long */ 128 i = scan_long(s, i, 10, va_arg(ap, int *)); 129 break; 130 case 'o': 131 /* octal long */ 132 i = scan_long(s, i, 8, va_arg(ap, int *)); 133 break; 134 case 'x': 135 /* hexadecimal long */ 136 i = scan_long(s, i, 16, va_arg(ap, int *)); 137 break; 138 } 139 break; 140 default: 141 if(s[i] != *fmt) 142 return -1; 143 break; 144 } 145 nb++; 146 } else 147 if(s[i] != *fmt) 148 return -1; 149 } 150 va_end(ap); 151 152 return nb; 153}