Question: 浮点数增加的问题

当f变大时，f的精度不够了，试试 double f。 具体的为啥精度会变化。。。就不清楚了。。。。。

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> float f; double d; void showf() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nf=%.6f\n",f);     p=(unsigned char *)&f;     printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);     ltoa(*(long *)&f,b,2);     sprintf(bs,"%032s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);     strncpy(e,bs+1,8);e[8]=0;     ex=strtol(e,&t,2);     printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);     ex-=127;     printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9); } void showd() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nd=%.15lf\n",d);     p=(unsigned char *)&d;     printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);     _i64toa(*(__int64 *)&d,b,2);     sprintf(bs,"%064s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);     strncpy(e,bs+1,11);e[11]=0;     ex=strtol(e,&t,2);     printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);     ex-=1023;     printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12); } int main() {      for (f=0.0f;f<=2.2f;f+=0.2f) showf();     printf("------------\n");     f=2.0f;showf();     printf("-----------------------------------\n");     for (d=0.0 ;d<=2.2 ;d+=0.2 ) showd();     printf("------------\n");     d=2.0 ;showd();      return 0; } // //f=0.000000 //hex=00 00 00 00 //bin=00000000000000000000000000000000 //bin=0 00000000   00000000000000000000000 //  + 0   -127 1.00000000000000000000000 //  + -127     1.00000000000000000000000 // //f=0.200000 //hex=3E 4C CC CD //bin=00111110010011001100110011001101 //bin=0 01111100   10011001100110011001101 //  + 124 -127 1.10011001100110011001101 //  + -3       1.10011001100110011001101 // //f=0.400000 //hex=3E CC CC CD //bin=00111110110011001100110011001101 //bin=0 01111101   10011001100110011001101 //  + 125 -127 1.10011001100110011001101 //  + -2       1.10011001100110011001101 // //f=0.600000 //hex=3F 19 99 9A //bin=00111111000110011001100110011010 //bin=0 01111110   00110011001100110011010 //  + 126 -127 1.00110011001100110011010 //  + -1       1.00110011001100110011010 // //f=0.800000 //hex=3F 4C CC CD //bin=00111111010011001100110011001101 //bin=0 01111110   10011001100110011001101 //  + 126 -127 1.10011001100110011001101 //  + -1       1.10011001100110011001101 // //f=1.000000 //hex=3F 80 00 00 //bin=00111111100000000000000000000000 //bin=0 01111111   00000000000000000000000 //  + 127 -127 1.00000000000000000000000 //  + 0        1.00000000000000000000000 // //f=1.200000 //hex=3F 99 99 9A //bin=00111111100110011001100110011010 //bin=0 01111111   00110011001100110011010 //  + 127 -127 1.00110011001100110011010 //  + 0        1.00110011001100110011010 // //f=1.400000 //hex=3F B3 33 34 //bin=00111111101100110011001100110100 //bin=0 01111111   01100110011001100110100 //  + 127 -127 1.01100110011001100110100 //  + 0        1.01100110011001100110100 // //f=1.600000 //hex=3F CC CC CE //bin=00111111110011001100110011001110 //bin=0 01111111   10011001100110011001110 //  + 127 -127 1.10011001100110011001110 //  + 0        1.10011001100110011001110 // //f=1.800000 //hex=3F E6 66 68 //bin=00111111111001100110011001101000 //bin=0 01111111   11001100110011001101000 //  + 127 -127 1.11001100110011001101000 //  + 0        1.11001100110011001101000 // //f=2.000000 //hex=40 00 00 01 //bin=01000000000000000000000000000001 //bin=0 10000000   00000000000000000000001 //  + 128 -127 1.00000000000000000000001 //  + 1        1.00000000000000000000001 //------------ // //f=2.000000 //hex=40 00 00 00 //bin=01000000000000000000000000000000 //bin=0 10000000   00000000000000000000000 //  + 128 -127 1.00000000000000000000000 //  + 1        1.00000000000000000000000 //----------------------------------- // //d=0.000000000000000 //hex=00 00 00 00 00 00 00 00 //bin=0000000000000000000000000000000000000000000000000000000000000000 //bin=0 00000000000   0000000000000000000000000000000000000000000000000000 //  + 0     -1023 1.0000000000000000000000000000000000000000000000000000 //  + -1023       1.0000000000000000000000000000000000000000000000000000 // //d=0.200000000000000 //hex=3F C9 99 99 99 99 99 9A //bin=0011111111001001100110011001100110011001100110011001100110011010 //bin=0 01111111100   1001100110011001100110011001100110011001100110011010 //  + 1020  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -3          1.1001100110011001100110011001100110011001100110011010 // //d=0.400000000000000 //hex=3F D9 99 99 99 99 99 9A //bin=0011111111011001100110011001100110011001100110011001100110011010 //bin=0 01111111101   1001100110011001100110011001100110011001100110011010 //  + 1021  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -2          1.1001100110011001100110011001100110011001100110011010 // //d=0.600000000000000 //hex=3F E3 33 33 33 33 33 34 //bin=0011111111100011001100110011001100110011001100110011001100110100 //bin=0 01111111110   0011001100110011001100110011001100110011001100110100 //  + 1022  -1023 1.0011001100110011001100110011001100110011001100110100 //  + -1          1.0011001100110011001100110011001100110011001100110100 // //d=0.800000000000000 //hex=3F E9 99 99 99 99 99 9A //bin=0011111111101001100110011001100110011001100110011001100110011010 //bin=0 01111111110   1001100110011001100110011001100110011001100110011010 //  + 1022  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -1          1.1001100110011001100110011001100110011001100110011010 // //d=1.000000000000000 //hex=3F F0 00 00 00 00 00 00 //bin=0011111111110000000000000000000000000000000000000000000000000000 //bin=0 01111111111   0000000000000000000000000000000000000000000000000000 //  + 1023  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 0           1.0000000000000000000000000000000000000000000000000000 // //d=1.200000000000000 //hex=3F F3 33 33 33 33 33 33 //bin=0011111111110011001100110011001100110011001100110011001100110011 //bin=0 01111111111   0011001100110011001100110011001100110011001100110011 //  + 1023  -1023 1.0011001100110011001100110011001100110011001100110011 //  + 0           1.0011001100110011001100110011001100110011001100110011 // //d=1.400000000000000 //hex=3F F6 66 66 66 66 66 66 //bin=0011111111110110011001100110011001100110011001100110011001100110 //bin=0 01111111111   0110011001100110011001100110011001100110011001100110 //  + 1023  -1023 1.0110011001100110011001100110011001100110011001100110 //  + 0           1.0110011001100110011001100110011001100110011001100110 // //d=1.600000000000000 //hex=3F F9 99 99 99 99 99 99 //bin=0011111111111001100110011001100110011001100110011001100110011001 //bin=0 01111111111   1001100110011001100110011001100110011001100110011001 //  + 1023  -1023 1.1001100110011001100110011001100110011001100110011001 //  + 0           1.1001100110011001100110011001100110011001100110011001 // //d=1.800000000000000 //hex=3F FC CC CC CC CC CC CC //bin=0011111111111100110011001100110011001100110011001100110011001100 //bin=0 01111111111   1100110011001100110011001100110011001100110011001100 //  + 1023  -1023 1.1100110011001100110011001100110011001100110011001100 //  + 0           1.1100110011001100110011001100110011001100110011001100 // //d=2.000000000000000 //hex=3F FF FF FF FF FF FF FF //bin=0011111111111111111111111111111111111111111111111111111111111111 //bin=0 01111111111   1111111111111111111111111111111111111111111111111111 //  + 1023  -1023 1.1111111111111111111111111111111111111111111111111111 //  + 0           1.1111111111111111111111111111111111111111111111111111 // //d=2.200000000000000 //hex=40 01 99 99 99 99 99 99 //bin=0100000000000001100110011001100110011001100110011001100110011001 //bin=0 10000000000   0001100110011001100110011001100110011001100110011001 //  + 1024  -1023 1.0001100110011001100110011001100110011001100110011001 //  + 1           1.0001100110011001100110011001100110011001100110011001 //------------ // //d=2.000000000000000 //hex=40 00 00 00 00 00 00 00 //bin=0100000000000000000000000000000000000000000000000000000000000000 //bin=0 10000000000   0000000000000000000000000000000000000000000000000000 //  + 1024  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 1           1.0000000000000000000000000000000000000000000000000000 //

因为是“浮点数”，数字越大，小数点后的精度越低


Question: c语言，函数执行完释放内存的相关问题。

指针指向的对象在函数 f 结束之后就不存在了。

局部变量的地址是在栈上的,函数调用使用的是栈,你注释掉的printf语句覆盖了stack上s变量地址的值,函数结束后是把ESP指针(指向栈顶)下移(就是释放了s的空间,下次操作栈的时候会把这部分当成可使用的,比如函数的参数,局部变量都会使用到),你用绝对地址的方式还是可以访问到的,并没有做可写可读的限制

栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……

不要让指针指向局部变量，否则结果是未定义的，也就是说可能与你期望的相同，也可能与你期望的不同，甚至出错  当你运行了printf之后，之前的变量被覆盖了，所以结果不同了

你函数里面的形参是int **型(指向指针的指针)，所以指向的s也得是一个指针，但是你s却定义成int型。


Question: C语言新手，写了一段代码用了很多goto语句。（不用goto感觉很复制），想请教一下大神遇到这种情况到底用不用goto。

现在有个疑问，你的 case2 和 case3 里面，那个 printf 之后不返回 0 吗？如果不返回，打出结果还继续的话，你这个逻辑不用 goto 很麻烦，只能少用。如果你那里的确是有 return 0 只是忘了写，那这个逻辑太容易实现了。

goto是無條件跳轉，在沒有if的時候用來獲得if的效果，現在沒必要用 goto會導致程序的可讀性變差，而且你很難考慮到發生跳轉時的所有可能，導致發生預料之外的錯誤 仍然有一些使用goto的好的例子，但是在你確信可以完全控制局面之前不要使用goto

1个goto也别用，如果你依然用GOTO 你的二维思维就别想那么快上升到三维甚至多维  一个程序，必然是一个多维思维的结果  你感觉复杂，是用二维思维去考虑多维的结果  似想，用多维思维去思考多维怎么会复杂呢？ 所以，别去纠结了  我只告诉你，任何需要GOTO去达到的效果，都一定存在恰当的方式方法替代GOTO

除了goto case7出现2次外，其他goto都只出现1次，完全可以用if else来是实现啊

过早的优化是万恶之源。

写成接口不是更方便吗

如果只是考虑当前的问题，goto还是很清晰的。  但是如果要做些修改，比如调整跳转，或者生成新的决策树，那么代码就不那么好维护了。  抛砖引玉吧：   # include <stdio.h>  struct Node;  enum NodeType {     question,     terminator, };  struct Option {     char * option;     struct Node * next; };  struct Node {     enum NodeType type;     char * question;     struct Option options[10];     char * result; };  int main() {     struct Node q1 = {         question,         "你想要多大尺寸的机型？",         {             { "13寸以下（极度便携)" },             { "13~15寸 （主流均衡)" },             { NULL, NULL }         },         NULL     },          q2 = {         question,         "是否愿意使用可拆分的PC平板二合一产品？",         {             { "是，我愿意" },             { "否，不愿意" },             { NULL, NULL }         },         NULL     },          q3 = {         question,         "你的主要用途（常用软件）是什么？",         {             { "网页浏览、Office、PDF Reader、Coding" },             { "制图、工业软件、其他对性能有要求的应用" },             { "需要 wacom 电磁屏的设计绘图行业" },             { NULL, NULL }         },         NULL     },          q4 = {         question,         "是否需要专为触摸设计的不可拆分笔记本？",         {             { "是，我需要" },             { "否，不需要" },             { NULL, NULL }         },         NULL     },          q5 = {         question,         "是否有一定的游戏需求？",         {             { "是，我偶尔会玩一些轻度游戏或者不玩（LOL、Dota、COD4、尘埃3)" },             { "是，玩大部分3D网游和非发烧单机游戏（剑灵、WOW、Dota2、COD）" },             { NULL, NULL }         },         NULL     },          q6 = {         question,         "是否属于需要 Nvidia Quadro 专业显卡的领域？（Quadro行业应用)",         {             { "是，我需要" },             { "否，不需要" },             { NULL, NULL }         },         NULL     },          q7 = {         question,         "是否属于需要高性能CPU的领域？（例如大量数据处理、虚拟机）",         {             { "是，要求很高" },             { "否，要求不高" },             { NULL, NULL }         },         NULL     },          q8 = {         question,         "有哪些必备的接口或装置？",         {             { "USB+HDMI+耳麦合一接口" },             { "除上述之外还需要VGA、网线接口" },             { NULL, NULL }         },         NULL     },          t1 = {         terminator,         NULL,         { },         "1. X1 Helix\n2. ThinkPad 10"     },          t2 = {         terminator,         NULL,         { },         "1. S1 Yoga、Helix\n2. ThinkPad 10"     },          t3 = {         terminator,         NULL,         { },         "S1 Yoga"     },          t4 = {         terminator,         NULL,         { },         "1. X250\n2. X1 Carbon系列"     },          t5 = {         terminator,         NULL,         { },         "1. T450\n2. S Yoga系列"     },          t6 = {         terminator,         NULL,         { },         "1. W541\n2. W550"     },          t7 = {         terminator,         NULL,         { },         "T450、T550的i7版本"     },          t8 = {         terminator,         NULL,         { },         "1. X1 Carbon系列\n2. S3 Yoga"     },          t9 = {         terminator,         NULL,         { },         "T450s、T450"     };     struct Node * node;      q1.options[0].next = &q2;     q1.options[1].next = &q3;      q2.options[0].next = &t1;     q2.options[1].next = &q4;      q3.options[0].next = &q5;     q3.options[1].next = &q6;     q3.options[2].next = &t2;      q4.options[0].next = &t3;     q4.options[1].next = &t4;      q5.options[0].next = &q7;     q5.options[1].next = &t5;      q6.options[0].next = &t6;     q6.options[1].next = &q7;      q7.options[0].next = &t7;     q7.options[1].next = &q8;      q8.options[0].next = &t8;     q8.options[1].next = &t9;      node = &q1;     while (node)     {         puts("");         if (node->type == question)         {             puts(node->question);              struct Option * option = node->options;             int i = 0;             while (option->option)             {                 printf("%d. ", i++);                 puts(option++->option);             }              scanf("%d", &i);              node = node->options[i].next;         }         else         {             puts(node->result);             node = NULL;         }     }      return 0; }

建议把各个部分封装成函数，然后直接调用即可，通常都可以用判断与循环代替掉，一样可以做到不是你说的那种“很复制”

如果你的每个型号列表那里都有 return 0，你的代码可以调整一下。 注意这个问题：是否有一定的游戏需求？A、B 被我互换了，为方便逻辑书写：#include <stdio.h> #include <conio.h>  int main() { 	char t; 	printf( "你想要多大尺寸的机型？\n" 			"A. 13寸以下（极度便携)\n" 			"B. 13～15寸（主流均衡)\n" ); 	t = getch(); 	if (t == 'a' || t == 'A') 	{ 		printf( "是否愿意使用可拆分的PC平板二合一产品？\n" 				"A. 是，我愿意\n" 				"B. 否，不愿意\n" ); 		t = getch(); 		if (t == 'a' || t == 'A') 		{ 			printf( "1. X1 Helix\n" 					"2. ThinkPad 10\n" ); 			return 0; 		}  		printf( "是否需要专为触摸设计的不可拆分笔记本？\n" 				"A. 是，我需要\n" 				"B. 否，不需要\n" ); 		t = getch(); 		if (t == 'a' || t == 'A') 		{ 			printf( "1. S1 Yoga" ); 			return 0; 		} 		else 		{ 			printf( "1. X250\n" 					"2. X1 Carbon系列\n"); 			return 0; 		} 	}  	printf( "你的主要用途 (常用软件) 是什么？\n" 			"A. 网页浏览、Office、PDF Reader、Coding\n" 			"B. 制图、工业软件、其他对性能有要求的应用\n" 			"C. 需要 wacom 电磁屏的设计绘图行业\n" ); 	t = getch(); 	if (t == 'a' || t == 'A') 	{ 		printf( "是否有一定的游戏需求？\n" 				"A. 是，玩大部分3D网游和非发烧单机游戏 (剑灵、WOW、Dota2、COD)\n" 				"B. 是，我偶尔会玩一些轻度游戏或者不玩 (LOL、Dota、COD4、尘埃3)\n" ); 		t = getch(); 		if (t == 'a' || t == 'A') 		{ 			printf( "1. T450\n" 					"2. S Yoga 系列\n" ); 			return 0; 		} 	} 	else if (t == 'b' || t == 'B') 	{ 		printf( "是否属于需要 Nvidia Quadro 专业显卡的领域(Quadro 行业应用)？\n" 				"A. 是，我需要\n" 				"B. 否，不需要\n" ); 		t = getch(); 		if (t == 'a' || t == 'A') 		{ 			printf( "1. W541\n" 					"2. W550\n" ); 			return 0; 		} 	} 	else 	{ 		printf( "1. S1 Yoga、Helix\n" 				"2. ThinkPad 10\n"); 		return 0; 	}  	printf( "是否属于需要高性能CPU的领域 (例如大量数据处理、虚拟机)？\n" 			"A. 是，要求很高\n" 			"B. 否，要求不高\n" ); 	t = getch(); 	if (t == 'a' || t == 'A') 	{ 		printf("T450、T550 i7 版本"); 		return 0; 	}  	printf( "有哪些必备的接口或装置？\n" 			"A. USB + HDMI + 耳麦合一接口\n" 			"B. 除上述之外还需要 VGA、网线接口\n" ); 	t = getch(); 	if (t == 'a' || t == 'A') 	{ 		printf( "1. X1 Carbon系列\n" 				"2. S3 Yoga\n" ); 		return 0; 	} 	else 	{ 		printf("T450/T450s"); 		return 0; 	}  	return 0; }

不好意思，是复杂，不是复制，题目打错了。


Question: 关于opencv里的内存泄漏

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

提醒：OpenCV是开源的。  检查是否资源泄漏的办法之一： 在任务管理器 进程 查看 选择列 里面选择：内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍，越多越好，比如1000000次甚至无限循环，记录以上各数值，再隔至少一小时，越长越好，比如一个月，再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加，则铁定有对应资源的资源泄漏！  搜“GDI泄露检测”


Question: 二级指针，绕不出来了，大神求指教

最好不要这样写char **p = NULL; 指针变量应该在定义的时候就赋值： char **p = &q;

q = s;    这一句是可以的。 *p = q;  这一句是不行的。 p 现在指向NULL，*p 就是非法的。  可以改成： p = &p；

理解和讨论之前请先学会如何观察！  仅供参考：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

引用 4 楼 qq_33242956 的回复:[quote=引用 2 楼 paschen 的回复:] *p = q; 明显不对，不管你什么类型指针，只要没有给它分配内存，或者让指针指向有效对象，就不能去解引指针（*p）  这是我想的就是这样，编译可以通过的，运行段错误；但是其他人运行就可以了 char **p; char s[12] = "hello"; char *q = s; printf("%p\n", p); *p = q; printf("%p\n", p); 别人运行两次的打印结果是一样的，我用的4.6.3的gcc在Ubuntu系统下编译运行，是段错误。出段错误的就是*p = q；[/quote]  解引野指针的结果是未定义的，看似正确不代表正确，或许你把什么不属于你的内存覆盖了，也或许这个内存还没有分配物理存储器，也就出错了

引用 2 楼 paschen 的回复:*p = q; 明显不对，不管你什么类型指针，只要没有给它分配内存，或者让指针指向有效对象，就不能去解引指针（*p）  这是我想的就是这样，编译可以通过的，运行段错误；但是其他人运行就可以了 char **p; char s[12] = "hello"; char *q = s; printf("%p\n", p); *p = q; printf("%p\n", p); 别人运行两次的打印结果是一样的，我用的4.6.3的gcc在Ubuntu系统下编译运行，是段错误。出段错误的就是*p = q；

q = s这个是可以的，表示q指向s中的第一个元素。 *p = q这个不行，就如同楼上说的那样。 在理解二级指针的时候，先要把指针弄清楚，把指针弄清楚了，二级指针其实不难理解。 http://blog.csdn.net/xiangdongwang1000/article/details/49658797?locationNum=7&fps=1


Question: 大神们请问一个有关科大讯飞sdk的问题

Windows系统：“不要调用我，请先填写好未来收到某个消息时你的处理流程，在那个消息到来时我会调用你！”


Question: 一道哈弗曼编码的题目

指针必须要分配空间才能使用，不然指向的是未知区域，尝试写入会导致异常  #include<stdio.h> #include<stdlib.h> #define MAX 100  typedef struct{ 	int bit[MAX]; 	int start; }HCodetype;  int main() { 	int n = 1; 	HCodetype *cd = (HCodetype *)malloc(sizeof(HCodetype)); 	cd->start = n - 1; 	return 0; }

学习 学习。

问题已解决，非常感谢上面三位大神的教导

改为HCodetype *cd=(HCodetype *)malloc(sizeof(HCodetype));还是不行

怎么改？？大神

意思就是你就定义了一个指针，但是你的指针没有指向的对象，你怎么用，用了当然要崩溃咯！

不要NULL也是崩溃啊

不太懂，应该怎么改？

因为你的cd是NULL，你的cd并滑指向有效的内存，你就cd->start所以错了  NULL这真内存是不可访问的

void HaffmanCode() {     HCodetype *cd=NULL;     int i,j,c,p;     FILE *fp;     for(i=0;i<n;i++)     {         cd->start=n-1;         c=i;         p=HuffMTree[c]->parent;         while(p!=-1)         {             if(HuffMTree[p]->lchild==c)                 cd->bit[cd->start]=0;             else                 cd->bit[cd->start]=1;             cd->start--;             c=p;             p=HuffMTree[c]->parent;         }         for(j=cd->start+1;j<n;j++)             HuffCode[i]->bit[j]=cd->bit[j];         HuffCode[i]->start=cd->start+1;     }


Question: 怎么把下面程序由求一组深度优先遍历改为求所有的深度优先遍历

仅供参考：/**  * @Title  老鼠走迷宫  * @Author 孙琨  * @Date   2013-11-16  * @At     XUST  * @All Copyright by 孙琨  *  */  #include <iostream> using namespace std;  int maze[7][7] = { // 初始化迷宫，英文maze为“迷宫”     {2,2,2,2,2,2,2},     {2,0,0,0,0,0,2},     {2,0,2,0,2,0,2},     {2,0,0,2,0,2,2},     {2,2,0,2,0,2,2},     {2,0,0,0,0,0,2},     {2,2,2,2,2,2,2} };  int startI = 1,startJ = 1; // 入口行列坐标 int endI = 5,endJ = 5;     // 出口行列坐标 int success = 0;           // 判断路是否走通  int visit(int i,int j)  // 自动搜寻路径 {     maze[i][j] = 1;      if((i == endI) && (j == endJ))         success = 1;      if((success != 1) && (maze[i][j+1] == 0))  // 下         visit(i,j+1);     if((success != 1) && (maze[i+1][j]) == 0)  // 右         visit(i+1,j);     if((success != 1) && (maze[i][j-1] == 0))  // 上         visit(i,j-1);     if((success != 1) && (maze[i-1][j] == 0))  // 左         visit(i-1,j);      if(success != 1)         maze[i][j] = 0;      return success;  }  int main(void) {     int i,j;      cout << "显示迷宫: " << endl;     for(i=0; i<7; i++)     {         for(j=0; j<7; j++)         {             if(maze[i][j] == 2)                 cout << "■" ;             else                 cout << "  " ;         }         cout << endl;     }      if(visit(startI,startJ) == 0)     {         cout << endl << "没有找到出口!" << endl;     }     else     {         cout << endl << "显示路径: " << endl;         for(i=0; i<7; i++)         {             for(j=0; j<7; j++)             {                 if(maze[i][j] == 2)                     cout << "■";                 else if(maze[i][j] == 1)                     cout << "♀";                 else                     cout << "  ";             }             cout << endl;         }     }     return 0; }   /**  * @Title  老鼠走迷宫的拓展探究  * @Author 孙琨  * @Date   2013-11-16  * @At     XUST  * @All Copyright by 孙琨  *  */  #include <iostream> using namespace std;  int maze[9][9] = { // 初始化迷宫，英文maze为“迷宫”     {2,2,2,2,2,2,2,2,2},     {2,0,0,0,0,0,0,0,2},     {2,0,2,2,0,2,2,0,2},     {2,0,2,0,0,2,0,0,2},     {2,0,2,0,2,0,2,0,2},     {2,0,0,0,0,0,2,0,2},     {2,2,0,2,2,0,2,2,2},     {2,0,0,0,0,0,0,0,2},     {2,2,2,2,2,2,2,2,2} };  int startI = 1,startJ = 1; // 入口行列坐标 int endI = 7,endJ = 7;     // 出口行列坐标  void visit(int i,int j)  // 自动搜寻路径 {     int m,n;      maze[i][j] = 1;      if((i == endI) && (j == endJ))     {         cout << endl << "显示路径:" << endl;         for(m=0; m<9; m++)         {             for(n=0; n<9; n++)             {                 if(maze[m][n] == 2)                     cout << "■";                 else if(maze[m][n] == 1)                     cout << "♀";                 else                     cout << "  ";             }             cout << endl;         }     }      if(maze[i][j+1] == 0)         visit(i,j+1);     if(maze[i+1][j] == 0)         visit(i+1,j);     if(maze[i][j-1] == 0)         visit(i,j-1);     if(maze[i-1][j] == 0)         visit(i-1,j);      maze[i][j] = 0;  }  int main(void) {     int i,j;      cout << "显示迷宫: " << endl;     for(i=0; i<9; i++)     {         for(j=0; j<9; j++)         {             if(maze[i][j] == 2)                 cout << "■" ;             else                 cout << "  " ;         }         cout << endl;     }      visit(startI,startJ);      return 0; }

兄弟，我觉得你讲自己的代码思路和问题要好点，很少人会去看别人的代码，而且还这么长，况且你只是需要知道怎么做而已

在线求教......


Question: 运行时出现了debug  assretion failed 问题，麻烦大神帮忙解决

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

出错时点中断，通过调用堆栈定位到相关位置，观察分析原因  必要时可设置断点，然后单步跟踪程序运行

/*16.加密总函数*/ void DataEncrypt(char *k, unsigned char key[][4], unsigned char bit[], FILE *fp1, FILE *fp2, unsigned char RoundKey[][4], unsigned char status[][4]) {     int sum, numOfBlock, numOfSurplus;     char ch;     int len = strlen(k);     if (len != 16){         free(k);         printf("\n\n输入密钥长度不满足要求!\n"); return;     }     KeyExpansion(k, key, bit);     sum = SumBytes(fp1);     fp1 = fopen("源文件.txt", "r");     numOfBlock = sum / 16;     numOfSurplus = sum % 16;      ch = fgetc(fp1);     /*第一种情况*/     if (numOfBlock != 0 && numOfSurplus == 0){         for (int n = 1; n <= numOfBlock; n++){             for (int i = 0; i < 4; i++)             for (int j = 0; j < 4; j++){                 status[i][j] = ch;                 ch = fgetc(fp1);             }//status赋值              RoundKeyChoice(key, RoundKey, 0);             AddRoundKey(RoundKey, status);             for (int nr = 1; nr <= 10; nr++){                 SubBytes(status, bit);                 ShiftRows(status);                 MixColumns(status);                 RoundKeyChoice(key, RoundKey, nr);                 AddRoundKey(RoundKey, status);             }//10轮加密             SubBytes(status, bit);             ShiftRows(status);             RoundKeyChoice(key, RoundKey, 4);             AddRoundKey(RoundKey, status);             BytesWrite(fp2, status);         }//Block循环     }//if     //第二种情况     else if (numOfBlock == 0 && numOfSurplus != 0){         for (int i = 0; i < 4; i++)         for (int j = 0; j < 4; j++){             if (ch == EOF) break;             status[i][j] = ch;             ch = fgetc(fp1);         }         for ( i = sum / 4; i < 4; i++)         for (int j = sum % 4; j < 4; j++)             status[i][j] = 0x00;         RoundKeyChoice(key, RoundKey, 0);         AddRoundKey(RoundKey, status);         for (int nr = 1; nr <= 10; nr++){             SubBytes(status, bit);             ShiftRows(status);             MixColumns(status);             RoundKeyChoice(key, RoundKey, nr);             AddRoundKey(RoundKey, status);         }//10轮加密         SubBytes(status, bit);         ShiftRows(status);         RoundKeyChoice(key, RoundKey, 4);         AddRoundKey(RoundKey, status);         BytesWrite(fp2, status);     }//else if     //第三种情况     else if (numOfBlock != 0 && numOfSurplus != 0){         for (int n = 1; n <= numOfBlock; n++){             for (int i = 0; i <4; i++)             for (int j = 0; j < 4; j++){                 status[i][j] = ch;                 ch = fgetc(fp1);             }//status赋值              RoundKeyChoice(key, RoundKey, 0);             AddRoundKey(RoundKey, status);             for (int nr = 1; nr <= 10; nr++){                 SubBytes(status, bit);                 ShiftRows(status);                 MixColumns(status);                 RoundKeyChoice(key, RoundKey, nr);                 AddRoundKey(RoundKey, status);             }//10轮加密             SubBytes(status, bit);             ShiftRows(status);             RoundKeyChoice(key, RoundKey, 4);             AddRoundKey(RoundKey, status);             BytesWrite(fp2, status);         }//Block循环         for (int i = 0; i < 4; i++)         for (int j = 0; j < 4; j++){             if (ch == EOF) break;             status[i][j] = ch;             char ch = fgetc(fp1);         }         for ( i = sum / 4; i < 4; i++)         for (int j = sum % 4; j < 4; j++)             status[i][j] = 0x00;         RoundKeyChoice(key, RoundKey, 0);         AddRoundKey(RoundKey, status);         for (int nr = 1; nr <= 10; nr++){             SubBytes(status, bit);             ShiftRows(status);             MixColumns(status);             RoundKeyChoice(key, RoundKey, nr);             AddRoundKey(RoundKey, status);         }//10轮加密         SubBytes(status, bit);         ShiftRows(status);         RoundKeyChoice(key, RoundKey, 4);         AddRoundKey(RoundKey, status);         BytesWrite(fp2, status);     }//else      free(k);     fclose(fp1);     fclose(fp2);     printf("\n\n加密文件成功!\n\n"); }  /*17.解密总函数*/ void DataDecrypt(char *k1, unsigned char key[][4], FILE *fp1, FILE *fp2, unsigned char status[][4], unsigned char RoundKey[][4], unsigned char bit[]) {     int numOfBlock, sum;     char ch;     int len = strlen(k1);     if (len != 16){         free(k1);         printf("\n\n输入密钥长度不满足要求!\n"); return;     }     sum = SumBytes(fp1);     fp1 = fopen("加密后文件.txt", "r");     numOfBlock = sum / 16;      ch = fgetc(fp1);     for (int i = 1; i <= numOfBlock; i++){         for (int i = 0; i < 4; i++)         for (int j = 0; j < 4; j++){             status[i][j] = ch;             ch = fgetc(fp1);         }         RoundKeyChoice(key, RoundKey, 4);         AddRoundKey(RoundKey, status);         Inv_ShiftRows(status);         Inv_SubBytes(status, bit);         for (int nr = 10; nr >= 1; nr--){             RoundKeyChoice(key, RoundKey, nr);             AddRoundKey(RoundKey, status);             Inv_MixColumns(status);             Inv_ShiftRows(status);             Inv_SubBytes(status, bit);         }//10轮解密          RoundKeyChoice(key, RoundKey, 0);         AddRoundKey(RoundKey, status);         BytesWrite(fp2, status);     }//Block     free(k1);     fclose(fp1);     fclose(fp2);     printf("\n\n解密文件成功!\n\n"); }  int main(){     int choice, sum1;     int flag = 1;     char *k, *k1;     FILE *fp1, *fp2;     unsigned char status[4][4] = { 0x00 };     unsigned char key[44][4] = { 0x00 };     unsigned char RoundKey[4][4] = { 0x00 };     unsigned char bit[8] = { 0x00 };     do{         printf("*****************************AES加密解密文件************************************");         printf("\n");         printf("                             1.加密文件\n\n");         printf("                             2.解密文件\n\n");         printf("                             3.退出\n\n");         printf("\n请选择要进行的操作:");         scanf("%d", &choice);         switch (choice){         case 1: fp1 = fopen("C://Users/WUWEI/Desktop/123/Debug/源文件.txt", "r");             if (fp1 == NULL){                 printf("打开源文件失败!\n");                 getchar();                 exit(0);             }             fp2 = fopen("加密后文件.txt", "w");             if (fp2 == NULL){                 printf("打开加密后文件失败!\n");                 getchar();                 exit(0);             }             printf("\n请输入加密密钥(128bit):");             k = (char *)malloc(20 * sizeof(char));             cin >> k;             DataEncrypt(k, key, bit, fp1, fp2, RoundKey, status);             break;         case 2: fp1 = fopen("加密后文件.txt", "r");             if (fp1 == NULL){                 printf("\n打开加密后文件失败!\n");                 getchar();                 exit(0);             }             fp2 = fopen("解密后文件.txt", "w");             if (fp2 == NULL){                 printf("\n打开解密后文件失败!\n");                 getchar();                 exit(0);             }             printf("\n\n请输入解密密钥(128bit):");             k1 = (char *)malloc(20 * sizeof(char));             cin >> k1;             DataDecrypt(k1, key, fp1, fp2, status, RoundKey, bit);             break;         case 3: flag = 0; break;         default: printf("\n\n所选操作不合法!\n");         }//switch     } while (flag); }

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。


Question: C语言 .exe已停止 大神们帮我看下代码哪里出错了

要在函数内修改指针的指向，必须传二级指针或者一级指针的引用才行 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

jie函数参数p、q是按值传递的，也就是说函数中的参数只是实参的一个复制品，你在jie函数中修改的p q 的值也只是修改一个复制的对象，主函数中的仍然是NULL，这导致后面解引出错  如果要修改指针的值，需要要传入指针的地址

主函数中p,q改成double类型，传参时改成&p, &q,  jie函数中，给p,q赋值改成*p = x1, *q = x2


Question: 如何将两个ASCII字符合成一个字节

这个能合并？你要用来干什么？如果是不可逆的，你自己随便定义操作就行，但如果要是可逆的，我想我不使用其他的存储信息，合并应该有问题吧

赵４老师，好像有点不对哦，验证了，42F0E666试下，　　BCD[i/2]=(sv[i]<<4)|(sv[i+1]&0x0F);

仅供参考：#include <stdio.h> #include <stdlib.h> #include <conio.h> unsigned int iv,i; unsigned char BCD[5];//定长10位BCD码 unsigned char sv[11]; void main() {     iv=123456789;//最大10位无符号正整数     //INT2BCD     sprintf(sv,"%010u",iv);     for (i=0;i<10;i+=2) {         BCD[i/2]=(sv[i]<<4)|(sv[i+1]&0x0F);     }     printf("BCD=%02x%02x%02x%02x%02x\n",BCD[0],BCD[1],BCD[2],BCD[3],BCD[4]);     //BCD2INT     for (i=0;i<10;i+=2) {         sv[i]='0'|(BCD[i/2]>>4);         sv[i+1]='0'|(BCD[i/2]&0x0F);     }     sscanf(sv,"%010u",&iv);     printf("iv=%010u\n",iv);     getch(); }

大神,给代码呗,随便c,c++或者oc都行啊

位运算 : 位左移和位或


Question: 蓝桥杯 十六进制转十进制

#include <stdio.h> #include <string.h> #include <math.h> int a[10]; char s[10]; int main() { 	gets(s); 	memset(a,0,sizeof(a)); 	int len=strlen(s); 	int i,k=0,sum=0; 	for(i=len-1;i>=0;i--) 	{ 		if(s[i]>='0'&&s[i]<='9') 			a[k++]=s[i]-'0'; 		else if(s[i]>='A'&&s[i]<='Z') 			a[k++]=s[i]-55; 		else 			a[k++]=s[i]-87; 	} 	for(i=9;i>=0;i--) 	{ 		sum+=a[i]*pow(16,i); 	} 	printf("%d\n",sum); 	return 0; } 我的也错了...有一组测试数据过不了

你让小写的a到f情何以堪？

除了不支持0x前缀的输入之外，第二个代码输入的A~F只能是大写，没有处理小写的情况

没仔细看，目测第二段代码不支持 0x123 这样的输入吧？

我觉得自己的代码应该没有问题吧，两个程序用来测试得到的结果是一样的


Question: 错误：expected ‘)’ before ‘*’ token

引用 1 楼 user-1 的回复:目测没什么问题，你加上防止重复编译的宏定义看看？另外，头文件自己include自己是什么意思？ 兄弟，刚才忘记刷新网页就结贴了，自己也是单文件拿出来测试的时候发现了这个隐蔽的错误的，不管怎样，非常感谢

引用 1 楼 user-1 的回复:目测没什么问题，你加上防止重复编译的宏定义看看？另外，头文件自己include自己是什么意思？ 确实是宏定义的问题，宏定义的头拷贝了其他文件的，忘记改过来了，应该是自己的头文件没有被包含，只是编译器提示有点不太准确


Question: 死循环怎么办

引用 3 楼 小灸舞的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 太对了，别人说在多变，自己不动手还是学不会。

你这个不能找水仙花数，返回0或1有啥用啊？你不应该返回水仙花数吗？

并不是 死循环吧，而是应为你是函数返回只有0和1，所以给你返回了900个0或者1让你有一种死循环的错觉吧


Question: 链表程序错误

#include <stdio.h> #include <stdlib.h> #include "list.h"  static void CopyToNode(Item item, Node *pnode);  void InitializerList(List *plist) {     *plist = NULL; }  bool ListIsEmpty(const List *plist) {     if(*plist == NULL)         return true;     else         return false; }  bool ListIsFull(const List *plist) {     Node *pt;     bool full;      pt = (Node *)malloc(sizeof(Node));     if(pt == NULL)         full = true;     else         full = false;     free(pt);     return full; }  unsigned int ListItemCount(const List *plist) {     unsigned int count = 0;     Node *pnode = *plist;      while(pnode != NULL)     {         count++;         pnode = pnode->next;     }     return count; }  bool AddItem(Item item, List *plist) {     Node *pnew;     Node *scan = *plist;      pnew = (Node *)malloc(sizeof(Node));     if(pnew == NULL)         return false;     CopyToNode(item, pnew);     pnew->next = NULL;     if(scan == NULL)         *plist = pnew;     else     {         while(scan->next != NULL)             scan = scan->next;         scan->next = pnew;     }     return true; }  void Traverse(const List *plist, void (*pfun)(Item item)) {     Node *pnode = *plist;     while(pnode != NULL)     {         (*pfun)(pnode->item);         pnode = pnode->next;     } }  void EmptyTheList(List *plist) {     Node *psave;     while(*plist != NULL)     {         psave = (*plist)->next;         free(*plist);         *plist = psave;     } }  static void CopyToNode(Item item, Node *pnode) {     pnode->item = item; }

引用 1 楼 user-1 的回复:可能pfun没有初始化 这个初始化是指实际传入的函数没有初始化吗

可能pfun没有初始化


Question: 关于C语言文件传输问题  新手求指点

tcp链路是一一对应的，关闭了服务端，还要求客户端不关闭，是啥需求？？

最好→最后

试试改变协议，让最后收到某条数据的那端关闭连接；而不是让最好发出某条数据的那端关闭连接。


Question: c语言 如何判断一个 字符串 中某一个字符 等于一个字符常量？

用指针或者数组的下标索引都可以

if (ch[3] == '-') {      //做你想做的事 }

利用数组判断a[3]是否等于'-'

const char* pstr = "123-456"; if( *(pstr + 3) == '-' ) { }


Question: 最近在做一个涉及缅甸文显示的项目，然后因为缅甸文字库的编码形式好像有别于我们使用的GBK编码格式，所以前来请教

仅供参考：#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, 0             , 0, 0, 0, 0, "Arial Unicode MS");     SelectObject(hdc,hfont);     TextOutW(hdc,10,10,L"你好",2);     DeleteObject(hfont);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, JOHAB_CHARSET , 0, 0, 0, 0, "Arial Unicode MS");     SelectObject(hdc,hfont);     TextOutW(hdc,10,80,L"\xb7f0\xb7f0\xb2dd\xb2dd",4);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }


Question: C语言 新手求教 while(*p++)； 为何不等于while(*p!='\0') *p++;

谢谢大家喽~~~

第一个ASCII码，对应的字符是（Null），其实就是‘\0’，即空字符。 可以被当做判断的表达式。

楼上(#4)要表达的是: 表示当a[i] 为0时退出循环a[i]非 0时循环.

引用另外关于 while(*p++=*q++)  最后停止是q指向了'\0'  停止了  是的   引用还有一个相似的 for(;a[i];) {......}  表示当a[i] 非0时退出循环  '\0'实际是一个值为0的字符，所以可以用作循环判断

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

打错了 标题中 应该是while(*p!='\0') p++;

用表达式的值作为条件进行判断。


Question: scanf和getchar的区别

引用 15 楼 赵4老师的回复:[quote=引用 13 楼 qq_36496856 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];为什么啊[/quote] Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored. [/quote] 是哪里找的啊?是某本书上的吗?

MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

引用 13 楼 qq_36496856 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];为什么啊[/quote] Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

我说的读入是指程序不能获取并判断用户输入的是回车、空格还是换行符，因为当输入这三个字符时scanf便会去缓冲区取数据，同时当遇到这三个字符时便停下来了，同时不会取这三个字符。  而getchar是能够取这三个字符的，也即用getchar是能判断用户输入的是回车还是空格和tab，而用scanf则就只会把这三个字符当做判断输入结束的标志

getchar()重点在于char，你可以通过该函数得到stream中的下一个character，无论这个字符是空白还是控制字符还是常规的字符； 而scanf()重点在于f，这个f指的是format，这就意味着它按照你给的“格式”，从stream中提取出你需要的东西，但往往出现的情况是你的format和实际的stream其实是不匹配的，然后你就感觉scanf工作起来“怪怪”的。

scanf不可读入回车和空格，getchar可以

出错估计是由于你缓冲区中留下的\n造成

scanf读取不了空白符（如\n \r \t ‘ ’），getchar()可以

scanf %c和getchar()都是读一个字符（而且都可以读回车符之类的） 楼主建议贴一下代码。

引用 1 楼 取个名字这么麻烦的回复:scanf不可读入回车和空格，getchar可以 说错了，，scanf是可以读空格的，在输入字符时。     你说的忽略是在输入别的东西时，比如字符串，整数

引用 1 楼 取个名字这么麻烦的回复:scanf不可读入回车和空格，getchar可以 还有tab,还是谢谢了

引用 5 楼 zhao4zhong1 的回复://请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];为什么啊

题目：Arithmetic expression can be defined recursively as following:  If a is a positive integer number, then a is an arithmetic expression. If a is a negative integer number, then (a) is an arithmetic expression. If e and f are arithmetic expressions, then (e+f), (e*f),(e-f),and (e/f) are all arithmetic expressions. The expression ((6*(-7))+(-9)) is an example of arithmetic expression, and its value is -51. Write a program that accepts an arithmetic expression represented as a string, output its value as an integer. Input  A string representing an arithmetic expression on one line. Output  The value of the arithmetic expression on one line. Sample Input  ((6*(-7))+((-9)/3)) Sample Output  -45 我代码：#include <stdio.h>   int main(void) {     int i, j, str[100];// i代表')'出现的位置， j代表'('出现的位置      char ch;          while( ( str[0]= getchar() ) && str[0] != EOF )//这里改成scanf就不可以，他测评的时候。总在它输出最后一个例子的时候     {     	/* 开始输入剩余的字符 */        if( str[0] != '(' )       {       	continue; 		}     	for( i = 1;( str[i] = getchar() ) != '\n' ;i++ )     	{	      	   /* 寻找‘）’的字符 ， 并且进行一定的操作 */ 			ch = str[i];     	   if( ch == 26 || ch == EOF)     	      break; 			if( str[i] == ')' )  			{ 				for( j = i - 3;j >= 0;j-- ) 				{ 					if( str[j] == '(') 					   break; 				}// 从出现')'的地方逆回去寻找'('  				 			/* 对'(' 和')'之间的数字进行计算 ，并且将计算的结果赋值给str[j],然后i = j */   				if( i - j == 3) 				{ 					str[j] = -(str[j + 2] - 48) + 48; 				} 				else 				{ 					switch( str[j + 2] ) 					{ 						case '+': 							str[j] = ( str[j + 1] - 48) + ( str[j + 3] - 48) + 48;break; 						case '-': 							str[j] = ( str[j + 1] - 48) - ( str[j + 3] - 48) + 48;break;	 						case '*': 							str[j] = ( str[j + 1] - 48) * ( str[j + 3] - 48) + 48;break; 						case '/': 							str[j] = ( str[j + 1] - 48) / ( str[j + 3] - 48) + 48;break;		 					} 				} 				 				i = j;	 	    		if( i == 0 ) 			      printf( "%d\n", str[i] - 48 ); 			 } 		  		 } 		  	 if( ch == EOF ) 	    break;	  	 }     return 0; } // 有些代码是无用的

[code=c][/code ]#include<stdio.h>  int main() {    char ch;        while( scanf( "%c", &ch) != EOF )    {    	printf( "%c\n", ch); 	} 	return 0;  // scanf可以读空格的  }


Question: 刚开始学数据结构的问题

引用 1 楼 取个名字这么麻烦的回复:node应该是一个自定义的结构体，然后通过typedef为这个新的结构体取了一个别名叫Node，例如 typedef struct node {     int a;     int b; }Node; 写错位置了，c用得不熟练

引用 2 楼 qq_36409192的回复:定义的结构是需要在程序中定义的，没有定义当然会给出错误提示。 ps：楼主多看看书吧，这是最基本的东西 在main里面已经定义了，自己试了一下要把这个insert写在main里面就可以，可是我之前是想写在main外面添加声明这样用的。

引用 3 楼 hxf0224的回复:[quote=引用 2 楼 qq_36409192的回复:]定义的结构是需要在程序中定义的，没有定义当然会给出错误提示。 ps：楼主多看看书吧，这是最基本的东西 在main里面已经定义了，自己试了一下要把这个insert写在main里面就可以，可是我之前是想写在main外面添加声明这样用的。[/quote] 楼主，请把问题说清楚点。


Question: 麻烦帮忙看下，谢谢了。功能1建立树为什么链不起来。

仅供参考：#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G

问题在于 功能1，建立树。  我觉得错误应该在连接的函数处，但我实在找不出来，麻烦大神帮忙。

这是个basic.h头文件 #include<string.h> #include<ctype.h> #include<malloc.h> /* malloc()等 */ #include<limits.h> /* INT_MAX等 */ #include<stdio.h> /* EOF(=^Z或F6),NULL */ #include<stdlib.h> /* atoi() */ #include<io.h> /* eof() */  #include<process.h> /* exit() */ #include<time.h> /* 函数结果状态代码 */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define EQUAL 0 #define GREATER 1 #define CONTINUE 1 #define END 0 #define LESSER -1  #define INFEASIBLE -1 #define LIST_OK 0   #define LIST_ERROR  -1   #define OVERFLOW 0  typedef int Status; /* Status是函数的类型,其值是函数结果状态代码，如OK等 */ typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

比如 费一周的时间，将复杂数据结构可视化，然后再费一天时间，调通 应该比 费五天时间调通而不追求将数据可视化 收获应该更大，且今后调试更复杂的数据结构更心里有底。  供显示复杂数据结构参考：#include <windows.h> #include <stdio.h>  void ConPrint(char *CharBuffer, int len); void ConPrintAt(int x, int y, char *CharBuffer, int len); void gotoXY(int x, int y); void ClearConsole(void); void ClearConsoleToColors(int ForgC, int BackC); void SetColorAndBackground(int ForgC, int BackC); void SetColor(int ForgC); void HideTheCursor(void); void ShowTheCursor(void);  int main(int argc, char* argv[]) {    HideTheCursor();    ClearConsoleToColors(15, 1);    ClearConsole();    gotoXY(1, 1);    SetColor(14);    printf("This is a test...\n");    Sleep(5000);    ShowTheCursor();    SetColorAndBackground(15, 12);    ConPrint("This is also a test...\n", 23);    SetColorAndBackground(1, 7);    ConPrintAt(22, 15, "This is also a test...\n", 23);    gotoXY(0, 24);    SetColorAndBackground(7, 1);    return 0; }  //This will clear the console while setting the forground and //background colors. void ClearConsoleToColors(int ForgC, int BackC) {    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //not used but we need to capture this since it will be    //written anyway (passing NULL causes an access violation).    DWORD count;     //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    SetConsoleTextAttribute(hStdOut, wColor);    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);        FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  //This will clear the console. void ClearConsole() {    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //   not used but we need to capture this since it will be    //   written anyway (passing NULL causes an access violation).    DWORD count;    //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  //This will set the position of the cursor void gotoXY(int x, int y) {    //Initialize the coordinates    COORD coord = {x, y};    //Set the position    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); }  //This will set the forground color for printing in a console window. void SetColor(int ForgC) {    WORD wColor;    //We will need this handle to get the current background attribute    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    CONSOLE_SCREEN_BUFFER_INFO csbi;     //We use csbi for the wAttributes word.    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //Mask out all but the background attribute, and add in the forgournd color       wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);       SetConsoleTextAttribute(hStdOut, wColor);    } }  //This will set the forground and background color for printing in a console window. void SetColorAndBackground(int ForgC, int BackC) {    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor); }  //Direct console output void ConPrint(char *CharBuffer, int len) {    DWORD count;    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), CharBuffer, len, &count, NULL); }  //Direct Console output at a particular coordinate. void ConPrintAt(int x, int y, char *CharBuffer, int len) {    DWORD count;    COORD coord = {x, y};    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleCursorPosition(hStdOut, coord);    WriteConsole(hStdOut, CharBuffer, len, &count, NULL); }  //Hides the console cursor void HideTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = FALSE; 	  SetConsoleCursorInfo(hStdOut, &cciCursor);    } }  //Shows the console cursor void ShowTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = TRUE; 	  SetConsoleCursorInfo(hStdOut, &cciCursor);    } }

引用 6 楼 zhao4zhong1 的回复:《算法精解（C语言描述）》 ？   并不是这个书，我是一名大二的学生，在做数据结构试验。因为多叉树的建立，网上并没有相关代码，只得自己构思然后去代码实现，在这个过程中遇到了困难，昨晚调试了4个小时因为编译器没报错，一直在思考为什么有点特别的链表连接不起来，因为这个实验今天要交，所以实在没办法才前来问的。   什么东西到最后都是要靠自己，这句话是对的。所以其实方法最重要。 再次感谢老师的再三回答。很是感谢

引用 8 楼 zhao4zhong1 的回复:再供参考： 十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495   谢谢大神又前来回答，给自己提意见，就在刚才调试了半天，终于成功了。  其实问题在于单链表的链接，只是情况有些不同。  具体在加入 指针->next 更改后成功的。 无论如何，成功了就是了。 很是感谢来回答的你们。

不要依赖调试器输出复杂数据结构！而要将复杂数据结构的整个内容在处理它的每一步使用一小段代码按自己很容易理解的格式输出，非常有助于调试！或者可以说是“基础设施” 仅供参考://不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=v;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=v;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

《算法精解（C语言描述）》 ？

谢谢各位大神的回答。但是我想说下自己观点，我是疑问在于树的建立那里链接不起来，而不是二叉树，这里的树指的是双亲孩子法建立的树，N叉树。这里楼上答非所问了。而版主的回复确实在理，但却比较万金油。因为我自己对这个VS确实不太熟，但编译器并没有报错，加上我代码的逻辑我思考过，我也调试过代码4个多小时，确实自己觉得能力不够，找不出错误，所以才来请教。并不是伸手主义。 希望后面的大大们能回答到点上。在这里十分谢谢来回答我的人。


Question: 这是我用vc++6.0做的一个星期查询，能不能把代码简单化？

仅供参考：#include <afxdisp.h> #include <stdio.h> #include <stdlib.h> int main(int argc, TCHAR* argv[]) {     COleDateTime t;     COleDateTimeSpan ts;     CString s,fmt;     int nYear;     int nMonth;     int nDay;     int nHour;     int nMin;     int nSec;     int lDays;     int nHours;     int nMins;     int nSecs;     int i,N;     // initialize MFC and print and error on failure     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {         printf("Fatal Error: MFC initialization failed\n");         return 1;     }     if (argc<13) {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 2;     }     if (stricmp(argv[12],"SQL")==0) fmt="%Y-%m-%d %H:%M:%S";     else if (stricmp(argv[12],"YYYY")==0) fmt="%Y%m%d %H%M%S";     else if (stricmp(argv[12],"YY")==0) fmt="%y%m%d %H%M%S";     else {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 3;     }     nYear =atoi(argv[ 1]);     nMonth=atoi(argv[ 2]);     nDay  =atoi(argv[ 3]);     nHour =atoi(argv[ 4]);     nMin  =atoi(argv[ 5]);     nSec  =atoi(argv[ 6]);     lDays =atoi(argv[ 7]);     nHours=atoi(argv[ 8]);     nMins =atoi(argv[ 9]);     nSecs =atoi(argv[10]);     N     =atoi(argv[11]);     if (N<=0) {         printf("Usage:%s sYYYY sMM sDD shh smm sss pDD phh pmm pss n {SQL|YYYY|YY}\n",argv[0]);         return 4;     }     t=COleDateTime( nYear, nMonth, nDay, nHour, nMin, nSec);     ts=COleDateTimeSpan( lDays, nHours, nMins, nSecs );     for (i=1;i<=N;i++) {         s=t.Format(fmt);         printf("%08d %s\n",i,s);         t=t+ts;     }     return 0; }

COleDateTime::GetDayOfWeek int GetDayOfWeek( ) const;  Return Value  The day of the week represented by the value of this COleDateTime object.  Remarks  Call this member function to get the day of the month represented by this date/time value.  Valid return values range between 1 and 7, where 1=Sunday, 2=Monday, and so on. If the status of this COleDateTime object is not valid, the return value is AFX_OLE_DATETIME_ERROR.  For information on other member functions that query the value of this COleDateTime object, see the following member functions:   GetDay   GetMonth   GetYear   GetHour   GetMinute   GetSecond   GetDayOfYear  COleDateTime Overview |  Class Members |  Hierarchy Chart  See Also   COleDateTime::COleDateTime, COleDateTime::SetDateTime, COleDateTime::operator =, COleDateTime::GetStatus

如果觉得主函数太长可以分成几个函数来执行相关功能


Question: 请问C语言怎么比较两张图的相似程度？

引用 16 楼 paschen 的回复:[quote=引用 15 楼 yyxgs 的回复:] [quote=引用 14 楼 paschen 的回复:] [quote=引用 10 楼 paschen 的回复:] [quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  OPENCV 1.0 是C语言的，之后版本好像也保留了C的接口[/quote]  我看了百科了，“保留了大量的C的接口”，也就是说真正适合的还是C++。。[/quote]  是的，OPENCV2.X 3.X都是用C++写的[/quote]   哦哦，谢谢！那还是等以后学了C++再考虑opencv吧。

引用 17 楼 yyxgs 的回复:[quote=引用 16 楼 paschen 的回复:] [quote=引用 15 楼 yyxgs 的回复:] [quote=引用 14 楼 paschen 的回复:] [quote=引用 10 楼 paschen 的回复:] [quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  OPENCV 1.0 是C语言的，之后版本好像也保留了C的接口[/quote]  我看了百科了，“保留了大量的C的接口”，也就是说真正适合的还是C++。。[/quote]  是的，OPENCV2.X 3.X都是用C++写的[/quote]   哦哦，谢谢！那还是等以后学了C++再考虑opencv吧。[/quote] 识时务者为俊杰。

引用 15 楼 yyxgs 的回复:[quote=引用 14 楼 paschen 的回复:] [quote=引用 10 楼 paschen 的回复:] [quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  OPENCV 1.0 是C语言的，之后版本好像也保留了C的接口[/quote]  我看了百科了，“保留了大量的C的接口”，也就是说真正适合的还是C++。。[/quote]  是的，OPENCV2.X 3.X都是用C++写的

引用 14 楼 paschen 的回复:[quote=引用 10 楼 paschen 的回复:] [quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  OPENCV 1.0 是C语言的，之后版本好像也保留了C的接口[/quote]  我看了百科了，“保留了大量的C的接口”，也就是说真正适合的还是C++。。

引用 10 楼 paschen 的回复:[quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  OPENCV 1.0 是C语言的，之后版本好像也保留了C的接口

引用 11 楼 zhao4zhong1 的回复:https://www.baidu.com/s?wd=sift   好算法！。。可是怎么使用呢？

引用 10 楼 paschen 的回复:[quote=引用 8 楼 yyxgs 的回复:] [quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的[/quote]  这个又是C++编写的....是不是要用它又得先会C++.....?

引用 8 楼 yyxgs 的回复:[quote=引用 2 楼 paschen 的回复:] opencv可以很容易实现  Windows和Android上都可以吗？[/quote]  可以，OPENCV是跨平台的

难道要一个一个像素比较

应该可以异或操作下吧。具体我也不知道。好像楼上的那个方法挺好的

引用 4 楼 shihengzhen101 的回复:难道要一个一个像素比较  哈哈，一个个像素比较也行啊，怎么个比法呢？

引用 2 楼 paschen 的回复:opencv可以很容易实现  Windows和Android上都可以吗？

引用 1 楼 user-5 的回复:什么图？不同的图不同的比较方法  就是一般的jpg、bmp、png格式的图片

(.)(.) 和 支付鸨 最新放出的哪几幅图片 相似？  http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E6%94%AF%E4%BB%98%E9%B8%A8

opencv可以很容易实现

什么图？不同的图不同的比较方法


Question: 单链表通用库

觉着，C语言的库稍微复杂点的功能，都很难做到“通用”。不具有作为组件的特性。 说道通用，还是linux内核那一坨链表的宏倒是很通用。

仅供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=v;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=v;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //


Question: （初学者）这个代码怎么哪错了？为什么没有输出？

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

#include <stdio.h>                                     int main() {          char array[100] = "我叫陈玉涛啦啦啦";      int length = 0;      while (array[length++])      |   ;      length--;      int min = 0;      int max = length - 1;      int tmp;       while (min < max)    /* Delete the ';' */                                                                                {      |   /*      |   char temp = array[min];      |   array[min] = array[max - 1];      |   array[max - 1] = temp;            |   temp = array[min + 1];      |   array[min + 1] = array[max];      |   array[max] = temp;             |   min += 2;      |   max -= 2;      |   */      |   tmp = array[min];        |   array[min] = array[max];      |   array[max] = tmp;      |   min++;      |   max--;                             }                            printf("%s\n", array);              return 0;                            }

while有分号就是空语句了

粗看了一下，你的第二个while后面多了个分号


Question: 又有莫名的新概念了，函数宏到底是个什么玩意儿？

引用 11 楼 ipqtjmqj 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] 理解和讨论之前请先学会如何观察！  VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898 赵老师自己也没观察，楼主问的是“函数宏”与“宏函数”的区别[/quote] 我不需要观察，只需要告诉人怎么去观察。

宏,  不管是常量宏, 还是函数宏.  都是成变不离其中.  都是编译时做代码替换,     比如最常用常用的 取最大值的宏    #define max(a,b)    (((a) > (b)) ? (a) : (b))  它就是一个宏函数 实际还不是代码替换,  展开后就是一个   问号表达式

你得给出上下文。

#define MACRO(x,y) ((x) + (y))  宏是可以带参数的

macro function, function macro你是从哪本书上看到的，要联系上下文

引用 2 楼 qq_36409192 的回复:概念性的问题可以自己去百度搜一下 度娘的结果含混不清，借东说西，有时候反而容易误导。还是来坛子里请教各位老师前辈比较有针对性。

引用 10 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898 赵老师自己也没观察，楼主问的是“函数宏”与“宏函数”的区别

个人理解：  函数宏—— 类似函数的宏，如max宏  宏函数——宏展开后调用的是一个函数，如ZeroMemory

宏的使用无非就是给代码起个别名，然后在使用的时候不必每次都把代码写上去。一般用在： 1.常用数字，如：#define  N  10 2.一句代码或者几句代码的替换（你说的函数其实就是这一种） 3.变量类型的说明（某些类型可能有多种意思，使用宏可以增加代码的可读性）

概念性的问题可以自己去百度搜一下

引用 4 楼 stalk12 的回复:[quote=引用 2 楼 qq_36409192 的回复:] 概念性的问题可以自己去百度搜一下 度娘的结果含混不清，借东说西，有时候反而容易误导。还是来坛子里请教各位老师前辈比较有针对性。[/quote] 楼主先看看这个 http://blog.csdn.net/hust_sheng/article/details/51093889?locationNum=2&fps=1

应该是一个东西，宏函数比较常用，说成函数宏是强调本质是个宏吧


Question: 请教C语言写的简单字典程序的问题

很明显是你申请的堆空间被越界写入了，导致堆被破坏，所以析构时出错。

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

点击重试，然后点击中断，通过调用堆栈定位到相关代码，观察分析原因，必要时可单步跟踪程序运行  从提示看，很可能是堆越界了

刚自学就那么厉害啦，膜


Question: 读取文件到链表的问题，希望各位大神帮忙看看

引用 1 楼 qq423399099 的回复:fread(p,sizeof(&p), 8, fq);这个不对吧？感谢！

引用 3 楼 zhao4zhong1 的回复:仅供参考：//将c:\\tmp文件夹下的所有文件的内容全部放到用malloc分配的内存中 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> struct FB {     char fn[256];     size_t fl;     char *b;     struct FB *next;     struct FB *prev; } *fh,*fb,*ft; char ln[256]; char fpn[256]; FILE *af; FILE *f; int L,n; int main() {     system("dir /b /a-d c:\\tmp\\*.* >c:\\allfn.txt");     af=fopen("c:\\allfn.txt","r");     if (NULL==af) {         printf("Can not open file c:\\allfn.txt!\n");         return 1;     }     fh=NULL;     fb=NULL;     n=0;     while (1) {         if (NULL==fgets(ln,256,af)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) ln[L-1]=0;         printf("read %s\n",ln);         strcpy(fpn,"c:\\tmp\\");         strcat(fpn,ln);         ft=(struct FB *)malloc(sizeof(struct FB));         if (NULL==ft) {             printf("Can not malloc ft!\n");             fclose(af);             return 2;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]==%p\n",n,ft);         strcpy(ft->fn,fpn);         f=fopen(fpn,"rb");         if (NULL==f) {             printf("Can not open file %s!\n",fpn);             fclose(af);             return 3;//之前的malloc在main退出后由操作系统自动free         }         ft->fl=_filelength(fileno(f));         ft->b=malloc(ft->fl);         if (NULL==ft->b) {             printf("Can not malloc ft->b!\n");             fclose(f);             fclose(af);             return 4;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]->b==%p\n",n,ft->b);         if (ft->fl!=fread(ft->b,1,ft->fl,f)) {             printf("fread error!\n");             fclose(f);             fclose(af);             return 5;//之前的malloc在main退出后由操作系统自动free         }         fclose(f);         ft->next=NULL;          if (NULL==fh) {             ft->prev=NULL;             fh=ft;         } else {             fb->next=ft;             ft->prev=fb;         }         fb=ft;         n++;     }     fclose(af);     printf("-----list-----\n");     for (ft=fh;NULL!=ft;ft=ft->next) {         printf("%8d %s\n",ft->fl,ft->fn);         if (NULL!=ft) fb=ft;     }     printf("-----free-----\n");     n--;     if (NULL!=fh) {         for (ft=fb->prev;NULL!=ft;ft=ft->prev) {             if (NULL!=ft->next->b) {                 printf("ft[%d]->b==%p\n",n,ft->next->b);                 free(ft->next->b);             }             if (NULL!=ft->next) {                 printf("ft[%d]==%p\n",n,ft->next);                 free(ft->next);             }             n--;         }         if (NULL!=fh->b) {             printf("ft[0]->b==%p\n",fh->b);             free(fh->b);         }         printf("ft[0]==%p\n",fh);         free(fh);     }     return 0; } //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //找不到文件 // //C:\tmp\tmp\Debug>tmp //找不到文件 //-----list----- //-----free----- // //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //2011-06-30  18:04            44,840 my_c.rar //2011-06-30  17:18             1,036 err.frm //2011-06-30  14:32            14,243 出租.txt //2011-06-28  12:08            23,681 MSDN98书签.txt //             4 个文件         83,800 字节 //             0 个目录 17,041,870,848 可用字节 // //C:\tmp\tmp\Debug>tmp //read my_c.rar //ft[0]==00421800 //ft[0]->b==00520068 //read err.frm //ft[1]==00421670 //ft[1]->b==0052AFC0 //read 出租.txt //ft[2]==00421530 //ft[2]->b==00378F28 //read MSDN98书签.txt //ft[3]==004213F0 //ft[3]->b==0052B3F8 //-----list----- // 44840 c:\tmp\my_c.rar //  1036 c:\tmp\err.frm // 14243 c:\tmp\出租.txt // 23681 c:\tmp\MSDN98书签.txt //-----free----- //ft[3]->b==0052B3F8 //ft[3]==004213F0 //ft[2]->b==00378F28 //ft[2]==00421530 //ft[1]->b==0052AFC0 //ft[1]==00421670 //ft[0]->b==00520068 //ft[0]==00421800 // //C:\tmp\tmp\Debug> 谢谢！

引用 2 楼 paschen 的回复:fread(p,sizeof(&p), 8, fq); 中sizeof(&p) 应该是：sizeof(struct zhigong) 吧谢谢！

fread(p,sizeof(&p), 8, fq);这个不对吧？


Question: 求乘方运算程序报错，求助

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

自己写的函数如果出现undefined reference to XXXXXX错误 此时检查下： 1.函数是不是只有声明而没有实现 2.函数的声明和实现是否一致（比如函数名的拼写，参数的个数，类型）

#include<stdio.h> #include<math.h> int main() { 	double calpow(double,double); 	double num,power,answer; 	printf("Please enter tne number you want to calculate it's power:\n"); 	scanf("%lf",&num); 	printf("Please enter hou much power of %f you want to know:\n",num); 	scanf("%lf",&power); 	answer=calpow(num,power); 	printf("The answer is %lf.\n",answer); 	return 0; } double calpow(double num,double power) { 	return pow(num,power); }

answer=pow(num,power);  改成：  int answer=pow(num,power);   #include<stdio.h> #include<math.h> int main() { 	float calpow(float,float); 	float num,power,answer; 	printf("Please enter tne number you want to calculate it's power:\n"); 	scanf("%f",&num); 	printf("Please enter hou much power of %f you want to know:\n",num); 	scanf("%f",&power); 	answer=calpow(num,power); 	printf("The answer is %f.\n",answer); 	return 0; } float calpow(float num,float power) { 	int answer=pow(num,power); 	return answer; }

int calpow(float num,float power,float answer)  改成  float calpow(float num,float power)

float calpow(float,float);    // 只有声明却没有定义  // 定义 与  声明的 函数参数 需要保持一致 int calpow(float num,float power) {     float  answer=pow(num,power);     return answer; }


Question: 关于函数内的一个问题

32位机上sizeof(a)恒为4 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

引用 1 楼 u014444402 的回复:要学会调试啊，函数参数中传递数组会退化成指针，所以你在查找函数里面的长度是不对的。谢谢


Question: 最近学习数据结构，按照例子写了个顺序栈，怎么写都是错的，求大神指教

引用 3 楼 qq423399099 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  提醒的很对，主要我一直搞得java，现在学习c，指针这块还不怎么了解，而且基本用的在线编译...没下什么ide、

引用 1 楼 u012924019 的回复:建议多看C语音基础吧 1. #define 2. 结构体指针 3. ==和=   赋值非初始化 4. 循环打印时i 初始值 修改后代码  #define Max_Size 100  typedef int SElemtype;  typedef struct { 	SElemtype data[Max_Size]; 	int top; }Sqstack;  void init(Sqstack *s) { 	s->top = 0; }   void Push(Sqstack *s, int e) { 	s->top++; 	s->data[s->top] = e; }  int Pop(Sqstack *s, int e) { 	s->top--; 	return s->data[s->top + 1]; }  int main() { 	Sqstack sq; 	int i = 0, j = 0; 	init(&sq);  	for (; i <= 5; i++) 	{ 		Push(&sq, i); 	}  	i = 0; 	for (; i <= 5; i++) 	{ 		j = Pop(&sq, i); 		printf("出栈[%d]\t", j); 	} 	return 0; }   多谢大神，对*和& 这块了解的不是很透彻，看来要抽时间学下了。

如果编译通过了，还是有问题，那么你可以进行单步调试或者在程序中通过使用输出相关变量的方法来找出有问题的语句。ps.建议楼主多看下书吧！感觉你基础的东西都没学清楚。


Question: Gtk+: 界面占据屏幕大小

图形界面已经不多了，还学gtk，

不懂帮顶


Question: 关于C语言文件读取fopen函数的问题

学习受教了，不过每天进步还是太少

引用 2 楼 Tony_cheer 的回复:问题解决谢谢！ 可是我记得新的C99?是可以在使用变量时再定义呀，为何这里不行呢？  VS不支持C99

C99真不支持  http://msdn.microsoft.com/en-us/library/02y9a5ye.aspx  Microsoft C conforms to the standard for the C language as set forth in the 9899:1990 edition of the ANSI C standard.

Microsoft Visual C++ 	Partial[13] 	 Visual C++ 2012 and earlier did not support C99.[28][29][30] Visual C++ 2013 implements a limited subset of C99 required to compile popular open-source projects.[31][32] Visual C++ 2015 implements the C99 standard library, with the exception of any library features that depend on compiler features not yet supported by the compiler (for example, <tgmath.h> is not implemented).[13]

引用 3 楼 Tony_cheer 的回复:@user-4 我查了下，好像也不是完全支持C99,参考

引用 3 楼 Tony_cheer 的回复:@user-4 估计得设置一下编译器吧

变量定义要放最前面


Question: 请问结构体应该怎样排序？

结构体排序和普通的数组排序道理是 一样的。 比较的时候比较的是结构体变量的某个成员。 交换的时候交换的是整个结构体，其他都一样。

引用 1 楼 paschen 的回复:具体没细看，不过for(k=j+1;k<i-1;k++){ 应该是：for(k=j+1;k<i;k++){ 吧  http://blog.chinaunix.net/uid-26404477-id-3086025.html 谢谢，我用冒泡法搞定了，我原意是想有选择排序的，一开始是k<i;，（我忘记改回来了），也不行

仅供参考：//学号 姓名 电话 成绩 //01 XXX 182XXXXXXXX 88 #include <stdio.h> #include <string.h> #define MAXS 10000 struct ST {     int XH;     char XM[11];     char DH[13];     int CJ; } st[MAXS],t; int n,i,j; char ln[80]; FILE *f; int main() {     f=fopen("in.txt","r");     if (NULL==f) {         printf("Can not open file in.txt!\n");         return 1;     }     i=0;     while (1) {         if (NULL==fgets(ln,80,f)) break;         if (4!=sscanf(ln,"%d%10s%12s%d",&st[i].XH,st[i].XM,st[i].DH,&st[i].CJ)) {             st[i].XH=0;             strcpy(st[i].XM,"Unknown");             strcpy(st[i].DH,"Unknown");             st[i].CJ=0;             printf("line %d format error:%s!\n",i+1,ln);         }         i++;         if (i>=MAXS) {             printf(">%d lines Ignored.\n",MAXS);             break;         }     }     fclose(f);     n=i;     for (i=0;i<n-1;i++) {         for (j=i+1;j<n;j++) {             if (st[i].CJ<st[j].CJ) {t=st[i];st[i]=st[j];st[j]=t}         }     }     for (i=0;i<n;i++) {         printf("%5d%10s%12s%4d\n",st[i].XH,st[i].XM,st[i].DH,st[i].CJ);     }     return 0; }


Question: 请教一下动态库和共享库的具体区别，以及.so和.dll的具体区别。

动态链接库 .dll  对应WINDOWS  共享库  .so  对应LINUX  本质差不多，都是动态装载链接  具体可看：《程序员的自我修养——链接、装载与库》

一个是 Linux 家的，一个是 Windows 家的。

库可以有三种使用的形式：静态、共享和动态。静态库的代码在编译时就已连接到开发人员开发的应用程序中，而共享库只是在程序开始运行时才载入，在编译时，只是简单地指定需要使用的库函数。动态库则是共享库的另一种变化形式。动态库也是在程序运行时载入，但与共享库不同的是，使用的库函数不是在程序运行开始，而是在程序中的语句需要使用该函数时才载入。动态库可以在程序运行期间释放动态库所占用的内存，腾出空间供其它程序使用。由于共享库和动态库并没有在程序中包括库函数的内容，只是包含了对库函数的引用，因此代码的规模比较小 PS：以上内容来自http://wenku.baidu.com/link?url=XDxbfNLKv3LwscptyjUEiet2rhI5idQYQD2pgo4OPS--iKZrxRLSfMtTjO0S8j244l3ctaffaVeQGxYz18Fc7jW6gH_1cF4D2hYhngndpNa

.so用objdump查看。  .dll用dumpbin.exe查看。


Question: 初学C语言，自己编了个计算器，带入几组数据没问题，不知道程序是否正确，应该怎样验证。求大神帮忙看看。

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }

多试一些测试用例，特别是边界条件

楼主可以单步调试一下，看看每个值是否都正确，如果都正确，说明你程序就没什么问题了。如果要考虑，就考虑一下程序安全性的问题。(简单的程序基本不用考虑)