cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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}