Question: 怎么  用C 编写 程序 运行的 窗口？

引用 9 楼 u012421456 的回复:你建的都是win2吧，需要看的还很多，建议先把基础的学扎实再进一步吧，我也是推荐windows程序设计 1600多页阿！看来要挑着学？

新建Windows项目（非Console项目） #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; }

你还刚刚起步编程，直接上界面开发，可能会很吃力

要实现你的目的，可以看《windows程序设计》，这本宝典。网上有电子版下。

引用 4 楼 u012903205 的回复:C语言可以用QT吗？有没有中文资料，我英文不会。。。。  QT是C++图形库。  资料的话看《C++ GUI Qt4编程》，PDF下载：http://pan.baidu.com/share/link?uk=3036839225&shareid=2760252208&fid=1758407184  我只能帮你到这了。

C语言可以用QT吗？有没有中文资料，我英文不会。。。。

用GUI图形库编程。。。

参考http://blog.csdn.net/liuchao35758600/article/details/7213978  引用 楼主 c704225271 的回复:用 VC  编写程序 都是  黑色的窗口运行的  ，怎么编写 出 我们自己 喜欢的 窗口运行啊，求大神帮忙~~~


Question: 分块查找的算法分析ASL为什么我始终算的和书上不一样，大神帮忙看看

引用 3 楼 u011410413 的回复:[quote=引用 2 楼 user-3 的回复:] 你算的和结论不是一致的吗，没有错啊，难道我眼花了？ 同觉奇怪，你的导数求出来的不就是那极小值么？  只是 s = -根号n代回原函数的得数不对，貌似是 1-根号n。[/quote]  或者在“所以”后面的结论，应该写  因为n很大， 所以f =（ 1-根号n）是没用的。那么只有 s = 根号n的时候，f = 1+根号n。 1是自然数，直接忽略，节点数变成了 根号n

引用 2 楼 user-3 的回复:你算的和结论不是一致的吗，没有错啊，难道我眼花了？ 同觉奇怪，你的导数求出来的不就是那极小值么？  只是 s = -根号n代回原函数的得数不对，貌似是 1-根号n。

路过。。。 最讨厌做数学题了

你算的和结论不是一致的吗，没有错啊，难道我眼花了？


Question: 新手入门碰到障碍希望高手指点

localtime系列函数，都有对应的线程安全的版本，localtime_r r是指可重入，reentrant

引用 3 楼 BEE_HY 的回复:[quote=引用 1 楼 user-1 的回复:] $ man localtime ...... The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. 返回值是一个静态指针大哥你能不能讲清楚点，我笨你这样回答我也不知道怎么改。谢谢谢谢在指导下谢谢[/quote]谢谢你

引用 6 楼 user-1 的回复:[quote=引用 4 楼 BEE_HY 的回复:] 嗯试了果然是的，这意思是我调用了localtime就要马上的用，或者就不要在调用这个函数了不然他会影响其他的类似指针么？ 对，就是这样的[/quote]很谢谢你

引用 5 楼 user-1 的回复:稍微改一下： struct  tm  tmp; ...... now = localtime(&calptr); tmp = *now; ...... printf("now_3 is:%d:%d:%d\n",now->tm_hour,now->tm_min,now->tm_sec);//这里时间为什么变了求指点 printf("tmp is:%d:%d:%d\n",tmp.tm_hour,tmp.tm_min,tmp.tm_sec); 你会看到，tmp没有变化。  总结一下：localtime以及类似的一系列函数，返回的指针都是指向同一个公用内存，每次调用这些函数，就把当前时间的内容覆盖那块内存，然后返回一个指向那块公用内存的指针。所以，之前返回的指针的内容会变化。 解决的办法：每次调用之后，马上使用或者保存返回值的内容，否则以后会失效。你好很谢谢你

引用 4 楼 BEE_HY 的回复:嗯试了果然是的，这意思是我调用了localtime就要马上的用，或者就不要在调用这个函数了不然他会影响其他的类似指针么？ 对，就是这样的

引用 2 楼 user-1 的回复:在report函数的最后加上这四行： printf("%p\n", now); printf("%p\n", accesstime); printf("%p\n", lmodifytime); printf("%p\n", lchangetime); 你会发现他们的值全都一样。 所以，每次调用localtime，now的内容都会变化，也就是man里面说的might be overwritten by subsequent calls嗯试了果然是的，这意思是我调用了localtime就要马上的用，或者就不要在调用这个函数了不然他会影响其他的类似指针么？

引用 1 楼 user-1 的回复:$ man localtime ...... The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. 返回值是一个静态指针大哥你能不能讲清楚点，我笨你这样回答我也不知道怎么改。谢谢谢谢在指导下谢谢


Question: 笔试题目来了，

引用 7 楼 u012879787 的回复:[quote=引用 5 楼 lovesmiles 的回复:] [quote=引用 3 楼 u012879787 的回复:] [quote=引用 2 楼 Evhung 的回复:] x = 1; 50  100;  为什么x++不是？  还有，为什么是50----100 之间？  [/quote] x++有三条汇编指令 x内存入寄存器 寄存器自加1 寄存器数据放回内存x  多线程可以在这三条指令中间插入其它的指令的，这些指令如果对x有操作，显然结果就不可知了。 tally += 1 一样是分为三条指令，最坏的情况就是线程一读x，线程二也读x，线程一寄存器加一，线程二寄存器加一，放回 x，线程二放加x，这种情况虽然二个线程都对x加1，但显然只加了一次。所以到最后只加50次。  最好的情况就是线程一的for结束，再到线程二的for 一共执行100次 [/quote]  编译器不是有个优化吗？  volatile的问题，是防止编译器优化。 由于 我提供的代码里是没有volatile这个关键字，  你说，会不会因为 没有volatile 影响结果，导致结果最终不会在50---100 以内啊？  [/quote] 已经分析了每次+1都有同时访问冲突和每次+1都没有访问冲突的情况。  你开不开优化都无关要紧了，不会跳出这两个极端情况的。

引用 5 楼 lovesmiles 的回复:[quote=引用 3 楼 u012879787 的回复:] [quote=引用 2 楼 Evhung 的回复:] x = 1; 50  100;  为什么x++不是？  还有，为什么是50----100 之间？  [/quote] x++有三条汇编指令 x内存入寄存器 寄存器自加1 寄存器数据放回内存x  多线程可以在这三条指令中间插入其它的指令的，这些指令如果对x有操作，显然结果就不可知了。 tally += 1 一样是分为三条指令，最坏的情况就是线程一读x，线程二也读x，线程一寄存器加一，线程二寄存器加一，放回 x，线程二放加x，这种情况虽然二个线程都对x加1，但显然只加了一次。所以到最后只加50次。  最好的情况就是线程一的for结束，再到线程二的for 一共执行100次 [/quote]  编译器不是有个优化吗？  volatile的问题，是防止编译器优化。 由于 我提供的代码里是没有volatile这个关键字，  你说，会不会因为 没有volatile 影响结果，导致结果最终不会在50---100 以内啊？

引用 5 楼 lovesmiles 的回复:[quote=引用 3 楼 u012879787 的回复:] [quote=引用 2 楼 Evhung 的回复:] x = 1; 50  100;  为什么x++不是？  还有，为什么是50----100 之间？  [/quote] x++有三条汇编指令 x内存入寄存器 寄存器自加1 寄存器数据放回内存x  多线程可以在这三条指令中间插入其它的指令的，这些指令如果对x有操作，显然结果就不可知了。 tally += 1 一样是分为三条指令，最坏的情况就是线程一读x，线程二也读x，线程一寄存器加一，线程二寄存器加一，放回 x，线程二放加x，这种情况虽然二个线程都对x加1，但显然只加了一次。所以到最后只加50次。  最好的情况就是线程一的for结束，再到线程二的for 一共执行100次 [/quote]1楼牛B,比我想的要多

引用 3 楼 u012879787 的回复:[quote=引用 2 楼 Evhung 的回复:] x = 1; 50  100;  为什么x++不是？  还有，为什么是50----100 之间？  [/quote] x++有三条汇编指令 x内存入寄存器 寄存器自加1 寄存器数据放回内存x  多线程可以在这三条指令中间插入其它的指令的，这些指令如果对x有操作，显然结果就不可知了。 tally += 1 一样是分为三条指令，最坏的情况就是线程一读x，线程二也读x，线程一寄存器加一，线程二寄存器加一，放回 x，线程二放加x，这种情况虽然二个线程都对x加1，但显然只加了一次。所以到最后只加50次。  最好的情况就是线程一的for结束，再到线程二的for 一共执行100次

我还以为是今天阿里的笔试题呢。。。有人分享就好了。。。

引用 2 楼 Evhung 的回复:x = 1; 50  100;  为什么x++不是？  还有，为什么是50----100 之间？

x = 1; 50  100;

第一题选d，因为这个操作可以用一条指令实现，是原子操作。 第二题最是50-100之间。


Question: 跪求大家推荐一款C的编程软件

VC 6或GCC

slickedit 和vs

win-tc

五花八门，学习了！我偶尔练习的话win下用dev C++,linux下用vi

引用 48 楼 Heaydeny 的回复:又看到推荐vim Emacs的，，，等新人学完，心都扒凉扒凉了，，，，，，，，新手就用vs2008 Express，或者vs2010 Express，VC6太老啦， 有道理。

引用 31 楼 Adol1111 的回复:[quote=引用 30 楼 ping_yourheart 的回复:] 楼主说了只是初学者，各位大神不要推荐什么vi,vim,emacs,刚开始就用这些只会让楼主失去兴趣，建议windows下用VS，linux下用Qt creater 或者 eclips，等楼主熟悉了语言之后再来推荐高大上的工具吧。 vim说实话对于大部分人来说纯粹使兴趣，新手用vim写项目相当吃力，而且非常容易出问题。不过纯粹把vim当成查看代码的工具也没啥问题，前提是配置好。 不过eclipse啥的也同样非常非常的不好用，包括用eclipse写Java，提示什么的非常的鸡肋，appcode和VS+vax/resharper就好很多，可惜都没有linux下的工具。Qt还算不错。还是希望Jetbrains的C++ IDE早点开发好，那才是神器啊（VS虽好，但实在是太大了....）。[/quote]  idea不错，最好用的Java IDE

引用 3 楼 maersi2013 的回复:C语言程序设计 谭浩强，书比较薄，适合初学者，待有点基础之后可以学点进阶的  刚看到有一个人推荐这本书是这么说的：找到这本书里面的错误，然后把它都改正确了，你就差不多了

dev cpp

Falcon C++  IDE; Falconcpp.sourceforge.net下载。

VC++6.0吧，虽然是个比较老的东西，但是足够初学者用了，调试什么的都很方便，初学者要尽快学会调试程序，不然程序出错了都不知道如何查错，很花费时间~

DEV C++

我推薦VC6.0 因為它可以看到彙編代碼，幫助你理解整個流程。 http://see.xidian.edu.cn/cpp/html/1117.html

引用 30 楼 ping_yourheart 的回复:楼主说了只是初学者，各位大神不要推荐什么vi,vim,emacs,刚开始就用这些只会让楼主失去兴趣，建议windows下用VS，linux下用Qt creater 或者 eclips，等楼主熟悉了语言之后再来推荐高大上的工具吧。 vim说实话对于大部分人来说纯粹使兴趣，新手用vim写项目相当吃力，而且非常容易出问题。不过纯粹把vim当成查看代码的工具也没啥问题，前提是配置好。 不过eclipse啥的也同样非常非常的不好用，包括用eclipse写Java，提示什么的非常的鸡肋，appcode和VS+vax/resharper就好很多，可惜都没有linux下的工具。Qt还算不错。还是希望Jetbrains的C++ IDE早点开发好，那才是神器啊（VS虽好，但实在是太大了....）。

vim 是一个强大的编辑器，不过里面有很多控制命令，如果新手能够坚持的话，那么对你的帮助是很大的，不过对于大一点的程序编程，我推荐source  insight，非常好用。编译器就用gcc吧，很好。 一般C开发公司都会用source insight+gcc开发。

引用 36 楼 mmlinux 的回复:如果是新手，并且希望Windows下编程，我建议用VC++，XP用6.0的，Win7以上用VC2008、VC2010吧。 如果在Linux下，我觉得你应该很清楚，用Vim+GCC就行。  很好

我个人推荐你使用vc++，入门简单

c应该是比较基本的，照着书本学也行的啊


Question: C语言指针方面的问题

第二个问题： 第一个程序，你分配了一个堆上的地址空间，让p去指向它，然后q也指向了他，但是p又重新指向了m所在的地址空间，其实最后就是p指向了栈，q指向了堆，按道理来说,malloc函数是不会对刚分配的堆空间进行初始化的，因此你打印出来的值应该是个随机数。 第二个程序，p和q都是指向堆，而且是同一个内存地址，因此你将m存入p指向的地方，那么q也是能够访问的，因此能打印出来1,。   讲的东西就完了，其中有几点要了解： 1，malloc,calloc,realloc函数分配的内存空间都是在堆上，因此作为程序管理员的你，必须在用完后手动释放该段内存，不然会造成内存泄露，这是最常见的内存错误，使用free函数进行释放。 2，对于堆上的数据，也就是你函数中定义的局部变量，他的生命周期就是你的函数的开始和结束，因此你不应该让一个全局指针去指向一个局部变量，不然有可能造成段错误。

一个一个讲吧，第一个问题： 第一个程序，你的指针变量p指向的是malloc出来的内存空间，这段内存空间其实是在堆上的，因此你将m（1）存入了p指向的内容空间，因此打印出来的1不是m的1，而是p指向的内容空间中的1，不信你可以在赋值后改变m的值，并不影响你p的值。 第二个程序，你的指针变量p指向的是m所在的内存空间，这段内存空间其实是在栈上面的，因此你打印的1是m的值，你将m的值变化了，那么p打印的也就变化了。

#include<stdio.h> #include<stdlib.h> int main()         {         	int *p;  //定义一个指针变量p，变量入栈         	int *q; // 定义一个指针变量q,变量入栈         	p=(int*)malloc(sizeof(int));  //在堆中开辟新的内存空间，p指向堆中的新空间的首地址         	q=p;//q指针也指向p指针所指的堆内存地址         	int m; //定义变量m，变量入栈         	m=1; //栈中m的值赋值为1         	p=&m; //p指针指向m在栈中的内存地址。         	printf("%d",*q); // 打印q指针所指的堆中的内存中int类型的值。         	return 0;         }    和   #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;          	int *q;         	p=(int*)malloc(sizeof(int));          	q=p;         	int m;         	m=1;         	*p=m; //p指针所指的堆中的内存 赋值为 栈中m内存中的值。 是堆内存的空间赋值为1了         	printf("%d",*q);  // 打印q指针所指的堆中的内存中int类型的值。         	return 0;         }

#include<stdio.h> #include<stdlib.h> int main()         {         	int *p;//定义一个指针变量p，变量入栈         	p=(int*)malloc(sizeof(int));//在堆中开辟内存空间，栈中的p指向堆中的内存地址         	int m;//定义一个int变量，变量入栈         	m=1; //栈中m变量的内存的值赋值为1         	*p=m;//修改栈中p所指向的堆中的内存的值为m内存中的值。         	printf("%d",*p);   //打印出的值与m相等，但是*p打印的是堆中内存的值，不是m所在栈内存的值         	return 0;         }  和  #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;//定义一个指针变量p，变量入栈         	int m;//定义一个int变量m，变量入栈         	m=1; //m所在栈内存的值赋值为1         	p=&m;// p指向m所在内存地址         	printf("%d",*p);  //打印p指针指向的m内存中的值         	return 0;         }

malloc 要检查返回值，因为有可能返回NULL。对NULL解引用也会报错。要注意

第一个问题： 第一个程序，你的指针变量p指向的是malloc出来的内存空间，这段内存空间其实是在堆上的，因此你将m（1）存入了p指向的内容空间，因此打印出来的1不是m的1，而是p指向的内容空间中的1，不信你可以在赋值后改变m的值，并不影响你p的值。 第二个程序，你的指针变量p指向的是m所在的内存空间，这段内存空间其实是在栈上面的，因此你打印的1是m的值，你将m的值变化了，那么p打印的也就变化了。  第二个问题： 第一个程序，你分配了一个堆上的地址空间，让p去指向它，然后q也指向了他，但是p又重新指向了m所在的地址空间，其实最后就是p指向了栈，q指向了堆，按道理来说,malloc函数是不会对刚分配的堆空间进行初始化的，因此你打印出来的值应该是个随机数。 第二个程序，p和q都是指向堆，而且是同一个内存地址，因此你将m存入p指向的地方，那么q也是能够访问的，因此能打印出来1,。

第一个输出值不确定 第二个输出1

问题一： 1.      int *p;         // 定义一个int型指针p，未初始化，指向不定          p=(int*)malloc(sizeof(int));   // p指向新开辟的int对象空间，动态开辟的空间需要程序员负责释放(free(p))          int m;                  m=1;          *p=m;      // 对指针p解引用操作（也就是引用到指针指向的对象），对其赋值为m的值 1          printf("%d",*p);       // 打印p指向的对象的值 1          return 0 2.        int *p;      // 同上          int m;          m=1;          p=&m;      // 让指针p指向对象m （也就是将m的地址赋给p）          printf("%d",*p);        // 打印p指向的对象的值 1          return 0;  问题二：以上解释过的不再赘述 1      q=p;     // 让q指向p指向的对象内存（也就是两个指针的指向相同）          p=&m;   // 让p指向m          printf("%d",*q);    // 打印q指向的对象的值 （不确定，因为q指向的是新开辟的空间，没有初始化）  2      *p=m;         // 将m的值 赋给p指向的空间的对象，因为q也指向这个对象，所以下一行打印q指向对象的值也就是 m 的值了          printf("%d",*q);

引用 楼主 baidu_18267771 的回复:有两个： 第一个问题： #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;         	p=(int*)malloc(sizeof(int));         	int m;         	m=1;         	*p=m;         	printf("%d",*p);         	return 0;         } 和 #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;         	int m;         	m=1;         	p=&m;         	printf("%d",*p);         	return 0;         } 这两种定义方式有区别么？区别在哪里？有区别最好从内存方面讲讲； 第二个问题： #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;         	int *q;         	p=(int*)malloc(sizeof(int));         	q=p;         	int m;         	m=1;         	p=&m;         	printf("%d",*q);         	return 0;         }  和 #include<stdio.h> #include<stdlib.h> int main()         {         	int *p;         	int *q;         	p=(int*)malloc(sizeof(int));         	q=p;         	int m;         	m=1;         	*p=m;         	printf("%d",*q);         	return 0;         } 两种代码的区别在哪里？希望大神仔细讲讲。谢谢大家。  尝试回答楼主的疑问。 问题一，这两种定义方式有区别么？区别在哪里？有区别最好从内存方面讲讲  从内存角度来说， 第一段代码中的整型指针*p指向了m的值，m为1。我们先给p申请一块它要用的内存。 第二段代码中，我们将指针p初始化到了指向m的位置，因此指针p自然指向了1（m位置上存的是1）。  问题二，两种代码的区别在哪里？ 这两段代码值得提一下的是 q = p以上部分，他们都一样，而到了q = p的时候，表明了 指针q 的指向完全就是指针p的指向位置（一块申请出来给p的内存）。而代码一之后是只把指针p初始化到了m的位置，指针q没有被初始化到m，所以它的指向自然没有被定义。代码二则不同，指针p的指向位置（即申请的那块内存）被明确赋值（值为1，和m的位置无关），因此q也就指向了1，同块内存位置。

malloc分配指定长度的空间，记得用完要释放free

malloc了，要free，，不然导致内存泄露

这种问题，最好的理解就是调试程序，查看每个变量的地址及其值的变化，别人说多少，你都不一定理解，调几遍就知道，地址、值的区别了

计算机组成原理→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


Question: 数学测试，用C描述，题目来了！分高点当散小分

#!/usr/bin/python  all = [ [a, b, c, d, e]     for a in range(1, 7)     for b in range(1, 7)     for c in range(1, 7)     for d in range(1, 7)     for e in range(1, 7) ]  def check(a):     b = [         abs(a[0] - a[1]),         abs(a[1] - a[2]),         abs(a[2] - a[3]),         abs(a[3] - a[4]) ]     return len(set(a)) > 2 and 5 not in b  count = 0  for a in all:     if check(a):         count += 1  print count  用python写了个穷举，结果是5880没错。 如果是穷举，那么主要还是两个判断条件要写对。 如果是当数学问题，那么复习下排列组合吧。

围观5楼大神.

谢谢大家辛苦帮忙啦，总算解决了问题，谢谢各位，爱CSDN！

输出行数太多，控制台显示不了，可加头文件 #include <Windows.h>，然后在main()中加入如下代码：  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 控制台窗口句柄 	COORD bufferSize = { 0 };  	system("mode con cols=65 lines=25");  	bufferSize.X = 80; bufferSize.Y = 6000; 	SetConsoleScreenBufferSize(hOut, bufferSize);

补个能完整输出所有组合的：  #include <stdio.h> #include <math.h>  int jdg1(int *p);//判断“相邻的两槽的高度差不能为5” int jdg2(int *p);//判断“至少有3个不同的数”  int main() { 	int a[6], num = 0;// a[1]到a[5]分别为5个槽的高度，num为符合条件的组合数 	for (a[1] = 1; a[1] < 7; a[1]++) 	{ 		for (a[2] = 1; a[2] < 7; a[2]++) 		{ 			for (a[3] = 1; a[3] < 7; a[3]++) 			{ 				for (a[4] = 1; a[4] < 7; a[4]++) 				{  					for (a[5] = 1; a[5] < 7; a[5]++) 					{ 						if (jdg1(a) && jdg2(a)) 						{ 							for (int i = 1; i < 6; i++) 							{ 								printf("%d ", a[i]); 							} 							printf("-- %d\n", ++num); 						} 					}  				}  			} 		} 	}  	return 0; }  int jdg1(int *p) { 	for (int i = 1; i < 5; i++) 	{ 		if (abs(*(p + i) - *(p + i + 1)) == 5) 			return 0; 	} 	return 1; }  int jdg2(int *p) { 	int i, b[7], count = 0; 	for (i = 1; i < 7; i++) 		b[i] = 0; 	for (i = 1; i < 6; i++) 		b[*(p + i)]++; 	for (i = 1; i < 7; i++) 	{ 		if (b[i] == 0) 			count++; 	} 	if (count>3) 		return 0; 	return 1; }

应该就是这样：  #include <stdio.h> #include <math.h>  int jdg1(int *p);//判断“相邻的两槽的高度差不能为5” int jdg2(int *p);//判断“至少有3个不同的数”  int main() { 	int a[6], num = 0;// a[1]到a[5]分别为5个槽的高度，num为符合条件的组合数 	for (a[1] = 1; a[1] < 7; a[1]++) 	{ 		for (a[2] = 1; a[2] < 7; a[2]++) 		{ 			for (a[3] = 1; a[3] < 7; a[3]++) 			{ 				for (a[4] = 1; a[4] < 7; a[4]++) 				{  					for (a[5] = 1; a[5] < 7; a[5]++) 					{ 						if (jdg1(a) && jdg2(a)) 								num++; 					}  				}  			} 		} 	} 	printf("符合条件的组合有：%d 个\n", num);  	return 0; }  int jdg1(int *p) { 	for (int i = 1; i < 5; i++) 	{ 		if (abs(*(p + i) - *(p + i + 1)) == 5) 			return 0; 	} 	return 1; }  int jdg2(int *p) { 	int i, b[7], count = 0;//b[1] 	for (i = 1; i < 7; i++) 		b[i] = 0; 	for (i = 1; i < 6; i++) 		b[*(p + i)]++; 	for (i = 1; i < 7; i++) 	{ 		if (b[i] == 0) 			count++; 	} 	if (count>3) 		return 0; 	return 1; }

// ConsoleApplication6.cpp : 定义控制台应用程序的入口点。 //  #include "stdafx.h" #include<cstdlib> #include<cmath> #include <vector> #include <set> #include <iostream> using namespace std;  bool Check(vector<int> &vi) { 	if (vi.size() != 5) 		return false; 	 	set<int>sc(vi.begin(), vi.end()); 	if (sc.size() < 3) 		return false;  	for (int i = 0; i < vi.size()-1;i++) 	{ 		if (abs(vi[i] - vi[i + 1]) == 5) 			return false; 	}  	return true; }  void Print(vector<int> &vi) {    for (vector<int>::iterator it = vi.begin(); it != vi.end();it++)    { 	   cout << *it << "\t";    }    cout << endl; }  void Qiujie(vector<int> &vi,int &nCount) {    if (vi.size()==5)    { 	   if (Check(vi)) 	   { 		   Print(vi); 		   nCount++; 	   } 	   return;    }     for (int i = 1; i <= 6;i++)    { 	   vi.push_back(i); 	   Qiujie(vi,nCount); 	   vi.pop_back();    }  }  int _tmain(int argc, _TCHAR* argv[]) { 	vector<int> vi; 	int iCount = 0; 	Qiujie(vi, iCount); 	cout << iCount << endl; 	system("pause"); 	return 0; }  加班看到此题，闲着无聊也写一下 C++代码，答案是5880个

引用 16 楼 u010957746 的回复:各位大大哥哥，我改了下代码后，结果得到5880的数据，但是还是有一些问题，没找到出错的原因。 代码如下： 最后出现了6 6 6 6 6 这样的数据 还有5880的重复数据，请教应该如何解决~先谢。敬上  if( (i!=j && i!=k && j!=k) || (i!=j && i!=n && j!=n) || (i!=j && i!=m && j!=m) || (j!=k && j!=n && k!=n) || (j!=k && j!=m && k!=m) || (k!=n && k!=m && n!=m) || (i!=j && i!=k && i!=n && i!=m && j!=k && j!=n && j!=m && k!=n && k!=m && n!=m)   最后一个()中的比较是怎么回事？你要想用暴力比较，就直接列10个表达式进行||, 每个表达式都是3个元素两两不等(5中取3的组合数是10) 或者参考我写的check()函数，用一个辅助数组计数。

顺便说一下，别用vc6.0了。和标准差别比较大，会养成坏习惯的。

各位大大哥哥，我改了下代码后，结果得到5880的数据，但是还是有一些问题，没找到出错的原因。 代码如下： #include<stdio.h> #include<math.h> int main(int argc,char *argv[]) { 	//int sert; 	int i,j,k,n,m; 	int num=0; 	for(i=1;i<=6;i++) 	{ 		for(j=1;j<=6;j++) 		{ 			for(k=1;k<=6;k++) 			{ 				for(n=1;n<=6;n++) 				{ 					for(m=1;m<=6;m++) 					{	 						if( abs(i-j) < 5 && abs(j-k) < 5 && abs(k-n) < 5 && abs(n-m) < 5 ) 						{ 							  if( (i!=j && i!=k && j!=k) || (i!=j && i!=n && j!=n) || (i!=j && i!=m && j!=m) || (j!=k && j!=n && k!=n) || (j!=k && j!=m && k!=m) || (k!=n && k!=m && n!=m) || (i!=j && i!=k && i!=n && i!=m && j!=k && j!=n && j!=m && k!=n && k!=m && n!=m) )//暴力不等	 								num++;		 							//printf("%d\n",num); 							printf("[%d,%d,%d,%d,%d]---%d\n",i,j,k,n,m,num); 							 						} 					} 				} 			} 		} 	}		 	return 0; }   最后出现了6 6 6 6 6 这样的数据 还有5880的重复数据，请教应该如何解决~先谢。敬上

引用 6 楼 u010957746 的回复:大哥您好，我在vc6.0环境下运行了一下，什么都不显示是怎么个情况呢，先谢啦。  因为vc6.0是不符合c标准的。你把代码里2处初始化改一下试试。 int v[M] = {0, 0, 0, 0, 0, 0};  int v[N] = {0, 0, 0, 0, 0}; c标准里定义初始化数组时，元素不足时都初始化成0；vc6.0会初始化成0xCD

引用 10 楼 u010030181 的回复:按照你的思路，写了个并不高明的算法，仅供参考！#include <stdio.h> #include <math.h>   #include<stdlib.h>   int main(int argc,char *argv[]) { 	//int sert; 	int i,j,k,n,m; 	int num=0; 	int arry[6] = {7,7,7,7,7,7};	//这个取值随便，只要值不是0-5即可  	for(i=1;i<=6;i++) 	{ 		for(j=1;j<=6;j++) 		{ 			for(k=1;k<=6;k++) 			{ 				for(n=1;n<=6;n++) 				{ 					for(m=1;m<=6;m++) 					{	 						if (abs(i - j) < 5 && abs(j - k) <  5 && abs(k -n) <  5 && abs(n - m) <  5) 						{ 				 			arry[i -1] = i- 1; 							arry[j-1] = j-1; 							arry[k-1] = k-1; 							arry[m-1] = m-1; 							arry[n-1] = n-1; 							int count = 0; 							for (int tmp = 0; tmp < 6; tmp++) 							{ 								if (arry[tmp] == 7) 									++count; 							} 							 							if (count <= 3) 							{ 								num++;		 								//printf("%d\n",num); 								printf("[%d,%d,%d,%d,%d]---%d\n",i,j,k,n,m,num); 								count = 0;	 							} 														 							for (int tmp = 0; tmp < 6; tmp++)	//记得一定要重新初始化  							{ 								arry[tmp] = 7; 									 							} 															 						} 					} 				} 			} 		} 	}		 	return 0;	 } 学习下，研究看看。

引用 9 楼 hilevel 的回复:用最笨的方法遍历所有的情况，结果是6500.... 然后把所有情况都写到文件里了，也没发现不对的地方，就这样吧  #include <stdlib.h> #include <math.h> #include <stdio.h>  const int iSlotNum=5; const int iMinHeight=1; const int iMaxHeight=6; const int iMinDiff=3; const int iMinu=5;  int main(int argc,char *argv[]) { 	//将每种可能的组合视作一个5进制数，对应十进制的0到6^5-1 	int step=iMaxHeight-iMinHeight+1; 	int numsta=0; 	int numend=pow((float)step,iSlotNum)-1; 	int count=0;  	FILE* file=fopen("d:\output.txt","w+"); 	for (int num=numsta;num<=numend;num++) 	{ 		int height[iSlotNum]; 		int tmpnum=num; 		int diff=iSlotNum; 		bool s=true;  		for (int i=0;i<iSlotNum;i++) 		{ 			//将10进制数转换成5进制数，获取每个孔的值 			height[i]=tmpnum%step+iMinHeight; 			tmpnum=(tmpnum-height[i]+iMinHeight)/step;  			printf("%d\t",height[i]); 			fprintf(file,"%d\t",height[i]);  			if (s) 			{ 				//差距必小于5 				if (i>0 && height[i]-height[i-1]>=iMinu) 				{ 					s=false; 				} 				else 				{ 					//计算相异的个数 					for (int j=0;j<i;j++) 					{ 						if (height[i]==height[j]) 						{ 							diff--; 							s=diff>=iMinDiff; 							break; 						} 					} 				} 			} 		}  		if (s) 		{ 			count++; 		}  		printf("%s\n",s?"符合":"不符合"); 		fprintf(file,"%s\n",s?"符合":"不符合"); 	}  	printf("%d",count); 	fprintf(file,"%d",count); 	fclose(file);  	system("pause" ); 	return 0; } 一开始我得出来的是7776。。。也是有一些问题没有考虑明白。

引用 7 楼 user-8 的回复:这是数学问题吧  是的呢版主大大，想用C来实现，数学问题中的A64什么的都忘记啦，嘿嘿，求帮助啦~

这是数学问题吧

引用 5 楼 truelance 的回复:#include <stdio.h>  #define N 5 #define M 6 #define abs(x) ((x)>0?(x):-(x))  int check(int x[]) {     int idx;     int v[M] = {0};     int num = 0;          for (idx = 0; idx < N-1; idx++)     {         if (abs(x[idx] - x[idx+1]) >= 5) return 0;         v[x[idx]] = 1;     }     v[x[N-1]] = 1;          for (idx = 0; idx < M; idx++)         if (v[idx] == 1) num++;     if (num >= 3)         return 1;     else         return 0; }  int main(void) {     int x[N] = {0};     int num = 0;     int idx = 0;      while (idx >=0)     {         if (++x[idx] <= M)         {             ++idx;             if (idx >= N)             {                 if (check(x)) num++;                 --idx;             }             else             {                 x[idx] = 0;             }         }         else         {             --idx;         }     }          printf("num = %d\n", num);     return 0; }    大哥您好，我在vc6.0环境下运行了一下，什么都不显示是怎么个情况呢，先谢啦。

引用 3 楼 zxh707wk 的回复:请贴上你的代码，否则我会认为你是来求代码的伸手党我自认为我的代码实在是太烂了，，都不好意思贴- - #include<stdio.h> int main(int argc,char *argv[]) { 	//int sert; 	int i,j,k,n,m; 	int num=0; 	for(i=1;i<=6;i++) 	{ 		for(j=1;j<=6;j++) 		{ 			for(k=1;k<=6;k++) 			{ 				for(n=1;n<=6;n++) 				{ 					for(m=1;m<=6;m++) 					{	 						if( ( (i==1 && j!=6) || (j==1 && i!=6 && k!=6) || (k==1 && j!=6 && n!=6) || (n==1 && k!=6 && m!=6) || (m==1 && n!=6 )) ) 						{ 							if( ( i!=j && i!=k ) || (i!=j && i!=n) || (i!=j && i!=m) || (j!=k && j!=n) || (j!=k && j!=m) || (k!=n && k!=m) || (i!=j && i!=k && i!=n) || (i!=j && i!=k && i!=m) || (i!=k && i!=n && i!=m) || (j!=k && j!=n && j!=m) || (i!=j && i!=k && i!=n && i!=m && j!=k && j!=n && j!=m && k!=n && k!=m && n!=m) )//300 								num++;		 								//printf("%d\n",num); 								printf("[%d,%d,%d,%d,%d]---%d\n",i,j,k,n,m,num); 						} 					} 				} 			} 		} 	}		 	return 0;	 }  见效了。各位大大。哥哥。


Question: 基于游程编码的二值图像连通区域标记

我最近也在做方面，楼主有代码吗？能发给我吗？谢谢了 1455727899@qq.com

楼主能否共享下 代码 我最近也在做这方面的东西 万分感谢 564354093@qq.com

谢谢，不过我已经自己写出来了

仅供参考#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <graphics.h> int xs[10000]; int ys[10000]; int i=0,xx,yy; int fc,bc; void push(int x,int y) {     xs[i]=x;     ys[i]=y;     if (i<10000-1) {         i=i+1;     } else {         printf("stack overflow!\n");         exit(1);     } } void pop(void) {     i=i-1;     xx=xs[i];     yy=ys[i]; } int check(int x,int y) {     int c;      c=getpixel(x,y); /* 获取当前点的颜色 */     return ((c!=bc)&&(c!=fc));/* 如果颜色为边界色或填充色则不填充 */ } void seedfilling(int x,int y,int fill_color,int boundary_color) {     fc=fill_color;     bc=boundary_color;     push(x,y);     while (1) {         if (i<=0) return;         pop();         if (check(xx,yy)) {             putpixel(xx, yy, 14);getch();  /* 加上这行显示当前填充状态 */              putpixel(xx, yy, fill_color); /* 画点 */              if (check(xx-1,yy  )) push(xx-1,yy  );             if (check(xx  ,yy+1)) push(xx  ,yy+1);             if (check(xx  ,yy-1)) push(xx  ,yy-1);             if (check(xx+1,yy  )) push(xx+1,yy  );             /* 去掉下面四句就是四连通 */             if (check(xx-1,yy-1)) push(xx-1,yy-1);             if (check(xx-1,yy+1)) push(xx-1,yy+1);             if (check(xx+1,yy-1)) push(xx+1,yy-1);             if (check(xx+1,yy+1)) push(xx+1,yy+1);         }     } } void main() {     int a,b,color;     int gdriver = DETECT, gmode, errorcode;     int poly[10];      initgraph(&gdriver, &gmode, "d:\\bc\\bgi");     a=150;     b=140;     color=4;     poly[0]=110;/* 第一个点的x坐标以及y坐标 */     poly[1]=110;     poly[2]=200;/* 第二点 */     poly[3]=105;     poly[4]=170;/* 第三点 */     poly[5]=120;     poly[6]=150;/* 第四点 */     poly[7]=170;     poly[8]=110;/* 多边形的起点与终点一样 */     poly[9]=110;     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 保证边界对八连通是封闭的 */     setviewport(0,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,0,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 恢复默认viewport */     setviewport(0,0,600,300,0);      seedfilling(a,b,color,15);  /* 种子填充多边形 */      getch();     closegraph(); }

我也在找，。。。。。。。


Question: 求大神解释signal（）函数的声明。

SYNOPSIS      #include <signal.h>       void (*      signal(int sig, void (*func)(int)))(int);       or in the equivalent but easier to read typedef'd version:       typedef void (*sig_t) (int);       sig_t      signal(int sig, sig_t func);

void * (signal(int sig, void (*fp)(int)))(int) 这个定义本来就不对  [root@localhost src]# gcc tmp.c tmp.c:21: error: ‘signal’ declared as function returning a function tmp.c: In function ‘signal’: tmp.c:22: warning: return makes integer from pointer without a cast [root@localhost src]#  编译器认为signal是一个函数，并且返回值也是一个函数。C语言不允许返回值是一个函数。 附：signal返回一个函数，函数的类型是 void* (int)，不是返回一个函数指针！

那赵老师，我从网上找的代码：

引用 6 楼 jwj070524 的回复:根据C语言操作符的优先级来看：最里面void (*func) (int)，func是一个函数指针变量；int sig，sig是一个变量；然后它们被()包围，表示它们是函数的参数。signal(int sig, void (*func)(int))，而且它们是signal函数的参数。既然是函数，那么一定会有返回值，signal函数左边是一个*，右边是一个()。括号（函数调用）优先级高于*（指针），但是由于*和signal同在一个括号内，优先级逆转，signal函数返回一个指针。为了清楚起见，把signal(int sig, void (*func)(int))看成一个整体，就叫A吧，变换后成为 void (*A)(int) 这下清楚了吧，A的返回值是一个指针（被括号包住了），然后左边是void，右边是(int)，括号优先级还是最高，表示A的返回值是一个函数指针，函数指针的参数是int，那么函数指针的返回值就是void了。 总结：signal是一个函数，参数是int和void (*func) (int)，signal函数的返回值是一个函数指针，该指针指向的函数参数为int，返回值是void  那如果改变一下呢： 什么情况下那个*指的是函数指针而不是返回值呢？  引用 6 楼 jwj070524 的回复:根据C语言操作符的优先级来看：最里面void (*func) (int)，func是一个函数指针变量；int sig，sig是一个变量；然后它们被()包围，表示它们是函数的参数。signal(int sig, void (*func)(int))，而且它们是signal函数的参数。既然是函数，那么一定会有返回值，signal函数左边是一个*，右边是一个()。括号（函数调用）优先级高于*（指针），但是由于*和signal同在一个括号内，优先级逆转，signal函数返回一个指针。为了清楚起见，把signal(int sig, void (*func)(int))看成一个整体，就叫A吧，变换后成为 void (*A)(int) 这下清楚了吧，A的返回值是一个指针（被括号包住了），然后左边是void，右边是(int)，括号优先级还是最高，表示A的返回值是一个函数指针，函数指针的参数是int，那么函数指针的返回值就是void了。 总结：signal是一个函数，参数是int和void (*func) (int)，signal函数的返回值是一个函数指针，该指针指向的函数参数为int，返回值是void   那如果改变一下：void *（signal (int sig,void (*func) (int)))(int)，先不说在实际中的意义，仅仅说理论上的意义：（）比*的优先级高，那么这个声明的意思就是：返回值是一个函数指针，函数指针所指向的函数有一个参数int，函数指针指向的函数的返回值是void*类型的？

引用 3 楼 zhao4zhong1 的回复:仅供参考//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*x000)[5];//返回值     char (*(x00)())[5];//函数原型，参数为空，返回值为指针     char (*(*x0)())[5];//数组的元素，是个函数指针     char (*(*x[3])())[5];//是个数组，大小为3      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]     赵老师，我是不是可以这么理解呢：   char (*x000)[5] 这个是指针，指向5个char型的字符串；   char (*(x00)())[5] 这是一个函数，返回值是char （*  ）[5];   char (*(*x0)())[5]这是一个函数指针，返回值是char （ *  ）[5];   char (*(*x[3])())[5]这是一个函数指针数组，返回值是char （*  ）[5]; 这里的char （* ）[5]指的是一个指向 五个char型元素的指针吧，我在看c专家编程，根据里边的声明的优先级别解释这个char （* ）[5]解释的通。

引用 1 楼 T5500 的回复:返回函数指针的函数，指向一个具有一个int型形参、返回类型为void的函数  为什么是这样呢？

我还有很多不知道的知识。。。

//C++11可以使用尾置返回类型的语法写出等价的声明，看起来会比较好理解一点 auto signal(int sig, void (*func)(int)) -> void(*) (int);

返回函数指针的函数，指向一个具有一个int型形参、返回类型为void的函数


Question: sscanf 如何得到下面的数据

仅供参考#include <stdio.h> #include <string.h> #include <time.h> #include <sys/timeb.h>  struct tm st; time_t tt; char mon[4]; char mn[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int i; char timstr[27]; char tmpbuf[128]; struct _timeb tb; int tz; char c;  void main() {     strcpy(timstr,"08/Dec/2011:15:25:03 +0800");     sscanf(timstr,"%2d/%3s/%4d:%2d:%2d:%2d",&st.tm_mday,mon,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec);     for (i=0;i<12;i++) if (0==stricmp(mn[i],mon)) {st.tm_mon=i; break;}     st.tm_year-=1900;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S\n",localtime(&tt));         printf(tmpbuf);//2011-12-08 15:25:03     } else {         printf("[%s] is Invalid time string!\n",timstr);     }      _ftime(&tb);     strftime(tmpbuf,128,"%m/%b/%Y:%H:%M:%S",localtime(&tb.time));     tz=-tb.timezone;     c=(tz>0)?'+':'-';     tz=(tz>0)?tz:-tz;     sprintf(tmpbuf,"%s %c%02d%02d\n",tmpbuf,c,tz/60,tz%60);     printf(tmpbuf);//12/Dec/2011:17:36:41 +0800 }

哦，我忘记传值了，难怪

你测试过?....

char *str="1988/07/01-22:33:10"; sscanf(str, "%d/%d/%d-%d:%d:%d",nyear,nmouth,nday,ntime,nminitue,nsecond);


Question: 求大牛帮忙，sscanf中的正则表达式

仅供参考#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

引用 1 楼 akirya 的回复:sscanf的正则太弱了，先strstr找到crash再用sscanf+1,c用正则表达式很麻烦。。。

引用 5 楼 truelance 的回复:当然不算。你应该知道什么是正则吧...只知道.net的类库。

引用 3 楼 judwenwen2009 的回复:[quote=引用 2 楼 truelance 的回复:] c的标准库里没有对正则表达式的支持。 你要找第三方库，或者按LS的方法近似处理。  sscanf里的不算正则吗。。。[/quote]  当然不算。你应该知道什么是正则吧...

引用 1 楼 akirya 的回复:sscanf的正则太弱了，先strstr找到crash再用sscanf  嗯，我之前是这种用法，但需要匹配的文本太多了，所以我想直接用sscanf进行的，花了一上午还没调查出结果，难道不可能吗？

引用 2 楼 truelance 的回复:c的标准库里没有对正则表达式的支持。 你要找第三方库，或者按LS的方法近似处理。  sscanf里的不算正则吗。。。

sscanf的正则太弱了，先strstr找到crash再用sscanf


Question: [菜鸟提问之3]关于C指针，这样在VC6下不能通过，codeblock却是OK的，为何？

只能说codeblock语法不严谨

引用 6 楼 truelance 的回复:c里对类型转换检查不严格，只会报warning. c++检查严格，会报error.  所以.c文件会报warning编译通过, .cpp文件编译不通过。+1

引用 4 楼 relaxisland 的回复:编译不过才是对的吧，太危险了 如果你要这么使用， 就用强转吧  #貌似没有设置项  就我目前的知识来说，是的。通不过才是对。我不是要这么使用，只是想知道原因。

编译不过才是对的吧，太危险了 如果你要这么使用， 就用强转吧  #貌似没有设置项

主要是C 和 C++的区别

.c和.cpp扩展名的区别

VC6 不要后缀.cpp 一样只是警告


Question: 如何快速求两个集合的交集，并集和差集

[code=java][/code]

赵4老师，回答大多是复制来的吧- =

引用 7 楼 mujiok2003 的回复:[quote=引用 3 楼 my3439955 的回复:] set_union 并集 set_difference 差集 set_intersection 交集 set_symmetric_difference 对称差集  都在#include <algorithm>  ++[/quote]+++

引用 3 楼 my3439955 的回复:set_union 并集 set_difference 差集 set_intersection 交集 set_symmetric_difference 对称差集  都在#include <algorithm>  ++

仅供参考： #include <algorithm> #include <iostream> #include <functional> #include <cstring> using namespace std; int main() {     char *Alphabet = "abcdefghijklmnopqrstuvwxyz" ;     char *Vowels   = "aeiou" ;     char *AlphaNum = "0123456789abcdef" ;     char result[45] ;     char *last ;      int lenA  = strlen(Alphabet) ;     int lenV  = strlen(Vowels  ) ;     int lenAN = strlen(AlphaNum) ;      cout << "Alphabet = " << Alphabet << endl ;     cout << "Vowels   = " << Vowels   << endl ;     cout << "AlphaNum = " << AlphaNum << endl ;      cout << "\nusing non-predicate versions" << endl ;      //non-predicate set_difference     last = set_difference(Alphabet, Alphabet+lenA,                           AlphaNum, AlphaNum+lenAN,                           result) ;     *last = 0 ;     cout << "set_difference(Alphabet, AlphaNum) =  " << result << endl ;      //non-predicate set_intersection     last = set_intersection(Alphabet, Alphabet+lenA,                             AlphaNum, AlphaNum+lenAN,                             result) ;     *last = 0 ;     cout << "set_intersection(Alphabet, AlphaNum) =  " << result << endl ;      //non-predicate set_symmetric_difference     last = set_symmetric_difference(Alphabet, Alphabet+lenA,                                     Vowels  , Vowels  +lenV,                                     result) ;     *last = 0 ;     cout << "set_symmetric_difference(Alphabet, Vowels) =  " << result << endl ;      //non-predicate set_union     last = set_union(Alphabet, Alphabet+lenA,                      AlphaNum, AlphaNum+lenAN,                      result) ;     *last = 0 ;     cout << "set_union(Alphabet, AlphaNum) =  " << result << endl ;      cout << "\nusing predicate versions" << endl ;      //predicate set_difference     last = set_difference(Alphabet, Alphabet+lenA,                           AlphaNum, AlphaNum+lenAN,                           result  , less<char>()) ;     *last = 0 ;     cout << "set_difference(Alphabet, AlphaNum) =  " << result << endl ;      //predicate set_intersection     last = set_intersection(Alphabet, Alphabet+lenA,                             AlphaNum, AlphaNum+lenAN,                             result  , less<char>()) ;     *last = 0 ;     cout << "set_intersection(Alphabet, AlphaNum) =  " << result << endl ;      //predicate set_symmetric_difference     last = set_symmetric_difference(Alphabet, Alphabet+lenA,                                     Vowels  , Vowels  +lenV,                                     result  , less<char>()) ;     *last = 0 ;     cout << "set_symmetric_difference(Alphabet, Vowels) =  " << result << endl ;      //predicate set_union     last = set_union(Alphabet, Alphabet+lenA,                      AlphaNum, AlphaNum+lenAN,                      result  , less<char>()) ;     *last = 0 ;     cout << "set_union(Alphabet, AlphaNum) =  " << result << endl ;      return 0 ; }

数组很不方便？？

引用 5 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 1 楼 Idle_ 的回复:] 主要看你两个集合中具体的数据类型是什么了，位串一般常用于集合中数据类型是bool型，那么每个bit对应一个bool变量，处理交并差集只能处理两个集合拥有同样意义的相同位置元素时。 如果是其它类型的，处理交并差集时主要是先排序原始集合然后同时遍历，根据元素数值的比较决定是否出现在最终结果集合中。 一个bool变量是只占一位吗？还是一个字节？[/quote]  这个随便你怎么定义这个集合了，你可以定义成一个bool占用1bit，也可以定义成一个bool类型元素占用1字节，也可以定义成int，long, int64, customBool1024....

引用 1 楼 Idle_ 的回复:主要看你两个集合中具体的数据类型是什么了，位串一般常用于集合中数据类型是bool型，那么每个bit对应一个bool变量，处理交并差集只能处理两个集合拥有同样意义的相同位置元素时。 如果是其它类型的，处理交并差集时主要是先排序原始集合然后同时遍历，根据元素数值的比较决定是否出现在最终结果集合中。 一个bool变量是只占一位吗？还是一个字节？


Question: 讨论下下面两个程序的运行速度差异

我没有时间去弄你这个程序，不过我可以告诉你大概的原因。 C程序在编译连接后，会变成机器码，而汇编语言是最接近机器码的语言，一起我用过汇编编写程序的。  你可以反汇编的打印下这个程序的汇编代码，你会发现，第二个的代码比第一个的代码的汇编指令要少 ，应该就是这个问题。 比如while(1)和for(;;)都是死循环，但是for(;;)的汇编指令数量比whle(1)少，因此我们做死循环的时候，for(;;)要快一些。

这个跟上面那两个比，哪个快一些？ #include <stdio.h>  int main() { 	int m, n; 	int num=0; 	int sum=0; 	int i; 	scanf("%d%d", &m, &n); 	getchar(); 	for (;m<=n;m++) 	{ 		for (i = 2; i*i <= m; i++) 		{ 			if (m%i == 0)goto _NEXT; 		} 		sum = sum + m; 		num++; 	_NEXT:; 	} 	printf("%d\t%d", num, sum);  	return 0; }

靠，贴代码会死啊，可怜我用手机接电脑上网的。。。，打开图片超慢。。。

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

算质数这么算也是醉了。

但当M取负数的时候2比1快，因为循环的条件不一样。 其它情况也很简单。

两段代码主要差异在内部的while循环 但最大执行次数 都是 M-a. 外层N-M次。

提供你的编译器+编译参数，和实际测试数据。 没有具体数据就不要讨论效率问题。


Question: 字符串指针跟字符串指针赋值问题

引用 3 楼 lovesmiles 的回复:……p全部是指向const char的指针，它所指的值是不能被改变的，当然会出问题了。 像楼上所说的将p必成指向数组空间才可以+1现在越来越喜欢用 "+1" 了

引用 8 楼 starytx 的回复:[quote=引用 5 楼 happyming0809 的回复:] [quote=引用 3 楼 lovesmiles 的回复:] ……p全部是指向const char的指针，它所指的值是不能被改变的，当然会出问题了。 像楼上所说的将p必成指向数组空间才可以 言之有理哦。但是又想用指针。[/quote]问题根本在于p指向哪里。如果指向一个字符串常量（"xxxxxx"），那么如果通过strcpy等函数往其指向的空间写如数据是不可以的，除非指向的这个空间可写（比如指向一个数组，或者指向动态分配的空间等等都可以）[/quote] 解释的很透彻。学习了。C语言还有很多东西值得去思考。

引用 5 楼 happyming0809 的回复:[quote=引用 3 楼 lovesmiles 的回复:] ……p全部是指向const char的指针，它所指的值是不能被改变的，当然会出问题了。 像楼上所说的将p必成指向数组空间才可以 言之有理哦。但是又想用指针。[/quote]问题根本在于p指向哪里。如果指向一个字符串常量（"xxxxxx"），那么如果通过strcpy等函数往其指向的空间写如数据是不可以的，除非指向的这个空间可写（比如指向一个数组，或者指向动态分配的空间等等都可以）

引用 5 楼 happyming0809 的回复:[quote=引用 3 楼 lovesmiles 的回复:] ……p全部是指向const char的指针，它所指的值是不能被改变的，当然会出问题了。 像楼上所说的将p必成指向数组空间才可以 言之有理哦。但是又想用指针。[/quote]1、字符数组也可以当指针用。2、让p指向内存的堆（使用malloc分配）、3让p指向字符数组（栈）。。。

p指向的地址空间“dd”是只读的，所以不能向它指向的内存空间赋值

引用 3 楼 lovesmiles 的回复:……p全部是指向const char的指针，它所指的值是不能被改变的，当然会出问题了。 像楼上所说的将p必成指向数组空间才可以 言之有理哦。但是又想用指针。

引用 2 楼 shenimenyilian 的回复:#include <string.h>  int main(void) {      char p[5];    char *part;     part = "ming";       strcpy(p,part);       printf("%s\n",p);  system("pause");  return 0; }一定要改为数组才行吗？

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

strcpy(p,part);    就可以了


我觉得最好用十六进制吧，这样好区分

你要用16进制数

楼主给的数据用我这边的工具验签不通过

引用 4 楼 Java_Devil 的回复:嗯 这个搞定了，自己写了个函数。  sm2你懂吗？不懂。。。

引用 3 楼 zxhuser-4 的回复:有些字符本来就是打不出来的噻嗯 这个搞定了，自己写了个函数。  sm2你懂吗？

有些字符本来就是打不出来的噻

引用 1 楼 mio__jiang 的回复:楼主给的数据用我这边的工具验签不通过那你那里有sm2的代码或资料可以给我参考下吗？


Question: 请教关于数组中输入数据自动结束的问题！

选个不可能的数据作为结束标志，比如需要的数据全是正数，那当输入负数的时候表示输入结束。

我还是楼主，不能连续3次回复，好不方便，我想说二楼不对，c语言支持变长数组

上面掉了输入语句  #include <stdio.h> #include <stdlib.h>  int *array;  int main(void) {     int n,i;     puts("please input the array number:");     scanf("%d",&n);     array=(int *)calloc(n,sizeof(int));      puts("please input the data:");     for(i=0;i<n;i++)     {         printf("%d: ",i+1);         scanf("%d",&array[i]);     }     puts("the data you input is:");     for(i=0;i<n;i++)         printf("%d: %d",i+1,array[i]);     return 0; }

谢谢6楼，先看看行不行

5楼的说法不对，  #include <stdio.h> #include <stdlib.h>  int *array;  int main(void) { int n,i; puts("please input the array number:"); scanf("%d",&n); array=(int *)calloc(n,sizeof(int)); puts("the data you input is:"); for(i=0;i<n;i++) printf("%d: %d",i+1,array[i]); return 0; }

放堆里。malloc（） c++可用new。       vector。 string

可以使用vector动态数组

仅供参考 #include <stdio.h> #include <stdlib.h>  int getnum(int num[], int max) { 	int i; 	char str[100]; 	for (i=0;;i++) 	{ 		scanf("%s", str); 		num[i]=atoi(str); 		if (getchar() == '\n')break; 	} 	return i+1; }  void putnum(int num[], int len) { 	int i; 	printf("\n"); 	for (i = 0; i < len; i++) 	{ 		printf("\t%3d", num[i]); 	} }  int main() { 	int num[100]; 	int len; 	len=getnum(num, 100); 	putnum(num, len); 	getchar(); 	return 0; }

基本数据类型数组是无法实现的，因为楼主的要求是不管输入多少数据。 要么使用容器或自己定义一个数据类型，实现内部动态内存管理， 无论如何，数组的长度在编译期间就应该确定，否则无法通过编译

可能需要用到HASH表

定义一个长一点的数组。。。

c里不支持可变长度的数组。尽快c99里定义了，但几乎没有编译器至此。 用c++的话，vector可以起到这个动态数组的作用


Question: windows下hbase客户端  Will not attempt to authenticate using SASL (unknown error)

我是来挖坟的

请问楼主这个问题解决了吗？我也遇到同样的问题。442074344这是我的qq，希望您联系我。

引用 8 楼 Sherry10250 的回复:遇到了类似的问题！刚安装好hbase，按照zookeeper》Hadoop》hbase的顺序开启的，开启前两个软件时jps显示都运行正常，可是开启hbase时显示：slave2:regionserver running as process 3491.   slave1:regionserver running as process 3566.   查看日志显示：  不知道到底是什么问题啊！？而且网页60010也打不开，显示无法连接。 求解！求帮助，弄了好几天了也没有搜到解决办法...算是挖坟吗？ 不过呢，既然你配置了外部zookeeper就应该设置Hbase使用外部zookeeper来管理，因为hbase默认带了一个zookeeper。所以日志提示，让你先关闭独立的zookeeper在开启hbase。 4个月了。其实我喜欢瞎看看

我本地就是服务器，对hbase还没什么概念，只是想先在自己机子上尝试一下，大师求教啊！

引用 5 楼 user-5 的回复:啊，在Windows系统上有没有什么区别，我还是一直有这个报错 你的服务器也在windows上吗？  首先你要保证的你的服务器启动成功！    在就是在客户端    要在 hosts这个文件下加上服务器的 主机名与ip的映射关系。

啊，在Windows系统上有没有什么区别，我还是一直有这个报错

引用 3 楼 user-5 的回复:啊，怎么弄的，能说详细点吗，还有你是在什么系统上执行的！ 什么意思，。。HBase服务器在 Ubuntu上啊。用eclipse写的客户端。去建表，，等一些操作。

啊，怎么弄的，能说详细点吗，还有你是在什么系统上执行的！

没人回吗。要结贴了。回就给分！！

问题已解决。  在winodws下的 C:\Windows\System32\drivers\etc\hosts文件中    添加服务器端host与ip的映射关系    如： 10.8.1.135 master


Question: 二分法查找的平均查找长度为log2(n+1)-1,请问这是怎么计算出来的呢？

也许，ASL == 树深度的值。

引用 7 楼 mortimer7866 的回复: 这是书本上的图，一共有11个结点，第一层结点需要比较1次，第二层需要比较两次，依次类推，那么总的比较次数是1+2*2+3*4+4*4=33，既然ASL是平均比较次数，那么用总次数除以总结点数就是ASL，答案33/11=3=log2(n+1)-1; 只是为什么会是这样呢，看不出来log2(n+1)-1的意义。似乎就只是个求高度的式子  感觉你已经自己说出了 log2(n+1)-1的意义。是我把你带沟里了...Sorry。当时我只想说明深度。

感谢五楼，您说的意思我明白了，可是似乎并没有说为什么用高度减1就是ASL呢，刚才又看了一下，知道怎么算这个ASL了，

引用 楼主 mortimer7866 的回复:书本上是这么写的，设内部结点的总数为n=2^n-1,则判定树是深度为h=log2(n+1)的满二叉树（深度为h不计内部结点）。树中第k层上的结点个数为2^(k-1),查找他们所需的比较次数是k.因此在等概率假设下，二分查找成功时的平均查找长度为：ASL约等于log2(n+1)-1  用图示举例法来说说，   说的啰嗦一些，先说二叉树，第一节点其实深度为零，然后往下每走一层则深度增加一。 每层都是2^n个点对吧，但别忘第一层是2^0。所以会有log(n+1)去算它的深度，而这样会多算出一层，比如图片里应该是4层呀，其实也对，只是和编号方式有关。标准编号方式第一层深度是零。

google了都没有

百度。。。

刚刚又翻了下严蔚敏的书，是log2(n+1)-1不会错，只是不知道怎么求得的，各路大神快过来帮帮忙吧！小弟感激不尽


Question: 如何快速查找头文件？

直接man有的找不到的。

man 还是挺好用的。  可以看看man man  man 2 fcntl  man 3 fcntl  显示的都不一样。

find  好用

直接find

可以用ctags这个东西，在/usr/src下面不是有Linux的源文件么，你到源文件根目录使用ctags -R .  生成索引，以后就可以通过在根目录使用vim命令后，再使用:ta xxxxx 找到对应的关键字了。这个效果更好。

当然是把库函数手册放在离开自己不超过一个手臂的距离！

find grep

find正解

根据函数名查找头文件名 。。。查函数库文档啊。。。

头文件放在哪些目录我是知道的，我想知道的是如何根据函数名查找头文件名

find / -name "*.h"

直接到include文件夹里查


Question: 求教VS 中C语言链接失败问题解决方案

只是打错字而已。。。 # include<stdio.h> # define N 3 struct Student { 	char name[10]; 	int mathS; 	int ChiS; 	int EngS; 	float averS; } ; void inputS(struct Student stu[]); struct Student maxarr(struct Student stu[]); void printS(struct Student stu); int main() { 	struct Student stuArr[N]; 	inputS(stuArr); 	printS(maxarr(stuArr)); 	return 0; } void inputS(struct Student stu[]) { 	printf("input the name and the score:\n"); 	int i = 0; 	for (i = 0; i<N; i++) 	{ 		scanf("%s %d %d %d", stu[i].name, stu[i].ChiS, stu[i].EngS, stu[i].mathS); 		stu[i].averS = (stu[i].ChiS + stu[i].EngS + stu[i].mathS) / 3.0; 	} } struct Student maxarr(struct Student stu[]) { 	int i, m = 0; 	for (i = 0; i<N; i++) 	{ 		if (stu[i].averS>stu[m].averS) 			m = i; 	} 	return stu[m]; } void printS(struct Student stu) { 	printf("%s:%d %d %d %f\n", stu.name, stu.ChiS, stu.EngS, stu.mathS, stu.averS); }

是不是要加上extern "C" 这个函数是不是C语言写的函数  extern "C" struct Student maxaver(struct Student stu[]);


Question: 这段代码是否有问题？出现非法访问提示

引用 1 楼 Idle_ 的回复:理论上不能，实践中有可能 -- 主要看你的free是否会引起下层堆管理器释放内存页还给操作系统。 引用 2 楼 brookmill 的回复:这个和返回局部变量指针的性质差不多，属于错误代码，虽然有个别情况能运行正确。 while(current != NULL) { tmp = current->next; free(current); current = tmp; } 引用 4 楼 lixiaobing3000 的回复:对current执行free操作后，之前current指向的内存已经被收回，不能再访问，而current->next是属于这块内存的一部分，所以不能访问。 引用 7 楼 shenimenyilian 的回复:使用一个临时变量先保存current->next   然后再释放current 你这样的结果是未定义的 ok，问题已经解决，散分

你都free掉了current指针，还去用current->next; 会报错的 应该像#2 说的那样，才是正确的

引用 3 楼 zxh707wk 的回复:[quote=引用 2 楼 brookmill 的回复:] 这个和返回局部变量指针的性质差不多，属于错误代码，虽然有个别情况能运行正确。 while(current != NULL) { tmp = current->next; free(current); current = tmp; }+1[/quote]

不要期望这代码有确定结果。

引用 2 楼 brookmill 的回复:这个和返回局部变量指针的性质差不多，属于错误代码，虽然有个别情况能运行正确。 while(current != NULL) { tmp = current->next; free(current); current = tmp; }+1


Question: C语言中scanf输入的问题

这样？  #include <stdio.h> #include <stdlib.h> #include <string.h>  int main(void) { 	int n; 	scanf("%d", &n); 	int arr[256][256];  	for(int i=0; i<n; i++) { 		for(int j=0; j<n; j++) { 			scanf(" %c", &arr[i][j]); 		} 	}  	for(int i=0; i<n; i++) { 		for(int j=0; j<n; j++) { 			printf("%c", arr[i][j]); 		}  		printf("\n"); 	} 	system("pause");  	return 0; }

永远不要scanf("%c",&ch);

大神好多 学习学习

scanf之后用getchar接收'\n'

上代码，vs中不能直接用scanf,要用 scanf_s,scanf()在读取时不检查边界，所以可能会造成内存泄露。所以vc++2005/2008中提供了scanf_s(),在最新的VS2013中也提供了scanf_s()。在调用时，必须提供一个数字以表明最多读取多少位字符。 若一定要使用scanf，在代码最前面接入#define _CRT_SECURE_NO_DEPRECATE

while（getchar（）！= '\n'）     continue；

对了，数据之间还要有空格


Question: 请问这个编译错误如何解决？

typedef是用来定义结构的，结构名不能放在struct后面

引用 2 楼 u010808402 的回复:typedef struct _seqof1 {                             //定义结构体_seqof1     struct _seqof1  *next;     HS_SCCH_Codes   value; } *_seqof1;                                                   //定义结构体指针_seqof1  typedef _seqof1* _seqof1; 两者命名相同，不可能编过，解决办法为使用去掉第一行的_seqof1或换成另外一个名字+1

要不然这样子:  typedef struct _seq { 	struct _seq* next; 	int value; }*_seq1;

引用 2 楼 u010808402 的回复:typedef struct _seqof1 {                             //定义结构体_seqof1     struct _seqof1  *next;     HS_SCCH_Codes   value; } *_seqof1;                                                   //定义结构体指针_seqof1  typedef _seqof1* _seqof1; 两者命名相同，不可能编过，解决办法为使用去掉第一行的_seqof1或换成另外一个名字    这个是花钱买的工具自动生成的，不是人编写的。这个不能修改的，只能通过选择编译器或者更改编译选项来解决。

typedef struct _seqof1 {                             //定义结构体_seqof1     struct _seqof1  *next;     HS_SCCH_Codes   value; } *_seqof1;                                                   //定义结构体指针_seqof1 这个是花钱买的工具自动生成的，不是人编写的。这个不能修改的，只能通过选择编译器或者更改编译选项来解决。

看报错提示就该明白，不能把struct _seqof1类型转化为*_seqof1类型 楼主清楚typedef什么概念吗？


Question: linux c 命名管道 聊天程序 求大神纠错

引用 4 楼 jwj070524 的回复:[quote=引用 3 楼 u012024694 的回复:] @jwj070524： 不会server client模型啊。。。 请教一下我的这种写法需要怎么改才行呢？ 我用循环读取另一个程序创建的管道，应该可以避免“两个程序互相需要对方创建fifo才能开始"这种问题吧？  循环是一个方法，但是不是最好的。还有一点，你发现没有，只有当A发给B后，B才能给A发，反之亦然，你不觉得很别扭吗？管道是单工的，所以你要创建两个来完成进程间通信，为什么不用socket呢，socket是全双工的。如果一定要用命名管道的话，建议开两个线程，一个线程专门来收数据，另外一个线程专门来读取stdin，并发送出去。[/quote] 暑假作业，要求用管道来完成，我也没办法哎。。。

引用 3 楼 u012024694 的回复:@jwj070524： 不会server client模型啊。。。 请教一下我的这种写法需要怎么改才行呢？ 我用循环读取另一个程序创建的管道，应该可以避免“两个程序互相需要对方创建fifo才能开始"这种问题吧？  循环是一个方法，但是不是最好的。还有一点，你发现没有，只有当A发给B后，B才能给A发，反之亦然，你不觉得很别扭吗？管道是单工的，所以你要创建两个来完成进程间通信，为什么不用socket呢，socket是全双工的。如果一定要用命名管道的话，建议开两个线程，一个线程专门来收数据，另外一个线程专门来读取stdin，并发送出去。

程序1创建管道fifo1，然后打开fifo2；程序2创建管道fifo2，然后打开fifo1。两个程序互相需要对方创建fifo才能开始。所以最好写成server client模型，server端先把要创建的都创建好，等待client来打开。

对于这种刚发的帖子，我总是毫不犹豫的顶了。如果火了就是个前排，可以混个脸熟，说不定谁好心就给粉了…稳赚不赔；如果沉了就感觉是我弄沉的，很有成就感，还能捞经验。


Question: 说好的四个字节呢？

四个字节是说好了的  只是没说非要连续

没有规定,自然有别的你想不到的用处  试试 Release版

不说堆，只说栈，内存来看，它的确是只用到了四个字节，但是栈中的分配不是按地址扩展的吗？怎么会不连续呢！

编译选项都有哪些，以及每项设置都起什么作用。 以上知识点迟早是要了解和有选择地掌握的。

你想看连续的    用LINUX下的G++编译一次吧

引用 6 楼 wu13623558890 的回复:[quote=引用 楼主 u012412518 的回复:]  说好的占用四个字节，这里为啥成了12个？有些迷糊了！ 32位win7下的vs2010.。。 没看懂你的问题，你说的占用四个字节说的是，i，j，tmep，还是malloc出来的动态内存？？[/quote] 我说的是栈上的，i，j，temp和指针？？？

引用 楼主 u012412518 的回复: 说好的占用四个字节，这里为啥成了12个？有些迷糊了！ 32位win7下的vs2010.。。 没看懂你的问题，你说的占用四个字节说的是，i，j，tmep，还是malloc出来的动态内存？？

没有规定i,j,temp等要连续。

没有问题的啊

占用4 字节  其他的 没占用啊  听正常的 怎么了

好吧，看错内容了。。。 不要用输出地址的形式来分析内存

你眼瞎，怎么不是4个字节了？这是用十六进制输出的


Question: 将一个正整数中的数字的顺序翻转

求商int a/int b      a<b则结果为0，a=b则为1，a>b则为算术运算中a除以b的商 求余int a%int b   a<b则结果为a,   a=b则为0， a>b则为算术运算中a除以b的余数

# include <stdio.h>    int main(void)  {     int number=0;     //the number to be reversed     int rebmun=0;      //the reversed number     int temp=0;       //working storage          //get the value to be reversed     printf("\nEnter a positive integer:");     scanf("%d",&number); //input digit 43     temp=number;          //reverse the number stored in temp     do    	{ 	   	printf("temp = %d\n", temp);///////////////////////////////////////////////////      	rebmun=10*rebmun+temp%10; //add the rightmost digit      	temp=temp/10;             //remove the rightmost      	printf("temp = %d\n", temp);///////////////////////////////////////////////////    	} while(temp);              //continue while temp>0    	     printf("\nThe number %d reversed is %d rebmun ehT\n", number, rebmun);          return 0;  } 看看这个17和20行， 你知道 除号 / 的用处吧 单步调试看看吧，不会搜搜就行

设断点，单步察看rebmun和temp的制，有助于你理解这个算法


Question: 使用APR库时“未定义的引用”

引用 3 楼 justin_bkdrong 的回复:使用静态方式链接dll (使用 lib),还是使用LoadLibrary ? GetProcess 得不到地址？ 在stack overflow上解决了，库依赖关系的原因，谢谢你了啊

引用 1 楼 justin_bkdrong 的回复:是否是C函数方式导出，而你用C++调用方式调用？ 程序都是C写的，编译器是GCC

是否是C函数方式导出，而你用C++调用方式调用？


Question: 调用函数进行字符串排序，运行出错是什么原因？

引用 4 楼 zxh707wk 的回复:第40行 j=i+1   感谢指正！！

引用 11 楼 wanght99 的回复:而且j是没初始化的.  感谢你的分析！ 写成j=j+1了，应该是j=i+1

引用 7 楼 yshhq 的回复:[quote=引用 5 楼 xiaohuh421 的回复:] char (*p)[20]   // 指向数组的指针, 这个指针可能指向一个char类型, 有20个元素的数组. char *p[]          //指针数组, 数组里面保存的是char*.  区别就在这里, 所以会提示你那个错误  谢谢，还是不太明白为什么会出错，char (*p)[20]  、char *p[]     对应的p[i]是不是一样的？ [/quote]  error C2664: 'sort' :    cannot convert parameter 1 from 'char [20]' to 'char *[]' 这都不明白?   这个错误就是提示参数类型不一致撒.

引用 10 楼 wanght99 的回复:[quote=引用 8 楼 yshhq 的回复:] [quote=引用 2 楼 wanght99 的回复:] 形参的问题 单看char *p[]这个p先和[]结合, 再和*结合, 表示p先是一个数组, 数组里内容是指针. 但如果它作为一个形参, C里是不能直接对数组传值的, 数组会转化成相应类型的指针, 所以 char *p[]相当于是char **p. 也就是"指针的指针"  但问题就来了,  char str[N][20]; 是一个 "数组的数组", 在作实参传递的时候,  它变成了"数组的指针". 而"数组的指针", 和 "指针的指针"是不一样的, 就出现的类型的不匹配. 所以会报错.  受教了！ 那么用char (*p)[20]做形参时，排序会出错是为什么？[/quote]  看了眼你的程序, 逻辑有问题吧, 你的j在第一次循环之后就是N了, 以后都不会去比较了.[/quote] 而且j是没初始化的.

引用 8 楼 yshhq 的回复:[quote=引用 2 楼 wanght99 的回复:] 形参的问题 单看char *p[]这个p先和[]结合, 再和*结合, 表示p先是一个数组, 数组里内容是指针. 但如果它作为一个形参, C里是不能直接对数组传值的, 数组会转化成相应类型的指针, 所以 char *p[]相当于是char **p. 也就是"指针的指针"  但问题就来了,  char str[N][20]; 是一个 "数组的数组", 在作实参传递的时候,  它变成了"数组的指针". 而"数组的指针", 和 "指针的指针"是不一样的, 就出现的类型的不匹配. 所以会报错.  受教了！ 那么用char (*p)[20]做形参时，排序会出错是为什么？[/quote]  看了眼你的程序, 逻辑有问题吧, 你的j在第一次循环之后就是N了, 以后都不会去比较了.

引用 1 楼 caozhy 的回复:char ** p看看  不行。提示error C2664: 'sort' : cannot convert parameter 1 from 'char [3][20]' to 'char ** '

引用 2 楼 wanght99 的回复:形参的问题 单看char *p[]这个p先和[]结合, 再和*结合, 表示p先是一个数组, 数组里内容是指针. 但如果它作为一个形参, C里是不能直接对数组传值的, 数组会转化成相应类型的指针, 所以 char *p[]相当于是char **p. 也就是"指针的指针"  但问题就来了,  char str[N][20]; 是一个 "数组的数组", 在作实参传递的时候,  它变成了"数组的指针". 而"数组的指针", 和 "指针的指针"是不一样的, 就出现的类型的不匹配. 所以会报错.  受教了！ 那么用char (*p)[20]做形参时，排序会出错是为什么？

引用 5 楼 xiaohuh421 的回复:char (*p)[20]   // 指向数组的指针, 这个指针可能指向一个char类型, 有20个元素的数组. char *p[]          //指针数组, 数组里面保存的是char*.  区别就在这里, 所以会提示你那个错误  谢谢，还是不太明白为什么会出错，char (*p)[20]  、char *p[]     对应的p[i]是不是一样的？

纯粹来骗分  void sort(char (*p)[20]) { 	char k[20]; 	int x; 	 	for(int i=0; i<N; i++) { 		x = i; 		for(int j=i+1; j<N; j++) {  			if(strcmp(*(p+i), *(p+j)) > 0) { 				x = j; 			} 		}  		if(x!=i) { 			strcpy(k, *(p+i)); 			strcpy(*(p+i), *(p+x)); 			strcpy(*(p+x), k); 		} 		 	} }

char ** p看看

第40行 j=i+1

void sort(char (*p)[N][20]); sort(&str);  void sort(char (*p)[N][20]) {     int i, j, k;     char temp[20];     for(i=0; i<N-1; i++)     {         k=i;         for(j=j+1; j<N; j++)             if(strcmp((*p)[k],(*p)[j])>0)    k=j;         if(k!=i)         {                 strcpy(temp, (*p)[k]); strcpy((*p)[k], (*p)[i]); strcpy((*p)[i], temp); //            temp=p[k]; p[k]=p[i]; p[i]=temp;    //为什么不可以这么写？因为temp等数组名是只读的         }     } }


Question: VS2013写的一个简单计算器编译不了

result = scanf_s( "%d %f %c %C %s %S", &i, &fp, &c, 1,                      &wc, 1, s, 80, ws, 80 );  注意跟上每个数据的大小.

改为scanf_s("%lf %c %lf", &shuzi, &fuhao,1, &shuzi1); 即在第二个参数后加一个参数1 或把scanf_s改为scanf 原因：scanf_f在输入字符或者字符串时会有边界检查，需要输入最多输入多少个字符的个数的参数

估计死在scanf_s（）上了，http://msdn.microsoft.com/zh-cn/library/w40768et%28VS.80%29.aspx，http://baike.baidu.com/view/3529726.htm?fr=aladdin，不是windows不能测试scanf_s（）


Question: 为什么会死锁？

这时间  引用 6 楼 u012879806 的回复:[quote=引用 5 楼 zhaowech 的回复:] 最常见的死锁就是A等着B给信号再发信号给B，B等着A的信号再发信号给A。 想实现死锁，你可以这样做，写2个函数fun1和fun2 fun1() {   waitfor(event1);   setevent(event2) ; }  fun2() {   waitfor(event2);   setevent(event1); } 这样初始2个都没有触发，永远等不到event1，那么event2就不会触发； event2,不会触发，永远等不到evnet2，那么event1就不会触发； 这样就死循环了，也就是死锁了  你这种太。。。。  基本不可能出现，  原因是： 2个事件都不触发，才会死锁。 可能性太低了。  我感觉 日常所见的 死锁，不是你这种吧。 这太明显低级了  [/quote] 好吧，被鄙视了，在大型程序中，逻辑分支过多，无意识的死锁很容易发生。 使你说，不懂，想举个例子的嘛

引用 1 楼 u010207727 的回复:不是原子操作，多线程调用的情况下会死锁。 同时等待资源  可以举例说明吗？   比如，线程1 ，线程2 ，如何到第几步的操作的时候，才会出现死锁。  我想了很久，找不到 “什么情况下会出现死锁“？

不是原子操作，多线程调用的情况下会死锁。 同时等待资源

引用 5 楼 zhaowech 的回复:最常见的死锁就是A等着B给信号再发信号给B，B等着A的信号再发信号给A。 想实现死锁，你可以这样做，写2个函数fun1和fun2 fun1() {   waitfor(event1);   setevent(event2) ; }  fun2() {   waitfor(event2);   setevent(event1); } 这样初始2个都没有触发，永远等不到event1，那么event2就不会触发； event2,不会触发，永远等不到evnet2，那么event1就不会触发； 这样就死循环了，也就是死锁了  你这种太。。。。  基本不可能出现，  原因是： 2个事件都不触发，才会死锁。 可能性太低了。  我感觉 日常所见的 死锁，不是你这种吧。 这太明显低级了

《Windows核心编程》   Synchronization Functions The following functions are used in synchronization.        CancelWaitableTimer   CreateEvent   CreateMutex   CreateSemaphore   CreateWaitableTimer   DeleteCriticalSection   EnterCriticalSection   GetOverlappedResult   InitializeCriticalSection   InitializeCriticalSectionAndSpinCount   InterlockedCompareExchange   InterlockedDecrement   InterlockedExchange   InterlockedExchangeAdd   InterlockedIncrement   LeaveCriticalSection   MsgWaitForMultipleObjects   MsgWaitForMultipleObjectsEx   OpenEvent   OpenMutex   OpenSemaphore   OpenWaitableTimer   PulseEvent   QueueUserAPC   ReleaseMutex   ReleaseSemaphore   ResetEvent   SetCriticalSectionSpinCount   SetEvent   SetWaitableTimer   SignalObjectAndWait   TimerAPCProc   TryEnterCriticalSection   WaitForMultipleObjects   WaitForMultipleObjectsEx   WaitForSingleObject   WaitForSingleObjectEx


Question: apc异步过程调用的次数

引用When you are using a waitable timer with an APC, the thread that sets the timer should not wait on the handle of the timer. By doing so, you would cause the thread to wake up as a result of the timer becoming signaled rather than as the result of an entry being added to the APC queue. As a result, the thread is no longer in an alertable state and the completion routine is not called. In the following code, the call to SleepEx awakens the thread when an entry is added to the thread's APC queue after the timer is set to the signaled state.  这段话怎么理解？  也就是说如果如果你通过completion routine调用SetWaitableTimer的话，不要用WaitFor...等待这个waitabletimer的变成signal, 因为这个timer只有时间到了才会signal（先）然后才queue APC（后）, 但是因为你wait的函数已经等到它signal了而被唤醒了，当前线程不再处于alertable状态了， APC只有等待下一轮alertable wait时才有机会执行，这样你等于漏了一次OnTimer()  另外APC和SleepEx的次数没有关系，即使你只SleepEx一次，所有队列中的APC（哪怕有几十个）都会依次得到执行并且队列会清空。

1. 每个APC只会执行一次，你的测试代码执行两次是因为SetWaitableTimer投递了两个APC   引用 楼主 u012879787 的回复:问题1. apc会执行几次，  代码测试后，发现2次，为什么是2次。  apc的执行次数是与 sleepex的调用次数有关系吗？   1. 每个APC只会执行一次，你的测试代码执行两次是因为SetWaitableTimer投递了两个APC  引用 楼主 u012879787 的回复:问题2。  by  a handle becoming signaled  是指waitabletimer有信号吗？  如果是的话，什么时候，会为signaled呢？  感觉只有超时才会触发。  是的，waitabletimer本身就有信号 当SetWaitableTimer到时间后就会signal. 但是如果没人wait它的话这个signal不会改变而是一直处于signal状态。另外waitabletimer到时间后如果你设置了completion routine那么它还会投递APC然后继续下一轮计时。  3. (最重要的问题） apc的效率在哪里？ 虽然目前没有能力查看底层代码，我也能猜测到， 线程的apc调用无非就是 用一个新的线程去调用这些apc函数而已，  注意： 你的线程， 依然有sleepex函数下面的代码依然不会执行。  只有异步过程全部调用完毕，才会去执行 sleepex下面的代码。  何来效率？   实在看不出效率来？   [/quote]  APC的效率主要体现在内核，内核中随时随地有大量的APC在调度。另外APC不需要一个新的线程去执行，它就在你当前线程中执行，只不过是在你wait函数调用从内核返回用户层的时候，当前线程内等待的APC都会先执行并且APC队列会清空，然后继续执行你线程中的代码，说起来你的线程本来就在wait，并没有执行任何代码，在你线程被唤醒时插入执行一点额外代码当然是最节省资源的方法，不需要额外耗时的线程调度和线程切换参与。

引用 1 楼 u012879787 的回复:[quote=引用 楼主 u012879787 的回复:] 代码来自：http://msdn.microsoft.com/en-us/library/windows/desktop/ms686898(v=vs.85).aspx  网址：  http://www.vckbase.com/index.php/wv/1304  问题1. apc会执行几次，  代码测试后，发现2次，为什么是2次。  apc的执行次数是与 sleepex的调用次数有关系吗？   问题2。  each thread has an APC queue. If there is an entry in the thread's APC queue at the time that one of the alertable functions is called, the thread is not put to sleep. Instead, the entry is removed from the APC queue and the completion routine is called. If no entry exists in the APC queue, the thread is suspended until the wait is satisfied. The wait can be satisfied by adding an entry to the APC queue, by a timeout, or by a handle becoming signaled. If the wait is satisfied by an entry in the APC queue, the thread is awakened and the completion routine is called. In this case, the return value of the function is WAIT_IO_COMPLETION.  by  a handle becoming signaled  是指waitabletimer有信号吗？  如果是的话，什么时候，会为signaled呢？  感觉只有超时才会触发。  3. (最重要的问题） apc的效率在哪里？ 虽然目前没有能力查看底层代码，我也能猜测到， 线程的apc调用无非就是 用一个新的线程去调用这些apc函数而已，  注意： 你的线程， 依然有sleepex函数下面的代码依然不会执行。  只有异步过程全部调用完毕，才会去执行 sleepex下面的代码。  何来效率？   实在看不出效率来？    #define UNICODE 1 #define _UNICODE 1  #include <windows.h> #include <stdio.h> #include <tchar.h>  #define _SECOND 10000000  typedef struct _MYDATA {    TCHAR *szText;    DWORD dwValue; } MYDATA;  VOID CALLBACK TimerAPCProc(    LPVOID lpArg,               // Data value    DWORD dwTimerLowValue,      // Timer low value    DWORD dwTimerHighValue )    // Timer high value  {    // Formal parameters not used in this example.    UNREFERENCED_PARAMETER(dwTimerLowValue);    UNREFERENCED_PARAMETER(dwTimerHighValue);     MYDATA *pMyData = (MYDATA *)lpArg;     _tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,           pMyData->dwValue );    MessageBeep(0);  }  int main( void )  {    HANDLE          hTimer;    BOOL            bSuccess;    __int64         qwDueTime;    LARGE_INTEGER   liDueTime;    MYDATA          MyData;     MyData.szText = TEXT("This is my data");    MyData.dwValue = 100;     hTimer = CreateWaitableTimer(            NULL,                   // Default security attributes            FALSE,                  // Create auto-reset timer            TEXT("MyTimer"));       // Name of waitable timer    if (hTimer != NULL)    {       __try        {          // Create an integer that will be used to signal the timer           // 5 seconds from now.          qwDueTime = -5 * _SECOND;           // Copy the relative time into a LARGE_INTEGER.          liDueTime.LowPart  = (DWORD) ( qwDueTime & 0xFFFFFFFF );          liDueTime.HighPart = (LONG)  ( qwDueTime >> 32 );           bSuccess = SetWaitableTimer(             hTimer,           // Handle to the timer object             &liDueTime,       // When timer will become signaled             2000,             // Periodic timer interval of 2 seconds             TimerAPCProc,     // Completion routine             &MyData,          // Argument to the completion routine             FALSE );          // Do not restore a suspended system           if ( bSuccess )           { for(int i = 0; i < 2; i++)           //  for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )              {                SleepEx(                   INFINITE,     // Wait forever                   TRUE );       // Put thread in an alertable state             }           }           else           {             printf("SetWaitableTimer failed with error %d\n", GetLastError());          }        }        __finally        {          CloseHandle( hTimer );       }    }     else     {       printf("CreateWaitableTimer failed with error %d\n", GetLastError());    }     return 0; }      When you are using a waitable timer with an APC, the thread that sets the timer should not wait on the handle of the timer. By doing so, you would cause the thread to wake up as a result of the timer becoming signaled rather than as the result of an entry being added to the APC queue. As a result, the thread is no longer in an alertable state and the completion routine is not called. In the following code, the call to SleepEx awakens the thread when an entry is added to the thread's APC queue after the timer is set to the signaled state.  这段话怎么理解？ [/quote]     引用 楼主 u012879787 的回复:代码来自：http://msdn.microsoft.com/en-us/library/windows/desktop/ms686898(v=vs.85).aspx  网址：  http://www.vckbase.com/index.php/wv/1304  问题1. apc会执行几次，  代码测试后，发现2次，为什么是2次。  apc的执行次数是与 sleepex的调用次数有关系吗？   问题2。  each thread has an APC queue. If there is an entry in the thread's APC queue at the time that one of the alertable functions is called, the thread is not put to sleep. Instead, the entry is removed from the APC queue and the completion routine is called. If no entry exists in the APC queue, the thread is suspended until the wait is satisfied. The wait can be satisfied by adding an entry to the APC queue, by a timeout, or by a handle becoming signaled. If the wait is satisfied by an entry in the APC queue, the thread is awakened and the completion routine is called. In this case, the return value of the function is WAIT_IO_COMPLETION.  by  a handle becoming signaled  是指waitabletimer有信号吗？  如果是的话，什么时候，会为signaled呢？  感觉只有超时才会触发。  3. (最重要的问题） apc的效率在哪里？ 虽然目前没有能力查看底层代码，我也能猜测到， 线程的apc调用无非就是 用一个新的线程去调用这些apc函数而已，  注意： 你的线程， 依然有sleepex函数下面的代码依然不会执行。  只有异步过程全部调用完毕，才会去执行 sleepex下面的代码。  何来效率？   实在看不出效率来？    #define UNICODE 1 #define _UNICODE 1  #include <windows.h> #include <stdio.h> #include <tchar.h>  #define _SECOND 10000000  typedef struct _MYDATA {    TCHAR *szText;    DWORD dwValue; } MYDATA;  VOID CALLBACK TimerAPCProc(    LPVOID lpArg,               // Data value    DWORD dwTimerLowValue,      // Timer low value    DWORD dwTimerHighValue )    // Timer high value  {    // Formal parameters not used in this example.    UNREFERENCED_PARAMETER(dwTimerLowValue);    UNREFERENCED_PARAMETER(dwTimerHighValue);     MYDATA *pMyData = (MYDATA *)lpArg;     _tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,           pMyData->dwValue );    MessageBeep(0);  }  int main( void )  {    HANDLE          hTimer;    BOOL            bSuccess;    __int64         qwDueTime;    LARGE_INTEGER   liDueTime;    MYDATA          MyData;     MyData.szText = TEXT("This is my data");    MyData.dwValue = 100;     hTimer = CreateWaitableTimer(            NULL,                   // Default security attributes            FALSE,                  // Create auto-reset timer            TEXT("MyTimer"));       // Name of waitable timer    if (hTimer != NULL)    {       __try        {          // Create an integer that will be used to signal the timer           // 5 seconds from now.          qwDueTime = -5 * _SECOND;           // Copy the relative time into a LARGE_INTEGER.          liDueTime.LowPart  = (DWORD) ( qwDueTime & 0xFFFFFFFF );          liDueTime.HighPart = (LONG)  ( qwDueTime >> 32 );           bSuccess = SetWaitableTimer(             hTimer,           // Handle to the timer object             &liDueTime,       // When timer will become signaled             2000,             // Periodic timer interval of 2 seconds             TimerAPCProc,     // Completion routine             &MyData,          // Argument to the completion routine             FALSE );          // Do not restore a suspended system           if ( bSuccess )           { for(int i = 0; i < 2; i++)           //  for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )              {                SleepEx(                   INFINITE,     // Wait forever                   TRUE );       // Put thread in an alertable state             }           }           else           {             printf("SetWaitableTimer failed with error %d\n", GetLastError());          }        }        __finally        {          CloseHandle( hTimer );       }    }     else     {       printf("CreateWaitableTimer failed with error %d\n", GetLastError());    }     return 0; }    定时器到时候，会插入一个apc到apc队列中。  sleepex让线程处于可提醒状态，由于apc不为空，所以调度线程，执行apc，  然后回到for， 由于再次调用sleepex，插入apc，执行apc。    所以是2次。

异步体现效率？

引用 楼主 u012879787 的回复:代码来自：http://msdn.microsoft.com/en-us/library/windows/desktop/ms686898(v=vs.85).aspx  网址：  http://www.vckbase.com/index.php/wv/1304  问题1. apc会执行几次，  代码测试后，发现2次，为什么是2次。  apc的执行次数是与 sleepex的调用次数有关系吗？   问题2。  each thread has an APC queue. If there is an entry in the thread's APC queue at the time that one of the alertable functions is called, the thread is not put to sleep. Instead, the entry is removed from the APC queue and the completion routine is called. If no entry exists in the APC queue, the thread is suspended until the wait is satisfied. The wait can be satisfied by adding an entry to the APC queue, by a timeout, or by a handle becoming signaled. If the wait is satisfied by an entry in the APC queue, the thread is awakened and the completion routine is called. In this case, the return value of the function is WAIT_IO_COMPLETION.  by  a handle becoming signaled  是指waitabletimer有信号吗？  如果是的话，什么时候，会为signaled呢？  感觉只有超时才会触发。  3. (最重要的问题） apc的效率在哪里？ 虽然目前没有能力查看底层代码，我也能猜测到， 线程的apc调用无非就是 用一个新的线程去调用这些apc函数而已，  注意： 你的线程， 依然有sleepex函数下面的代码依然不会执行。  只有异步过程全部调用完毕，才会去执行 sleepex下面的代码。  何来效率？   实在看不出效率来？    #define UNICODE 1 #define _UNICODE 1  #include <windows.h> #include <stdio.h> #include <tchar.h>  #define _SECOND 10000000  typedef struct _MYDATA {    TCHAR *szText;    DWORD dwValue; } MYDATA;  VOID CALLBACK TimerAPCProc(    LPVOID lpArg,               // Data value    DWORD dwTimerLowValue,      // Timer low value    DWORD dwTimerHighValue )    // Timer high value  {    // Formal parameters not used in this example.    UNREFERENCED_PARAMETER(dwTimerLowValue);    UNREFERENCED_PARAMETER(dwTimerHighValue);     MYDATA *pMyData = (MYDATA *)lpArg;     _tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,           pMyData->dwValue );    MessageBeep(0);  }  int main( void )  {    HANDLE          hTimer;    BOOL            bSuccess;    __int64         qwDueTime;    LARGE_INTEGER   liDueTime;    MYDATA          MyData;     MyData.szText = TEXT("This is my data");    MyData.dwValue = 100;     hTimer = CreateWaitableTimer(            NULL,                   // Default security attributes            FALSE,                  // Create auto-reset timer            TEXT("MyTimer"));       // Name of waitable timer    if (hTimer != NULL)    {       __try        {          // Create an integer that will be used to signal the timer           // 5 seconds from now.          qwDueTime = -5 * _SECOND;           // Copy the relative time into a LARGE_INTEGER.          liDueTime.LowPart  = (DWORD) ( qwDueTime & 0xFFFFFFFF );          liDueTime.HighPart = (LONG)  ( qwDueTime >> 32 );           bSuccess = SetWaitableTimer(             hTimer,           // Handle to the timer object             &liDueTime,       // When timer will become signaled             2000,             // Periodic timer interval of 2 seconds             TimerAPCProc,     // Completion routine             &MyData,          // Argument to the completion routine             FALSE );          // Do not restore a suspended system           if ( bSuccess )           { for(int i = 0; i < 2; i++)           //  for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )              {                SleepEx(                   INFINITE,     // Wait forever                   TRUE );       // Put thread in an alertable state             }           }           else           {             printf("SetWaitableTimer failed with error %d\n", GetLastError());          }        }        __finally        {          CloseHandle( hTimer );       }    }     else     {       printf("CreateWaitableTimer failed with error %d\n", GetLastError());    }     return 0; }      When you are using a waitable timer with an APC, the thread that sets the timer should not wait on the handle of the timer. By doing so, you would cause the thread to wake up as a result of the timer becoming signaled rather than as the result of an entry being added to the APC queue. As a result, the thread is no longer in an alertable state and the completion routine is not called. In the following code, the call to SleepEx awakens the thread when an entry is added to the thread's APC queue after the timer is set to the signaled state.  这段话怎么理解？


Question: 利用有限差分法计算一根金属棒的温度演化

这是一个空间一维、时间一维的纯计算问题，超级简单

@mujiok2003  大神能给翻译翻译吗  初学者。。。

要开学了，作业还没做完，目测这几天学生作业帖会多起来。

有qq吗  我把文本发给你

公式都有了， 做个翻译而已。

没看懂。。。

公式请先用Word中的公式编辑器输入。再截图贴上来。

先把公式拆分，从左到右，每一个括号，运算符都分开，然后再实现，很难么？


Question: 求助C语言泛型指针有疑问

计算机组成原理→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


Question: c语言指针方面赋值的问题

C是面向过程的语言 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（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对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解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

#include <stdio.h>  #include <stdlib.h>  int main() {       int *p;        int **q;         p=(int *)malloc(sizeof(int));       q=&p;          int m=1;       p=&m;        printf("%d\n",**q);  return 0;  }

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

#include<stdio.h> #include<stdlib.h> void main() {         	int *p;         	int *q;	 		int m;         	p=(int*)malloc(sizeof(int));  //設記憶體位置是 100 		q=p;                                         //在此 q 和 p 記憶體位置都是 100  		m=1;         	p=&m;                                     // 設m 的記憶體位置是102 所以p記憶體位置由100變成 102  		q = p;                                       //重新將 q的記憶體位置更改為102就可以了          	printf("%d\n",*q); }

引用 4 楼 starytx 的回复:int *p;       // 定义一个指针，没有指向任何对象          int *q;  // 同上          p=(int*)malloc(sizeof(int));  // p指向动态开辟的int对象的地址          q=p;                                        // q 和p指向同一个东西（上边开辟的空间地址）          int m;          m=1;          p=&m;           // p改变指向对象m          printf("%d",*q);    // 打印q指向的对象的值（q的指向不会因为p的改变而改变，此时和p没有任何关系，降入他们指向同一个对象，那么通过p来修改指向的对象的值，通过q也可以访问到这个改变）

p = malloc(sizeof(int); /* 这其实就是使p指向一个堆空间 */ q = p; /* 现在p和q都指向同一地址 */ p=&m; /* p现在又指向了m的地址空间，m是一个局部变量，他存在栈上 */ printf("%d",*q); /* q还指向刚才的堆空间，由于是malloc函数分配的空间，他不会对其进行初始化，因此会是一个随机数，因此你打印的也是随机数，你给*q进行赋值，就会发现，打印的是你赋的值 */

#include<stdio.h> #include<stdlib.h> int main()         {             int *p;  //定义一个指针变量p，变量入栈             int *q; // 定义一个指针变量q,变量入栈             p=(int*)malloc(sizeof(int));  //在堆中开辟新的内存空间，p指向堆中的新空间的首地址             q=p;//q指针也指向p指针所指的堆内存地址             int m; //定义变量m，变量入栈             m=1; //栈中m的值赋值为1             p=&m; //p指针指向m在栈中的内存地址。             printf("%d",*q); // 打印q指针所指的堆中的内存中int类型的值。             return 0;         }

你赋一个地址过去，想通过一个地址来表示一个值，但忽视了C赋值的根本原理，定义一个变量申请一块内存空间，给它起一个名字，这个名字（变量名 函数名等）就一般就是地址（我把地址看作指针），然后你改变了P的指向，忘记了Q

再好好看看指针吧——http://blog.csdn.net/u012421456/article/details/20296865

p 指针指向的内存变了  q仍然指向p原来的内存地址

理解下何为赋值吧！

p=&m;  改成  *p=m;

楼上的解释很清楚了 时刻记住此时这个指针指到哪里  换种写法  #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { 	int m; 	m = 1; 	int *p, *q; 	p = &m;  	q = p;  	printf("%d",*q);  	system("pause"); 	return 0; }

p=&m;  改成  *p=m;  不然你白忙活了

p=&m; 了，但是q仍然指向原来的p指向的地方（malloc(sizeof(int))的结果）


Question: 关于C语言指针的疑问

引用 6 楼 grggrggrw 的回复:后一个问题我自己弄明白了。 无符号char扩展成四字节的时候，高位填充0. 有符号char扩展成四字节的时候，高位填充符号位。  无符号类型左移的时候，最低位补0，右移的时候，最高位补0。 有符号类型左移的时候，最低位补0，右移的时候，最高位补符号位。  总之谢谢你之前的解释了！ 对，就是这样。把代码里面的char换成unsigned char试试就看出来了

引用 3 楼 user-1 的回复:[quote=引用 楼主 grggrggrw 的回复:] 我所理解的指针是这样的：它依靠自己的类型来寻址（用于p++），然后还是依靠自己的类型来输出目标地址的值，如char*就输出连续1字节的目标地址，如int*就连续输出4字节的目标地址。 刚才忘了说，楼主对指针的理解是正确的。[/quote] 奇怪，刚才明明点了引用的。。。

我完全理解了您的回答，十分感谢！  再次请教一下： 您说"按符号位扩展"，请问这个特性是编译器相关的呢，或是此为C语言规定因此与编译器无关呢？  这句话也让我想到了位移操作，<<的话都是用0来填充最低位，>>的话我记得是编译器相关，有的按照符号位，有的直接赋0到最高位

引用 楼主 grggrggrw 的回复:我所理解的指针是这样的：它依靠自己的类型来寻址（用于p++），然后还是依靠自己的类型来输出目标地址的值，如char*就输出连续1字节的目标地址，如int*就连续输出4字节的目标地址。 刚才忘了说，楼主对指针的理解是正确的。

1楼运行的结果是类似于你的第一第四段代码的结果。 把1楼的0xF7换成0x78，你会看到类似于你的第二第三段代码的结果。 关键是printf对%x的处理，它把传进去的一个字节扩展到4个字节再输出，而且是按符号位扩展。所以0xF7和0xFF会加上6个F；而0x78和0x00会加上6个0，最后等于什么都没加。

这个问题和指针没关系，关键在于printf的格式。 运行以下代码试试： #include <stdio.h> int main() {   char c = 0xF7;   printf("%x\n", c);   printf("%d\n", c);   return 0; }


Question: createevent打开失败？

你是创建都, 当然是会成功. MSDN上你帖那段英文说的是打开操作, 即非创建或者拥有者调用OpenEvent时, 才会需要考虑这些问题.  你那个名字都传了NULL了, 根本不用考虑什么管理员权限问题了.

引用 3 楼 Idle_ 的回复:OK, 让我们重新来过： CreateEvent可以用于创建或者打开一个Event. 对于创建来说，默认创建的Event的操作种类（读/写/同步等）标记中包含了EVENT_ALL_ACCESS标记，这些标记表示对event可以进行的操作，而标记和标记代表的具体操作可以授权给谁去执行记录在Event相关的Security Descriptor中的DACL结构中。所以Event具备了EVENT_ALL_ACCESS标记并不表示你可以使用该标记代表的操作（如果该标记的相关ACE中没有你的话），至于创建的event默认都具备EVENT_ALL_ACCESS标记（不管是不是admin用户），但是不同用户创建的Event的EVENT_ALL_ACCESS操作默认却是授权给不同用户/组的。 对于打开命名Event来说（别人创建的Event）， 该Event必须创建时具备EVENT_ALL_ACCESS标记（默认都是满足的），但是如果EVENT_ALL_ACCESS标记未授权给你时你的打开操作就会失败。  看了半天， 似乎说msdn是错误的。  1. security despriction这个东西，几乎很多内核都有这个结构体，  这个结构体与 访问控制模型 access control modole 是有很大关系的。  我也承认有关系。  2. 结合msdn看，似乎只有管理员才能够将该安全对象（ vista之后，资源，内核句柄，都可以叫安全对象）  授权，至于授权给谁我就不知道了。  虽然我不是对access control module很熟悉， 但是能大概了解一些。  我始终搞不懂，msdn为什么要提管理员？   3. 谢谢你

引用 1 楼 Idle_ 的回复:默认创建的是全部权限，但是这个权限是这个event的权限而不是用户权限。使用时系统会以event的权限和用户权限联合判断最终权限的。  Using this access right increases the possibility that your application must be run by an Administrator.  这句话怎么解释呢？   说明程序的 完整性级别值必须是high。  标准用户是medium


Question: C语言中scanf为什么没有执行呀？

哦  是这样呀  谢谢各位老师

#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { 	char num[50]; 	scanf("%[^\n]", num); //输入test1回车,此时num读到了test1 	printf("%s\n", num);   	int len = strlen(num); 	scanf("%[^\n]", &num[len]); //这个读取到了空白字符，所以是执行了scanf,运行结果让你以为没执行而已 	printf("%s\n", num);  	system("pause"); 	return 0; }   解决方法 1.在scanf输入个空格 2.使用fflush   #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { 	char num[50]; 	scanf(" %[^\n]", num); //注意有个空格 	printf("%s\n", num);   	int len = strlen(num); 	scanf(" %[^\n]", &num[len]); //注意有个空格 	printf("%s\n", num);  	system("pause"); 	return 0; }   #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { 	char num[50]; 	scanf("%[^\n]", num);  	printf("%s\n", num);   	fflush(stdin); //清空缓冲区 	int len = strlen(num); 	scanf("%[^\n]", &num[len]);  	printf("%s\n", num);   	system("pause"); 	return 0; }

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。

输入的字符串都在标准输入缓存中，为了避免回车键的干扰，可以在scanf前面加上fflush(stdin); 来清除标准输入的缓存。  #include <stdio.h> #include <string.h> void main() { 	char num[50]; 	scanf("%s",num); 	printf("%s\n",num); 	int len=strlen(num); 	fflush(stdin);  	scanf("%c",&num[len]); 	printf("%s\n",num); }  这样就可以得到你想要的答案

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

引用 2 楼 user-4 的回复:第二个scanf指定是执行了的，只不过你的这两个scanf的写法有问题。  你第一个scanf读到 \n 返回了，然后让第二个scanf去读这个\n，不还是直接返回么 恩 你说的对老师，改成scanf（“%s”,num）后就可以执行了，但是我有一点不明白的是在没有修改之前scanf是从哪个地方开始读字符的？从数组开头还是从上次输入的结尾？修改后的scanf输入时我也是用的回车结束输入，第二个scanf为什么没有影响呢？

有三个“hello”，第一个是执行第一个scanf的时候我输入的，后两个是执行了两个printf输出的，唯独第二个scanf没有执行。


Question: C语言A+B+C 一个题目运算有些不懂的地方求解答

理由很简单 printf("%d%d%d\n", A + B + C); 第一个%d，会得到正确的解析，即是A+B+C的值， 后面两个%d，由于没有了实参，会错误解析未知的内存空间，故是乱码

#include <stdio.h>   int main() {         int A, B, C,D;         scanf("%d %d %d", &A, &B, &C);         if (A<-40 || B<-40 || C<-40 || A>40 || B>40 || C>40)         {             break;         }         else         {              D=A+B+C;              printf("%d\n",D);         }        return 0; }

#include<stdio.h> int main(void) {     int a, b, c;     scanf("%d%d%d", &a, &b, &c);     if(a > 40 || a < -40 || b > 40 || b < -40 || c > 40 || c < -40)         return 0;     printf("%d", a+b+c);          return 0; }

好无聊的题目啊

语法都是错的,你想干嘛!

“你的答案是:26-10771516890    标准答案是:6 ” 这题还有标准答案啊。。。

先要年入门书哇！！ 题目没说是“整数”，不能用int，用double更合理吧  #include <stdio.h>  int main() { 	double A, B, C; 	char c = 'y'; 	do 	{ 		printf("请输入三个在[-40，40]内的数(各数之间用空格隔开):\n"); 		scanf("%lf %lf %lf", &A, &B, &C); 		while (A<-40 || B<-40 || C<-40 || A>40 || B>40 || C>40) 		{ 			printf("吾草啊！请输入三个在[-40，40]内的数(各数之间用空格隔开):\n"); 			scanf("%lf %lf %lf", &A, &B, &C); 		} 		printf("A+B+C = %lg\n", A + B + C); 		printf("输入\"y\"继续，请输入其它字符结束： "); 		scanf(" %c", &c); 	} while (c == 'y' || c == 'Y'); 	return 0; }

#include <stdio.h> int main() {      int A,B,C;      A=22,B=1,C=3;      printf("%d\n",A+B+C);  //A+B+C的結果用%d顯示      return 0; }

连语法都是错的

引用 楼主 linxiaobin2 的回复:题目：输入为一行，包括了用空格分隔的三个数据A、B、C（数据范围均在-40~40之间）。输出为一行，为“A+B+C”的计算结果。   我写的代码： #include <stdio.h>  int main()  {      int A,B,C;      A=22,B=1,C=3;      printf("%d%d%d\n",A+B+C);      return 0;  }  我个人觉得算出来应该是26  但系统说我是错的！ “你的答案是:26-10771516890    标准答案是:6 ” 求大牛解答！ 怎么会是6呢？？心算一下  22+1+3=26啊  你的printf语句语法有问题，A+B+C的值会在第一个%d输出，后两个%d输出的值会是随机值（垃圾值）

你printf有错误导致的   #include <stdio.h> #include <stdlib.h> int main() {     int A,B,C,D;      A=22,B=1,C=3,D=5;      printf("1.%d\n2.%d\n3.%d\n4.%d\n5.%d\n6.%d\n7.%d\n",A+B+C);      //要求输入7个变量,这里只输入了一个变量，那么剩下的6个是随机的      	system("pause"); 	return 0; }

没scanf输入。

引用 8 楼 liuhengxiao 的回复:答案错误~~ 题目是输入3个数（-40-40之间），输入没有，判断数值大小也没有哦~我只改lz的代码，不写

引用 7 楼 zxh707wk 的回复:好吧，我被惊呆了 #include <stdio.h> int main() { 	int A, B, C; 	A = 22, B = 1, C = 3; 	printf("%d\n", A + B + C); 	return 0; }  答案错误~~ 题目是输入3个数（-40-40之间），输入没有，判断数值大小也没有哦~

晕。。手快敲错注释符号了。。。

printf("%d\n",A+B+C);\\这是打印A+B+C的值 printf("%d%d%d\n",A,B,C);\\这是打印ABC的值，但这里你会发现打印的是2613 //因为这里"%d%d%d\n"每个数之间没有用空格或者其他标识符分开 //printf函数中要输出多个值时，后面的每个参数中间要用逗号","隔开 //你还是看看C语言基础书吧，你这样的学习方式很累的

引用 1 楼 dbzhang800 的回复:1. 你写的代码不符合题目要求 2. 你的printf语句本身也不对 那要怎么写了还有我的printf  怎么不对  新手不懂刚学  请多多指教！

那要怎么写了还有我的printf  怎么不对  新手不懂刚学  请多多指教！

你的语法都不对


Question: 线性表（顺序表）的销毁问题

推介楼主看看经典的《C语言程序设计语言》，我最近也在学吴伟民 严蔚敏的《数据结构》，推介配套看看高一凡的《数据结构算法实现及解析》用c和c++实现，完全配套《数据结构》，还有就是，对于有些自己掌握不好的函数，最好查查经典的《C语言程序设计语言》，

哎，上面插队很严重啊

再补充一下： 如果楼主不是用指针，而是直接用SqList  L;定义，那么就不用malloc动态分配内存了，所以也就不用free回收内存了，因为此时L是系统自动在栈上分配内存，当此函数结束时，此函数内申明的变量所占空间都被回收，所以变量也就无效了。而malloc是在堆上分配内存，当此函数结束时，堆还是继续存在，所以需要程序员自己用free释放掉内存。 下面贴上非指针的代码，效果和上面指针的一样： 	         SqList L;     s = InitList(&L); 	printf("初始化后长度为:%d\n",L.length); 	for (i=0;i<MAXSIZE;i++) 	{ 		L.data[i]=i; 	} 	L.length=i;  	for (i=0;i<L.length;i++) 	{ 		printf("%d ",L.data[i]); 	}

仅供参考//带表头结点的单向链表 #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-> //

3楼正解。  如果楼主定义的是指针类型，那么就要用malloc动态分配内存，后面才能用free回收内存。  	SqList *L = (SqList*)malloc(sizeof(SqList));     s = InitList(L); 	printf("初始化后长度为:%d\n",L->length); 	for (i=0;i<MAXSIZE;i++) 	{ 		L->data[i]=i; 	} 	L->length=i;  	for (i=0;i<L->length;i++) 	{ 		printf("%d ",L->data[i]); 	}     s=DestoryList(L);   在mian()函数中加了个测试，可以运行出正确结果。

引用 7 楼 hyde100 的回复:[quote=引用 6 楼 modyaj 的回复:] 那样的话 不需要你操作吧  自动销毁  我也有这种考虑，但是数据结构的教材里的ADT里有这个函数，或者是对于这种不是动态分配方式产生的顺序表根本就不需要这个函数？[/quote] 当时那个书我就看得晕乎乎的！有 没关系  空函数吧！ 而且重点在于实现  你知道是怎么回事！ 人是活的！

仅供参考 http://pan.baidu.com/s/17yIcQ

引用 7 楼 hyde100 的回复:我也有这种考虑，但是数据结构的教材里的ADT里有这个函数，或者是对于这种不是动态分配方式产生的顺序表根本就不需要这个函数？  这种情况确实不需要destroy

malloc和free 一定要一一对应，有malloc的地方一定要在某个地方使用free进行释放  使用free之前确定你之前对这个地方进行过malloc操作

引用 6 楼 modyaj 的回复:那样的话 不需要你操作吧  自动销毁  我也有这种考虑，但是数据结构的教材里的ADT里有这个函数，或者是对于这种不是动态分配方式产生的顺序表根本就不需要这个函数？

那样的话 不需要你操作吧  自动销毁

引用 3 楼 lisong694767315 的回复:[quote=引用 1 楼 hyde100 的回复:] 有人在吗？我调试了半天，还是奔溃！  在main函数里：  SqList *L = (SqList*)malloc(sizeof(SqList)); // ... s = InitList(L); s=DestoryList(L); [/quote]  但这样会导致我的L变成了指针，那换一个思路，如果不应用动态分配（malloc）的话， 按照我的L声明方式，DestoryList该如何正确书写？

就是楼上那样  要申请空间才能释放

引用 1 楼 hyde100 的回复:有人在吗？我调试了半天，还是奔溃！  在main函数里：  SqList *L = (SqList*)malloc(sizeof(SqList)); // ... s = InitList(L); s=DestoryList(L);

没有malloc，free必然出错啊。。。

有人在吗？我调试了半天，还是奔溃！


Question: [菜鸟提问之2]为何定义成布尔类型就出错？

需要头文件 stdbool.h  或 自定义 bool 类型

引用 5 楼 guankle 的回复:C89标准里没有定义布尔型，可以用int型0判断为假，1判断为真。 从C99标准开始，引入布尔类型名字为“_Bool”。 也可以自己定义布尔型。  恩，因为bool/true/false都不是C99中的关键词，所以需要头文件 stdbool.h 来使用它们，不然只能用 _Bool / 1 / 0

引用 3 楼 dbzhang800 的回复:因为C89中没有 bool 这个类型  如果你的编译器支持C99，你可以包含头文件 stdbool.h

# include <stdbool.h>   。

这个？ http://bbs.csdn.net/topics/380024461