Question: 数据结构  递归创建二叉树

楼上的代码需要运行时输入，我希望的是能够自动从一个数组里面读入数据。即在代码里面就有数据，类似与5楼这位哥们的代码

仅供参考：#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

else if (*ch == '#') 要加else  可能还有bug, 你自己试试吧

你参考一下,  1.字符数组最后加了个\n, 用来结束递归   t->lchild=create(ch);     t->rchild=create(ch); 2, 左右child, 在create的时候是同一个ch.  所以需要BTnode *create(const char * &ch), 参数改成引用. 这样递归的时候, 内层ch++的时候, 外层ch也会被修改    #include <stdio.h> #include <stdlib.h>  struct BTnode { 	char data; 	BTnode *lchild; 	BTnode *rchild; };  const char *pCh = NULL;  BTnode *create(const char * &ch)/*建立二叉树*/ { 	BTnode *t; 	if (*ch == '\n') 	{ 		t = NULL; 	} 	if (*ch == '#') 	{ 		t = NULL; 		ch++; 	} 	else 	{ 		t = (BTnode *)malloc(sizeof(BTnode)); 		printf("%c\n", *ch); 		t->data = *ch++; 		t->lchild = create(ch); 		t->rchild = create(ch); 	} 	return t; }  void printTree(BTnode *T) { 	if (T) 	{  		printf("%c", T->data);  		if (T->lchild != NULL) 		{ 			printTree(T->lchild); 		}  		if (T->rchild != NULL) 		{ 			printTree(T->rchild); 		} 	} } int main() { 	const char ch[] = { 'D','E','H','#','#','F','J','#','#', 		'G','#','C','K','#','#','#', 		'A','#','B','#','#', '\n' 	}; 	pCh = ch; 	BTnode *t = create(pCh); 	printTree(t); 	getchar(); 	return 0; }

http://paste.ubuntu.com/10731143/    还是贴代码吧  #include "stdio.h"  #include "malloc.h"  #define M 100  typedef struct node 	{  /* 链式存储的指针类型和结点定义 */ 	   char data; 	   struct node *lchild,*rchild; 	}BTnode;  BTnode *create( const char * ch)/*建立二叉树*/ 	{ 		 BTnode *t; 		if( * ch=='#') 		{ 			 t=NULL; 			 ch++; 		}   		else 		   { 		   t=(BTnode *)malloc(sizeof(BTnode)) ; 		    t->data= *ch; 		    ch++; 		    t->lchild=create(ch); 		    t->rchild=create(ch); 		    } 		  return t; 	} void preorder(BTnode *t)/*先序遍历二叉树*/ 	{ 		 if(t!=NULL) 		 printf("%c ",t->data); 		 if(t->lchild!=NULL) 		 preorder(t->lchild); 		 if(t->rchild!=NULL) 		 preorder(t->rchild); 	 	} void inorder(BTnode *t)/*中序遍历二叉树*/ 	{ 	  if(t!=NULL) 	  { 	    if(t->lchild!=NULL) 	    inorder(t->lchild); 	    printf("%c ",t->data); 	    if(t->rchild!=NULL) 	    inorder(t->rchild); 	  } 	} void postorder(BTnode *t)/*后序遍历二叉树*/ 	{ 	  if(t!=NULL) 	  { if(t->lchild!=NULL) 	    postorder(t->lchild); 	    if(t->rchild!=NULL) 	    postorder(t->rchild); 	    printf("%c ",t->data); 	  } 	} int main() 	{ 		BTnode *t; //		printf("Input data:") ; 		char ch[21]={'D','E','H','#','#','F','J','#','#','G','#','C','K','#','#','#','A','#','B','#','#'}; 		t=create(ch); //		printf("==================The result==========================/n"); 		printf("The preorder is:"); 		preorder(t); 		printf("\n"); 		printf("The inorder is:"); 		inorder(t); 		printf("\n"); 		printf("The postorder is:"); 		postorder(t); 		printf("\n"); 		return 0; 	}

引用 2 楼 xialibaran 的回复:我的思路对吗？ 字符数组末尾应该设一个标志位, 要不然怎么判断没元素了 if( * ch=='#')的时候, 也应该ch++吧

我的思路对吗？

请单步调试.


Question: 关于libevent删除事件的问题（还请大神耐心看下，不胜感激~）

引用 3 楼 zhao4zhong1 的回复:嘿嘿！这分得的轻松哈！  是赵大师的答案给力啊，那个例子很不错

嘿嘿！这分得的轻松哈！

引用 1 楼 zhao4zhong1 的回复:http://www.baigoogledu.com/s.php?hl=zh-CN&q=libevent+%CA%B9%D3%C3   多谢赵大师，我查了下可以使用         release_sock_event(ev);         close(sock);单独关掉client的监听。  非常感谢~~


Question: Ｃ语言求助

引用 14 楼 dumanyi007 的回复:又看到赵老师了，好开心 开心就好！

又看到赵老师了，好开心

引用 11 楼 benben0729 的回复:结果就是有好多错误信息。 偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

结果就是有好多错误信息。

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

# include<stdio.h> void main() { int x,y; x=18; y=16; y=x+y; printf("%d\n",y); return 0; }

好不整齐

#include<stdio.h> void main() {     int x,y; 	x=12;y=13; 	y=x+y;   printf("%d\n",y); } 你把我这个重敲一遍，你那个中间写的有点问题，我编译不出来，估计中间英汉你交替了，特别是int那行，重新敲次

最后一句没分号！终结此贴！

你想干什么，代码敲错了

y=x+y 是把x+y后的值再赋给y，而不是数学意义上的相等

引用 2 楼 adusuccessfully 的回复: #include <stdio.h> void main() { 	int  x,y; 	x=18; 	y=16; 	y=x+y; 	printf("%d\n",y); }  请问楼主要验证什么？？+1

无语......


Question: c语言编程求助

文件操作~~~

可以直接用VS生成个简单的MFC然后自己加些功能。

网上一大把。自己找去吧


Question: 求C语音程序，关于编码译码，或者调制解调的

参考ffmpeg库？bass库？


Question: c语言图形化界面问题

打开visual studio，新建项目，c++→win32→win32应用程序→确定→生成项目 →运行。 至于添加其它东西可以百度 win32+关键词

仅供参考：#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }


Question: 指针在内存中的存储问题

32位系统中使用大于4GB内存的多了去了。

引用 6 楼 wlcshh 的回复:[quote=引用 5 楼 u014238422 的回复:]        我说说我的理解吧！        首先指针的大小是和系统位数相关的，一般是32位操作系统占4个字节，64位操作系统8个字节，用来给内存地址编号。        在32位操作系统上指针占4个字节，可以为内存寻址的最大范围为2^32，也就是最多只能2^32这么大的内存空间，这也是为什么32位操作系统就算你安装超过4GB的内存条，它也只会最多读取到小于4GB的大小。在64位操作系统上，理论上最大的寻址范围是2^64，但由于硬件处理技术上的瓶颈问题，也不可能真正达到这么大，一般都是16GB（应该比这个还要小很多）。        虽然理论上4字节指针的内存空间大小为2^32，但我所说的大小并不是你所说的大小，而是最大寻址的范围为2^32。        本人愚见，希望对你有帮助！  其实我问的就是寻址，豁然开朗，怪不得32位系统最大支持4G内存 你比他们强多了，却那么谦虚[/quote]  忠言逆耳利于行，良药苦口利于病

这就是为什么说的32位地址总线的内存瓶颈是4g。

32位系统下你能申请2G内存就不错了

指针是放的内存地址，4个字节表示32位，可以存储2的32次方以内的地址范围

指针在内存中都是4个字节，这就是一个内存地址。

指针占四个字节  就像一个int类型的变量在32位系统占四个字节一样     并不是表示存储的最大空间！

引用 5 楼 u014238422 的回复:我说说我的理解吧！        首先指针的大小是和系统位数相关的，一般是32位操作系统占4个字节，64位操作系统8个字节，用来给内存地址编号。        在32位操作系统上指针占4个字节，可以为内存寻址的最大范围为2^32，也就是最多只能2^32这么大的内存空间，这也是为什么32位操作系统就算你安装超过4GB的内存条，它也只会最多读取到小于4GB的大小。在64位操作系统上，理论上最大的寻址范围是2^64，但由于硬件处理技术上的瓶颈问题，也不可能真正达到这么大，一般都是16GB（应该比这个还要小很多）。        虽然理论上4字节指针的内存空间大小为2^32，但我所说的大小并不是你所说的大小，而是最大寻址的范围为2^32。        本人愚见，希望对你有帮助！  其实我问的就是寻址，豁然开朗，怪不得32位系统最大支持4G内存 你比他们强多了，却那么谦虚

指针的内存空间，还有这说法？你是说指针能指向的内存范围吧。32位系统的内存就是2^32，任何指针变量都占据4个字节，就是32位，这样就可以指向所有的内存空间了。我是这么理解的，不知道对不对

char* 指针类型是4个字节，这个指针变量的值是4个字节，而指针的值是内存地址，所以指针的值的区间是2的32次方

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

是不是就意味着存储char指针地址的内存空间最大只可能是0xFFFFFFFF=4294967295字节？


Question: fopen打不开文本本件，返回空指针，是什么情况

把编码方式变成mbcs 即：“使用多字节字符集”  操作步骤：右键项目-属性-配置属性-常规-字符集  代码(断点测试)： char* filename="F:\\sn.txt"; FILE* hFile; if ((hFile = _tfopen((char*)filename, _T("rb"))) == NULL)   { } else { }

看看文件是否存在，是否有权限读写 最直接的就是把错误码打印出来

调试看文件路径是否正确

应该是文件没找到吧，捕捉一下错误。

你没输入文件路径？参照3楼输入，或者直接把文件路径写在代码中，如：  fp=fopen(“filepath”, "r")

VC6：  工程、设置、Debug、U程序变量：填写命令行参数。 VS20XX：  项目、属性、配置属性、调试、命令参数：填写命令行参数。

最关键的是，你的路径对不对， 给的相对路径还是绝对路径。 文件名给对没有， 或者把权限rw改成， 文件不存在就创建。  或者，不用命令行参数， 先给个固定的文件地址去打开看，再找到原因。


Question: c++遍历目录下所有指定格式的文件

system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。

引用 5 楼 liu15073458538 的回复:   大神，我用VS10好像不行诶！ 将UNICODE改为多字节, 或者将char改为TCHAR

引用 3 楼 ForestDB 的回复:find /path/to/directory -name '*.off' >output.txt 这个是在windows下使用的吗？

大神，我用VS10好像不行诶！

用cmd多省事 if exist paths.txt (del paths.txt) for /r %i in (*.off) do @echo %~fi >> paths.txt

DirectoryTraverser.h #pragma once #include <windows.h>  #ifndef __in #define __in #endif  #ifndef __out #define __out #endif  typedef void(*TraverseCallback)(const LPWIN32_FIND_DATAA, void*); class CDirectoryTraverser { public: 	CDirectoryTraverser(__in TraverseCallback callback); 	~CDirectoryTraverser();  private: 	bool IsDirectory(__in const char*); 	void RecurringTraverse(__in const char*); 	TraverseCallback fTraverseCallback_; 	void* p_user_data_; 	char c_str_type_[MAX_PATH];  public: 	bool Traverse(__in const char*, __in void* p_user_data); 	void SetType(__in const char*); }; DirectoryTraverser.cpp #include "DirectoryTraverser.h" #include <iostream>  CDirectoryTraverser::CDirectoryTraverser(__in TraverseCallback callback) 	: fTraverseCallback_(callback) 	, p_user_data_(NULL) { 	memset(c_str_type_, 0, MAX_PATH); }  CDirectoryTraverser::~CDirectoryTraverser() { }  bool CDirectoryTraverser::Traverse(__in const char* c_str_path, __in void* p_user_data) { 	p_user_data_ = p_user_data; 	if (!IsDirectory(c_str_path)) 		return false; 	RecurringTraverse(c_str_path); 	return true; }   bool CDirectoryTraverser::IsDirectory(__in const char* c_str_path) { 	HANDLE hFind = INVALID_HANDLE_VALUE; 	WIN32_FIND_DATAA wfd = { 0 };  	hFind = FindFirstFile(c_str_path, &wfd); 	if (INVALID_HANDLE_VALUE == hFind) 		return false;  	if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 		return true; 	else 		return false; }   void CDirectoryTraverser::RecurringTraverse(__in const char* c_str_path) { 	if (c_str_path == NULL) 		return;  	HANDLE hFind = INVALID_HANDLE_VALUE; 	WIN32_FIND_DATAA wfd = { 0 }; 	char c_str_path_buf[MAX_PATH] = { 0 }; 	if (c_str_type_[0] == 0) 		sprintf_s(c_str_path_buf, MAX_PATH, "%s\\*", c_str_path); 	else 		sprintf_s(c_str_path_buf, MAX_PATH, "%s\\*.%s", c_str_path, c_str_type_);  	hFind = FindFirstFile(c_str_path_buf, &wfd); 	if (INVALID_HANDLE_VALUE == hFind) 		return;  	do 	{ 		if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 		{ 			if (strcmp(wfd.cFileName, ".") != 0 				&& strcmp(wfd.cFileName, "..") != 0) 				RecurringTraverse(wfd.cFileName); 		} 		else if (fTraverseCallback_) 			fTraverseCallback_(&wfd, p_user_data_); 		else 			break; 	} while (FindNextFile(hFind, &wfd) != 0);  	FindClose(hFind); }  void CDirectoryTraverser::SetType(__in const char* str_type) { 	strcpy_s(c_str_type_, MAX_PATH, str_type); }  test.cpp #include "DirectoryTraverser.h"  static void TraverserDirectoryCallback(LPWIN32_FIND_DATAA p_wfd, void* p_user_data) { 	printf(_T("%s\r\n"), p_wfd->cFileName); }  int _tmain(int argc, _TCHAR* argv[]) { 	CDirectoryTraverser dt(TraverserDirectoryCallback); 	dt.SetType("otf"); 	bool b_result = dt.Traverse("C:\\Windows\\Fonts", NULL); 	if (b_result) 		printf(_T("Traverse Successful\r\n")); 	else 		printf(_T("Traverse Failed\r\n"));  	system("pause"); 	return 0; }

给个例子参考，我这里是遍历C:\test目录及其子目录下所有的.txt文件，然后将txt文件的路径保存在C:\fileinfo.txt文件中 #define _AFXDLL #include <afx.h> #include <fstream> using namespace std;  void MyFindFile(CString strPath,CString strType,fstream& fs) { 	CFileFind fd; 	CString strDir=strPath+"\\*.*"; 	bool bRet=true; 	bRet=fd.FindFile(strDir,0); 	while(bRet) 	{ 		bRet=fd.FindNextFile(); 		if(fd.IsDots()) 		{ 			continue; 		} 		if(fd.IsDirectory()) 		{ 			MyFindFile(fd.GetFilePath(),strType,fs); 		} 		else 		{ 			CString strTemp=fd.GetFilePath(); 			char buf[1024]={0}; 			strcpy(buf,strTemp.GetBuffer()); 			strTemp.ReleaseBuffer(); 			if(strTemp.Right(strType.GetLength()).Compare(strType)==0) 			{ 				fs<<buf<<endl; 			} 		} 	}  	fd.Close(); } void main() { 	CString strPath="C:\\test"; 	CString strType=".txt"; 	fstream fs("C:\\fileinfo.txt",fstream::out); 	if(fs) 	{ 		MyFindFile(strPath,strType,fs); 		fs.close(); 	} }


Question: for循环下scanf函数中止问题

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”   代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

链表的增删改：供参考！ 链表的“增删改” 过程：输入链表长度，判断长度是否大于0，循环创建结点，判断头结点是否为空，若为空将新结点追加其后，若不为空，则输入结点信息，将指针域置空，并将该结点地址赋给上一结点的指针域，移动上个指针至新结点，重新申请新空间，返回头结点。 #include <stdio.h> #include <stdlib.h> struct node*creat(struct node *head); void Output(struct node *head); void Insert(struct node *head,int k); void Delete(struct node *head,int j); void Replace(struct node *head,int n); struct node {  	int data; 	struct node *next; }; int main(){      int a,b,c,d; 	struct node *head; 	head=NULL;   	head=creat(head);//新建链表 	Output(head);   	do{ 		printf("\n"); 		printf("请选择您要进行的操作：\n"); 		printf("----------------------------------------\n"); 		printf("1.添加新结点\n"); 		printf("2.删除结点\n"); 		printf("3.修改结点数据\n"); 		printf("4.退出\n"); 		printf("----------------------------------------\n"); 		printf("\n"); 		printf("请选择："); 		scanf("%d",&d);  	switch(d) 	{ 		case 1: 			printf("您选择了添加新结点\n"); 	       printf("请输入要插入结点位置:");//插入新结点 	       scanf("%d",&a); 	       Insert(head,a); 	       Output(head); 		   break; 		case 2: 			printf("您选择了删除结点\n"); 	       printf("请输入要删除的结点:");//删除结点 	       scanf("%d",&b); 	       Delete(head,b); 	       Output(head); 		   break; 		case 3: 			printf("您选择了修改结点数据\n"); 	       printf("请输入要修改结点的位置:");//修改结点数据            scanf("%d",&c); 	       Replace(head,c); 	       Output(head); 		   break; 		case 4: 			break; 	} 	}while(d!=4);  	//printf("\n"); 	//printf("请输入要插入结点位置:");//插入新结点 	//scanf("%d",&a); 	//Insert(head,a); 	//Output(head);  	//printf("\n"); 	//printf("请输入要删除的结点:");//删除结点 	//scanf("%d",&b); 	//Delete(head,b); 	//Output(head);   	//printf("\n"); 	//printf("请输入要修改结点的位置:");//修改结点数据 	//scanf("%d",&c); 	//Replace(head,c); 	//Output(head);  	return 0; } struct node *creat(struct node *head){  	int i,LEN; 	struct node *p,*s; 	printf("请输入链表的长度："); 	scanf("%d",&LEN); 	 	if(LEN>=1){ 		for(i=1;i<=LEN;i++){		           p=(struct node *)malloc(sizeof(struct node *)); 			 			if(head==NULL) 				s=head=p; 			printf("请输入第%d个结点中的数据：",i); 			scanf("%d",&p->data); 			p->next=NULL; 			s->next=p; 			s=p; 		} 	}return (head); } void Output(struct node *head){  	struct node *temp; 	temp=head; 	printf("新链表如下："); 	while(temp!=NULL){ 	 		printf("%d->",temp->data); 		temp=temp->next; 	} }  void Insert(struct node *head,int k){  	struct node *p1,*p2,*p3; 	int i; 	p3=p1=head; 	for(i=1;i<k;i++){ 		p1=p1->next; 	} 		for(i=1;i<k-1;i++){ 		p3=p3->next; 	} 	p2=(struct node *)malloc(sizeof(struct node)); 	printf("请输入新结点的数据："); 	scanf("%d",&p2->data); 	p2->next=p1; 	p3->next=p2; }  void Delete(struct node *head,int j){  	int i; 	struct node *p1,*p2,*p3; 	p1=p2=p3=head; 	for(i=1;i<=j;i++){ 		p2=p2->next; 	} 	/*p1->next=NULL; 	p3=p2->next; 	free(p2); 	p1->next=p3;*/  		for(i=1;i<j-1;i++){ 		p1=p1->next; 	} 			for(i=1;i<j+1;i++){ 		p3=p3->next; 	} 			p1->next=p3; 			//free(p2); }  void Replace(struct node *head,int n){  	int i,m; 	struct node *p; 	p=head; 	for(i=1;i<n;i++){ 		p=p->next; 	} 	printf("请输入该结点的新数据："); 	scanf("%d",&m); 	p->data=m; 	//free(p);  }

while(scanf("%d %d",&i,&j)!=EOF);

运行时在命令行情况下输入没法中止


Question: 这个求两点距离的c源码有什么问题么？运行出错？

蒽，前辈说得对，我发现自己的错误了~

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

#include <stdio.h> #include <math.h> double distance(double x1, double y1, double x2, double y2); int main() {     int n;     double x1,y1,x2,y2;     double d[100]};     while (1) {         printf("please input the total group number(1..100)\n");         rewind(stdin);         scanf("%d",&n);         if (1<=n && n<=100) break;     }     printf("please input the numbers\n");     for (int i=0;i<n;i++)     {         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);         d[i]=distance(x1,y1,x2,y2);     }     for (int a=0;a<n;a++)         printf("%.4lf\n",d[a]);     return 0; } double distance(double x1, double y1, double x2, double y2) {     return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); }


Question: c

引用 2 楼 zhao4zhong1 的回复:自己写代码搞不清楚算符优先级请多加括号。 看别人代码搞不清楚算符优先级能调试的话请单步调试对应汇编。 看别人代码搞不清楚算符优先级不能调试的话想办法照写一小段孤立的可调试的代码然后单步调试对应汇编。 看别人代码搞不清楚算符优先级不能调试的话且没有办法照写一小段孤立的可调试的代码然后单步调试对应汇编的话只能参考算符优先级表猜了（提醒：并不能100%猜对）。 //C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

引用 1 楼 user-3 的回复:第一步：m = j % k 第二步：k = k + 1

第一步：m = j % k 第二步：k = k + 1


Question: c语言运行问题

先编译，再运行 gcc *.c  ./a.out 如果是在windows上面，会有开发环境的，它为你提供了编译和执行的按钮

引用 5 楼 adusuccessfully 的回复: #include "stdio.h" #include "stdlib.h" #define MAXSIZE 100 typedef  int  ElemType;  typedef  struct {   	ElemType elem[MAXSIZE];    	/*数组域*/ 	int  length;               	 /*线性表长域*/ } Sqlist;                    	 /*结构体类型名*/   void outlin(Sqlist s);  	    /*此处参数必须与下边函数说明一致*/ void creat( Sqlist *v); void insert(Sqlist *v,int i,int x); void del(Sqlist *v,int i);  void main( ) {   	Sqlist pz; 	int i,y,cord; 	do  	{   		printf("\n      主菜单   \n")  ; 		printf("    1   建立线性表  \n"); 		printf("    2   插入一个元素 \n"); 		printf("    3   删除一个元素 \n");  		printf("    4   结束程序运行 \n"); 		printf("-----------------------------\n"); 		printf(" 请输入您的选择(1， 2， 3， 4) "); 		scanf("%d",&cord);  		switch (cord) 		{   			case 1: 				{   					creat(&pz); outlin(pz); 				} break; 			case 2: 				{   					printf("\n 请输入插入的位置 i ，数据 x ："); 					scanf("%d%d",&i,&y); 					insert(&pz,i,y); 					outlin(pz); 				} break; 			case 3 : 				{  					printf("\n 请输入删除的位置 i:"); scanf("%d",&i); 					del(&pz,i);   					outlin(pz); 				}  break; 			case 4 :  				exit(0); 		} 	} while (cord<=4 ); } /*  main  end  */   void  outlin(Sqlist s) {   	int  i,j; 	for (i=1; i<=s.length; i++) 	printf("\n %2d  %6d",i,s.elem[i]); } /* outlin  end */   void  insert(Sqlist *v,  int i,  ElemType x) {  	int j; 	if((i<0)||(i>v->length))    		printf("\n   Error！"); /*插入位置出错*/ 	else  	{ /* 向后移动数据元素 */ 		for (j=v->length-1; j>=i; j--)   			v->elem[j+1]=v->elem[j]; 		v->elem[j]=x;              	/*插入元素*/ 		v->length ++;              	/*线性表长度加1*/ 	} }  /*  insert end   */  void del(Sqlist *v,int i) {  	int j; 	if ((i<0) || (i > v->length-1))  		printf("\n  Not exist!"); 	else   	{  /* 向前移动数据元素 */ 		for (j=i;j< v->length-1;j++) 			v->elem[j]=v->elem[j+1]; 		v->length--;  /* 线性表长度减1  */ 	} } /*  delete  end  */  void creat(Sqlist *v) {   	int  i,j; 	printf("\n n= "); scanf("%d",&(v->length)); 	for(i=0; i<v->length; i++)   	{   		printf("\n data= "); 		scanf("%d",&(v->elem[i])); 	}  }   /*  creat  end  */   1、楼主的delete函数与关键字delete相同，应换一个函数名； 2、楼主的main函数应有返回值类型，无返回值也要有void； 3、楼主的程序有缩进换行的话，会易读些……  小问题：  void  outlin(Sqlist s) { 	int  i, j; 	//for (i = 1; i <= s.length; i++) 	//	printf("\n %2d  %6d", i, s.elem[i]); 	for (i = 1; i <= s.length; i++) 		printf("\n %2d  %6d", i, s.elem[i - 1]); } /* outlin  end */

楼主来干嘛的

不是本人做的，是一道作业，怎么运行啊。

这是你自己写的代码吗？

运行出来怎么做啊

链表的创建以及增删改，供参考！ 链表的“增删改”  #include <stdio.h> #include <stdlib.h> struct node*creat(struct node *head); void Output(struct node *head); void Insert(struct node *head,int k); void Delete(struct node *head,int j); void Replace(struct node *head,int n); struct node {  	int data; 	struct node *next; }; int main(){      int a,b,c,d; 	struct node *head; 	head=NULL;   	head=creat(head);//新建链表 	Output(head);   	do{ 		printf("\n"); 		printf("请选择您要进行的操作：\n"); 		printf("----------------------------------------\n"); 		printf("1.添加新结点\n"); 		printf("2.删除结点\n"); 		printf("3.修改结点数据\n"); 		printf("4.退出\n"); 		printf("----------------------------------------\n"); 		printf("\n"); 		printf("请选择："); 		scanf("%d",&d);  	switch(d) 	{ 		case 1: 			printf("您选择了添加新结点\n"); 	       printf("请输入要插入结点位置:");//插入新结点 	       scanf("%d",&a); 	       Insert(head,a); 	       Output(head); 		   break; 		case 2: 			printf("您选择了删除结点\n"); 	       printf("请输入要删除的结点:");//删除结点 	       scanf("%d",&b); 	       Delete(head,b); 	       Output(head); 		   break; 		case 3: 			printf("您选择了修改结点数据\n"); 	       printf("请输入要修改结点的位置:");//修改结点数据            scanf("%d",&c); 	       Replace(head,c); 	       Output(head); 		   break; 		case 4: 			break; 	} 	}while(d!=4);  	//printf("\n"); 	//printf("请输入要插入结点位置:");//插入新结点 	//scanf("%d",&a); 	//Insert(head,a); 	//Output(head);  	//printf("\n"); 	//printf("请输入要删除的结点:");//删除结点 	//scanf("%d",&b); 	//Delete(head,b); 	//Output(head);   	//printf("\n"); 	//printf("请输入要修改结点的位置:");//修改结点数据 	//scanf("%d",&c); 	//Replace(head,c); 	//Output(head);  	return 0; } struct node *creat(struct node *head){  	int i,LEN; 	struct node *p,*s; 	printf("请输入链表的长度："); 	scanf("%d",&LEN); 	 	if(LEN>=1){ 		for(i=1;i<=LEN;i++){		           p=(struct node *)malloc(sizeof(struct node *)); 			 			if(head==NULL) 				s=head=p; 			printf("请输入第%d个结点中的数据：",i); 			scanf("%d",&p->data); 			p->next=NULL; 			s->next=p; 			s=p; 		} 	}return (head); } void Output(struct node *head){  	struct node *temp; 	temp=head; 	printf("新链表如下："); 	while(temp!=NULL){ 	 		printf("%d->",temp->data); 		temp=temp->next; 	} }  void Insert(struct node *head,int k){  	struct node *p1,*p2,*p3; 	int i; 	p3=p1=head; 	for(i=1;i<k;i++){ 		p1=p1->next; 	} 		for(i=1;i<k-1;i++){ 		p3=p3->next; 	} 	p2=(struct node *)malloc(sizeof(struct node)); 	printf("请输入新结点的数据："); 	scanf("%d",&p2->data); 	p2->next=p1; 	p3->next=p2; }  void Delete(struct node *head,int j){  	int i; 	struct node *p1,*p2,*p3; 	p1=p2=p3=head; 	for(i=1;i<=j;i++){ 		p2=p2->next; 	} 	/*p1->next=NULL; 	p3=p2->next; 	free(p2); 	p1->next=p3;*/  		for(i=1;i<j-1;i++){ 		p1=p1->next; 	} 			for(i=1;i<j+1;i++){ 		p3=p3->next; 	} 			p1->next=p3; 			//free(p2); }  void Replace(struct node *head,int n){  	int i,m; 	struct node *p; 	p=head; 	for(i=1;i<n;i++){ 		p=p->next; 	} 	printf("请输入该结点的新数据："); 	scanf("%d",&m); 	p->data=m; 	//free(p);  }


Question: Openssl 如何获取ECC  sm2证书公钥数据？

可以的，直接解析X509，把公钥拿出来重写一下就行了。粘几行关键代码吧，希望对受困扰的小伙伴有用         x = strToX509(pbCert, pulCertLen); 	dwRet = getCertPubKey(x, &pRSAPubKeyBlob, &pECCPubKeyBlob); 	ECCPUBLICKEYBLOB  pec = { 0 };//目标公钥 	pec.BitLen = 256; 	int i = 0; 	for (i = 0; i < 64; i++){ 		if (i <= 31){ 			pec.XCoordinate[i] = 0; 			pec.YCoordinate[i] = 0; 		} 		else{ 			pec.XCoordinate[i] = pECCPubKeyBlob.XCoordinate[i - 32]; 			pec.YCoordinate[i] = pECCPubKeyBlob.YCoordinate[i - 32]; 		} 	} 其实就是公钥结构解析的问题，SM2公钥所需要的格式和X509解析出来的X,Y位置是颠倒的，要求的结果是X,Y数组前32为0；而X509提供的为后32为0，正好颠倒了。

具体怎么解析公钥呢，最近也在搞这个，用openssl好像不行。

有两种方案，比较简单的一种是自己封个接口去cert_info的pub_key里读data解析，另一种就是通过get_pubkey接口了，不过这个需要加入sm2的曲线参数，算法oid也要加，因为sm2和Openssl的ecc不太一样，中间还要改一些东西，一步一步的调试跟下来

我最近也有这个问题，但说实话，ECC没人或没几个人能说的清楚。  网上的东西，都搬来搬去。  比如，最大的问题就是ECC算法的非对称加密解密。  网上根本没人谈及到过。

ecc的过程与rsa相比有很大的不同，ecc涉及到了很多额外的概念，比如group等等，另外ecc包含两套截然不同的机制ecdh ,ecdsa struct ec_key_st {     int version;     EC_GROUP *group;       EC_POINT *pub_key;       BIGNUM     *priv_key;      unsigned int enc_flag;     point_conversion_form_t conv_form;     int     references;     EC_EXTRA_DATA *method_data; } /* EC_KEY */;


Question: 菜鸟又来啦！！！如何把歌曲文件放到c对话框程序中

DirectShow 呵呵

我引入到 资源中了，然后用 palysound 播放 老显示这个 问题   'PlaySoundA' : cannot convert parameter 1 from 'const int' to 'const char *'  ，我的语句是这样子的    	PlaySound(IDR_WAVE1,NULL,SND_RESOURCE);

引用 3 楼 zhao4zhong1 的回复:打包到资源中。  老师，怎么打包到资源中呀/?新手勿喷

C语言对话框？ 对话框是MFC的吧？

打包到资源中。

我顶！ 大神快粗线


Question: 关于库函数的一点疑问

引用 11 楼 my_live_123 的回复: If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.  嗯嗯，就像http://blog.csdn.net/heyabo/article/details/8745942这里面讲的确实是未定义行为。和编译器相关吧。

应该是这样的，由编译器自己按自己方式来处理。

引用 12 楼 E_Herohawk 的回复:[quote=引用 11 楼 my_live_123 的回复:]  If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.  嗯嗯，就像http://blog.csdn.net/heyabo/article/details/8745942这里面讲的确实是未定义行为。和编译器相关吧。[/quote]   标准里说未定义，那意思就是交个编译器自己处理吧，想怎么处理就怎么处理

引用 10 楼 u012436960 的回复:[quote=引用 9 楼 E_Herohawk 的回复:] 回一楼：在VC6.0下试了一下将const指针赋给非const指针，完了再操作确实可以。那会不会是strcpy这个库函数里有一个指针转换的过程。大侠说的“代码可以无视它”能说明白一点么，嘿嘿，有些不明白。 回二楼：嗯，const是修饰只读的，我们程序员不能对const修饰的变量赋值，但调用该库函数就可实现，其实我是想知道strcpy这个库函数的具体实现方法。通过一楼我有个猜想，会不会就像我回一楼的那样。 回六楼：你这个测试代码在VC6.0下编译通过无警告并运行正常。 回七楼：const修饰的变量不就放在只读存储区么，这不对么。  你可以看一下strcpy的声明：  char *strcpy(    char *strDestination,    const char *strSource  );  strDestination的类型是char*,而不是const char*,与我的代码类似，都是将类型为const type*的值传入参数类型为type*的函数,这种情况编译是可以通过的。[/quote] strcpy是将后一个参数传入的值赋给第一个参数，改变的是第一个的值，后一个没动，你的函数传入的参数是const型，但在函数f内部，参数值被改变。还是感谢大家的解答，这种问题吧，写程序的时候最好不要出现，一般都不会这么做，既然声明为const，那就是不希望改变其值了，我只是闲来没事试一下。

引用 9 楼 E_Herohawk 的回复:回一楼：在VC6.0下试了一下将const指针赋给非const指针，完了再操作确实可以。那会不会是strcpy这个库函数里有一个指针转换的过程。大侠说的“代码可以无视它”能说明白一点么，嘿嘿，有些不明白。 回二楼：嗯，const是修饰只读的，我们程序员不能对const修饰的变量赋值，但调用该库函数就可实现，其实我是想知道strcpy这个库函数的具体实现方法。通过一楼我有个猜想，会不会就像我回一楼的那样。 回六楼：你这个测试代码在VC6.0下编译通过无警告并运行正常。 回七楼：const修饰的变量不就放在只读存储区么，这不对么。  你可以看一下strcpy的声明：  char *strcpy(    char *strDestination,    const char *strSource  );  strDestination的类型是char*,而不是const char*,与我的代码类似，都是将类型为const type*的值传入参数类型为type*的函数,这种情况编译是可以通过的。

没有不能修改的内存，const只是在编译时的一个标记

编译器内部的实现

const 只是在编译时做检查的，运行时你直接修改的是内存，除非你的const变量存放的内存区域在只读存储区（实际就是代码区）

#include<stdio.h> void f(int *n) {     if(n)*n=6; } int main() {     const int a=3;     printf("%d\n",a);     f(&a);     printf("%d\n",a);     return 0; }  楼主可以试一下，通常会有个warning。

不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！

编译器的锅~

首先字符串数组的赋值只能在初始化数组时 进行赋值， 之后是不能直接赋值的， 要想赋值只能使用库函数strcpy， memcpy等来进行赋值， 这跟const没有关系， const在C中修饰的 变量 表示不可修改的， 也是个变量，在C++中是产量，  列如：  Int  const *a = 1；         int * const b = 1；                 a++；               b++；错误          *a++；错误           *b++；

C\C++里面，const指针是可以强制转换成非const指针的，不是吗？ const修饰符只是让编译器检查用的，代码完全可以无视它。总之，没有不能修改的内存。


Question: win7系统日志校验和分析

我就看看不说话了


Question: 以每行一个单词打印其输出

为什么不选下面简单的呢？#include <stdio.h> int main(void) { int c; int state = 0;  while((c = getchar())!= EOF) {       if(c == '\n' || c== ' ' || c == '\t')       {    putchar('\n');          } else { putchar(c); } } return 0; }

这格式看着真难受。。。

#include <stdio.h> int main(void) { 	int c; 	int state = 0;  	while((c = getchar())!= EOF) 	{ 	      if(c == '\n' || c== ' ' || c == '\t') 	      { 		   putchar('\n'); 	         } 		else 		{ 			putchar(c); 		} 	} 	return 0; } 没那么麻烦 ， 吧问题简单化，这样子要还不能理解也没办法了

运行试试，就知道了

先不说程序，弄个例子试下，比如输入abcd    cde 很明显应该输出两个单词 abcd cde 两个单词之间的分隔符可以是空格、TAB和换行符，两个单词中间可以有多个分隔符，那么遇到分隔符的时候，可能是一个单词输入结束了，也可能就是上个分隔符的继续，就是多个分隔符，那怎么判断本次是一个单词的结束还是分割符的继续呢？ 可以用一个状态记录。如果用户输入了一个普通字符，那就认为当前状态“输入单词”；如果遇到了分隔符，那就设置状态为分隔符，并且如果当前状态是“输入单词”，那就说明这个单词输入结束了。  #include<stdio.h> #define OUT 0 #define IN 1 main(){     int c,state;     state=OUT;     while((c=getchar())!=EOF){         if(c==' '||c=='\n'||c=='\t'){   // 遇到了分隔符             if(state==IN){               // 当前状态为正在输入单词，说明单词输入结束了                 putchar('\n');                  state=OUT;            // 设置状态为分隔符             }         }else if(state==OUT){  // 如果是普通字符且状态是分隔符状态             state=IN;                   // 一个新单词开始了             putchar(c);         } else                             // 普通字符，状态不需要更新         putchar(c);     }    }


Question: 求一些C语言面试题和答案

搜索里搜 面试题

百度 里搜 面试题

抛砖引玉  http://blog.csdn.net/hackbuteer1/article/details/6550824  http://wenku.baidu.com/link?url=EGdiKsrkjMmwpfUvh27xcoTZADrIEZa35FE6k0kT0LmdFx9va-J0jrKiL_I5fG3WyBgutVaqIxy4nXfbesadeUP8PD5iFn0p1OORnQeCMIi

下面是本人今年参加笔试遇到的试题： 2015百度，腾讯，新浪，美团，360，去哪儿网，迈瑞，展讯通信，杰发科校园招聘笔试题（软件开发类） http://download.csdn.net/detail/adusuccessfully/8096019


Question: 关于c语言的const问题

const char *p  表示char *的内容不可以被修改。  char * const p  表示p不可以被修改，永远只能指向这个位置。  const 靠近哪个表示哪个不能被修改。  编译器会把const修饰的变量放在只读区域。在MMU的系统上，会在cpu中的虚拟地址到物理地址的内存描述符中设置read only属性。在没有mmu的系统上，没有实际的意义，只能作为编译器的提醒作用。

C专家编程 里面说过 某个变量加了const这个关键字。表示限制这个符号不能够修改。但是并不代表不可以通过其它的方法来修改  const char a='a';//在这里const只是用来限制变量名为a这个符号不能改。 char *p=(char*)&a;//这里不存在问题 *p='b';  只不过在C++里面const又是另外一种解释。在C语言里面const只是把变量作为一个只读变量。但是说到底还是变量。在C++里面用const修改的变量。就只只是常量。不能通过更改。上面的代码如果是C++编译器。结果是a的值不变。如果是C编译器。变量a的值会变为'b'。 楼主可以去看看C专家编程。里面有说过这个问题。

引用 7 楼 q328965539 的回复:[quote=引用 3 楼 Falleyes 的回复:] a不是指向const数据，所以a可以修改数据内容。 b声明为const char* b=a;意思是说不能通过b这个指针改变其所指向的数据。跟a能不能修改没有关系。 有深层次点的解释么，我是想知道为什么不能通过b这个指针改变其所指向的数据？ 内部是不是const指定那块内存为只读的？（事实证明那块内存还是可读写的） 还是用const去限制了这个指针去读那块内存？那又是怎么限制的，这机制怎么实现的？[/quote] const更多的意义是用于语法检查。在C语言的实现里，一般真正不可修改的只有字符常量这类位于常量内存区的数据（当然内存读写控制需要CPU和操作系统支持）。 一般比如我们写memcpy这样功能的函数，源地址const指针，目标地址是普通指针。这样就能防止我们代码中的bug导致不小心修改了源内存。 另外像const char *p= “abc"; 这样的，如果写成char *p=”abc“，就会有隐患。如果我们程序不小心修改了"abc”的内存，这个编译器就检查不出来。只能等到程序运行时发生段错误，然后死得很难看了。（对于DOS等环境，甚至不会有段错误，程序的bug更隐蔽）

const & 指针  　　类型声明中const用来修饰一个常量，有如下两种写法，那么，请问，下面分别用const限定不可变的内容是什么?  　　1)、const在前面  　　const int nValue； //nValue是const  　　const char *pContent; //*pContent是const, pContent可变  　　const (char *) pContent;//pContent是const,*pContent可变  　　char* const pContent; //pContent是const,*pContent可变  　　const char* const pContent; //pContent和*pContent都是const  　　2)、const在后面，与上面的声明对等  　　int const nValue； // nValue是const  　　char const * pContent;// *pContent是const, pContent可变  　　(char *) const pContent;//pContent是const,*pContent可变  　　char* const pContent;// pContent是const,*pContent可变  　　char const* const pContent;// pContent和*pContent都是const  　　答案与分析：  　　const和指针一起使用是C语言中一个很常见的困惑之处，在实际开发中，特别是在看别人代码的时候，常常会因为这样而不好判断作者的意图，下面讲一下我的判断原则：  　　当const所在代码段中不包含括号时，沿着*号划一条线，如果const位于*的左侧，则const就是用来修饰指针所指向的变量，即指针指向为常量；如果const位于*的右侧，const就是修饰指针本身，即指针本身是常量。你可以根据这个规则来看上面声明的实际意义，相信定会一目了然。  　　另外，需要注意：对于const (char *) ; 因为char *是一个整体，相当于一个类型(如 char)，因此，这时限定指针是const。  　　一个简单的判断方法：指针运算符*，是从右到左，那么如：char const * pContent，可以理解为char const (* pContent)，即* pContent为const，而pContent则是可变的。

上面打错，是const char* const b

你那种情况是表示指针指向的地址是常量，而不是该地址的内容  const char const* b  就连指向地址的内容也要是常量

只是不能通过b来修改其指向的内容，a还是可以修改的

引用 8 楼 q328965539 的回复:int main(void) {       const int a=10;    int* p=(int*)(&a);    *p=20;    cout<<a<<" "<<*p<<endl;    return 0; } 这样又如何？这样的代码是错的 结果没有意义

引用 11 楼 yizhizhuen 的回复:这个问题，关乎这一点，首先C语言是一种弱类型的语言。也就是说每次读取数据的时候，都会从内存地址中读取，尽管用const修饰，但是内存的内容依旧可以修改（弱类型语言），多说一点，相比较C而言，C++在这一点就做的和好，尽管C++中，虽然采用指针也可以修改内存地址的数据，但是C++编译器编译时对其进行了优化，读取数据的时候，是不在内存地址读取的。不知道这样能否解决你的问题。 可以看看这个例子：http://www.cnblogs.com/gongxijun/p/4375458.html  加 volatile 关键字的变量才会每次从内存中读取, 否则编译器会结合上下文进行优化

const int a = 0; a的值不能改  int  b = 0; int c = 0; const int* a = &b; 还是a的值不能改，但a指向的地址里的内容是可以改的 之后在执行 a=&c 就是错误的了

引用 15 楼 tangtangtangbaoli 的回复:首先,源代码内的各种变量,在编译链接以后生成的执行文件中都被转变成了内存的相对地址,运行时cpu会根据寄存器保存的绝对地址+相对地址 = 通过地址总线译码找到真正的物理地址 然后通过数据总线去读入或写人数值     char a[]="abcd"; //a变量在内存j就是比如地址0x1000,里面存放了31 32 33 34 就是abcd字符的ascill码     const char* b=a; //b变量在内存就是比如地址0x8000,但注意这个0x8000是在内存的常量区,这段地址里面的值被赋值后是不能被改写的,里面放了一个值0x1000,     //b[0]='!'; a[0]='f'; //然后通过这条指令对地址0x1000写人一个值,这个就是跟0x8000里面那个x1000没一点关系了!!!     printf("%s\n",b); 解释挺不错。 但是b真的在常量区？ b确定在常量区吗？b指针不是应该在栈区吗，他是局部变量啊

这里指针b是指向常量的指针变量，只是不能通过指针b改变它指向的对象的值，通过a改变没问题。而且这里b指针的指向也可以改变。谭浩强的c++程序设计讲的很清楚

引用 7 楼 q328965539 的回复:[quote=引用 3 楼 Falleyes 的回复:] a不是指向const数据，所以a可以修改数据内容。 b声明为const char* b=a;意思是说不能通过b这个指针改变其所指向的数据。跟a能不能修改没有关系。 有深层次点的解释么，我是想知道为什么不能通过b这个指针改变其所指向的数据？ 内部是不是const指定那块内存为只读的？（事实证明那块内存还是可读写的） 还是用const去限制了这个指针去读那块内存？那又是怎么限制的，这机制怎么实现的？[/quote] 这些都是编译器做的，编译器会检查有没有对const修饰内容做修改，若发现编译时刻就告诉你错误了。

引用 8 楼 q328965539 的回复:int main(void) {       const int a=10;    int* p=(int*)(&a);    *p=20;    cout<<a<<" "<<*p<<endl;    return 0; } 这样又如何？阿里面试题

const 常量符其实在 c\c++ 中被认为是多余的了, 最多的作用是提示自己或提示交接项目的人, 这个变量或地址不能被更改而已 它只能在编译的时候提示你有非法修改, 熬过了编译到了实际运行阶段, 与普通的变量是一个样

引用 3 楼 Falleyes 的回复:a不是指向const数据，所以a可以修改数据内容。 b声明为const char* b=a;意思是说不能通过b这个指针改变其所指向的数据。跟a能不能修改没有关系。 有深层次点的解释么，我是想知道为什么不能通过b这个指针改变其所指向的数据？ 内部是不是const指定那块内存为只读的？（事实证明那块内存还是可读写的） 还是用const去限制了这个指针去读那块内存？那又是怎么限制的，这机制怎么实现的？


Question: 《深入理解计算机系统（第二版）》 练习题3.18疑惑求教

楼主，我按照你的代码（不是书上的标准答案），写了程序，在虚拟机上编译成汇编，我看到你的结果和书上的汇编很相似，反而是书上标准答案编译成汇编，不符合书上的汇编代码的结果。我感觉书上是不是错了啊。 按照楼主的C代码，编译出的汇编代码是这样的：  （注意看.L2） 	.file	"18.c" 	.text .globl test 	.type	test, @function test: 	pushl	%ebp 	movl	%esp, %ebp 	subl	$16, %esp 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	movl	%edx, %ecx 	subl	%eax, %ecx 	movl	%ecx, %eax 	movl	%eax, -4(%ebp) 	cmpl	$-3, 8(%ebp) 	jge	.L2 	movl	12(%ebp), %eax 	cmpl	8(%ebp), %eax 	jge	.L3 	movl	8(%ebp), %eax 	imull	12(%ebp), %eax 	movl	%eax, -4(%ebp) 	jmp	.L4 .L3: 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	leal	(%edx,%eax), %eax 	movl	%eax, -4(%ebp) 	jmp	.L4 .L2: 	cmpl	$2, 8(%ebp) 	jg	.L4 	movl	12(%ebp), %eax 	movl	8(%ebp), %edx 	xorl	%edx, %eax 	movl	%eax, -4(%ebp) .L4: 	movl	-4(%ebp), %eax 	leave 	ret 	.size	test, .-test 	.ident	"GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" 	.section	.note.GNU-stack,"",@progbits

理解和讨论之前请先学会如何观察！

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

楼上能具体解释下吗，谢了

晕，“ int val = x*y;” 和 “ int val = x ^ y;”不同，反正code path的白盒测试要过

1 楼正解呀  另外你说的汇编代码第3,4行，%eax 与 -3比较，即 x >= -3（jge） 时是跳到L2，如果x < -3 则往下继续执行，也即汇编代码第五行 cmpl %edx, %eax 翻译就是campare x and y 再第六行，就是如果 x <= y 调到L3 如果x > y 继续执行 imul x , y  剩下的就不多说了 所以答案肯定是if(x<-3)

那是为什么呢

引用 4 楼 wjiech 的回复:我的意思是习题答案可不可是以下代码呢？ 1    int  test(int x, int y) { 2          int val = x*y; 3          if ( x >= -3) { 4             if(x>2)  5                 val = x - y; 6             else  7                    val = x ^ y; 8          }  else if(x<=y) { 9                      val = x + y; 10        return val; 11 }  不行

汇编代码如下 x at %ebp+8, y at %ebp+12 1     movl    8(%ebp), %eax 2     movl    12(%ebp), %edx  3     cmpl     $-3, %eax 4     jge       .L2 5     cmpl    %edx, %eax 6     jle        .L3 7     imull    %edx, %eax 8     jmp     .L4 9  .L3: 10   leal     (%edx, %eax), %eax 11   jmp       .L4 12 .L2: 13   cmpl    $2, %eax 14   jg       .L5 15   xorl    %edx, %eax 16   jmp      .L4 17 .L5: 18   subl     %edx ,   %eax 19 .L4:   按user-5同学所述，汇编代码第3、4行,寄存器eax的内容和立即数-3比较后是用的jge,而书中答案为何是if(x<-3)呢？

这位同学，你好像忘了贴汇编的代码了，我看了一下习题，请注意第14行的汇编，在eax寄存器中的内容和立即数2比较之后，使用的是jg跳转指令，如果使用你的写法，那么对应的汇编将是jle，当然下面的汇编也会相应更改。


Question: 新手C语言程序作业求教！！！！！！！

引用 4 楼 sinat_27077631 的回复:[quote=引用 3 楼 u010005508 的回复:] scanf_s()在读取字符时必须提供一个数字以表明最多读取多少位字符。所以你要这样写scanf_s("%d%c%d=%d", &n, &a,1, &m, &sum1)才行！或者改用scanf()函数！ VS用scanf的话会报错啊[/quote] 怎么会报错了?你咋用的？

引用 3 楼 u010005508 的回复:scanf_s()在读取字符时必须提供一个数字以表明最多读取多少位字符。所以你要这样写scanf_s("%d%c%d=%d", &n, &a,1, &m, &sum1)才行！或者改用scanf()函数！ VS用scanf的话会报错啊

代码里不让搞颜色，改成这样  scanf_s("%d%c%d=%d", &n, &a, 1,  &m, &sum1);

在vs2013中运行的时候，把这句话改一下。  scanf_s("%d%c%d=%d", &n, &a, 1, &m, &sum1);


Question: 结构体内存空间

2楼下解  引用 1 楼 user-3 的回复:union U 最大是13, 由于8字节对齐, sizeof U=16 color=4  16+4=20, 8字节对齐, 变成24        http://www.cnblogs.com/growing/archive/2010/08/18/1802162.html

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

引用 2 楼 Jutland 的回复:[quote=引用 1 楼 user-3 的回复:] union U 最大是13, 由于8字节对齐, sizeof U=16 color=4  16+4=20, 8字节对齐, 变成24        http://www.cnblogs.com/growing/archive/2010/08/18/1802162.htmlunion里面不是还有double=8，float=4吗？怎么不算进去[/quote] 联合体和结构体不一样, 联合体里面实际上只有一个变量, 去看看书上怎么说的

引用 1 楼 user-3 的回复:union U 最大是13, 由于8字节对齐, sizeof U=16 color=4  16+4=20, 8字节对齐, 变成24        http://www.cnblogs.com/growing/archive/2010/08/18/1802162.htmlunion里面不是还有double=8，float=4吗？怎么不算进去


Question: 函数返回值，用了malloc 申请内存，如何释放呢？

free释放

引用 16 楼 wanyeye 的回复:[quote=引用 15 楼 lq5672 的回复:] 个人感觉。LZ这段代码不是很好。解决的办法上面已经给了。  个人建议，内存申请和释放尽量不要跨函数，除法是一个类内可以统一调度。  可以改成 bool analyData(const char * buf,const int bufLen，char * payloadData);  调用者申请释放payloadData。  现在就改成这样了 呵呵  [/quote]  这样也不太好，因为有的时候无法预测需要多大空间。 我觉得比较简单的做法是：提供两个函数，一个用于正常的处理，另一个用于销毁内存。（为什么不在调用方直接free，而必须专门提供销毁函数，请自行百度）  简便做法：用守卫或者智能指针或者……，在调用方出了某个作用域的时候，自动调用销毁内存的函数。

引用 15 楼 lq5672 的回复:个人感觉。LZ这段代码不是很好。解决的办法上面已经给了。  个人建议，内存申请和释放尽量不要跨函数，除法是一个类内可以统一调度。  可以改成 bool analyData(const char * buf,const int bufLen，char * payloadData);  调用者申请释放payloadData。  现在就改成这样了 呵呵

8楼正解，但是最好把free调的指针置NULL吧，安全点

这块内存不需要的时候，直接free。

引用 3 楼 wanyeye 的回复:[quote=引用 2 楼 D_PCA 的回复:] 这是在子函数中申请的内存吧。用free函数就释放掉了么。不过不要在这个子函数内释放，否则这个函数就没意义了。 是对  函数内释放就没意义了  只好用数组替代了？   [/quote]    我想2楼的意思是，如果你在一个函数里malloc，但是不在这个函数里free，这样的设计不好，但是并不是错的～～～ 你在一个函数里malloc，然后返回这个地址，在外面free，也可以的

你调用函数后再释放。 char *callFunc = analyData(); ... free(callFunc);

malloc不是对应free吗

直接free不可以吗?

仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //

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

引用 3 楼 wanyeye 的回复:函数内释放就没意义了  只好用数组替代了？  不是， 你在调用这个函数的地方， 记录下这个函数的返回值（一个指针）， 使用了返回值之后， 就可以free掉这个指针了。  这段代码在windos下也可以运行，就你贴出来的代码中都是标准c的东西， 没有linux的库函数。除非省略的地方有linux库函数。

更可气的是，这函数在 Linux下是正常的  移植到windows下，就不行

引用 2 楼 D_PCA 的回复:这是在子函数中申请的内存吧。用free函数就释放掉了么。不过不要在这个子函数内释放，否则这个函数就没意义了。 是对  函数内释放就没意义了  只好用数组替代了？

free (analyData (buf, 2048));

引用 3 楼 wanyeye 的回复:[quote=引用 2 楼 D_PCA 的回复:] 这是在子函数中申请的内存吧。用free函数就释放掉了么。不过不要在这个子函数内释放，否则这个函数就没意义了。 是对  函数内释放就没意义了  只好用数组替代了？   [/quote]  在程序中，一个malloc对应一个free，哪怕malloc在子函数中，free在主函数中。 你这个函数的作用应该是返回一个字符串，但是实际返回的是指向字符串首地址的指针。所以如果不在函数内部malloc，而是简单地直接char payloadData[254]，那么，函数返回后，程序会自动把函数中开辟的空间释放掉，自然也就把那个字符串释放掉了。所以你返回的指针会指向一个莫名其妙的玩意儿。只有malloc，才能保证函数返回后内存不会被释放掉。这就是我说函数内释放就没有意义了。  但是释放是必须要做的事情。只要你还能找得到你malloc后的那个地址，哪怕变量名改变了，也可以直接free的。  参考下这个：http://blog.163.com/lover_j_j/blog/static/16824744720072124301222/


Question: C语言数据结构基础问题：两个有序链表并为一个有序链表

有序链表合并且去重 http://blog.csdn.net/zhangxiangdavaid/article/details/26340587

-     if(pa->data<=pa->data){ +     if(pa->data<=pb->data){   找一个笔，一张纸，自己画！

1, 有个pc和pa两个节点 [     ]        [     ]    ||             ||    pc          pa -------------------------- 2. pc->next = pa [     ]    ->  [     ]    ||             ||    pc          pa ---------------------------------- 3 pc=pa [      ]  ->[     ]                 || pc=pa


Question: 求问个算法问题，题目如下

if (res < ans) res = ans;//?????

引用 37 楼 super_miker 的回复:位运算+记忆化搜索 核心代码：   int mask[20] = {    0x00012, 0x00025, 0x0004A, 0x00084,    0x00121, 0x00252, 0x004A4, 0x00848,    0x01210, 0x02520, 0x04A40, 0x08480,    0x12100, 0x25200, 0x4A400, 0x84800,    0x21000, 0x52000, 0xA4000, 0x48000, }; int memory[1<<20]; memset(memory, -1, sizeof(memory)); memory[0] = 0; int dfs(int code){    if (memory[code] >= 0) return memory[code];    else{       int ans = INT_MAX;       for (int i = 0; i < 20; ++i){          if ((code & 1 << i) == 0 && (code & mask[i]) != 0){             int res = dfs(code & ~mask[i]);             if (res < ans) res = ans;          }       }       return memory[code] = ans;    } }  1	213443	cfltdf	------	------	C	------	2015-04-10 16:20:58 已过

内存限制居然有32M。。这样的话2^20=1048576，直接生成一个表然后每次查表速度不能再快。。

引用 34 楼 dooX8086 的回复:[quote=引用 32 楼 zhao4zhong1 的回复:] 26楼代码正确。   15楼代码有Bug！   这种取巧的方法是错的[/quote] 多费几颗炸弹，还能提振军工业呢！

引用 32 楼 zhao4zhong1 的回复:26楼代码正确。   15楼代码有Bug！   这种取巧的方法是错的

Ada不喜欢学数字,却喜欢玩游戏,看着她的小手指在手机屏上戳来戳去,顿时感觉祖国的游戏事业有了未来.

26楼代码正确。   15楼代码有Bug！

引用 30 楼 my_bkb 的回复:[quote=引用 29 楼 zhao4zhong1 的回复:] “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出 内个 对于调试我有个问 全局数组 还有传入函数的数组 在调试时无法显示各成员数值怎么办啊[/quote] 自己写一小段代码或一个函数，显示你想看的数据结构，例如： //带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

引用 29 楼 zhao4zhong1 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出 内个 对于调试我有个问 全局数组 还有传入函数的数组 在调试时无法显示各成员数值怎么办啊

引用 26 楼 my_bkb 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 保存现场 测试下一个1旁边的0 模拟爆炸 若全0，记录本轮共炸几次，恢复现场，递归 若非全0，递归 这段代码是我一朋友写的 过了 还挺简便的 可是看不懂  #include<iostream> #include<cstdio> using namespace std; #define MAXN 1<<20 const int MASK=(1<<20)-1; char str[1000]; int ans[MAXN]; int dfs(int pos){     if(ans[pos]!=MAXN) return ans[pos];     int rt = MAXN;     for(int i=0;i<20;i++){         if( pos&1<<i ){             if( i>3 && ( (pos&1<<(i-4))==0) ) {                 int boom = i-4 ,newpos = pos & ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i<16 && ( (pos&1<<(i+4))==0) ) {                 int boom = i+4 ,newpos = pos & ~(1<<i);                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=0 && ( (pos&1<<(i-1))==0) ) {                 int boom = i-1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=3 && ( (pos&1<<(i+1))==0) ) {                 int boom = i+1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }         }     }     return ans[pos]=rt; } int main(){     int case_cnt=1;     for(int i=1;i<MAXN;i++){         ans[i]=MAXN;     }     ans[0]=0;     while(gets(str)){         int tmp=0,tmpcnt=1;         for(int i=0;i<5;i++){             gets(str);             for(int j=0;j<4;j++){                 if(str[j]=='1') tmp+=tmpcnt;                 tmpcnt<<=1;             }         }         //printf("tmp=%d\n",tmp);         printf("The result of case %d is %d\n",case_cnt++,dfs(tmp));     }     return 0; }[/quote] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

22楼再试试这个： Case 1: 1100 0100 1010 0100 0010

引用 1 楼 zhao4zhong1 的回复:保存现场 测试下一个1旁边的0 模拟爆炸 若全0，记录本轮共炸几次，恢复现场，递归 若非全0，递归 这段代码是我一朋友写的 过了 还挺简便的 可是看不懂  #include<iostream> #include<cstdio> using namespace std; #define MAXN 1<<20 const int MASK=(1<<20)-1; char str[1000]; int ans[MAXN]; int dfs(int pos){     if(ans[pos]!=MAXN) return ans[pos];     int rt = MAXN;     for(int i=0;i<20;i++){         if( pos&1<<i ){             if( i>3 && ( (pos&1<<(i-4))==0) ) {                 int boom = i-4 ,newpos = pos & ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i<16 && ( (pos&1<<(i+4))==0) ) {                 int boom = i+4 ,newpos = pos & ~(1<<i);                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=0 && ( (pos&1<<(i-1))==0) ) {                 int boom = i-1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=3 && ( (pos&1<<(i+1))==0) ) {                 int boom = i+1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }         }     }     return ans[pos]=rt; } int main(){     int case_cnt=1;     for(int i=1;i<MAXN;i++){         ans[i]=MAXN;     }     ans[0]=0;     while(gets(str)){         int tmp=0,tmpcnt=1;         for(int i=0;i<5;i++){             gets(str);             for(int j=0;j<4;j++){                 if(str[j]=='1') tmp+=tmpcnt;                 tmpcnt<<=1;             }         }         //printf("tmp=%d\n",tmp);         printf("The result of case %d is %d\n",case_cnt++,dfs(tmp));     }     return 0; }

引用 16 楼 zhao4zhong1 的回复: 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 喜欢这句话

22楼试试这个： Case 1: 1111 0101 0101 1101 1001

这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。

引用 16 楼 zhao4zhong1 的回复: 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 严重同意！ 比如建筑师和搬砖的！ apple 和富士康

引用 13 楼 dooX8086 的回复:1 计算格子权值（0的上下左右有多少个1 -- 障碍物) 2 在权值最大的格子放 炸弹 （清除四个相邻格的障碍物） 3 --- loop --> 1  (直到所有格子为0)  ================================ 应该可以秒杀 如果去除IO部份时间应该毫秒级别完成， 如加上IO时间，估算一下都没有1M数据，也应该在1秒内完成   ////////=========================================================== 测试数据   结果     #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>   #define MAP_ROW 5 #define MAP_COL 4   #define RES_0 '0' #define RES_1 '1'   typedef char map_t[MAP_ROW][MAP_COL]; typedef char byte;   typedef struct { 	byte row, col; 	byte val; } mpos_t;    int is_vaild(byte row, byte col) { 	return 0 <= row && row < MAP_ROW && 0 <= col && col < MAP_COL; }   void bomb_out(map_t map, byte row, byte col) { 	if ( is_vaild(row + 1, col) ) map[row + 1][col] = RES_0; 	if ( is_vaild(row, col + 1) ) map[row][col + 1] = RES_0; 	if ( is_vaild(row - 1, col) ) map[row - 1][col] = RES_0;  	if ( is_vaild(row, col - 1) ) map[row][col - 1] = RES_0; }   // 计算权值 int calc_val(map_t map, byte row, byte col) { 	return (is_vaild(row + 1, col) && RES_1 == map[row + 1][col]) 		 + (is_vaild(row, col + 1) && RES_1 == map[row][col + 1]) 		 + (is_vaild(row - 1, col) && RES_1 == map[row - 1][col]) 		 + (is_vaild(row, col - 1) && RES_1 == map[row][col - 1]); }   // 查找权值最大的格子 void find_max_mpv(map_t map, mpos_t *mpos) { 	byte val; 	memset(mpos, 0x0, sizeof(mpos_t)); 	for (int row=0; row < MAP_ROW; ++row) { 		for (int col=0; col < MAP_COL; ++col) { 			if (RES_0 == map[row][col]) { 				val = calc_val(map, row, col); 				if (mpos->val < val) { 					mpos->val = val; 					mpos->row = row; 					mpos->col = col;  					if (4 == mpos->val) return ;		// 权值4 已是最大了,不用再找 				} 			} 		} 	} }    void generate_test_data(int num) { 	srand( time(NULL) ); 	char buf[MAP_ROW * MAP_COL] = {0}; 	for (int id=1; id<=num; ++id) {  		memset(buf, RES_0, MAP_ROW * MAP_COL);  		int bc = 1 + rand() % 18; 		memset(buf, RES_1, bc);  		printf("Case %d:\n", id); 		 		int tmp; 		for (int bit=0; bit<MAP_ROW * MAP_COL; ++bit) { 			int i = rand() % MAP_ROW * MAP_COL; 			tmp = buf[i]; 			buf[i] = buf[bit]; 			buf[bit] = tmp; 		}  		for (int row=0; row < MAP_ROW; ++row) printf("%.4s\n", buf + row * MAP_COL); 	}  }  int main(int argc, char *argv[]) { 	// generate test data 	//generate_test_data(20000); 	//exit(0);  	// 数据测试  	if (2 <= argc) 		freopen(argv[1], "r", stdin);  	if (3 == argc) 		freopen(argv[2], "w", stdout);  	clock_t start_time, end_time; 	start_time = clock();  	 	char buf[64]; 	int id = 0; 	map_t map; 		 	for(;;) 	{ 		// ------------------------------ 		// 输入数据 		// 		if (EOF == fscanf(stdin, "%*[^\n] ") ) break;  		++id; 		//printf("-- case %d ---\n", id); 		for (int row=0; row < MAP_ROW; ++row) { 			fgets(buf, 64, stdin); 			memcpy(map[row], buf, MAP_COL); 			//printf("%.4s\n", map[row]); 		} 		 		// -------------------------------- 		// 处理 		// 		mpos_t mpos = {0}; 		int bomb_count = {0}; 		 		for (find_max_mpv(map, &mpos); 0 < mpos.val; find_max_mpv(map, &mpos)) { 			++bomb_count; 			bomb_out(map, mpos.row, mpos.col); 		}  		// ------------------------------- 		// 输出 		// 		fprintf(stdout, "the result of case %d is %d\n", id, bomb_count); 	}	  	end_time = clock();  	fprintf(stdout, "\ntime:%f second\n", (double)(end_time - start_time) / CLOCKS_PER_SEC);  	return 0; }


Question: 菜鸟求助一个简单问题

引用 3 楼 xiaolei1982 的回复:[quote=引用 1 楼 a30037338 的回复:] 这个取决于你需要读取多少数据啊， 可以是一个结构体，也可以是一个数组。。  但是这个是二进制流，还有信号中断等处理，未必可以一次拿到啊[/quote] 如果被信号中断，会设置设置errno值为EINTR，你需要每次read后测定erron值以确定后续的操作。 像这样  again: if ((n = read(fd, buf, BUFFSIZE)) < 0) { if (errno == EINTR) goto again; /* just an interrupted system call */ /* handle other errors */ }   不同的系统有不同的设置，有些系统(比如BSD)把read系统调用被信号中断后自动重启，而不用显式处理EINTR；有些系统需要用户设置此行为属性。

引用 3 楼 xiaolei1982 的回复:[quote=引用 1 楼 a30037338 的回复:] 这个取决于你需要读取多少数据啊， 可以是一个结构体，也可以是一个数组。。  但是这个是二进制流，还有信号中断等处理，未必可以一次拿到啊[/quote] Linux/Unix一切皆文件，不区分二进制还是文本流

引用 1 楼 a30037338 的回复:这个取决于你需要读取多少数据啊， 可以是一个结构体，也可以是一个数组。。  但是这个是二进制流，还有信号中断等处理，未必可以一次拿到啊

仅供参考：#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

这个取决于你需要读取多少数据啊， 可以是一个结构体，也可以是一个数组。。

引用 5 楼 my_live_123 的回复:[quote=引用 3 楼 xiaolei1982 的回复:] [quote=引用 1 楼 a30037338 的回复:] 这个取决于你需要读取多少数据啊， 可以是一个结构体，也可以是一个数组。。  但是这个是二进制流，还有信号中断等处理，未必可以一次拿到啊[/quote] 如果被信号中断，会设置设置errno值为EINTR，你需要每次read后测定erron值以确定后续的操作。 像这样  again: if ((n = read(fd, buf, BUFFSIZE)) < 0) { if (errno == EINTR) goto again; /* just an interrupted system call */ /* handle other errors */ }   不同的系统有不同的设置，有些系统(比如BSD)把read系统调用被信号中断后自动重启，而不用显式处理EINTR；有些系统需要用户设置此行为属性。[/quote]    非常感谢，但是我看的这是现在很出名的swoole的代码，代码里确实就是这样来读取一个结构的，我想应该是有什么作用，要不这么明显的错误，怎么会出现呢？


Question: 各种排序的辅助空间

写一个排序的程序，看看里面用到了那些变量，变量大小跟输入有什么关系

引用 2 楼 tianzhenseu 的回复:引用 1 楼 jiht594 的回复:书上有....要是有，我就不问了 算法导论上有详细的

引用 2 楼 tianzhenseu 的回复:引用 1 楼 jiht594 的回复:书上有....要是有，我就不问了  百度百科 空间复杂度 http://baike.baidu.com/view/540497.htm  比如插入排序, 交换元素的时候, 需要一个额外的空间 如 int temp = a; a = b; b =tenp; 这个temp就是要算如空间复杂度, 因为n个元素排序只需要1(常数)个额外空间,空间复杂度是O(1)

指完成算法至少需提供的额外存储空间。

引用 1 楼 jiht594 的回复:书上有....要是有，我就不问了

书上有....

就是为了完成你的程序，你需要使用的保存信息的空间和


Question: 关于windows平台上GUI程序的绘图效率

引用 1 楼 a30037338 的回复:opencv 。。 支持！  参考OpenCV源代码中逐像素处理相关源代码。

opencv 。。

直接用Win API就是这种效果，他是用CPU来渲染的。属于串行处理。想加快速度就用其他支持并行的图形接口，什么OpenGL、DirectX、OpenCV的都可以。


Question: acm的一个题关于序号互换

26进制的问题 利用itoa(number, string, 26); 和strtol(string, &stopstring, 26); 自己再处理下就可以解决了

引用 2 楼 u012878380 的回复:[quote=引用 1 楼 my_live_123 的回复:]  #include <stdio.h> #include <stdlib.h>   #define MAX_DEEP 32 void function(int num) { 	char *alpha ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 	char array[MAX_DEEP] = {0}; 	int top = -1;  	num--; 	do{ 		if(top + 1 >= MAX_DEEP) 			break; 		array[++top] = alpha[num % 26]; 		num /= 26; 	}while(num);  	while(top >= 0) { 		printf("%c", array[top]); 		--top; 	} }  int main(int argc, char *argv[]) { 	int i; 	 	for(i = 1; i < 100; ++i) { 		printf("%d = ", i); 		function(i); 		printf("\n"); 	}  	exit(0); } 怎末理解的啊  能否给定思路[/quote]  和十进制转换二进制一样的道理，只不过这里是十进制转26进制

//Input a string : AA //AA = 27 //Input a num : 27 //27 = AA //Input a string : ABC //ABC = 731 //Input a num : 731 //731 = ABC //Input a string : Ctrl + c

仅供参考：  #include <stdio.h> #include <stdlib.h> unsigned int StrToU(char *s, int n) { 	if (s == NULL || n < 0) 		return 0; 	unsigned int res = 0; 	int i, radix = 1; 	for (i = n - 1; i >= 0; i--) 	{ 		if (i < n - 1) 			radix *= 26; 		res += (s[i] - 'A' + 1)*radix; 	} 	return res; } char *UToStr(char *dest, unsigned int n) { 	char buf[10]; 	int i, pos = 9; 	while (n) 	{ 		i = n % 26; 		buf[pos--] = i - 1 + 'A'; 		n /= 26; 	} 	strncpy(dest, buf + pos + 1, 10 - pos); 	dest[9 - pos] = 0; 	return dest; } int main(void)//11 { 	char str[10]; 	unsigned int n; 	char dest[10]; 	while (1) 	{ 		memset(str, 0, 10); 		memset(dest, 0, 10); 		printf("Input a string : "); 		if (1 == scanf("%s", str)) 			printf("%s=%u\n", str, StrToU(str, strlen(str))); 		else break; 		printf("Input a num : "); 		if (1 == scanf("%d", &n)) 			printf("%u=%s\n", n, UToStr(dest, n)); 		else break; 	} 	return 0; }

对于单个字母：A-Z对应1-26。 对于两个字母：第一个字母的值乘以26加第二个字母的值 比如：AA：26*1+1，ZZ:26*26+26 对于N个字母，值为26^(N-1)*第一个字母+26^(N-2)*第二个字母+...+第N个字母 反过来，通过数字求字母，设数字为n,则(n-1)%26+1为最后一个字母的值。前面的字母可用递归求得。 代码如下：  #include<stdio.h> void kong(int n) {     if(n>26)         kong((n-1)/26);     putchar((n-1)%26+'A'); } int main() {     int n;     scanf("%d",&n);     kong(n);     putchar('\n');     return 0; }

引用 1 楼 my_live_123 的回复: #include <stdio.h> #include <stdlib.h>   #define MAX_DEEP 32 void function(int num) { 	char *alpha ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 	char array[MAX_DEEP] = {0}; 	int top = -1;  	num--; 	do{ 		if(top + 1 >= MAX_DEEP) 			break; 		array[++top] = alpha[num % 26]; 		num /= 26; 	}while(num);  	while(top >= 0) { 		printf("%c", array[top]); 		--top; 	} }  int main(int argc, char *argv[]) { 	int i; 	 	for(i = 1; i < 100; ++i) { 		printf("%d = ", i); 		function(i); 		printf("\n"); 	}  	exit(0); } 怎末理解的啊  能否给定思路


Question: 遇到bug，不知道哪儿出问题，求助

#include <stdio.h> #define K 100000 int main(void) { 	int i,j,l,N[K],sum_time,sum_max; 	scanf("%d",&i); 	if(i>=K||i<1) 		return 1; 	for(j=1;j<=i;j++) 		scanf("%d",&N[j]);  	sum_time=sum_max=0;  	l=1; 	for(j=1;j<=i;j++) 	{ 		sum_time+=N[j]; 		if(sum_time>sum_max) 		{ 			sum_max=sum_time; 			l=j; 		} 		else if(sum_time<0) 		{	 			sum_time=0; 		} 	} 	if(sum_max==0) 		printf("%d %d %d",sum_max,N[1],N[i]); 	else 	{	 		for(j=l,sum_time=0;sum_time<sum_max;j--) 			sum_time+=N[j];	 		printf("%d %d %d",sum_max,N[j+1],N[l]); 	} 	return 0;	 }  这个代码运行的话测试比上面的好一点，但还是有一些问题

for(j=l,sum_time=0;sum_time！=sum_max;j++) sum_time+=N[j];//这里N[j]如果不是1, 运行之后, 很大 可能sum_time>sum_max, 死循环

就是给定K个整数组成的序列{ N1, N2, ..., NK }，“连续子列”被定义为{ Ni, Ni+1, ..., Nj }，其中 1 <= i <= j <= K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 }，其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序，计算给定整数序列的最大子列和，并且给出最大子列的第一个元素和最后一个元素（如果最大值为0，则输出第一个和最后一个元素，如果有相同的列，则输出子标小的列）。

只想说一句，题目全是英文 看不懂要求

#include <stdio.h> #define K 100000 int main(void) { 	int i,j,l,N[K],sum_time,sum_max; 	scanf("%d",&i); 	if(i>K||i<1) 		return 1; 	for(j=1;j<=i;j++) 		scanf("%d",&N[j]);  	sum_time=sum_max=0;  	l=1; 	for(j=1;j<=i;j++) 	{ 		sum_time+=N[j]; 		if(sum_time>sum_max) 			sum_max=sum_time; 		else if(sum_time<0) 		{	 			sum_time=0; 			l=j+1; 		} 	} 	if(sum_max==0) 		printf("%d %d %d",sum_max,N[1],N[i]); 	else 	{	 		for(j=l,sum_time=0;sum_time<sum_max;j++) 			sum_time+=N[j];	 		printf("%d %d %d",sum_max,N[l],N[j-1]); 	} 	return 0;	 }


Question: 菜鸟求助，创建一个单链表，程序检查没错，但运行老是出问题

void printlist(linklist l)  { node *p;//少了一个p = l while(p->data!=null) { printf("information:"); printf(" d%\n",p->data); p=p->next; } }

引用 2 楼 PingShanJuShi 的回复:你创建链表的逻辑有问题，你应该先创建一个头结点设为空，然后再去调用加入一个节点的函数，如果头结点为空，那么这个新加入的节点就是头结点，如果头结点不为空，那么遍历这个链表找到最后一个节点，然后将新节点连入末尾，要记得每加入一个节点的next要指向空哦创建链表只要有清晰的思路，很容易的！二楼说的对！

单链表的创建及增删改，供参考！ 链表的“增删改”  #include <stdio.h> #include <stdlib.h> struct node*creat(struct node *head); void Output(struct node *head); void Insert(struct node *head,int k); void Delete(struct node *head,int j); void Replace(struct node *head,int n); struct node {  	int data; 	struct node *next; }; int main(){      int a,b,c,d; 	struct node *head; 	head=NULL;   	head=creat(head);//新建链表 	Output(head);   	do{ 		printf("\n"); 		printf("请选择您要进行的操作：\n"); 		printf("----------------------------------------\n"); 		printf("1.添加新结点\n"); 		printf("2.删除结点\n"); 		printf("3.修改结点数据\n"); 		printf("4.退出\n"); 		printf("----------------------------------------\n"); 		printf("\n"); 		printf("请选择："); 		scanf("%d",&d);  	switch(d) 	{ 		case 1: 			printf("您选择了添加新结点\n"); 	       printf("请输入要插入结点位置:");//插入新结点 	       scanf("%d",&a); 	       Insert(head,a); 	       Output(head); 		   break; 		case 2: 			printf("您选择了删除结点\n"); 	       printf("请输入要删除的结点:");//删除结点 	       scanf("%d",&b); 	       Delete(head,b); 	       Output(head); 		   break; 		case 3: 			printf("您选择了修改结点数据\n"); 	       printf("请输入要修改结点的位置:");//修改结点数据            scanf("%d",&c); 	       Replace(head,c); 	       Output(head); 		   break; 		case 4: 			break; 	} 	}while(d!=4);  	//printf("\n"); 	//printf("请输入要插入结点位置:");//插入新结点 	//scanf("%d",&a); 	//Insert(head,a); 	//Output(head);  	//printf("\n"); 	//printf("请输入要删除的结点:");//删除结点 	//scanf("%d",&b); 	//Delete(head,b); 	//Output(head);   	//printf("\n"); 	//printf("请输入要修改结点的位置:");//修改结点数据 	//scanf("%d",&c); 	//Replace(head,c); 	//Output(head);  	return 0; } struct node *creat(struct node *head){  	int i,LEN; 	struct node *p,*s; 	printf("请输入链表的长度："); 	scanf("%d",&LEN); 	 	if(LEN>=1){ 		for(i=1;i<=LEN;i++){		           p=(struct node *)malloc(sizeof(struct node *)); 			 			if(head==NULL) 				s=head=p; 			printf("请输入第%d个结点中的数据：",i); 			scanf("%d",&p->data); 			p->next=NULL; 			s->next=p; 			s=p; 		} 	}return (head); } void Output(struct node *head){  	struct node *temp; 	temp=head; 	printf("新链表如下："); 	while(temp!=NULL){ 	 		printf("%d->",temp->data); 		temp=temp->next; 	} }  void Insert(struct node *head,int k){  	struct node *p1,*p2,*p3; 	int i; 	p3=p1=head; 	for(i=1;i<k;i++){ 		p1=p1->next; 	} 		for(i=1;i<k-1;i++){ 		p3=p3->next; 	} 	p2=(struct node *)malloc(sizeof(struct node)); 	printf("请输入新结点的数据："); 	scanf("%d",&p2->data); 	p2->next=p1; 	p3->next=p2; }  void Delete(struct node *head,int j){  	int i; 	struct node *p1,*p2,*p3; 	p1=p2=p3=head; 	for(i=1;i<=j;i++){ 		p2=p2->next; 	} 	/*p1->next=NULL; 	p3=p2->next; 	free(p2); 	p1->next=p3;*/  		for(i=1;i<j-1;i++){ 		p1=p1->next; 	} 			for(i=1;i<j+1;i++){ 		p3=p3->next; 	} 			p1->next=p3; 			//free(p2); }  void Replace(struct node *head,int n){  	int i,m; 	struct node *p; 	p=head; 	for(i=1;i<n;i++){ 		p=p->next; 	} 	printf("请输入该结点的新数据："); 	scanf("%d",&m); 	p->data=m; 	//free(p);  }

仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //


Question: Node节点

尾插入法 插入节点

自己画图其实就会很清楚了，先创造一个节点，然后将节点从原链表的L节点后面顺序插入

下次自己画一画

嗯 这个要仔细看，谢谢！


Question: 利用c语言随机数模拟概率，为什么生成的概率结果总是不符合预期？

随机种子在每一次srand后，都需要重新初始化，不然是伪随机。  具体细节没去深究。

首先rand()产生的随机数范围是0~32767，根据你的代码getRatio(0.00123 * 10000, 10000)，将变成rand() % 10000 < 12。  继续往下分析，rand() % 10000其实把0~32767分成了4个区间：[0, 9999], [10000, 19999], [20000, 29999], [30000, 32767]。 发现第4个区间好像有点不公平，范围被分得很小，也就是说产生的随机数落于第4个区间的话，<12的概率会稍高一些。 很容易可以算出总的<12的概率：4*12/32768≈0.001465。  于是，这样模拟概率是不行的。 有个简单的做法，实现一个生成在[0, 1)区间上的小数的随机数生成器，直接让“随机数<概率值”就行。

赵4老师 真是经验丰富，什么样的代码都有。。  引用 2 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <stdlib.h> #include <time.h> unsigned long ulrand(void) {     return (      (((unsigned long)rand()<<24)&0xFF000000ul)     |(((unsigned long)rand()<<12)&0x00FFF000ul)     |(((unsigned long)rand()    )&0x00000FFFul)); } unsigned __int64 ullrand(void) {     return (      (((unsigned __int64)ulrand())<<32)     | ((unsigned __int64)ulrand())); } int i; unsigned long ul; unsigned __int64 ull; void main() {     srand(time(NULL));     for (i=0;i<10;i++) {         ul=ulrand();         printf("%010lu 0x%08x\n",ul,ul);     }     for (i=0;i<10;i++) {         ull=ullrand();         printf("%020I64u 0x%016I64x\n",ull,ull);     } } //3971076432 0xecb1d150 //2433428051 0x910b2a53 //1415415336 0x545d8628 //1312330759 0x4e389407 //1845758378 0x6e0409aa //0008069933 0x007b232d //4202720757 0xfa806df5 //2669855255 0x9f22c217 //0312068736 0x1299ca80 //2084555989 0x7c3fccd5 //03502077880857307931 0x3099e1472040ab1b //16884702393146816355 0xea52835e19b43763 //01877364819396611730 0x1a0dbd5b45f34e92 //07839440151924835771 0x6ccb4948756a05bb //09471412086917299176 0x8371371c820bfbe8 //04411255971577469925 0x3d37edef2f321be5 //13735846279546091130 0xbe9f876a65b7367a //04512980766520059820 0x3ea15418aa9927ac //15821377118299441610 0xdb90d2a9f1bb49ca //15512417228822200185 0xd7472d480398bf79

再供参考： http://www.cplusplus.com/reference/random/index.html


Question: libevent 如何选择epool模式通信？跪求大神解答

引用 1 楼 user-2 的回复:event_get_supported_methods，这个函数查看libevent支持哪些后端方法（select、poll、epoll，，，） event_config_avoid_method，这个函数手动禁止掉一个后端方法 参考http://www.cnblogs.com/zhangchaoyang/articles/2683826.html  非常好，不愧是大神，非常感谢，那个例子很不错

2楼大神给了很好的答案，非常感谢，也非常感谢3楼的热心帮助

编译阶段会检测环境的


Question: 统计问题

Linux：Ctrl+D Windows：Enter，Ctrl+Z，Enter

引用 2 楼 z549069443 的回复:[quote=引用 1 楼 user-2 的回复:] 输入完了之后  回车 ctrl+z 回车 为什么是按Ctrl+z啊 书上没讲啊- -[/quote]  while((c=getchar())!=EOF) 遇到EOF结束, 书上没说EOF什么意思吗 http://baike.baidu.com/link?url=XXHULmcq8XPhM7BiMyVpfldSonpolgL29Omm4K9pckURJ-ggh1AdiKh65lqw6rmZyloRCaEW1D6G1NjPMLNUSa

引用 1 楼 user-2 的回复:输入完了之后  回车 ctrl+z 回车 为什么是按Ctrl+z啊 书上没讲啊- -

输入完了之后  回车 ctrl+z 回车


Question: 求解答

应该就是2楼说的那个问题了

V的结果不对，V1的结果是对的；  4/3的结果是1，不是个小数；应该写4.0/3

在我这里完全正确


Question: 如何对正在运行的程序的文件进行修改

了解了，多谢各位的指点！

去看看《操作系统》吧，操作系统肯定要保证对同一文件写操作进程之间互斥的。


Question: c语言函数指针指向的函数的参数与定义该指针的原型参数个数不一致

请问楼主找到答案了吗？  编译的地方有什么特殊的指定吗？  我也遇到了类似的黑魔法

C里面是允许的,C++不允许

搜 “堆栈平衡” “调用约定” “参数默认值” "C和CPP编译的不同" 必有一款适合你！


Question: 求解，为何输出结果不一样。

谢谢，文字貌似看的可以，你的那些程序真心看不懂

pb--与--pb含义不同 pb--是先capy再减一 --pb是先capy再减一

支持2楼！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

while( (pb--) >= b1) 004113FF  mov         eax,dword ptr [ebp-2Ch]  00411402  lea         ecx,[ebp-10h]  00411405  mov         edx,dword ptr [ebp-2Ch]  00411408  sub         edx,1  0041140B  mov         dword ptr [ebp-2Ch],edx  0041140E  cmp         eax,ecx  00411410  jb          wmain+5Eh (41141Eh)  00411412  mov         dword ptr [ebp-0F4h],1  0041141C  jmp         wmain+68h (411428h)  0041141E  mov         dword ptr [ebp-0F4h],0  00411428  cmp         dword ptr [ebp-0F4h],0  0041142F  je          wmain+83h (411443h)  		strcpy(b2, pb); 00411431  mov         eax,dword ptr [ebp-2Ch]  00411434  push        eax   00411435  lea         ecx,[ebp-20h]  00411438  push        ecx   00411439  call        @ILT+170(_strcpy) (4110AFh)  0041143E  add         esp,8  00411441  jmp         wmain+3Fh (4113FFh)  这是第一段的反汇编，我们可以看到编译器现将pb当前的值存储到eax寄存器中，然后利用edx寄存器对pb执行--的操作，但是要注意到接下来的cmp语句是用的eax的值进行的比较,ecx寄存器中存储的是b1的值。所以相对第二种而言，多执行了一次。要提醒的是，这种写法会导致内存访问越界，原因在于当eax指向b1第一个元素的时候，edx已经指向b1前面一个字节的未知内容，这样其实会把这个字节的内容也拷贝到b2中，这样加上结尾的'\0'一共9个字节,strlen调用的时候就会报一个数组越界的错误，不知道你运行的时候有没有出现。  	while( (--pb) >= b1) 004113FF  mov         eax,dword ptr [ebp-2Ch]  00411402  sub         eax,1  00411405  mov         dword ptr [ebp-2Ch],eax  00411408  mov         ecx,dword ptr [ebp-2Ch]  0041140B  lea         edx,[ebp-10h]  0041140E  cmp         ecx,edx  00411410  jb          wmain+64h (411424h)  		strcpy(b2, pb); 00411412  mov         eax,dword ptr [ebp-2Ch]  00411415  push        eax   00411416  lea         ecx,[ebp-20h]  00411419  push        ecx   0041141A  call        @ILT+170(_strcpy) (4110AFh)  0041141F  add         esp,8  00411422  jmp         wmain+3Fh (4113FFh)  第二段的反汇编，比较好理解了，利用eax寄存器对pb进行了--的操作，然后需要注意把自减的值又写回到了pb中，接着把这个值取到了edx中，接下来的cmp指令就是使用的edx中的值，所以会少执行一次，值得注意的是，这种写法不会出现访问越界。

第一个：pb和b1比较之后再将pb减1 第二个：pb减1之后在将pb和b1比较


Question: 求助文本文件读和写的问题

引用 3 楼 dooX8086 的回复:行未的换行符你没有处理 //------------------------------------ fgets(str[0],13,read);                        //读取filename1文件的.........发票起始号：  fputs(str[0],write);                          //将读取的数据写入filename2文件 fscanf(read,"%d",&Fpqsh);           // 读取 00000001 了,  但后面还有一个换行符  fprintf(write,"%d",Fpqsh);   fgets(str[1],13,read);     // 第二行  .... 因为前面还有一个换行符,........就有问题..  //----------------------------------------------------------------------------------- // 修改方式可把换行符读取掉就可以  fscanf(read,"%d ",&Fpqsh);    // %d 的后面加个空格  fprintf(write,"%d\n",Fpqsh);   // 写回 file2 时 添加一个换行符 // 其它类似...........   // ------------------------------ 你这样读法也太不科学了 .....  谢谢，你解释的很详细

如果你只是将a文件内容复制到b文件，像你那样得知道源文件每一行的内容及排列，假如内容或者行数太多的话，代码得有多长。。给你段参考： #include "stdio.h" void main() { 	FILE* pInFile=NULL; 	FILE* pOutFile=NULL; 	char ch=0; 	pInFile=fopen("D:\\filename1.txt","r"); 	if(pInFile) 	{ 		pOutFile=fopen("D:\\filename2.txt","w"); 		if(pOutFile) 		{ 			while((ch=getc(pInFile))!=EOF) 			{ 				putc(ch,pOutFile); 			} 			fclose(pOutFile); 		} 		fclose(pInFile); 	} }

fscanf(read,"%d",&Fpqsh); 后面加上fgetc(read), 读换行符  fgets(str[2],10,read);  长度10不对  fgets(str[3],45,read);    长度45不对


Question: 关于对话框函数的问题求助

DialogBox The DialogBox macro creates a modal dialog box from a dialog box template resource. DialogBox does not return control until the specified callback function terminates the modal dialog box by calling the EndDialog function. The DialogBox macro uses the DialogBoxParam function.  int DialogBox(   HINSTANCE hInstance,  // handle to application instance   LPCTSTR lpTemplate,   // identifies dialog box template   HWND hWndParent,      // handle to owner window   DLGPROC lpDialogFunc  // pointer to dialog box procedure );   Parameters hInstance  Identifies an instance of the module whose executable file contains the dialog box template.  lpTemplate  Identifies the dialog box template. This parameter is either the pointer to a null-terminated character string that specifies the name of the dialog box template or an integer value that specifies the resource identifier of the dialog box template. If the parameter specifies a resource identifier, its high-order word must be zero and its low-order word must contain the identifier. You can use the MAKEINTRESOURCE macro to create this value.  hWndParent  Identifies the window that owns the dialog box.  lpDialogFunc  Pointer to the dialog box procedure. For more information about the dialog box procedure, see DialogProc.  Return Values If the function succeeds, the return value is the nResult parameter in the call to the EndDialog function used to terminate the dialog box.  If the function fails, the return value is –1. To get extended error information, callGetLastError.  Remarks The DialogBox macro uses the CreateWindowEx function to create the dialog box. DialogBox then sends a WM_INITDIALOG message (and a WM_SETFONT message if the template specifies the DS_SETFONT style) to the dialog box procedure. The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.   When the dialog box procedure calls the EndDialog function, DialogBox destroys the dialog box, ends the message loop, enables the owner window (if previously enabled), and returns the nResult parameter specified by the dialog box procedure when it called EndDialog.   Windows 95 and later: The system can support a maximum of 255 controls per dialog box template. To place more than 255 controls in a dialog box, create the controls in the WM_INITDIALOG message handler rather than placing them in the template.  Windows CE: Not all styles are supported in the DLGTEMPLATE structure in the dialog template referred to by the lpTemplate parameter.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: Use user32.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also Dialog Boxes Overview, Dialog Box Functions, CreateDialog, CreateWindowEx, DialogBoxIndirect, DialogBoxIndirectParam, DialogBoxParam, DialogProc, EndDialog, MAKEINTRESOURCE, WM_INITDIALOG, WM_SETFONT     DialogProc The DialogProc function is an application-defined callback function used with the DialogBox function. It processes messages sent to a modal or modeless dialog box. The DLGPROC type defines a pointer to this callback function. DialogProc is a placeholder for the application-defined function name.   BOOL CALLBACK DialogProc(   HWND hwndDlg,  // handle to dialog box   UINT uMsg,     // message   WPARAM wParam, // first message parameter   LPARAM lParam  // second message parameter );   Parameters hwndDlg  Identifies the dialog box.  uMsg  Specifies the message.  wParam  Specifies additional message-specific information.  lParam  Specifies additional message-specific information.  Return Values Except in response to the WM_INITDIALOG message, the dialog box procedure should return nonzero if it processes the message, and zero if it does not. In response to a WM_INITDIALOG message, the dialog box procedure should return zero if it calls the SetFocus function to set the focus to one of the controls in the dialog box. Otherwise, it should return nonzero, in which case the system sets the focus to the first control in the dialog box that can be given the focus.   Remarks You should use the dialog box procedure only if you use the dialog box class for the dialog box. This is the default class and is used when no explicit class is specified in the dialog box template. Although the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc function to process unwanted messages. Unwanted messages are processed internally by the dialog box window procedure.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: User-defined.  See Also Dialog Boxes Overview, Dialog Box Functions, CreateDialog, CreateDialogIndirect, CreateDialogIndirectParam, CreateDialogParam, DefWindowProc, DialogBox, DialogBoxIndirect, DialogBoxIndirectParam, DialogBoxParam, SetFocus, WM_INITDIALOG