user-0 提问: C语言中，如何为可变参数赋值？

回复:
user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c你的回答好让人头大，不过还是感谢你热心回答~~我写出我要的函数了~~  int Scanf(FILE *fp, char *format,...) { 	int *i; 	char *ch; 	float *f; 	int count, k, len;		 	int tmp; 	 	len = strlen(format); 	 	va_list ap;	 	va_start(ap, format); 	 	count = 0; 	for(k=2; k<=len; k=k+2) 	{ 		if(format[k-1]=='c')		//读取字符 		{ 			ch = va_arg(ap, char*);			 			count += fscanf(fp, "%c", ch);		 		}	 		 		if(format[k-1]=='d') 		{ 			i = va_arg(ap, int*); 			 			while((tmp=getc(fp))!=EOF) 			{ 				if((tmp>='0' && tmp<='9') || tmp=='-') 				{ 					ungetc(tmp, fp); 					break; 				} 			} 			 			if(tmp!=EOF) 				count += fscanf(fp, "%d", i); 		}  		if(format[k-1]=='f') 		{ 			f = va_arg(ap, float*); 			 			while((tmp=getc(fp))!=EOF) 			{ 				if((tmp>='0' && tmp<='9') || tmp=='-') 				{ 					ungetc(tmp, fp); 					break; 				} 			} 			 			if(tmp!=EOF) 				count += fscanf(fp, "%f", f); 		} 	} 		 	va_end(ap); 	 	return count; }

user: user-0
content: 引用 4 楼 yan597478677 的回复:厉害，我还没看到过这种东西，楼主求解这种技巧一般用在什么地方？我写了一个多项式的函数操作集合，但是在进行赋值时，需要从一个文档里依次读入系数值和指数值，文档中除了整数和小数还有别的字符，这时候就要自己设定一个读取函数进行录入了~~

user: user-1
content: C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c：     1002:                     case _T('d') :    1003:     1004:                         if (_T('-') == ch) {    1005:                             ++negative;    1006:     1007:                             goto d_incwidth;    1008:     1009:                         } else if (_T('+') == ch) {    1010: d_incwidth:    1011:                             if (!--width && widthset)    1012:                                 ++done_flag;    1013:                             else    1014:                                 ch = INC();    1015:                         }    1016:     1017: getnum:    1018:                         if ( integer64 ) {    1019:     1020:                             while (!done_flag) {    1021:     1022:                                 if (_T('x') == comchr || _T('p') == comchr)    1023:     1024:                                     if (_ISXDIGIT(ch)) {    1025:                                         num64 <<= 4;    1026:                                         ch = _hextodec(ch);    1027:                                     }    1028:                                     else    1029:                                         ++done_flag;    1030:     1031:                                 else if (_ISDIGIT(ch))    1032:     1033:                                     if (_T('o') == comchr)    1034:                                         if (_T('8') > ch)    1035:                                                 num64 <<= 3;    1036:                                         else {    1037:                                                 ++done_flag;    1038:                                         }    1039:                                     else /* _T('d') == comchr */    1040:                                         num64 = MUL10(num64);    1041:     1042:                                 else    1043:                                     ++done_flag;    1044:     1045:                                 if (!done_flag) {    1046:                                     ++started;    1047:                                     num64 += ch - _T('0');    1048:     1049:                                     if (widthset && !--width)    1050:                                         ++done_flag;    1051:                                     else    1052:                                         ch = INC();    1053:                                 } else    1054:                                     UN_INC(ch);    1055:     1056:                             } /* end of WHILE loop */    1057:     1058:                             if (negative)    1059:                                 num64 = (unsigned __int64 )(-(__int64)num64);    1060:                         }    1061:                         else {    1062:                             while (!done_flag) {    1063:     1064:                                 if (_T('x') == comchr || _T('p') == comchr)    1065:     1066:                                     if (_ISXDIGIT(ch)) {    1067:                                         number = (number << 4);    1068:                                         ch = _hextodec(ch);    1069:                                     }    1070:                                     else    1071:                                         ++done_flag;    1072:     1073:                                 else if (_ISDIGIT(ch))    1074:     1075:                                     if (_T('o') == comchr)    1076:                                         if (_T('8') > ch)    1077:                                             number = (number << 3);    1078:                                         else {    1079:                                             ++done_flag;    1080:                                         }    1081:                                     else /* _T('d') == comchr */    1082:                                         number = MUL10(number);    1083:     1084:                                 else    1085:                                     ++done_flag;    1086:     1087:                                 if (!done_flag) {    1088:                                     ++started;    1089:                                     number += ch - _T('0');    1090:     1091:                                     if (widthset && !--width)    1092:                                         ++done_flag;    1093:                                     else    1094:                                         ch = INC();    1095:                                 } else    1096:                                     UN_INC(ch);    1097:     1098:                             } /* end of WHILE loop */    1099:     1100:                             if (negative)    1101:                                 number = (unsigned long)(-(long)number);    1102:                         }    1103:                         if (_T('F')==comchr) /* expected ':' in long pointer */    1104:                             started = 0;    1105:     1106:                         if (started)    1107:                             if (!suppress) {    1108:     1109:                                 ++count;    1110: assign_num:    1111:                                 if ( integer64 )    1112:                                     *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64;    1113:                                 else    1114:                                 if (longone)    1115:                                     *(long UNALIGNED *)pointer = (unsigned long)number;    1116:                                 else    1117:                                     *(short UNALIGNED *)pointer = (unsigned short)number;    1118:     1119:                             } else /*NULL*/;    1120:                         else    1121:                             goto error_return;    1122:     1123:                         break;    1124:

user: user-2
content: 引用 楼主 kangjianwei101 的回复:例如scanf("%d", &i)中，系统如何为i赋值？ 我知道一些可变参数的知识。例如在printf("%d",i);中，调用va_list ap等相关函数，可使va_list类型的ap指向字符i，此时i的内容已知，自然也就可以输出其值。但是在scanf("%d", &i)中，我的疑惑是&i取了整数i的地址，那么va_list类型的ap如何识别i并为其赋值呢？ 如果有大神能写出一个简单的例子更好，比如写一个函数如int Scanf(FILE *fp, char* format,...)以便从文件fp中根据format格式读取字符，函数的调用方式为Scanf(fp, "%d", &i)，i提前定义为int类型。  "%d" 指示了 &i是一个 int*类型的指针。

user: user-1
content: 引用 2 楼 kangjianwei101 的回复:你这意思是让我看源码....我看C标准库这本书的源码了，我要是能看懂就不来这提问了 理解和讨论之前请先学会如何观察！  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

user: user-3
content: 厉害，我还没看到过这种东西，楼主求解这种技巧一般用在什么地方？

user: user-4
content: 那么va_list类型的ap如何识别i并为其赋值呢？  它是通过%d来做这个判断的，可以简单想象，有这样一小段代码：  if (!strcmp(format, "%d") {  *((int*)ap) = the_number_get_from_input; }

user: user-0
content: 你这意思是让我看源码....我看C标准库这本书的源码了，我要是能看懂就不来这提问了

user: user-1
content: 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c