📄 scanf.c
字号:
} /* ok -- back to common work */ if (sc.width <= 0) { goto done; } if (store) { b = va_arg(ap, unsigned char *); } else { b = buf; } cc = scan_getc(&sc); if (cc <= 0) { scan_ungetc(&sc); goto done; /* return EOF if cnt == 0 */ } i = 0; while ((cc>0) && (scanset[cc] != invert)) { i = 1; /* yes, we stored something */ *b = cc; b += store; cc = scan_getc(&sc); } if (i==0) { scan_ungetc(&sc); goto done; /* return cnt */ } if (*p != 'c') { /* nul-terminate the stored string */ *b = 0; } cnt += store; goto nextfmt; } if (p-spec < 12) { /* o,u,p,x,X,i,d - (un)signed integer */ if (*p == 'p') { /* assume pointer same size as int or long. */ lval = (sizeof(char *) == sizeof(long)); } usflag = ((p-spec) < 10); /* (1)0 if (un)signed */ base = radix[(int)(p-spec) - 5]; b = buf; if (sc.width <= 0) { goto done; } cc = scan_getc(&sc); if ((cc == '+') || (cc == '-')) { /* Handle leading sign.*/ *b++ = cc; cc = scan_getc(&sc); } if (cc == '0') { /* Possibly set base and handle prefix. */ if ((base == 0) || (base == 16)) { cc = scan_getc(&sc); if ((cc == 'x') || (cc == 'X')) { /* We're committed to base 16 now. */ base = 16; cc = scan_getc(&sc); } else { /* oops... back up */ scan_ungetc(&sc); cc = '0'; if (base == 0) { base = 8; } } } } if (base == 0) { /* Default to base 10 */ base = 10; } /* At this point, we're ready to start reading digits. */ if (cc == '0') { *b++ = cc; /* Store first leading 0 */ do { /* but ignore others. */ cc = scan_getc(&sc); } while (cc == '0'); } while (valid_digit(cc,base)) { /* Now for nonzero digits.*/ if (b - buf < MAX_DIGITS) { *b++ = cc; } cc = scan_getc(&sc); } *b = 0; /* null-terminate */ if ((b == buf) || (*--b == '+') || (*b == '-')) { scan_ungetc(&sc); goto done; /* No digits! */ } if (store) { if (*buf == '-') { usflag = 0; } uv = STRTO_L_(buf, NULL, base, usflag); vp = va_arg(ap, void *); switch (lval) { case 2: /* If no long long, treat as long . */#ifdef __UCLIBC_HAS_LONG_LONG__ *((unsigned long long *)vp) = uv; break;#endif case 1:#if ULONG_MAX == UINT_MAX case 0: /* int and long int are the same */#endif#ifdef __UCLIBC_HAS_LONG_LONG__ if (usflag) { if (uv > ULONG_MAX) { uv = ULONG_MAX; } } else if (((V_TYPE)uv) > LONG_MAX) { uv = LONG_MAX; } else if (((V_TYPE)uv) < LONG_MIN) { uv = (UV_TYPE) LONG_MIN; }#endif *((unsigned long *)vp) = (unsigned long)uv; break;#if ULONG_MAX != UINT_MAX case 0: /* int and long int are different */ if (usflag) { if (uv > UINT_MAX) { uv = UINT_MAX; } } else if (((V_TYPE)uv) > INT_MAX) { uv = INT_MAX; } else if (((V_TYPE)uv) < INT_MIN) { uv = (UV_TYPE) INT_MIN; } *((unsigned int *)vp) = (unsigned int)uv; break;#endif case -1: if (usflag) { if (uv > USHRT_MAX) { uv = USHRT_MAX; } } else if (((V_TYPE)uv) > SHRT_MAX) { uv = SHRT_MAX; } else if (((V_TYPE)uv) < SHRT_MIN) { uv = (UV_TYPE) SHRT_MIN; } *((unsigned short *)vp) = (unsigned short)uv; break; case -2: if (usflag) { if (uv > UCHAR_MAX) { uv = UCHAR_MAX; } } else if (((V_TYPE)uv) > CHAR_MAX) { uv = CHAR_MAX; } else if (((V_TYPE)uv) < CHAR_MIN) { uv = (UV_TYPE) CHAR_MIN; } *((unsigned char *)vp) = (unsigned char) uv; break; default: assert(0); } ++cnt; } goto nextfmt; }#ifdef __UCLIBC_HAS_FLOATS__ else { /* floating point */ if (sc.width <= 0) { goto done; } if (__strtold(&ld, &sc)) { /* Success! */ if (store) { vp = va_arg(ap, void *); switch (lval) { case 2: *((long double *)vp) = ld; break; case 1: *((double *)vp) = (double) ld; break; case 0: *((float *)vp) = (float) ld; break; default: /* Illegal qualifier! */ assert(0); goto done; } ++cnt; } goto nextfmt; } }#else assert(0);#endif goto done; } /* Unrecognized specifier! */ goto done; } if (isspace(*fmt)) { /* Consume all whitespace. */ while (isspace(scan_getc_nw(&sc))) {} } else { /* Match the current fmt char. */ matchchar: if (scan_getc_nw(&sc) != *fmt) { goto done; } scan_getc_nw(&sc); } nextfmt: scan_ungetc(&sc); ++fmt; } done: /* end of scan */ kill_scan_cookie(&sc); if ((sc.ungot_char <= 0) && (cnt == 0) && (*fmt)) { return (EOF); } return (cnt);}/*****************************************************************************/#ifdef __UCLIBC_HAS_FLOATS__#include <float.h>#define MAX_SIG_DIGITS 20#define MAX_IGNORED_DIGITS 2000#define MAX_ALLOWED_EXP (MAX_SIG_DIGITS + MAX_IGNORED_DIGITS + LDBL_MAX_10_EXP)#if LDBL_DIG > MAX_SIG_DIGITS#error need to adjust MAX_SIG_DIGITS#endif#include <limits.h>#if MAX_ALLOWED_EXP > INT_MAX#error size assumption violated for MAX_ALLOWED_EXP#endifint __strtold(long double *ld, struct scan_cookie *sc){ long double number; long double p10; int exponent_power; int exponent_temp; int negative; int num_digits; int since_decimal; int c; c = scan_getc(sc); /* Decrements width. */ negative = 0; switch(c) { /* Handle optional sign. */ case '-': negative = 1; /* Fall through to get next char. */ case '+': c = scan_getc(sc); } number = 0.; num_digits = -1; exponent_power = 0; since_decimal = INT_MIN; LOOP: while (isdigit(c)) { /* Process string of digits. */ ++since_decimal; if (num_digits < 0) { /* First time through? */ ++num_digits; /* We've now seen a digit. */ } if (num_digits || (c != '0')) { /* had/have nonzero */ ++num_digits; if (num_digits <= MAX_SIG_DIGITS) { /* Is digit significant? */ number = number * 10. + (c - '0'); } } c = scan_getc(sc); } if ((c == '.') && (since_decimal < 0)) { /* If no previous decimal pt, */ since_decimal = 0; /* save position of decimal point */ c = scan_getc(sc); /* and process rest of digits */ goto LOOP; } if (num_digits<0) { /* Must have at least one digit. */ goto FAIL; } if (num_digits > MAX_SIG_DIGITS) { /* Adjust exp for skipped digits. */ exponent_power += num_digits - MAX_SIG_DIGITS; } if (since_decimal >= 0) { /* Adjust exponent for decimal point. */ exponent_power -= since_decimal; } if (negative) { /* Correct for sign. */ number = -number; negative = 0; /* Reset for exponent processing below. */ } /* Process an exponent string. */ if (c == 'e' || c == 'E') { c = scan_getc(sc); switch(c) { /* Handle optional sign. */ case '-': negative = 1; /* Fall through to get next char. */ case '+': c = scan_getc(sc); } num_digits = 0; exponent_temp = 0; while (isdigit(c)) { /* Process string of digits. */ if (exponent_temp < MAX_ALLOWED_EXP) { /* overflow check */ exponent_temp = exponent_temp * 10 + (c - '0'); } c = scan_getc(sc); ++num_digits; } if (num_digits == 0) { /* Were there no exp digits? */ goto FAIL; } /* else */ if (negative) { exponent_power -= exponent_temp; } else { exponent_power += exponent_temp; } } if (number != 0.) { /* Now scale the result. */ exponent_temp = exponent_power; p10 = 10.; if (exponent_temp < 0) { exponent_temp = -exponent_temp; } while (exponent_temp) { if (exponent_temp & 1) { if (exponent_power < 0) { number /= p10; } else { number *= p10; } } exponent_temp >>= 1; p10 *= p10; } } *ld = number; return 1; FAIL: scan_ungetc(sc); return 0;}#endif /* __UCLIBC_HAS_FLOATS__ */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -