📄 input.c
字号:
#define INC() (++charcount, _inc())
#define UN_INC(chr) (--charcount, _ungetch_lk(chr))
#define EAT_WHITE() _whiteout(&charcount)
static int __cdecl _inc(void);
static int __cdecl _whiteout(int *);
#else /* CPRFLAG */
#define INC() (++charcount, _inc(stream))
#define UN_INC(chr) (--charcount, _un_inc(chr, stream))
#define EAT_WHITE() _whiteout(&charcount, stream)
#ifndef _UNICODE
static int __cdecl _inc(FILE *);
static void __cdecl _un_inc(int, FILE *);
static int __cdecl _whiteout(int *, FILE *);
#else /* _UNICODE */
static wchar_t __cdecl _inc(FILE *);
static void __cdecl _un_inc(wchar_t, FILE *);
static wchar_t __cdecl _whiteout(int *, FILE *);
#endif /* _UNICODE */
#endif /* CPRFLAG */
#ifdef _UNICODE
static int __cdecl _winput(FILE *, const unsigned char *, va_list);
#endif /* _UNICODE */
#ifdef CPRFLAG
static int __cdecl input(const unsigned char *, va_list);
/***
*int _cscanf(format, arglist) - read formatted input direct from console
*
*Purpose:
* Reads formatted data like scanf, but uses console I/O functions.
*
*Entry:
* char *format - format string to determine data formats
* arglist - list of POINTERS to where to put data
*
*Exit:
* returns number of successfully matched data items (from input)
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _cscanf (
const char *format,
...
)
{
va_list arglist;
va_start(arglist, format);
_ASSERTE(format != NULL);
return input(format,arglist); /* get the input */
}
#endif /* CPRFLAG */
#define ASCII 32 /* # of bytes needed to hold 256 bits */
#define SCAN_SHORT 0 /* also for FLOAT */
#define SCAN_LONG 1 /* also for DOUBLE */
#define SCAN_L_DOUBLE 2 /* only for LONG DOUBLE */
#define SCAN_NEAR 0
#define SCAN_FAR 1
static char sbrackset[] = " \t-\n]"; /* use range-style list, cl68 swaps \n to \r*/
static char cbrackset[] = "]";
/***
*int _input(stream, format, arglist), static int input(format, arglist)
*
*Purpose:
* get input items (data items or literal matches) from the input stream
* and assign them if appropriate to the items thru the arglist. this
* function is intended for internal library use only, not for the user
*
* The _input entry point is for the normal scanf() functions
* The input entry point is used when compiling for _cscanf() [CPRFLAF
* defined] and is a static function called only by _cscanf() -- reads from
* console.
*
*Entry:
* FILE *stream - file to read from
* char *format - format string to determine the data to read
* arglist - list of pointer to data items
*
*Exit:
* returns number of items assigned and fills in data items
* returns EOF if error or EOF found on stream before 1st data item matched
*
*Exceptions:
*
*******************************************************************************/
#ifdef CPRFLAG
static int __cdecl input (
const unsigned char *format,
va_list arglist
)
#elif defined (_UNICODE)
static int __cdecl _winput (
FILE *stream,
const unsigned char *format,
va_list arglist
)
#else /* defined (_UNICODE) */
int __cdecl _input (
FILE *stream,
const unsigned char *format,
va_list arglist
)
#endif /* defined (_UNICODE) */
{
char table[ASCII]; /* which chars allowed for %[], %s */
#ifndef _UNICODE
char floatstring[CVTBUFSIZE + 1]; /* ASCII buffer for floats */
#else /* _UNICODE */
wchar_t floatstring[CVTBUFSIZE + 1];
#endif /* _UNICODE */
unsigned long number; /* temp hold-value */
unsigned __int64 num64; /* temp for 64-bit integers */
void *pointer; /* points to user data receptacle */
void *start; /* indicate non-empty string */
unsigned char *scanptr; /* for building "table" data */
#ifdef _UNICODE
REG2 wchar_t ch;
#else /* _UNICODE */
REG2 int ch;
#endif /* _UNICODE */
int charcount; /* total number of chars read */
REG1 int comchr; /* holds designator type */
int count; /* return value. # of assignments */
int started; /* indicate good number */
int width; /* width of field */
int widthset; /* user has specified width */
/* Neither coerceshort nor farone are need for the 386 */
unsigned char rngch; /* used while scanning range */
char done_flag; /* general purpose loop monitor */
unsigned char last; /* also for %[a-z] */
char longone; /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */
int integer64; /* 1 for 64-bit integer, 0 otherwise */
char negative; /* flag for '-' detected */
unsigned char prevchar; /* for %[a-z] */
char reject; /* %[^ABC] instead of %[ABC] */
char suppress; /* don't assign anything */
char match; /* flag: !0 if any fields matched */
va_list arglistsave; /* save arglist value */
char fl_wchar_arg; /* flags wide char/string argument */
#ifdef _UNICODE
wchar_t wdecimal; /* wide version of decimal point */
wchar_t *wptr; /* pointer traverses wide floatstring*/
#endif /* _UNICODE */
int _tflag = 0;
_ASSERTE(format != NULL);
#ifndef CPRFLAG
_ASSERTE(stream != NULL);
#endif /* CPRFLAG */
/*
count = # fields assigned
charcount = # chars read
match = flag indicating if any fields were matched
[Note that we need both count and match. For example, a field
may match a format but have assignments suppressed. In this case,
match will get set, but 'count' will still equal 0. We need to
distinguish 'match vs no-match' when terminating due to EOF.]
*/
count = charcount = match = 0;
while (*format) {
if (isspace((int)*format)) {
UN_INC(EAT_WHITE()); /* put first non-space char back */
while ((isspace)(*++format)); /* NULL */
/* careful: isspace macro may evaluate argument more than once! */
}
if ('%' == *format) {
number = width = widthset = started = done_flag =
/* ints are the same size as longs and all pointers are 'near' for
the 386 */
suppress = negative = reject = prevchar = 0;
longone = 1;
integer64 = 0;
fl_wchar_arg = 0;
while (!done_flag) {
comchr = *++format;
if (isdigit(comchr)) {
++widthset;
width = MUL10(width) + (comchr - '0');
} else
switch (comchr) {
case 'F':
case 'N': /* no way to push NEAR in large model */
break; /* NEAR is default in small model */
case 'h':
/* set longone to 0 */
--longone;
break;
case _T('I'):
if ( (*(format + 1) == _T('6')) &&
(*(format + 2) == _T('4')) )
{
format += 2;
++integer64;
num64 = 0;
break;
}
goto DEFAULT_LABEL;
case 'L':
++longone;
/* NOBREAK */
case 'l':
++longone;
break;
case '*':
++suppress;
break;
default:
DEFAULT_LABEL:
++done_flag;
break;
}
}
if (!suppress) {
arglistsave = arglist;
pointer = va_arg(arglist,void *);
}
done_flag = 0;
/* switch to lowercase to allow %E,%G, and to
keep the switch table small */
comchr = *format | ('a' - 'A');
/*
* Generic string handling support: %tc, %ts accept
* either chars or wide-chars depending on _tflag.
* _tflag == 1 means wide-chars.
*/
if (comchr == 't') {
if (_tflag == 1)
comchr = 'w';
else
comchr = *(++format);
}
if ('n' != comchr)
if ('w' == comchr) {
fl_wchar_arg = 1;
comchr = *++format;
if (comchr == 'c')
ch = INC();
else if (comchr == 's')
ch = EAT_WHITE();
else
goto error_return; /* not 'wc' or 'ws' */
} else
if ('c' != comchr && LEFT_BRACKET != comchr)
ch = EAT_WHITE();
else
ch = INC();
if (!widthset || width) {
switch(comchr) {
case 'c':
if (!widthset) {
++widthset;
++width;
}
scanptr = cbrackset;
--reject; /* set reject to 255 */
goto scanit2;
case 's':
scanptr = sbrackset;
--reject; /* set reject to 255 */
goto scanit2;
case LEFT_BRACKET : /* scanset */
scanptr = (char *)(++format);
if ('^' == *scanptr) {
++scanptr;
--reject; /* set reject to 255 */
}
scanit2:
memset(table, 0, ASCII);
if (LEFT_BRACKET == comchr)
if (']' == *scanptr) {
prevchar = ']';
++scanptr;
table[ ']' >> 3] = 1 << (']' & 7);
}
while (']' != *scanptr) {
rngch = *scanptr++;
if ('-' != rngch ||
!prevchar || /* first char */
']' == *scanptr) /* last char */
table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7);
else { /* handle a-z type set */
rngch = *scanptr++; /* get end of range */
if (prevchar < rngch) /* %[a-z] */
last = rngch;
else { /* %[z-a] */
last = prevchar;
prevchar = rngch;
}
for (rngch = prevchar; rngch <= last; ++rngch)
table[rngch >> 3] |= 1 << (rngch & 7);
prevchar = 0;
}
}
if (!*scanptr)
goto error_return; /* trunc'd format string */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -