http://www.chinaspx.com/archive/develop/18135.htm 这个上面有说明很清楚的..你可以看看就知道了 给你一段代码. 你可以看看关于printf 是怎么写出来的 int _xoutput ( BYTE *strbuf, const char *format, va_list argptr ) { int hexadd; // offset to add to number to get 'a'..'f' char ch; // character just read int flags; // flag word -- see #defines above for flag values int state; // current state char chclass; // class of current character int radix; // current conversion radix int charsout; // characters currently written so far, -1 = IO error //int fldwidth; // selected field width -- 0 means default int precision; // selected precision -- -1 means default //char prefix[2]; // numeric prefix -- up to two characters //int prefixlen; // length of prefix -- 0 means no prefix //int capexp; // non-zero = 'E' exponent signifient, zero = 'e' //int no_xoutput; // non-zero = prodcue no output for this specifier union { char *sz; // pointer text to be printed, not zero terminated } text; int textlen; // length of the text in bytes/wchars to be printed. //textlen is in multibyte or wide chars if _UNICODE union { char sz[BUFFERSIZE]; } buffer; //wchar_t wchar; // temp wchar_t //int bufferiswide; // non-zero = buffer contains wide chars already m_pStrBuf=strbuf; textlen = 0; // no text yet charsout = 0; // no characters written yet state = ST_NORMAL; // starting state // main loop -- loop while format character exist and no I/O errors while ((ch = *format++) != '\0' && charsout >= 0) { chclass = xfind_char_class(ch); // find character class state = xfind_next_state(chclass, state); // find next state // execute code for each state switch (state) { case ST_NORMAL: // normal state -- just write character //bufferiswide = 0; XWRITE_CHAR(ch, &charsout); continue; case ST_PERCENT: // set default value of conversion parameters //prefixlen = fldwidth = no_xoutput = capexp = 0; flags = 0; precision = -1; //bufferiswide = 0; // default continue; case ST_SIZE: // just read a size specifier, set the flags based on it switch (ch) { case SELF('l'): flags |= FL_LONG; // 'l' => long int or wchar_t break; case SELF('h'): flags |= FL_SHORT; // 'h' => short int or char break; } continue;
case ST_TYPE: switch (ch) { case SELF('c'): XWRITE_CHAR(xget_char_arg(&argptr),&charsout); continue; case SELF('s'):{ char *pStr; pStr = xget_ptr_arg(&argptr); XWRITE_STRING(pStr,strlen(pStr),&charsout); } continue; case SELF('d'): case SELF('i'): // signed decimal output flags |= FL_SIGNED; radix = 10; goto COMMON_INT; case SELF('u'): radix = 10; goto COMMON_INT; case SELF('X'): // unsigned upper hex output hexadd = SELF('A') - SELF('9') - 1; // set hexadd for uppercase hex goto COMMON_HEX; case SELF('x'): // unsigned lower hex output hexadd = SELF('a') - SELF('9') - 1; // set hexadd for lowercase hex // DROP THROUGH TO COMMON_HEX COMMON_HEX: radix = 16; if (flags & FL_ALTERNATE) { // alternate form means '0x' prefix //prefix[0] = SELF('0'); //prefix[1] = (char)(SELF('x') - SELF('a') + SELF('9') + 1 + hexadd); // 'x' or 'X' //prefixlen = 2; } goto COMMON_INT; COMMON_INT: { // This is the general integer formatting routine. // Basically, we get an argument, make it positive // if necessary, and convert it according to the // correct radix, setting text and textlen // appropriately. unsigned long number; // number to convert int digit; // ascii value of digit long l; // temp long value if (flags & FL_SHORT) { if (flags & FL_SIGNED) l = (short) xget_int_arg(&argptr); // sign extend else l = (unsigned short) xget_int_arg(&argptr); // zero-extend }else{ if (flags & FL_SIGNED) l = xget_int_arg(&argptr); // sign extend else l = (unsigned int) xget_int_arg(&argptr); // zero-extend } // 2. check for negative; copy into number if ( (flags & FL_SIGNED) && l < 0) { number = -l; flags |= FL_NEGATIVE; // remember negative sign } else { number = l; } // 3. check precision value for default; non-default // turns off 0 flag, according to ANSI. if (precision < 0) precision = 1; // default precision else flags &= ~FL_LEADZERO; // 4. Check if data is 0; if so, turn off hex prefix if (number == 0) ; //prefixlen = 0; // 5. Convert data to ASCII -- note if precision is zero // and number is zero, we get no digits at all. text.sz = &buffer.sz[BUFFERSIZE-1]; // last digit at end of buffer while (precision-- > 0 || number != 0) { digit = (int)(number % radix) + '0'; number /= radix; // reduce number if (digit > '9') { // a hex digit, make it a letter digit += hexadd; } *text.sz-- = (char)digit; // store the digit } textlen = (char *)&buffer.sz[BUFFERSIZE-1] - text.sz; // compute length of number ++text.sz; // text points to first digit now // 6. Force a leading zero if FORCEOCTAL flag set if ((flags & FL_FORCEOCTAL) && (text.sz[0] != '0' || textlen == 0)) { *--text.sz = '0'; ++textlen; // add a zero } } break; }//end switch XWRITE_STRING(text.sz, textlen, &charsout); break; default: continue; }//switch(state) } m_pStrBuf[charsout]=0; //$$printf("charsout=%u\n",charsout); return charsout; // return value = number of characters written } int xprintf(BYTE *strbuf, char const *fmt, ...) { int ret; va_list ap; //FILE f; //$$f._flags = __SWR | __SSTR; //$$f._bf._base = f._p = (unsigned char *)str; //$$f._bf._size = f._w = INT_MAX; va_start(ap, fmt);//"这是一个宏" //ret = _xoutput(&f,fmt,ap ); ret = _xoutput(strbuf,fmt,ap ); //ret = _output(&f,fmt,ap ); va_end(ap);//"这是一个宏" //$$*f._p = 0; return (ret); }
函数是你遵循这种规范来写的,
strcpy你可以写,malloc你也可以写,如果你仔细看过谭浩强的c程序设计就会对malloc有个明白,其实这要用到操作系统对程序内存的分配,其实大致原理是一样,不明白可以慢慢来,
其实C中提供的库函数你可以实现,只要你足够年,OK
看来你是个初学者
如:我要在屏幕上打印出字符,没有printf(),你会怎么搞?
这个上面有说明很清楚的..你可以看看就知道了
给你一段代码.
你可以看看关于printf 是怎么写出来的
int _xoutput (
BYTE *strbuf,
const char *format,
va_list argptr
)
{
int hexadd; // offset to add to number to get 'a'..'f'
char ch; // character just read
int flags; // flag word -- see #defines above for flag values
int state; // current state
char chclass; // class of current character
int radix; // current conversion radix
int charsout; // characters currently written so far, -1 = IO error
//int fldwidth; // selected field width -- 0 means default
int precision; // selected precision -- -1 means default
//char prefix[2]; // numeric prefix -- up to two characters
//int prefixlen; // length of prefix -- 0 means no prefix
//int capexp; // non-zero = 'E' exponent signifient, zero = 'e'
//int no_xoutput; // non-zero = prodcue no output for this specifier
union {
char *sz; // pointer text to be printed, not zero terminated
} text;
int textlen; // length of the text in bytes/wchars to be printed.
//textlen is in multibyte or wide chars if _UNICODE
union {
char sz[BUFFERSIZE];
} buffer;
//wchar_t wchar; // temp wchar_t
//int bufferiswide; // non-zero = buffer contains wide chars already m_pStrBuf=strbuf;
textlen = 0; // no text yet
charsout = 0; // no characters written yet
state = ST_NORMAL; // starting state // main loop -- loop while format character exist and no I/O errors
while ((ch = *format++) != '\0' && charsout >= 0) {
chclass = xfind_char_class(ch); // find character class
state = xfind_next_state(chclass, state); // find next state // execute code for each state
switch (state) { case ST_NORMAL:
// normal state -- just write character
//bufferiswide = 0;
XWRITE_CHAR(ch, &charsout);
continue; case ST_PERCENT:
// set default value of conversion parameters
//prefixlen = fldwidth = no_xoutput = capexp = 0;
flags = 0;
precision = -1;
//bufferiswide = 0; // default
continue; case ST_SIZE:
// just read a size specifier, set the flags based on it
switch (ch) {
case SELF('l'):
flags |= FL_LONG; // 'l' => long int or wchar_t
break;
case SELF('h'):
flags |= FL_SHORT; // 'h' => short int or char
break;
}
continue;
case ST_TYPE:
switch (ch) {
case SELF('c'):
XWRITE_CHAR(xget_char_arg(&argptr),&charsout);
continue; case SELF('s'):{
char *pStr;
pStr = xget_ptr_arg(&argptr);
XWRITE_STRING(pStr,strlen(pStr),&charsout);
}
continue; case SELF('d'):
case SELF('i'):
// signed decimal output
flags |= FL_SIGNED;
radix = 10;
goto COMMON_INT; case SELF('u'):
radix = 10;
goto COMMON_INT; case SELF('X'):
// unsigned upper hex output
hexadd = SELF('A') - SELF('9') - 1; // set hexadd for uppercase hex
goto COMMON_HEX; case SELF('x'):
// unsigned lower hex output
hexadd = SELF('a') - SELF('9') - 1; // set hexadd for lowercase hex
// DROP THROUGH TO COMMON_HEX COMMON_HEX:
radix = 16;
if (flags & FL_ALTERNATE) {
// alternate form means '0x' prefix
//prefix[0] = SELF('0');
//prefix[1] = (char)(SELF('x') - SELF('a') + SELF('9') + 1 + hexadd); // 'x' or 'X'
//prefixlen = 2;
}
goto COMMON_INT;
COMMON_INT: {
// This is the general integer formatting routine.
// Basically, we get an argument, make it positive
// if necessary, and convert it according to the
// correct radix, setting text and textlen
// appropriately. unsigned long number; // number to convert
int digit; // ascii value of digit
long l; // temp long value
if (flags & FL_SHORT) {
if (flags & FL_SIGNED)
l = (short) xget_int_arg(&argptr); // sign extend
else
l = (unsigned short) xget_int_arg(&argptr); // zero-extend
}else{
if (flags & FL_SIGNED)
l = xget_int_arg(&argptr); // sign extend
else
l = (unsigned int) xget_int_arg(&argptr); // zero-extend
} // 2. check for negative; copy into number
if ( (flags & FL_SIGNED) && l < 0) {
number = -l;
flags |= FL_NEGATIVE; // remember negative sign
} else {
number = l;
}
// 3. check precision value for default; non-default
// turns off 0 flag, according to ANSI.
if (precision < 0)
precision = 1; // default precision
else
flags &= ~FL_LEADZERO; // 4. Check if data is 0; if so, turn off hex prefix
if (number == 0)
;
//prefixlen = 0; // 5. Convert data to ASCII -- note if precision is zero
// and number is zero, we get no digits at all. text.sz = &buffer.sz[BUFFERSIZE-1]; // last digit at end of buffer while (precision-- > 0 || number != 0) {
digit = (int)(number % radix) + '0';
number /= radix; // reduce number
if (digit > '9') {
// a hex digit, make it a letter
digit += hexadd;
}
*text.sz-- = (char)digit; // store the digit
} textlen = (char *)&buffer.sz[BUFFERSIZE-1] - text.sz; // compute length of number
++text.sz; // text points to first digit now
// 6. Force a leading zero if FORCEOCTAL flag set
if ((flags & FL_FORCEOCTAL) && (text.sz[0] != '0' || textlen == 0)) {
*--text.sz = '0';
++textlen; // add a zero
}
}
break;
}//end switch
XWRITE_STRING(text.sz, textlen, &charsout);
break;
default:
continue;
}//switch(state)
}
m_pStrBuf[charsout]=0;
//$$printf("charsout=%u\n",charsout);
return charsout; // return value = number of characters written
}
int xprintf(BYTE *strbuf, char const *fmt, ...)
{
int ret;
va_list ap;
//FILE f; //$$f._flags = __SWR | __SSTR;
//$$f._bf._base = f._p = (unsigned char *)str;
//$$f._bf._size = f._w = INT_MAX;
va_start(ap, fmt);//"这是一个宏"
//ret = _xoutput(&f,fmt,ap );
ret = _xoutput(strbuf,fmt,ap );
//ret = _output(&f,fmt,ap );
va_end(ap);//"这是一个宏"
//$$*f._p = 0;
return (ret);
}