在scanf.c檔案中,可以看到scanf函式,**如下:
#include #include #include "loc_incl.h"
int scanf(const char *format, ...)
對於va_list、va_start、va_end等在stdarg.h標頭檔案中定義的巨集,都已經在(stdarg.h標頭檔案源**分析)一文中介紹過。
在上述**中我們可以看到有乙個_doscan函式,而這一函式在標頭檔案loc_incl.h中定義,函式宣告如下:
int _doscan(file * stream, const char *format, va_list ap);
_doscan函式的實現源**如下:
int
_doscan(register file *stream, const char *format, va_list ap)
if (ic != eof) ungetc(ic,stream);
nrchars--;
}if (!*format) break; /* end of format */
if (*format != '%')
format++;
if (*format == '%')
else break;
}flags = 0;
if (*format == '*')
if (isdigit (*format))
switch (*format)
kind = *format;
if ((kind != 'c') && (kind != '[') && (kind != 'n')) while (isspace(ic));
if (ic == eof) break; /* outer while */
} else if (kind != 'n')
switch (kind)
break;
case 'p': /* pointer */
set_pointer(flags);
/* fallthrough */
case 'b': /* binary */
case 'd': /* decimal */
case 'i': /* general integer */
case 'o': /* octal */
case 'u': /* unsigned */
case 'x': /* hexadecimal */
case 'x': /* ditto */
if (!(flags & fl_widthspec) || width > numlen)
width = numlen;
if (!width) return done;
str = o_collect(ic, stream, kind, width, &base);
if (str < inp_buf
|| (str == inp_buf
&& (*str == '-'
|| *str == '+'))) return done;
/** although the length of the number is str-inp_buf+1
* we don't add the 1 since we counted it already
*/nrchars += str - inp_buf;
if (!(flags & fl_noassign))
break;
case 'c':
if (!(flags & fl_widthspec))
width = 1;
if (!(flags & fl_noassign))
str = va_arg(ap, char *);
if (!width) return done;
while (width && ic != eof)
}if (width)
break;
case 's':
if (!(flags & fl_widthspec))
width = 0xffff;
if (!(flags & fl_noassign))
str = va_arg(ap, char *);
if (!width) return done;
while (width && ic != eof && !isspace(ic))
}/* terminate the string */
if (!(flags & fl_noassign))
*str = '\0';
if (width)
break;
case '[':
if (!(flags & fl_widthspec))
width = 0xffff;
if (!width) return done;
if ( *++format == '^' ) else
reverse = 0;
for (str = xtable; str < &xtable[nr_chars]
; str++)
*str = 0;
if (*format == ']') xtable[*format++] = 1;
while (*format && *format != ']')
else xtable['-'] = 1;}}
if (!*format) return done;
if (!(xtable[ic] ^ reverse))
if (!(flags & fl_noassign))
str = va_arg(ap, char *);
do } while (width && ic != eof && (xtable[ic] ^ reverse));
if (width)
if (!(flags & fl_noassign))
break;
#ifndef nofloat
case 'e':
case 'e':
case 'f':
case 'g':
case 'g':
if (!(flags & fl_widthspec) || width > numlen)
width = numlen;
if (!width) return done;
str = f_collect(ic, stream, width);
if (str < inp_buf
|| (str == inp_buf
&& (*str == '-'
|| *str == '+'))) return done;
/** although the length of the number is str-inp_buf+1
* we don't add the 1 since we counted it already
*/nrchars += str - inp_buf;
if (!(flags & fl_noassign))
break;
#endif
} /* end switch */
conv++;
if (!(flags & fl_noassign) && kind != 'n') done++;
format++;
}return conv || (ic != eof) ? done : eof;
}_doscan函式**
在上面的源**中,值得注意的是第26行的getc巨集,定義**如下:
#define getc(p) (--(p)->_count >= 0 ? (int) (*(p)->_ptr++) : \
__fillbuf(p))
getc的呼叫形式:ch=getc(fp); 功能是從檔案指標指向的檔案讀入乙個字元,並把它作為函式值返回給int型變數ch。
第4行~第17行,定義一些後面需要用到的變數
第23行~第
34行,跳過format格式串中的空格,並且跳過輸入流中的空格
第37行~第
42行,輸入流stream與format格式串中的空白符(空白符可以是空格(space)、製表符(tab)和新行符(newline))保持一致
第44行~第
52行,在format中的字元為'%'的前提下,stream中的字元也為'%',則繼續
第54行
~第57行,format當前字元為'*',表示讀指定型別的資料但不儲存
第58行
~第62行,指定說明最大域寬。 在百分號(%)與格式碼之間的整數用於限制從對應域讀入的最大字元數於寬度
第64行
~第282行,switch語句,用於格式修飾符,這些修飾符包括: h、l、l、c、p、b、d、i、o、u……,還有基於掃瞄集的'['修飾符
對scanf函式的原始碼分析,需要在scanf函式的語法格式詳細的理解基礎上進行,由於scanf函式實現十分複雜,需要仔細的品味,這裡只是比較初步的分析,具體還有待後期不斷的完善
cpoint
出處:
C語言中scanf函式
scanf 函式每次讀取乙個字元,跳過所有的空白字元,直至遇到第1個非空白字元才開始讀取。因為要讀取整數,所以 scanf 希望發現乙個數字字元或者乙個符號 或 如果找到乙個數字或符號,它便儲存該字元,並讀取下乙個字元。如果下乙個字元是數字,它便儲存該數字並讀取下乙個字元。scanf 不斷地讀取和儲...
C語言中的scanf函式
思考 如果,我們想拿到使用者輸入的東西,怎麼辦?解決 我們需要使用 scanf 這個函式 1.scanf 的作用 在程式執行到 scanf 的時候,接收使用者輸入的一些資料,並儲存在變數之中 2.scanf 的語法 scanf 格式控制字串 變數位址列表 語義 格式控制字串裡寫佔位符,佔位符用來接收...
C語言中scanf 函式的小結
1.scanf 的返回值 scanf函式是有返回值的,接受乙個變數返回1。如 c scanf d d a,b 若輸入的全是整數,則c為2 若全是字元,則c為0 因為scanf在佔位符存在的情況下,只接受符合佔位符的資料。2.scanf的結束 如果不是 c,則以空格,回車,tab鍵結束,或非法字元結束...