📄 xscanf.c
字号:
/*---------------------------------------------------------------*/
/* If we've reached the end of format, return num of successful */
/* assignments or EOF. */
/*---------------------------------------------------------------*/
if (c == '\0')
return (vars_assigned) ? vars_assigned : EOF;
/*---------------------------------------------------------------*/
/* Else if c is format specifier, go ahead and parse format. */
/*---------------------------------------------------------------*/
else if (c == '%')
state = 1;
/*---------------------------------------------------------------*/
/* If c is white space, ignore it. */
/*---------------------------------------------------------------*/
else if (isspace(c))
state = 2;
/*---------------------------------------------------------------*/
/* Else match character from format with input character. */
/*---------------------------------------------------------------*/
else
{
--format;
state = 3;
}
break;
}
/*-----------------------------------------------------------------*/
/* State 1 parses a format specifier, looking for a store first. */
/*-----------------------------------------------------------------*/
case 1:
{
++format;
store = 1;
value = width = 0;
if (c == '*')
store = 0;
else if (c == '%')
state = 0;
else
--format;
state = 4;
break;
}
/*-----------------------------------------------------------------*/
/* State 2 reads in all white spaces from input. */
/*-----------------------------------------------------------------*/
case 2:
{
c_i = get_char(stream, s, &index);
for (; isspace(c_i); ++count, c_i = get_char(stream, s, &index)) ;
put_char(stream, &index, c_i);
state = 0;
break;
}
/*-----------------------------------------------------------------*/
/* State 3 matches a character from format with a char from input. */
/*-----------------------------------------------------------------*/
case 3:
{
++count;
c_i = get_char(stream, s, &index);
if (c_i != c)
{
return (vars_assigned) ? vars_assigned : EOF;
}
++format;
state = 0;
break;
}
/*-----------------------------------------------------------------*/
/* State 4 looks for the width. */
/*-----------------------------------------------------------------*/
case 4:
{
for (; isdigit(c); ++format, c = *format)
width = 10 * width + c - '0';
state = 5;
break;
}
/*-----------------------------------------------------------------*/
/* State 5 looks for an 'l', 'L', or 'h'. */
/*-----------------------------------------------------------------*/
case 5:
{
++format;
if (c == 'l')
value = l_VALUE;
else if (c == 'h')
value = h_VALUE;
else
--format;
state = 6;
break;
}
/*-----------------------------------------------------------------*/
/* State 6 gets the conversion specifier. */
/*-----------------------------------------------------------------*/
case 6:
{
++format;
if (c == 'd')
state = 7;
else if (c == 'i')
state = 8;
else if (c == 'o')
state = 9;
else if (c == 'u')
state = 10;
else if (c == 's')
state = 11;
else if (c == 'p')
state = 12;
else if (c == 'x' || c == 'X')
state = 13;
else if (c == '[')
/*-------------------------------------------------------------*/
/* Handle the scanset (mentioned between the ']'s). */
/*-------------------------------------------------------------*/
state = 14;
else if (c == 'n')
state = 15;
else if (c == 'c')
state = 16;
else if (c == 'e' || c == 'f' || c == 'g' || c == 'E' || c == 'G')
state = 17;
else
{
/*-------------------------------------------------------------*/
/* For an invalid conversion specifier return. */
/*-------------------------------------------------------------*/
return vars_assigned ? vars_assigned : EOF;
}
/*---------------------------------------------------------------*/
/* Except for the 'c' specifier, skip leading white spaces. */
/*---------------------------------------------------------------*/
if (state && (c != 'c' && c != '[' && c != 'n'))
{
c_i = get_char(stream, s, &index);
for (; isspace(c_i); ++count)
c_i = get_char(stream, s, &index);
}
break;
}
/*-----------------------------------------------------------------*/
/* State 7 handles the 'd' specifier. */
/*-----------------------------------------------------------------*/
case 7:
{
void *curr_ptr;
int which_pointer;
/*---------------------------------------------------------------*/
/* Set curr_ptr to the appropriate value. */
/*---------------------------------------------------------------*/
if (store)
{
if (value == DEFAULT_VALUE)
{
which_pointer = INT;
curr_ptr = va_arg(args, int *);
}
else if (value == l_VALUE)
{
which_pointer = LONG_INT;
curr_ptr = va_arg(args, long *);
}
else
{
which_pointer = SHORT_INT;
curr_ptr = va_arg(args, short *);
}
++vars_assigned;
}
else
{
which_pointer = INT;
curr_ptr = &UnusedInt;
}
plus = get_sign(stream, s, &index, &c_i, &count);
/*---------------------------------------------------------------*/
/* Get the actual number, as a sequence of digits. */
/*---------------------------------------------------------------*/
count = get_num(stream, s, &index, c_i, count, 10, curr_ptr,
width, plus, which_pointer);
state = 0;
break;
}
/*-----------------------------------------------------------------*/
/* State 8 handles the 'i' specifier. */
/*-----------------------------------------------------------------*/
case 8:
{
void *curr_ptr;
int which_pointer;
/*---------------------------------------------------------------*/
/* Set curr_ptr to the appropriate value. */
/*---------------------------------------------------------------*/
if (store)
{
if (value == DEFAULT_VALUE)
{
which_pointer = INT;
curr_ptr = va_arg(args, int *);
}
else if (value == l_VALUE)
{
which_pointer = LONG_INT;
curr_ptr = va_arg(args, long *);
}
else
{
which_pointer = SHORT_INT;
curr_ptr = va_arg(args, short *);
}
++vars_assigned;
}
else
{
which_pointer = INT;
curr_ptr = &UnusedInt;
}
plus = get_sign(stream, s, &index, &c_i, &count);
/*---------------------------------------------------------------*/
/* If c_i is a number, look for the base. */
/*---------------------------------------------------------------*/
if (isdigit(c_i))
{
/*-------------------------------------------------------------*/
/* If c_i is 0, it's either octal or hexadecimal, else it's */
/* decimal. */
/*-------------------------------------------------------------*/
if (c_i == '0')
{
++count;
c_i = get_char(stream, s, &index);
/*-----------------------------------------------------------*/
/* If c_i is 'x' or 'X', it's hexadecimal, else it's octal. */
/*-----------------------------------------------------------*/
if (c_i == 'x' || c_i == 'X')
{
++count;
c_i = get_char(stream, s, &index);
count = get_num(stream, s, &index, c_i, count, 16, curr_ptr,
width, plus, which_pointer);
}
else
count = get_num(stream, s, &index, c_i, count, 8, curr_ptr,
width, plus, which_pointer);
}
else
count = get_num(stream, s, &index, c_i, count, 10, curr_ptr,
width, plus, which_pointer);
}
state = 0;
break;
}
/*-----------------------------------------------------------------*/
/* State 9 handles the 'o' specifier. */
/*-----------------------------------------------------------------*/
case 9:
{
void *curr_ptr;
int which_pointer;
/*---------------------------------------------------------------*/
/* Set curr_ptr to the appropriate value. */
/*---------------------------------------------------------------*/
if (store)
{
if (value == DEFAULT_VALUE)
{
which_pointer = U_INT;
curr_ptr = va_arg(args, unsigned int *);
}
else if (value == l_VALUE)
{
which_pointer = U_LONG_INT;
curr_ptr = va_arg(args, unsigned long *);
}
else
{
which_pointer = U_SHORT_INT;
curr_ptr = va_arg(args, unsigned short *);
}
++vars_assigned;
}
c_i = ignore_plus(stream, s, &index, &count, c_i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -