Question: 我可以请教大家一些白痴的问题嘛..？

学习在于交流，更在于你寻求一个好老师！这是一种捷径！现在所有的东西都跟基础公式一样，你只有了解了才可以好好应用，怎么快速了解？看视频，问老师！另外，确定好自己的方向，不能弄得太宽泛，导致什么都好像懂，又什么都不懂！

1.为什么我写出来的程序全都是一些黑白的东西...然而别人的程序中能够拥有彩色的图标..和炫耀的背景和选项...  黑白也是彩色中的颜色； 黑白的东西也有图标； 黑色的背景虽然不炫但它的确也是背景； 黑白的东西也可以有选项； 此乃一。  想要在这一行走远，把概念弄清楚很重要； 而要把概念弄清楚，首先得把它的名字弄清楚； 黑白的东西叫控制台程序，或者console application，或者命令行程序； 名字可以有很多，但是指的都是同一个东西，就是黑白的东西； 无论叫它什么名字，都比叫黑白的东西要好； 别人的程序叫图形界面程序，或者GUI程序； 此乃二。  你的疑问来自于你并没有去写GUI程序，所以你的程序不是别人的程序； 你没有去写（GUI程序）是因为你不会； 你不会是因为你没有去学； 你没有去学极有可能是因为你没有意识到它是GUI程序（你没有GUI程序的概念）； 相信你没有学习，连黑白的东西（console application）都写不出来； 此乃三。  编程的本质都是一样的，所以说写console还是写GUI其实是一样的； 编程的外延又是很广泛的，所以能写console不代表立马能写出GUI来，因为它们各有各的细节需要学习／处理。  2.为什么学习高级语言的编程还要学习操作系统..?是不是这些操作系统能提供一些API的函数为高级语言所使用?  不用强调高级语言，目前学的都是高级语言；相信LZ暂时对汇编也没兴趣； 没有规定说学习语言就要学习操作系统；完全可以学习语言和语言的库； 之所以说要学习操作系统，是因为语言本身做不了什么事情；而库有一部分，是对系统的封装；还有一部分功能，是需要直接调用系统的服务（API）来完成。  3.数据库和高级语言的关系是什么.?或者说..学数据库对高级语言有什么帮助..?  没有什么特别的关系，编程领域的两个不同的方面； 编程的时候，有很大一块是处理数据，数据库是处理数据的好工具； 数据库的语言SQL，也是种语言。  4.对于深造高级语言的选择是选择C好还是选择C++好,如果以后想编写软件的话.?  这个问题有问题； 想要“深造语言”，选C还是C++都很好； 想要写软件的话，选择更多，C，Java，Python⋯⋯都很好。  5.可以举一些用C或者C++写出来的软件吗?...  可以这样认为，其实现在LZ能接触到的，和程序有关的，其实都是基于C的； 比如UNIX/Linux操作系统，比如浏览器，比如网络，比如Web服务器（这些都是LZ能发这个贴子而需要的东西，也是C语言写出来的软件）； http://www.stroustrup.com/applications.html  由于一直都是在自学编程...这些的基础知识我都不知道..搜索百度都没有统一的回答..所有在这里想请教一下csdn的大神...  // 也许可以尝试下Google  还有就是自学编程真的不是一件容易的事......因为一直都只知道在win32控制台下写代码...确不知开发一个项目和产品除了要高级语言后还需要一些什么..  // 先把语言学好，这是最简单的东西  最后的是..c、c++、Linux c、网络编程、多进程 、多线程、数据结构、数据库、脚本语言（主流shell）这样的学习方向以后的就业方向是什么..?  // Linux程序员（这是最典型的，但是不限于）； 可以上招聘网转转。

1楼的回答很详细，学习之~~ 说的这句话更好： 以编程为工作，你只需要在需要用什么的时候，会用。 以编程为兴趣，没有什么不是你不需要学的。@zhouqinghe24  10楼赵4老师的这样的回复在很多帖子都可见啊！@zhao4zhong1

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

1.为什么我写出来的程序全都是一些黑白的东西...然而别人的程序中能够拥有彩色的图标..和炫耀的背景和选项... 他们这些炫酷的东西的核心也是有些黑白的东西。比如你用c++写控制台的程序，出来的就是黑白的（最多有一些字体颜色的变化），但是假如你写的是java，MFC之类的应用程序，你运行出来的就是一个有图像有按钮的东西。慢慢来，先把控制台的学好。然后再学习其他的。 ps：炫酷的仅仅是外观，编写这些程序的时候也是会用到数组，指针等你现在理解的东西。  2.为什么学习高级语言的编程还要学习操作系统..?是不是这些操作系统能提供一些API的函数为高级语言所使用? 学习高级语言了解操作系统是有好处的，但是这不是必须的。不同的操作系统提供了不同的API，有专门的文档告诉你怎么用，将来看到了去百度一下或者查查说明文件即可。比如UNIX环境高级编程这本书就是讲解了UNIX提供编程的APT。而MFC则是使用windows的API。  3.数据库和高级语言的关系是什么.?或者说..学数据库对高级语言有什么帮助..? 就像文件和C语言的关系，数据库提供接口（文件也有接口，比如fopen等），供程序使用，然后就可以再数据库中操作数据（就好比在文件中操作一样）；数据库对高级语言没有帮助——它对软件有帮助，对编程人员有帮助——因为他是一个工具，高级语言是不会讲解数据库的，你需要找额外的讲解数据库的书看  4.对于深造高级语言的选择是选择C好还是选择C++好,如果以后想编写软件的话.? C 或者C++都是其他很多高级语言的基石，你要学好这两者！但是看你以后想怎么发展，假如想做Android开发的话我告诉你你可能学的很多都用不上，因为你要重新学习java。所以先选好自己的路很重要  5.可以举一些用C或者C++写出来的软件吗?... Linux内核是用C、c++写的。然后还有 Microsoft Windows Symbian OS Apple MacOS UI (Aqua) KDE Oracle database MySQL Microsoft SQL Server Microsoft Internet Explorer Mozilla Firefox Safari Google Chrome Opera Microsoft Visual Studio Microsoft .Net CLR Java Virtual Machine (JVM) Adobe Photoshop Google Microsoft Visual C++         Microsoft Visual Basic Microsoft Visual C# Microsoft DirectX

引用 楼主 ikuovbs 的回复:我是一位自学编程的人...在自学的过程中...有些东西难免让我郁闷... 1.为什么我写出来的程序全都是一些黑白的东西...然而别人的程序中能够拥有彩色的图标..和炫耀的背景和选项... 2.为什么学习高级语言的编程还要学习操作系统..?是不是这些操作系统能提供一些API的函数为高级语言所使用? 3.数据库和高级语言的关系是什么.?或者说..学数据库对高级语言有什么帮助..? 4.对于深造高级语言的选择是选择C好还是选择C++好,如果以后想编写软件的话.? 5.可以举一些用C或者C++写出来的软件吗?... 由于一直都是在自学编程...这些的基础知识我都不知道..搜索百度都没有统一的回答..所有在这里想请教一下csdn的大神... 还有就是自学编程真的不是一件容易的事......因为一直都只知道在win32控制台下写代码...确不知开发一个项目和产品除了要高级语言后还需要一些什么..  最后的是..c、c++、Linux c、网络编程、多进程 、多线程、数据结构、数据库、脚本语言（主流shell）这样的学习方向以后的就业方向是什么..? 回答这么认真，顶一个！

重要的是 打好基础。不要 好高骛远。   高楼大厦起于平地。

引用 3 楼 ikuovbs 的回复:[quote=引用 1 楼 zhouqinghe24 的回复:] 1.为什么我写出来的程序全都是一些黑白的东西...然而别人的程序中能够拥有彩色的图标..和炫耀的背景和选项...   色彩炫酷只是程序的外衣。外衣一般来说是美工做的。写程序只是把衣服展现出来，就像一个衣架子。 再漂亮的衣服叠起来也没人知道它漂亮。需要有人穿起来才行。   2.为什么学习高级语言的编程还要学习操作系统..?是不是这些操作系统能提供一些API的函数为高级语言所使用?    操作系统是要你了解系统设计的原理，就如你要学习物理学，就需要知道牛顿的定律一样，你要开发在操作系统上运行的程序，就应该知道，或者了解操作系统的原理，哪怕是简单原理。  3.数据库和高级语言的关系是什么.?或者说..学数据库对高级语言有什么帮助..?   数据库跟高级语言一毛钱关系都没有。 数据库只是提供存储数据的一种方式，就像你把你的日记写在日记本上，记录了你的数据，但是 ，日记本，跟你从小学习的中文有什么关系呢？   数据库只是一个特殊的日记本，你需要按照它的规则来记录你的数据，配合开发语言，可以按照一定的标准开发程序，提高开发效率，避免重复造车轮的事情（这里是指不用自己定义数据存储结构了）。   4.对于深造高级语言的选择是选择C好还是选择C++好,如果以后想编写软件的话.?   C 和C ++ 都是工具。语言的差异，使得每个语言在某个领域或业务非常擅长，比如迅雷和快播的区别，都可以下载电影，但是他们 的区别你懂得。 擅长不同而已。   这个擅长不同不仅仅指C 和C++。  5.可以举一些用C或者C++写出来的软件吗?...   今天帮别人安装Dreamweaver时发现， 它就有MFC的程序。还有很多，比如你现在在用的windows 系统， linux 操作系统，大部分都是C 的实现。  最后的是..c、c++、Linux c、网络编程、多进程 、多线程、数据结构、数据库、脚本语言（主流shell）这样的学习方向以后的就业方向是什么..?   就业问题，最是复杂了。。这个学习方向，可以做linux服务器编程。   那我可以理解为数据库那些 操作系统那些对于编程来说只是为了了解而已嘛?真正重要的是深造语言和数据结构和算法吗?[/quote]  以编程为工作，你只需要在需要用什么的时候，会用。  以编程为兴趣，没有什么不是你不需要学的。

引用 2 楼 user-8 的回复:这种问题就好像是问 如果我想成为像爱因斯坦一样的科学家  我需要学习什么？ 没有人可以回答  因为没人知道你究竟懂什么  或许吧..当你学一样东西没人指引的情况下..你又不知这东西最后能变成什么....这样你将很难找到一个适当的理由让自己坚持下去.....当然除了兴趣

引用 1 楼 zhouqinghe24 的回复:1.为什么我写出来的程序全都是一些黑白的东西...然而别人的程序中能够拥有彩色的图标..和炫耀的背景和选项...   色彩炫酷只是程序的外衣。外衣一般来说是美工做的。写程序只是把衣服展现出来，就像一个衣架子。 再漂亮的衣服叠起来也没人知道它漂亮。需要有人穿起来才行。   2.为什么学习高级语言的编程还要学习操作系统..?是不是这些操作系统能提供一些API的函数为高级语言所使用?    操作系统是要你了解系统设计的原理，就如你要学习物理学，就需要知道牛顿的定律一样，你要开发在操作系统上运行的程序，就应该知道，或者了解操作系统的原理，哪怕是简单原理。  3.数据库和高级语言的关系是什么.?或者说..学数据库对高级语言有什么帮助..?   数据库跟高级语言一毛钱关系都没有。 数据库只是提供存储数据的一种方式，就像你把你的日记写在日记本上，记录了你的数据，但是 ，日记本，跟你从小学习的中文有什么关系呢？   数据库只是一个特殊的日记本，你需要按照它的规则来记录你的数据，配合开发语言，可以按照一定的标准开发程序，提高开发效率，避免重复造车轮的事情（这里是指不用自己定义数据存储结构了）。   4.对于深造高级语言的选择是选择C好还是选择C++好,如果以后想编写软件的话.?   C 和C ++ 都是工具。语言的差异，使得每个语言在某个领域或业务非常擅长，比如迅雷和快播的区别，都可以下载电影，但是他们 的区别你懂得。 擅长不同而已。   这个擅长不同不仅仅指C 和C++。  5.可以举一些用C或者C++写出来的软件吗?...   今天帮别人安装Dreamweaver时发现， 它就有MFC的程序。还有很多，比如你现在在用的windows 系统， linux 操作系统，大部分都是C 的实现。  最后的是..c、c++、Linux c、网络编程、多进程 、多线程、数据结构、数据库、脚本语言（主流shell）这样的学习方向以后的就业方向是什么..?   就业问题，最是复杂了。。这个学习方向，可以做linux服务器编程。   那我可以理解为数据库那些 操作系统那些对于编程来说只是为了了解而已嘛?真正重要的是深造语言和数据结构和算法吗?


Question: 看TCPIP详解要不要C语言的基础？

需要 因为你单纯学tcp/ip协议而不用代码实现socket的话    我不知道你只学协议的理论有什么用.....  当然，如果你只是要学理论，确实不需要懂得任何代码

三次握手0.0 要是不是搞编程的，完全没必要有C 基础，编程语言只是把设想编程现实而已。  如是真要搞编程，C语言基础完全不够， 还要大数据的概念，大数据小并发，大并发大数据，小数据大并发等等

引用 16 楼 mosquitoh 的回复:[quote=引用 11 楼 luciferisnotsatan 的回复:] 卷一不用，卷一是介绍这些协议的。 谢谢，那些IP地址，子网掩码，数据路由第1卷有没有介绍？看中文版的行不？我是想看英文版，但只有MOBI格式的。要不就要买英文的书。[/quote] 应该有，几年前看的了，记不清了。

引用 16 楼 mosquitoh 的回复:[quote=引用 11 楼 luciferisnotsatan 的回复:] 卷一不用，卷一是介绍这些协议的。 谢谢，那些IP地址，子网掩码，数据路由第1卷有没有介绍？看中文版的行不？我是想看英文版，但只有MOBI格式的。要不就要买英文的书。[/quote] 看自己英语底子如何喽，能读懂，英文版当然最好不过了

引用 10 楼 zhao4zhong1 的回复:[quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 8 楼 zhao4zhong1 的回复:] 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545老赵，真没听懂说什么[/quote] 等你能听懂我说什么的时候你就成熟了！ 大妈好腻害哦  小时候跟妈妈去洗澡，总去女澡堂，记得曾经问过那里搞卫生的阿姨，我什么时候才能不进女澡堂洗澡。  大妈头也不抬地说：“等你什么时候想进了你就不能进了。”  当时没明白，多年以后，我才恍然大悟，这位大妈是搞哲学的么？ [/quote]  哲理啊！  想进就不能进了。

卷一不用，卷一是介绍这些协议的。

引用 9 楼 mosquitoh 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545老赵，真没听懂说什么[/quote] 等你能听懂我说什么的时候你就成熟了！ 大妈好腻害哦  小时候跟妈妈去洗澡，总去女澡堂，记得曾经问过那里搞卫生的阿姨，我什么时候才能不进女澡堂洗澡。  大妈头也不抬地说：“等你什么时候想进了你就不能进了。”  当时没明白，多年以后，我才恍然大悟，这位大妈是搞哲学的么？

引用 11 楼 luciferisnotsatan 的回复:卷一不用，卷一是介绍这些协议的。 谢谢，那些IP地址，子网掩码，数据路由第1卷有没有介绍？看中文版的行不？我是想看英文版，但只有MOBI格式的。要不就要买英文的书。

卷一不大需要. 卷二必须的,没有C基础看不懂.

不会也行，会最好 卷一基本不需要C基础  单纯学习网络没必要看TCPIP详解，比较底层，更适合程序员

引用 8 楼 zhao4zhong1 的回复:不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545老赵，真没听懂说什么

C语言还是会的好

客户端： #include <iostream> #include <Winsock2.h> #include <stdio.h>  //！！！！要连接一个Ws2_32.lib这样一个连接   int main() {    	using namespace std; 	 	WORD wVersionRequested; 	WSADATA wsaData; 	int err;      wVersionRequested = MAKEWORD(1, 1);      err = WSAStartup(wVersionRequested, &wsaData);     if (err != 0)  	{         cout<<"WSAStartup failed with error: "<<err<<endl;         return 1;     }      if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  	{         printf("Could not find a usable version of Winsock.dll\n");         WSACleanup();         return 1;     }     else         printf("The Winsock 2.2 dll was found okay\n"); 	 	//创建套接字 	SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);  	//建立一个连接connect 	SOCKADDR_IN addrSrv; 	addrSrv.sin_addr.S_un.S_addr=(inet_addr)("127.0.0.1");               //127.0.0.1  特殊地址，表示本地地址 																		 //inet_addr函数将十进制点格表示的IP地址切换成U_LONG类型的TCP/IP可以接受的地址 	addrSrv.sin_family=AF_INET; 	addrSrv.sin_port=htons(6000); 	connect(sockClient,(SOCKADDR*)(&addrSrv),sizeof(SOCKADDR));  	//接受数据 	char recvBuff[100]; 	recv(sockClient,recvBuff,100,0); 	printf("%s\n",recvBuff);  	//发送数据 	send(sockClient,"This is Zhangsan",sizeof("This is Zhangsan")+1,0);  	//关闭套接字，释放为套接字分配的资源 	closesocket(sockClient); 	WSACleanup();  	cin.get(); } 服务器： #include <iostream> #include <Winsock2.h> #include <stdio.h>  //！！！！要连接一个Ws2_32.lib这样一个连接   int main() {    	using namespace std; 	 	WORD wVersionRequested; 	WSADATA wsaData; 	int err;      wVersionRequested = MAKEWORD(1, 1);      err = WSAStartup(wVersionRequested, &wsaData);     if (err != 0)  	{         cout<<"WSAStartup failed with error: "<<err<<endl;         return 1;     }      if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  	{         printf("Could not find a usable version of Winsock.dll\n");         WSACleanup();         return 1;     }     else         printf("The Winsock 2.2 dll was found okay\n");  	//创建套接字 	SOCKET SockSrv=socket(AF_INET,SOCK_STREAM,0);          //SOCK_STREAM流式套接字         SOCK_DGRAM数据报套接字 	//套接字和本地地址绑定 	SOCKADDR_IN addrSrv;      addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);        //htonl转换一个u_long类型从主机字节序到TCP/IP网络字节序 	                                                       //htons转换一个u_short类型从主机字节序到TCP/IP网络字节序 	addrSrv.sin_family=AF_INET; 	addrSrv.sin_port=htons(6000);  	bind(SockSrv,(SOCKADDR*)(&addrSrv),sizeof(SOCKADDR));  	//将套接字设置为监听模式,并监听客户的连接请求 	listen(SockSrv,5);  	SOCKADDR_IN addrClient; 	int len=sizeof(SOCKADDR);  	while(1) 	{ 		SOCKET sockConn=accept(SockSrv,(SOCKADDR*)(&addrClient),&len); 		 		//发送 		char sendBuff[100];																							 		sprintf(sendBuff,"Welcome %s to 113 workspace \n",(inet_ntoa)(addrClient.sin_addr));     //sprintf用于初始化一个数组 																								 //inet_ntoa函数接受一个in_adrr类型的参数返回一个 																							     //点分十进制表示的IP地址的一个字符串 		send(sockConn,sendBuff,strlen(sendBuff)+1,0); 		 		//接收 		char recvBuff[100]={0}; 		recv(sockConn,recvBuff,100,0); 		printf("%s\n",recvBuff); 		 		//关闭套接字,释放为套接字分配的资源 		closesocket(sockConn); 	}  /* then call WSACleanup when done using the Winsock dll */          WSACleanup();  	cin.get(); }

引用 3 楼 qq_17612923 的回复:引用 2 楼 mosquitoh 的回复:[quote=引用 1 楼 qq_17612923 的回复:] 其实C基础就够了，用到的也不过~~~~~最近在写通讯程序，就看了一下就自己写了，重点在于自己实践发现问题再解决问题还是要点吧？没有的话能不能勉强看？ 用的不多，不会的就去百度吧，如果要从C开始要很久的（当然这样肯定更好），前几天写了一个最简单的服务器和客户端程序，你要的话可以发给你看下，是最基础的[/quote]呵呵呵，谢谢，本人很菜的，看不懂，还要努力。

引用 2 楼 mosquitoh 的回复:引用 1 楼 qq_17612923 的回复:其实C基础就够了，用到的也不过~~~~~最近在写通讯程序，就看了一下就自己写了，重点在于自己实践发现问题再解决问题还是要点吧？没有的话能不能勉强看？ 用的不多，不会的就去百度吧，如果要从C开始要很久的（当然这样肯定更好），前几天写了一个最简单的服务器和客户端程序，你要的话可以发给你看下，是最基础的


Question: 用c语言将一个数分解成加数相加的形式

#include <stdio.h> #include <stdlib.h> void print(int res[], int num) {     static int L=0;     L++;     printf("%8d:",L);     for (int i=0;i<num;++i) {         printf(" %d", res[i]);     }     printf("\n"); } void split(int n, int m) {// n表示总数，m表示最大因子     static int res[100];// 保存结果     static int num=-1;// 当前因子下标      if (n<m || n<0 || m<1) return;     num++;     if (0==n) {// 递归终止条件，为0不可再分，直接输出         print(res,num+1);         num--;         return;     } else {         if (n==m) {// 不拆，直接输出             res[num]=m;             print(res,num+1);             num--;         } else {             // 拆分出第一个             res[num]=m;             n=n-m;              if (m>n) m = n; // 最大因子不可能大于总数              for (int i=m;i>=1;--i) {// 循环，第二个因子可以继续拆分，而且按照最大因子不同可以拆分成多个                 split(n,i);             }             num--;         }     } } void Split(int n) {     if (n<=0) return;     if (100<n) {         printf("Up to 100\n");         return;     }     for (int i=n;i>=1;--i) {         split(n, i);     } } void main(int argc,char **argv) {          if (argc<=1) Split(5);     else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));     else              Split(atoi(argv[1])); }

有点难度引用 2 楼 user-4 的回复:[quote=引用 1 楼 iyomumx 的回复:] 仅供参考 #include <stdio.h> #include <stdlib.h>  #define MIN(X,Y) (((X)<(Y))?(X):(Y))  void WriteBuffer(const int * buffer) { 	while (buffer[1] != 0) 	{ 		printf("%d+", *buffer++); 	} 	printf("%d\n", *buffer); }  void _splitnum(int * buffer, const int x, const size_t pos) { 	if (x <= 1) 	{ 		buffer[pos + 1] = x; 		buffer[pos + 2] = 0; 		WriteBuffer(buffer); 	} 	else 	{ 		size_t npos = pos + 1; 		for (int i = 1; i <= MIN(x, buffer[pos]); i++) 		{ 			buffer[npos] = i; 			_splitnum(buffer, x - i, npos); 		}                buffer[npos] = x;           //修改了下                buffer[npos+1] = 0;                WriteBuffer(buffer); 	} }  void SplitNum(const int x) { 	if (x <= 0) return; 	int * buffer = (int*)malloc(sizeof(int) * (x + 1)); 	for (int i = 1; i < x; i++) 	{ 		buffer[0] = i; 		_splitnum(buffer, x - i, 0); 	} }  int main() { 	int x = 0; 	if (scanf("%d", &x)) 		SplitNum(x);     return EXIT_SUCCESS; }  修改了些，试试[/quote]

引用 1 楼 iyomumx 的回复:仅供参考 #include <stdio.h> #include <stdlib.h>  #define MIN(X,Y) (((X)<(Y))?(X):(Y))  void WriteBuffer(const int * buffer) { 	while (buffer[1] != 0) 	{ 		printf("%d+", *buffer++); 	} 	printf("%d\n", *buffer); }  void _splitnum(int * buffer, const int x, const size_t pos) { 	if (x <= 1) 	{ 		buffer[pos + 1] = x; 		buffer[pos + 2] = 0; 		WriteBuffer(buffer); 	} 	else 	{ 		size_t npos = pos + 1; 		for (int i = 1; i <= MIN(x, buffer[pos]); i++) 		{ 			buffer[npos] = i; 			_splitnum(buffer, x - i, npos); 		}                buffer[npos] = x;           //修改了下                buffer[npos+1] = 0;                WriteBuffer(buffer); 	} }  void SplitNum(const int x) { 	if (x <= 0) return; 	int * buffer = (int*)malloc(sizeof(int) * (x + 1)); 	for (int i = 1; i < x; i++) 	{ 		buffer[0] = i; 		_splitnum(buffer, x - i, 0); 	} }  int main() { 	int x = 0; 	if (scanf("%d", &x)) 		SplitNum(x);     return EXIT_SUCCESS; }  修改了些，试试

引用 1 楼 iyomumx 的回复:仅供参考 #include <stdio.h> #include <stdlib.h>  #define MIN(X,Y) (((X)<(Y))?(X):(Y))  void WriteBuffer(const int * buffer) { 	while (buffer[1] != 0) 	{ 		printf("%d+", *buffer++); 	} 	printf("%d\n", *buffer); }  void _splitnum(int * buffer, const int x, const size_t pos) { 	if (x <= 1) 	{ 		buffer[pos + 1] = x; 		buffer[pos + 2] = 0; 		WriteBuffer(buffer); 	} 	else 	{ 		size_t npos = pos + 1; 		for (int i = 1; i <= MIN(x, buffer[pos]); i++) 		{ 			buffer[npos] = i; 			_splitnum(buffer, x - i, npos); 		} 	} }  void SplitNum(const int x) { 	if (x <= 0) return; 	int * buffer = (int*)malloc(sizeof(int) * (x + 1)); 	for (int i = 1; i < x; i++) 	{ 		buffer[0] = i; 		_splitnum(buffer, x - i, 0); 	} }  int main() { 	int x = 0; 	if (scanf("%d", &x)) 		SplitNum(x);     return EXIT_SUCCESS; }  谢谢

引用 5 楼 zhao4zhong1 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出 赵老师的回答太专业了 赞一个 先谢谢了 我好好学习学习下

赵老师的回答太专业了 赞一个 先谢谢了 我好好学习学习下


Question: 谁能详解C中for循坏堆栈的变化

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

首先堆和栈是两个不同的概念，堆空间一般用于程序动态的申请及释放，栈则供函数调用存储当前的入参、局部变量、返回地址等，一般每个函数调用在栈中的空间分配都以“栈帧”的概念来标识。 而for循环只是一个代码段，其执行的代码存储在独立的代码段(区)，不是堆也不是栈，代码需要使用到的变量及空间等都从堆和栈中存取。 简单说for循环里面存储的只是命令，命令执行时要使用到堆和栈中的数据。是这样一个关系吧。。。

对于一个空for，堆栈无任何变化。如果有调用其他函数，定义了新变量，申请释放空间等操作，栈会有变化  你可能想问的是for是如何一步步执行的

参考 http://www.cnblogs.com/lds85930/archive/2007/07/22/827453.html

没变化。。。。。。


Question: 怎么用C语言实现包含所有元素的所有组合

烦请楼主补全此示例： 例如:数组arr={1,11,111,1111}  包含所有元素的组合结果为:

引用 13 楼 u011997922 的回复:[quote=引用 12 楼 zhao4zhong1 的回复:] 烦请楼主补全此示例： 例如:数组arr={18,27,39}  包含所有元素的组合结果为: {18,27,39}   {18,2739}  {1827,39}  {1839,27} {182739}[/quote] 烦请楼主补全此示例： 例如:数组arr={1,27,309,4273}  包含所有元素的组合结果为:

嗯,不过是要包含所有元素的所有组合,不能有重复的元素

好難阿< 剛開始以為很簡單

引用 17 楼 u010936098 的回复:10这个数量就已经不小了。 要知道处理全子集就已经是指数级的算法了，而全子集相当于2分组，而你这个是1..N分组 象这类问题你应该考虑如何去求满意解而不是求最做优解。 有什么好的方法可以求得满意解?

引用 15 楼 u011997922 的回复:[quote=引用 14 楼 my_live_123 的回复:] 集合的组合：计数还可以n个元素，2^n - 1种组合，如果列举话，指数数量级，当n很大时，这是惊人的！楼主三思 这个我已经考虑到了.10以内就可以了[/quote] 10这个数量就已经不小了。 要知道处理全子集就已经是指数级的算法了，而全子集相当于2分组，而你这个是1..N分组 象这类问题你应该考虑如何去求满意解而不是求最做优解。

引用 15 楼 u011997922 的回复:[quote=引用 14 楼 my_live_123 的回复:] 集合的组合：计数还可以n个元素，2^n - 1种组合，如果列举话，指数数量级，当n很大时，这是惊人的！楼主三思 这个我已经考虑到了.10以内就可以了[/quote] 可以尝试下递归

引用 14 楼 my_live_123 的回复:集合的组合：计数还可以n个元素，2^n - 1种组合，如果列举话，指数数量级，当n很大时，这是惊人的！楼主三思 这个我已经考虑到了.10以内就可以了

引用 12 楼 zhao4zhong1 的回复:烦请楼主补全此示例： 例如:数组arr={18,27,39}  包含所有元素的组合结果为: {18,27,39}   {18,2739}  {1827,39}  {1839,27} {182739}

引用 9 楼 u010936098 的回复:样是行不通的，枚举法是指数级的算法，数据量稍大一点就不得了。 可有什么好办法,我是分区域来组合降低数据量.

先全排列123,然后在里面插入逗号,可以插入一个u逗号,i也可以h插入两个逗号, 要求逗号不可以插 最前面,也不可以插咋最后面.

引用 4 楼 u011997922 的回复:我想弄一个物流提送货自动配载功能，思路是先把所有要提送的货物组合然后再根据各种约束挑选车辆和行车路径最后计算出各种组合的花费，选出比较合理的方案。不知大家可有相似的事例提供或者方案。  这样是行不通的，枚举法是指数级的算法，数据量稍大一点就不得了。

可能是描述不准，看示例理解。哈哈。。。

我也感觉楼主的命题有问题..... {1, 2, 3} 算上逗号..... 这组合好多呀

楼主此命题有误。

其实这就是一个简单的组合问题，思路如下： 比如：{1,2,3}  C(0,3) + C(1, 3) + C(3,3) = 5 =  2^3 - C(2,3) 这里需要考虑到C(2,3)跟C(1,3)是一样的，你只要去重就可以了，在这里你只需要定义一个C(m,n)函数就可以了

楼主需要的是列出所有组合的算法吧？？


Question: C语言渣渣问题T^T，求大神

在switch前 把 return 的ch打印出来

二楼说得对，menu（）中的 scanf("%c",&ch); 会把缓冲区的回车键\n 当输入的，加个循环判断去掉回车，详细看C Primer Plus有关输入输出的地方

引用 4 楼 futurebc 的回复:引用printf("姓名:");         scanf("%s",&s[i].name);这里有问题  search()里面 的if判断都有问题 引用scanf("%s",&filename);这里filename是个指针，没指向，不用字符数组？ 引用case'10':write();break;         case'11':read();break;这里'10','11' 是个错误的东西  最后，一个个把警告解决吧在最前面的还有错。。。我找不出来了。。。是主函数和菜单函数衔接转换的地方。。。我输入了两个学生信息，然后最好一个学生的总分和平均分主动变成了下一次主函数的选项。。。。一直跟我说Wrong choice...怎么转换回主函数。。。还有。。学生信息怎么保存不了。。。是哪个版块有问题。。。求大神解答

引用 2 楼 nwcfafniw 的回复:在scanf后面加一个getchar试试吧。。回车符留在输入缓冲里了。。 哪个scanf???????????..........

在scanf后面加一个getchar试试吧。。回车符留在输入缓冲里了。。

为什么调试没有查出错误，运行起来就不能用了，只能用1的选项，其他的选项都直接出现Wrong choiceT^T,求大神


Question: 新手，求杨辉三角【等边三角形】C语言题，求程序和思路！！

第N层最多N个数，用MAX_BUF来控制，SEP_W来控制宽度，感觉层数太大也没用，屏幕显示不下。 代码仅供参考！ #include <stdio.h> #include <stdlib.h> #define SEP_W 8 #define MAX_BUF 20  void primt_yang(int lev) {     int buf[MAX_BUF];     int  anchor =lev-1;     printf("%*d\n",lev*SEP_W/2,1);     buf[anchor--]=1;     for(int i=1,pos=anchor;i<lev;i++,pos=--anchor)     {         printf("%*d",(lev-i)*SEP_W/2,1);         buf[pos++]    =1;         for(int j=0;j<i-1;++j)         {             buf[pos]+=buf[pos+1];             printf("%*d",SEP_W,buf[pos++]);         }         printf("%*d\n",SEP_W,1);     } }   int main(int   argc,   char*   argv[])  {     primt_yang(10);     return 0;  }

#define LEVEL 8    int main(int   argc,   char*   argv[])     {    	int a[LEVEL+1]; 	int i = 0; 	int c;   	for(i=0;i<=LEVEL;i++)   	{   		a[i]=1;   		for(c=i-1;c>=1;a[c--]+=a[c-1]);   		{ 			printf("%*d",(LEVEL-i)*3+1,a[0]);  		} 		for(c=1;c<=i;printf("%6d",a[c++]));   		{ 			printf("\n");  		} 	}   	     return 0; 	 }

#include <stdio.h> #define MAXN 10 unsigned __int64 y[MAXN][MAXN]; int i,j; char s[60]; void main() {     printf("%30s\n","1  ");     printf("%33s\n","1     1  ");     y[1][0]=1ui64;y[1][1]=1ui64;     for (i=2;i<MAXN;i++) {         y[i][0]=1ui64;sprintf(s,"1  ");         for (j=1;j<=i-1;j++) {             y[i][j]=y[i-1][j-1]+y[i-1][j];             sprintf(s,"%s   %-3I64u",s,y[i][j]);         }         y[i][i]=1ui64;sprintf(s,"%s   1  ",s);         printf("%*s\n",30+i*3,s);     } } //                           1 //                        1     1 //                     1     2     1 //                  1     3     3     1 //               1     4     6     4     1 //            1     5     10    10    5     1 //         1     6     15    20    15    6     1 //      1     7     21    35    35    21    7     1 //   1     8     28    56    70    56    28    8     1 //1     9     36    84    126   126   84    36    9     1


Question: 炫耀帖，记录本人在CSDN上的活动，以免以后找不到了。

过来水一下

引用 52 楼 cysccnu 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b); [/quote]  你的观点很荒谬。汇编说明不了任何问题。  引用 52 楼 cysccnu 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b); [/quote]  汇编输出能够代替C标准？就凭这一点，我就知道说再多，也白费口舌。 不解释 ，我知道没用的……

for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }

引用 42 楼 sholber 的回复:今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b);

楼主先改代码

我是引用错了，csdn的bug，第二次引用居然没有覆盖第一次。 我引用的其实是你这个贴   天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： C/C++ code ? 1 2 int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b);  帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-

引用 48 楼 ypzhong 的回复:[quote=引用 46 楼 sholber 的回复:] 问题： 函数 void play（void） {      int datalen；          unsigned char  *data1 = "*abvxdfkg";      datalen = strlen(data1);  } 编译一直出现 argument of type "unsigned char *" is incompatible with parameter of type "const char *"；  请问将其强制转换是否有问题datalen = strlen((const char *)data1);   问题的分析如下：  翻一下ISO/IEC 9899:201x Committee Draft 文件N1570，strlen函数的原型如下：  # include <string.h>  size_t strlen (const char * s);  很清楚，strlen函数的参数类型是const char *。  N1570，6.5.2.2 Function calls  In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the  corresponding argument. 这即是说，参数传递类似于赋值。那么，我们再看赋值时，如果=运算符左右两个操作数都是指针类型时，有什么样的要求--> N1570，6.5.16.1 Simple assignment  the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed  to by the left has all the qualifiers of the type pointed to by the right; 简言之，左右两个指针所指向的类型，在去掉限定符后，应当是兼容类型。而且，左边那个指针所指向的类型，应当具有右边那个指针所指向的类型的所有限定符。  因为strlen函数的参数类型是const char *，传递给该函数的参数类型是unsigned char *，那么， 1，左边指针所指向的类型具有const限定符，右边指针指向的类型没有限定符。可以视为，左边指针指向的类型具有自己的限定符const，加上右边指针所指向的类型的限定符（无）。这一条件通过； 2，两个指针所指向的类型在去掉限定符后，一个是char，另一个是unsigned char。不管char等价于unsigned char，还是等价于signed char，它们都是三种彼此不兼容的类型。问题就出在这里。  关于char、unsigned char和signed char的标准说明： N1570，6.2.7  Compatible type and composite type  Two  types  have compatible type if their types are the same.   N1570，第45页，注脚45： CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.  Irrespective of the choice made,char is a separate type from the other two and is not compatible with either. 引用 44 楼 sholber 的回复:[quote=引用 43 楼 lm_whales 的回复:] [quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。[/quote]    呵呵，语言的目的是用来解决现实问题的。钻牛角尖，舍本求末是没有意义。[/quote]  连细节都没搞清楚，你还怎么解决现实问题。所以你也只能呵呵了。

引用 46 楼 sholber 的回复:问题： 函数 void play（void） {      int datalen；          unsigned char  *data1 = "*abvxdfkg";      datalen = strlen(data1);  } 编译一直出现 argument of type "unsigned char *" is incompatible with parameter of type "const char *"；  请问将其强制转换是否有问题datalen = strlen((const char *)data1);   问题的分析如下：  翻一下ISO/IEC 9899:201x Committee Draft 文件N1570，strlen函数的原型如下：  # include <string.h>  size_t strlen (const char * s);  很清楚，strlen函数的参数类型是const char *。  N1570，6.5.2.2 Function calls  In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the  corresponding argument. 这即是说，参数传递类似于赋值。那么，我们再看赋值时，如果=运算符左右两个操作数都是指针类型时，有什么样的要求--> N1570，6.5.16.1 Simple assignment  the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed  to by the left has all the qualifiers of the type pointed to by the right; 简言之，左右两个指针所指向的类型，在去掉限定符后，应当是兼容类型。而且，左边那个指针所指向的类型，应当具有右边那个指针所指向的类型的所有限定符。  因为strlen函数的参数类型是const char *，传递给该函数的参数类型是unsigned char *，那么， 1，左边指针所指向的类型具有const限定符，右边指针指向的类型没有限定符。可以视为，左边指针指向的类型具有自己的限定符const，加上右边指针所指向的类型的限定符（无）。这一条件通过； 2，两个指针所指向的类型在去掉限定符后，一个是char，另一个是unsigned char。不管char等价于unsigned char，还是等价于signed char，它们都是三种彼此不兼容的类型。问题就出在这里。  关于char、unsigned char和signed char的标准说明： N1570，6.2.7  Compatible type and composite type  Two  types  have compatible type if their types are the same.   N1570，第45页，注脚45： CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.  Irrespective of the choice made,char is a separate type from the other two and is not compatible with either. 引用 44 楼 sholber 的回复:[quote=引用 43 楼 lm_whales 的回复:] [quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。[/quote]    呵呵，语言的目的是用来解决现实问题的。钻牛角尖，舍本求末是没有意义。

已经很久没看到有人愿意这么去翻标准了。

原来作为 void 是这个意思， 我还以为直接不用求值了呢 直接不用求值虽然好， 但是会造成表达式求值过程的不统一。 想必编译器，不会这样做，  但是针对 这种情况， 直接丢弃表达式的值， 道是很简单方便。  当然这个表达式 也可以本身就是 void 类型的。  例如调用一个无返回值的函数（void 类型的函数）的函数调用表达式。

引用 43 楼 lm_whales 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。

引用 42 楼 sholber 的回复:今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。

声明：以下内容，同写代码又臭又长的赵老湿切磋一下。   给定声明： int * * p; 则p是指向“指向int类型的指针”的指针。  可以动态创建一个数组，令p指向它的首元素。但是，这个数组的元素类型必须是int * ： p = (int * *) malloc (sizeof (int *) * ROWS); 那么，如何利用p访问这个数组的每一个元素呢（比如，将它的每个元素都赋NULL指针）？  第一种方法是利用指针运算的规则： for (int i = 0; i < ROWS; i ++)      * (p + i) = NULL; 第二种方法是利用“在某些情况下，数组和指向它首元素的指针等价”： for (int i = 0; i < ROWS; i ++)      p [i] = NULL; 第三种方法也是利用数组下标运算，但是要先将p从“指向数组首元素的指针”转化为“指向一个数组的指针”： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      (* q) [i] = NULL; 以上，声明q为指向数组的指针，然后将p转化为指向数组的指针，赋给q。当q解引用（*q）后，就得到一个数组，这时就可以利用下标来访问数组的每一个元素了。考虑到在某些情况下，数组和指向它首元素的指针等价，故上述代码也可以写成： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      * ((* q) + i) = NULL;  前面那个动态创建的数组，其元素都是指向int类型的指针，我们已经全部赋值为NULL。如果希望令它们各自指向一个int类型的数组的首元素，怎么办呢？很简单，只需要使用上述四种方法中的一种，将NULL改成 (int *) malloc (sizeof (int) * COLS); 即可。如： for (int i = 0; i < ROWS; i ++)      * (p + i) = (int *) malloc (sizeof (int) * COLS);  最后，我们来看看，如何用前面的四种方法来读写这个奇怪数组的每一个元素。为简单起见，用前两种方法写，用后两种方法读。  写入数据的方法一： for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          * (* (p + i) + j) = j; 写入数据的方法二： for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          p [i] [j] = j; 读出数据的方法一： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          {              int (* r) [] = (int (*) [])(* q) [i];  //先将(* q) [i]转化为指向数组的指针             printf("%d\n", (* r) [j]);  //r解引用后是数组，下标j引用它的第j个元素         } 读出数据的方法二： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          printf("%d\n", *(* (* q + i) + j));

这是昨天晚上闲来无事，为某网友写的一个函数，目前自认为已经达到最简，看有没有谁能使之更简。 /* 功能：在字符串中找出连续最长的数字串，并把这个串的长度返回，例如：输入akjs123ccd458965，则输出458965，返回6 函数原型：    unsigned int Continumax(char** pOutputstr,  char* intputstr) 输入参数：    char* intputstr  输入字符串  输出参数：    char** pOutputstr: 连续最长的数字串，如果连续最长的数字串的长度为0，应该返回空字符串    pOutputstr 指向的内存应该在函数内用malloc函数申请，由调用处负责释放  返回值：   连续最长的数字串的长度  */ unsigned int Continumax(char * * pOutputstr,  char * intputstr) {     int cnt = 0, c = 0;     char * pos;       while (* intputstr ++ != '\0')         if (* (intputstr - 1) >= '0' && * (intputstr - 1) <= '9')             c ++;         else         {             if (c > cnt) cnt = c, pos = intputstr - c - 1;             c = 0;         }       if ((c = cnt)  != 0)     {         * pOutputstr = malloc (c + 1);         (* pOutputstr) [c] = '\0';         while (c --) (* pOutputstr) [c] = pos [c];     }     else * pOutputstr = 0;       return cnt; }   以上，之所以有     while (* intputstr ++ != '\0')         if (* (intputstr - 1) >= '0' && * (intputstr - 1) <= '9') 是因为，数字串可能位于源串的尾部，即'\0'之前。当然，你可能说使用do ... while语句，但那样还得多一条判断intputstr不为空的语句。

引用 18 楼 zhao4zhong1 的回复:TDD 小心驶得万年船！ #include <stdio.h> #include <string.h> int del_substr (char * str, char const * substr) {     int cnt = 0;     char * p, * q, * r;     while (q = (char *)substr, * (p = r = str ++) != '\0')         while (* q != '\0' && * p ++ == * q)             if (* ++ q == '\0' && ++ cnt && -- str)                 while ((* r ++ = * p ++) != '\0') ;     return cnt; } int main() {     char *s1,*s2;     char b1[100],b2[100];      printf("del_substr(NULL,NULL)==%d\n",del_substr(NULL,NULL));     printf("del_substr(NULL,\"\")==%d\n",del_substr(NULL,""));     printf("del_substr(NULL,\"s\")==%d\n",del_substr(NULL,"s"));      strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));       strcpy(b1,"1sss2s3");s1=b1;strcpy(b2,"sss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));     strcpy(b1,"1sss2ss3");s1=b1;strcpy(b2,"ss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));     strcpy(b1,"sss");s1=b1;strcpy(b2,"sss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));      return 0; }  楼主受累完善一下以上代码。 郑重声明：楼主累死我不赔命。

引用 16 楼 sholber 的回复:就像 if (5 == x) {/* …… */} 这就做作了，令人作呕。要知道，能够这样写的人，已经表明他意识到不能把==写成=。既然自己意识到了，还这么写，不是叫人倒胃吗？至于扯编码风格，什么别人来帮你维护什么的，只能滚犊子了。 这样写是为了避开手误，直接写=编译是不会出错的，特别是你写某些不常见分支没能测出来，就麻烦了。

当然是看看究竟为主


Question: C和指针课后习题疑问

FileTool.exe 替换打开和添加到项目中 Visual C++ 的新功能 http://support.microsoft.com/kb/241396/zh-cn  以管理员身份运行 以XP兼容模式运行  关闭UAC、防火墙、杀毒软件。

还用啥子6.0.块换了吧。

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

粗心大意了吧 * dst++== * str++; 赋值咋能用俩等号呢，要改成* dst++=* str++;  debug跟踪调试一下，编程需要细心耐心~~


Question: 很久以来，关于malloc的疑惑

Polynode *head,*rear,*s; 这样只是定义了几个指针变量，那么这些指针指向哪里呢？学习指针就要时刻问自己：这个指针指向哪里呢？你可以让他指向一个对象，比如head = &xxx;这就是让head保存了xxx的地址，也就是指向了他。如果只是单纯定义了指针没有说明指向，这样的指针是不能使用的（俗称的野指针）。让head=malloc就是让他指向新开辟的内存空间的首地址，才可以正常使用

很久以来，还是要把基础打好。。。

基本概念.. 1) 如楼上所言，head本身是个指针变量，变量本身的空间在栈上 2) head没有初始化之前，指向的地址都不明确，对其指向的内容赋值(楼主所说的直接对head->num=x进行赋值）后果是无法预料的，很大几率会宕掉 3) head=(Polynode *)malloc(sizeof(Polynode));   malloc在堆上申请了一块内存空间，空间大小是Polynode大小，供存放一个Polynode结构体数据，把head指向这个地址，然后就可以通过Head对这块地址进行操作了(如结构体赋值啥的) 4) 堆上申请的内存注意用完后要释放

非常感谢大家的指点与教导~~

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

很久以来，楼主没看到过以下回复：  计算机组成原理→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

指针n本身只占4个字节，这四个字节是用来保存一个地址的，所以地址的最大值是INT_MAX

一个萝卜一个坑,现在你有了一个萝卜(指针),需要一个坑(内存). 好了现在有很多坑(很多内存),你需要抢一个给你自己的萝卜(malloc). 成功后你就可以在自己的坑里削自己的萝卜,想咋削就咋削(修改自己的内存内容). 最后记住,坑用完了,还回去就行了(free).

引用 4 楼 mujiok2003 的回复:head本身的空间在栈上， 不需要分配。 “不需要分配”---> “不需要显式分申请/释放, 空间分配自动进行”。

head本身的空间在栈上， 不需要分配。

malloc的结果是个地址， 不是为了存放head,而是让head的值是这个地址（指向这个地址）。

很久以来，每个学习C语言的人应该在学习指针的第一节课就被告诉指针先初始化再使用

既然是很久以来，那么你在学指针的时候，没看到过使用指针前必须要分配空间的相关知识么？


Question: 新手学C语言

多抄，先会抄，在会写！

引用 7 楼 sholber 的回复:赵四老湿推荐谭浩强、VC和TC，还有BC++。 完全彻底地污蔑！ 本ID啥时候推荐谭浩强了？

如果完全一点基础都没有的话，那就找本零基础的书 遇到问题百度，google，真的好用

Pointers on C

参考我的博文 http://blog.csdn.net/turingo/article/details/8115042

我也在自学，慢慢写些简单的挺有意思的，慢慢来把

书山有路勤为径，学海无涯苦作舟。 有的方法可能适合于A，却不见得适合B。 找些大多数人都看过的书，把基础先练扎实，内功修好了，以后大有好处。 我觉得边做边看书比单纯看书效果要好，或者多做练习题，也可以想些生活中的实际问题来联系实现他，由易到难，一步一步来，急不得。同时不要死抠某些问题，要知道很多问题是和编译器相关的，所以过分纠结就是在浪费时间。

赵四老湿推荐谭浩强、VC和TC，还有BC++。

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

多做,多练,多思考....无捷径...  码农是在一次次的犯错中成熟的....除非你是天才,天才别论.

你这是在寻找武林秘籍么？

别做程序员。


Question: 动态申请的结构体指针属性不能释放

引用 6 楼 starytx 的回复:[quote=引用 5 楼 asdfg48_ 的回复:] 非常感谢您的回答。在结构体中不能这样干啊，比如 typedef struct{  char *RecordData_01[Max_Record_Number][Max_Attribute_Number]; //训练数据  int Record_Number_01;       /*训练数据的行数*/ int  Attribute_Number_01;    /*训练数据的列数*/ }DataNode;   	DataNode  *PreprocessedTrain_Data; 	PreprocessedTrain_Data=(DataNode **)malloc(sizeof(DataNode*));	 	DataPreprocessing(Train_Data,Attribute_Information,PreprocessedTrain_Data,Tree); 编译不通过，在普通变量中二级指针确实无敌于天下，可是在这真不行就是需要传入main中定义的PreprocessedTrain_Data的地址才可以，否则无法改变该指针指向的内容。这样改 void DataPreprocessing(DataNode *Train_Data,Attribute_Node  *Attribute_Information[],DataNode **PreprocessedTrain_Data,DecisionTree &Tree)//训练数据预处理 把函数内部的PreprocessedTrain_Data替换成(*PreprocessedTrain_Data) 调用时DataPreprocessing(Train_Data,Attribute_Information,&PreprocessedTrain_Data,Tree);/*预处理训练数据*/ [/quote]  谢谢版主的回复，我试试

引用 5 楼 asdfg48_ 的回复:非常感谢您的回答。在结构体中不能这样干啊，比如 typedef struct{  char *RecordData_01[Max_Record_Number][Max_Attribute_Number]; //训练数据  int Record_Number_01;       /*训练数据的行数*/ int  Attribute_Number_01;    /*训练数据的列数*/ }DataNode;   	DataNode  *PreprocessedTrain_Data; 	PreprocessedTrain_Data=(DataNode **)malloc(sizeof(DataNode*));	 	DataPreprocessing(Train_Data,Attribute_Information,PreprocessedTrain_Data,Tree); 编译不通过，在普通变量中二级指针确实无敌于天下，可是在这真不行就是需要传入main中定义的PreprocessedTrain_Data的地址才可以，否则无法改变该指针指向的内容。这样改 void DataPreprocessing(DataNode *Train_Data,Attribute_Node  *Attribute_Information[],DataNode **PreprocessedTrain_Data,DecisionTree &Tree)//训练数据预处理 把函数内部的PreprocessedTrain_Data替换成(*PreprocessedTrain_Data) 调用时DataPreprocessing(Train_Data,Attribute_Information,&PreprocessedTrain_Data,Tree);/*预处理训练数据*/

引用 2 楼 u010030181 的回复:改成void DataPreprocessing(DataNode *Train_Data,Attribute_Node  *Attribute_Information[],DataNode **PreprocessedTrain_Data,DecisionTree &Tree)//训练数据预处理 比如说你要改变int a的值，你需要用func(int* temp),你用func(int temp)是改变不了的，你要改变int* a的值，你就需要func(int **temp);  非常感谢您的回答。在结构体中不能这样干啊，比如 typedef struct{  char *RecordData_01[Max_Record_Number][Max_Attribute_Number]; //训练数据  int Record_Number_01;       /*训练数据的行数*/ int  Attribute_Number_01;    /*训练数据的列数*/ }DataNode;   	DataNode  *PreprocessedTrain_Data; 	PreprocessedTrain_Data=(DataNode **)malloc(sizeof(DataNode*));	 	DataPreprocessing(Train_Data,Attribute_Information,PreprocessedTrain_Data,Tree); 编译不通过，在普通变量中二级指针确实无敌于天下，可是在这真不行

引用 1 楼 user-4 的回复:Train_Data在哪定义?具体报错是什么。。  整体代码是封装的DLL，下面是我的结构体定义的部分以及部分代码，基本上动态申请的空间double用红色标注出来了，现在报错的是for(int j=0;j<Train_Data->Attribute_Number;j++){ 		for(int i=0;i<Train_Data->Record_Number;i++){ 			PreprocessedTrain_Data->RecordData[i][j]=(char *)malloc(strlen(Train_Data->RecordData[i][j]) + 1);  提示错误为内存读取受保护，不能读写。但是我觉得错误应该是我在void C4_5_main( )中空间释放的不对，您帮我看看应该怎么改，谢谢 typedef struct Attribute_Node{ 	char  Name[Max_Attribute_Name_Length];             //属性名 	char  kind[Max_Attribute_Name_Length];             //属性类型，如离散型、连续性属性等 	int   Value_Number; 	char  *Value_Name[Max_Record_Number]; 	double Value_Name_Count[Max_Record_Number]; 	double Rntropy; 	double GainRatio; }Attribute_Node; typedef struct{	 	char *RecordData[Max_Record_Number][Max_Attribute_Number]; //训练数据 	int Record_Number;       /*训练数据的行数*/ 	int Attribute_Number;    /*训练数据的列数*/ }DataNode; typedef struct{ 	 char *RecordData_01[Max_Record_Number][Max_Attribute_Number]; //训练数据 	 int Record_Number_01;       /*训练数据的行数*/ 	int  Attribute_Number_01;    /*训练数据的列数*/ }DataNode_01;  typedef	struct DecisionTreeNode{ 	int  keynum;	     char SelectedAttributeName[Max_Attribute_Name_Length];  	char AttributeValue[Max_Attribute_Name_Length];  	int  Record_Marker[Max_Record_Number]; 	int  Attribute_Marker[Max_Attribute_Number]; 	struct DecisionTreeNode  *ptr[Max_Discrete_Value_Number]; }DecisionTreeNode, *DecisionTree;  typedef	struct TreeNode{     char *AttributeName[Max_Attribute_Number];  	char *AttributeValue[Max_Attribute_Number];  	int Top; }TreeNode;  extern"C"_declspec(dllexport)void DataPreprocessing(DataNode *Train_Data,Attribute_Node  *Attribute_Information[],DataNode *PreprocessedTrain_Data,DecisionTree &Tree)//训练数据预处理 { 	char *AttributeValueName[Max_Record_Number]; 	for(int j=0;j<Train_Data->Attribute_Number;j++){ 		for(int i=0;i<Train_Data->Record_Number;i++){ 			PreprocessedTrain_Data->RecordData[i][j]=(char *)malloc(strlen(Train_Data->RecordData[i][j]) + 1); 			strcpy(PreprocessedTrain_Data->RecordData[i][j],Train_Data->RecordData[i][j]); 		} 	}//创建与处理后的训练数据 	PreprocessedTrain_Data->Attribute_Number=Train_Data->Attribute_Number; 	PreprocessedTrain_Data->Record_Number=Train_Data->Record_Number; 	StatisticAttribute_Value(PreprocessedTrain_Data,PreprocessedTrain_Data->Attribute_Number-1,Attribute_Information,Tree->Record_Marker);//统计第Num列各属性取值频率。 	CalculateRntropy(PreprocessedTrain_Data,PreprocessedTrain_Data->Attribute_Number-1,Attribute_Information,Tree->Record_Marker); 	for(int j=0;j<Train_Data->Attribute_Number;j++){ 		if(!strcmp(Attribute_Information[j]->kind,"连续")&&Tree->Attribute_Marker[j]){			 			char *TempChar; 			TempChar=(char *) malloc(sizeof(char)); 			StatisticAttribute_Value(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker);//统计第Num列各属性取值频率。 			for(int i=0;i<Attribute_Information[j]->Value_Number-1;i++){ 				for(int k=i+1;k<Attribute_Information[j]->Value_Number;k++){ 					if(atof(Attribute_Information[j]->Value_Name[i])>atof(Attribute_Information[j]->Value_Name[k])){ 						strcpy(TempChar,Attribute_Information[j]->Value_Name[i]); 						strcpy(Attribute_Information[j]->Value_Name[i],Attribute_Information[j]->Value_Name[k]); 						strcpy(Attribute_Information[j]->Value_Name[k],TempChar); 					} 				} 			} 			for(int i=0;i<Attribute_Information[j]->Value_Number;i++){ 				AttributeValueName[i]=(char *) malloc(sizeof(char)); 				strcpy(AttributeValueName[i],Attribute_Information[j]->Value_Name[i]); 			} 			int TempNumber=Attribute_Information[j]->Value_Number; 			double GainRatio;int Number; 			for(int  i=0;i<TempNumber-1;i++){				 				for(int k=0;k<Train_Data->Record_Number;k++){ 					if(Tree->Record_Marker[k]){ 						if(atof(Train_Data->RecordData[k][j])>atof(AttributeValueName[i])){ 							strcpy(TempChar,">"); 						} 						else{ 							strcpy(TempChar,"<="); 						} 						strcat(TempChar,Attribute_Information[j]->Value_Name[i]); 						strcpy(PreprocessedTrain_Data->RecordData[k][j],TempChar); 					} 				} 				StatisticAttribute_Value(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker);//统计第Num列各属性取值频率。 				CalculateRntropy(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker); 				CalculateGainRatio(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker); 				if(0==i){ 					Number=i; 					GainRatio=Attribute_Information[j]->GainRatio ; 				} 				else if(i>0&&GainRatio<Attribute_Information[j]->GainRatio){ 					Number=i; 					GainRatio=Attribute_Information[j]->GainRatio; 				} 			} 			for(int k=0;k<Train_Data->Record_Number;k++){ 				if(Tree->Record_Marker[k]){ 					if(atof(Train_Data->RecordData[k][j])>atof(AttributeValueName[Number])){ 						strcpy(TempChar,">"); 					} 					else{ 						strcpy(TempChar,"<="); 					} 					strcat(TempChar,AttributeValueName[Number]); 					strcpy(PreprocessedTrain_Data->RecordData[k][j],TempChar); 				} 			} 			StatisticAttribute_Value(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker);//统计第Num列各属性取值频率。 			CalculateRntropy(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker); 			CalculateGainRatio(PreprocessedTrain_Data,j,Attribute_Information,Tree->Record_Marker); 		} 	}//连续属性离散化 }    extern"C"_declspec(dllexport)void C4_5_main(char *A[][6],int s,int p,int *Y)  //DLL入口 { 	Attribute_Node  *Attribute_Information[Max_Attribute_Number]; 	DataNode  *Train_Data; 	Train_Data=(DataNode *)malloc(sizeof(DataNode));	 	FILE *stream1,*stream2;	 	stream1=fopen("C:\\Users\\Cwq\\Documents\\Visual Studio 2012\\Projects\\C4.5_DLL\\C4.5_DLL\\Atribution.txt", "r" ); 	Train_Data->Attribute_Number=0; 	while (!feof(stream1)){ 		Attribute_Information[Train_Data->Attribute_Number]=(Attribute_Node *)malloc(sizeof(Attribute_Node));		 		fscanf(stream1,"%s %s\n",Attribute_Information[Train_Data->Attribute_Number]->Name,Attribute_Information[Train_Data->Attribute_Number]->kind); 		Train_Data->Attribute_Number++; 	} 	fclose(stream1);	 	//Dispay_Attribute_Information(Train_Data,Attribute_Information);//输出属性信息 	stream2=fopen("C:\\Users\\Cwq\\Documents\\Visual Studio 2012\\Projects\\C4.5_DLL\\C4.5_DLL\\trainData01.txt", "r" ); 	Train_Data->Record_Number=0; 	while (!feof(stream2)){ 		for(int i=0;i<Train_Data->Attribute_Number;i++){ 			Train_Data->RecordData[Train_Data->Record_Number][i]=(char *)malloc(sizeof(char)); 			fscanf(stream2,"%s\n",Train_Data->RecordData[Train_Data->Record_Number][i]); 		} 		Train_Data->Record_Number++; 	} 	fclose(stream2);	 	/** 	获取训练数据 	**/ 	DataNode_01  *train_data_01; 	train_data_01=(DataNode_01 *)malloc(sizeof(DataNode_01));  	 for(int i=0;i<s;i++) 	 { 		 for(int j=0;j<p;j++) 		 { 			//PreprocessedTrain_Data->RecordData[i][j]=(char *)malloc(strlen(Train_Data->RecordData[i][j]) + 1); 			//strcpy(PreprocessedTrain_Data->RecordData[i][j],Train_Data->RecordData[i][j]); 			//train_data_01->RecordData_01[i][j]=(char *)malloc(sizeof(char)*10); 			train_data_01->RecordData_01[i][j]=(char *)malloc(strlen(A[i][j])); 		    train_data_01->RecordData_01[i][j]=A[i][j]; 		 } 	 } 	 train_data_01->Attribute_Number_01=p; 	 train_data_01->Record_Number_01=s; 	 //测试训练数据获取完毕  	DecisionTree Tree; 	Tree=(DecisionTree)malloc(sizeof(DecisionTreeNode)); 	for(int i=0;i<Train_Data->Attribute_Number;i++){ 		Tree->Attribute_Marker[i]=1; 	} 	for(int i=0;i<Train_Data->Record_Number;i++){ 		Tree->Record_Marker[i]=1; 	} 	//DispayTrain_Data(Train_Data,Attribute_Information,"输出训练数据",Tree);//输出训练数据 	DataNode  *PreprocessedTrain_Data; 	PreprocessedTrain_Data=(DataNode *)malloc(sizeof(DataNode));	 	DataPreprocessing(Train_Data,Attribute_Information,PreprocessedTrain_Data,Tree);/*预处理训练数据*/ 	//DispayTrain_Data(PreprocessedTrain_Data,Attribute_Information,"输出预处理后的训练数据",Tree);//输出预处理后的训练数据 	char *MaxClass; 	MaxClass=(char *)malloc(sizeof(char)); 	CreateDecisionTree(Tree,PreprocessedTrain_Data,Attribute_Information,MaxClass); 	//printf("决策树预测:\n"); 	StatisticAttribute_Value(Train_Data,Train_Data->Attribute_Number-1,Attribute_Information,Tree->Record_Marker);//统计第Num列各属性取值频率。 	for(int i=0;i<train_data_01->Record_Number_01;i++){ 		ClassSample(Tree,train_data_01,Attribute_Information,i,Y);	 	}  	for(int i=0;i<Train_Data->Attribute_Number;i++)     //释放空间 		free(Attribute_Information[i]);  	free(PreprocessedTrain_Data->RecordData); 	PreprocessedTrain_Data=NULL; 	free(Train_Data); 	Train_Data=NULL;      free(train_data_01->RecordData_01); 	//free(train_data_01); 	train_data_01=NULL;  	free(Tree); 	Tree=NULL; 	free(MaxClass); 	MaxClass=NULL; }

楼主能不能贴一个详细一点的，别人可以编译的例子啊


Question: 怎么样求出数组中元素出现最大次数最多的有多少个？

想着用链表试了一下，代码不完整， 后面释放内存没写 struct rec_data{     int num;     int occur;     rec_data *next; };  int add(rec_data *head,rec_data **tail,int n) {     rec_data *p =head->next;     for(;p;p=p->next) if(p->num==n) break;     if(!p) {         p =(rec_data *)malloc(sizeof(*p));         p->num  =n;         p->occur =0;         p->next =NULL;         (*tail)->next =p;         *tail =p;     }     return ++p->occur; }  int getcnt(int *ar,int len) {     rec_data *head = (rec_data *)malloc(sizeof(*head));     rec_data *tail =head;     head->next =NULL;     int mo=0;     for(int i=0;i<len;i++)     {         int o =add(head,&tail,ar[i]);         if(o>mo) mo=o;     }      rec_data *p =head->next;     int cnt=0;     for(;p;p=p->next)         if(p->occur==mo) ++cnt;     // release list     return cnt; }

如果数字是10以内的，那么用下面的方法还是比较好的，如果数字比较大，那么可以先排序，再计算，这个就得自己动手了……#include <stdio.h>  int countmax(int arry[], int num) { 	int arrycount[10] = {0}; 	 	int i = 0,  maxnum, result; 	for (; i < num; i++) 		arrycount[arry[i]]++;		  	maxnum = arrycount[0]; 	result = 1; 	 	for (i = 1; i < 10; i++) 	{ 		if (arrycount[i] > maxnum) 			maxnum = arrycount[i]; 		else if (arrycount[i] == maxnum && maxnum != 0) 			++result; 	} 	return result;			 }  int main(void) { 	int arry1[] ={1, 0, 1, 2, 1, 3}; 	int arry2[] = {7, 0, 2, 0, 4, 4}; 	int arry3[] ={1,2,3,4,5,6}; 	int result1, result2, result3; 	result1 = countmax(arry1, sizeof(arry1)/ sizeof(arry1[0])); 	result2 = countmax(arry2, sizeof(arry2)/ sizeof(arry2[0]));	 	result3 = countmax(arry3, sizeof(arry3) / sizeof(arry3[0])); 	printf("the arry1 maxnum: %d\nthe arry2 maxnum: %d\nthe arry2 maxnum: %d\n", result1, result2,result3);	 }

写的比较丑，但基本实现功能。  int findMaxOccur(int* array,int len) 	{ 		if(array==NULL||len<1) return -1; 		map<int,unsigned int> map_temp; //key is array[i],value is the times of array[i] appears 		for(int i=0;i<len;++i) 		{ 			if(map_temp.end()==map_temp.find(array[i])) //map内没有，插入 				map_temp.insert(pair<int,unsigned int>(array[i],1)); 			 				else //map内存在，则相应的value+1 					map_temp.at(array[i])++; 					 		} 		map<int,unsigned int>::iterator map_iter=map_temp.begin(); 		int temp_max = map_iter++->second; 		int result = 1; 		for(;map_iter!=map_temp.end();map_iter++) 		{ 			if(map_iter->second==temp_max) 				result++; 			else if(map_iter->second>temp_max) 			{ 				result = 1; 				temp_max = map_iter->second; 			} 		} 		return result; 	}

引用 5 楼 user-5 的回复:假如数组的6个元素各不相同，那么你要的结果就是6，对吧，因为出现最多的次数都是1，所以一共有6个（也就是说1次也是要考虑的）。那就再循环一次咯，在free之前加入 	int k = 0; 	for (int i = 0; i != nNum; ++i) 	{ 		if (nTmp == p[i]) 		{ 			k++; 		} 	} 注意最后返回这个 k    谢谢了，看起来符合了要求了。

遍历数组，用一个N行2列的数组保存 第一列，出现的数字 第二列，对应数字出现的次数

引用 2 楼 user-5 的回复:[quote=引用 1 楼 user-5 的回复:] 方法比较笨，仅供参考 unsigned int FindNum( int *n ,int nNum ) { 	unsigned int *p = (unsigned int *)malloc(sizeof(int)*nNum); 	memset(p ,0 ,sizeof(int)*nNum); 	for (int i = 0; i != nNum ;++i) 	{ 		p[i] = 1; 		for (int j = 0; j != i; ++j) 		{ 			if (n[i] == n[j]) 			{ 				p[j]++; 			} 		} 	} 	unsigned int nTmp = p[0]; 	for (int i = 0; i != nNum; ++i) 	{ 		if (p[i] > nTmp) 		{ 			nTmp = p[i]; 		} 	} 	free(p); 	return nTmp; }  int main() { 	int array1[]={1,0,1,2,5,3}; 	int n = FindIndex(array1,6); 	printf("最多出现了%d次\n" ,n); 	return 0; }31行调用名写错了，应该是FindNum[/quote]    我的题意不是找出一组数组中元素最大出现次数由多少。。。。而已找出最大出现次数的元素有多少个....不知道这样能表达清楚我的意思没= =

引用 楼主 qq_23017575 的回复:可能题目说的不是很明白。。。 比如说有数组array1[]={1,0,1,2,1,3}和数组array2[]={7,0,2,0,4,4}. 其中,数组一中数字1出现次数为3且次数最大，则该数组中只有一个次数最大的元素，即ans=1。 在数组二中，数字0和数字4都是出现次数为2，一样都是最大次数，那么该数组出现的最大次数元素有两个，即ans=2。 大概就是这个意思，求怎么去实现这个问题？   我的题意不是找出一组数组中元素最大出现次数由多少。。。。而已找出最大出现次数的元素有多少个....不知道这样能表达清楚我的意思没= =

引用 1 楼 user-5 的回复:方法比较笨，仅供参考 unsigned int FindNum( int *n ,int nNum ) { 	unsigned int *p = (unsigned int *)malloc(sizeof(int)*nNum); 	memset(p ,0 ,sizeof(int)*nNum); 	for (int i = 0; i != nNum ;++i) 	{ 		p[i] = 1; 		for (int j = 0; j != i; ++j) 		{ 			if (n[i] == n[j]) 			{ 				p[j]++; 			} 		} 	} 	unsigned int nTmp = p[0]; 	for (int i = 0; i != nNum; ++i) 	{ 		if (p[i] > nTmp) 		{ 			nTmp = p[i]; 		} 	} 	free(p); 	return nTmp; }  int main() { 	int array1[]={1,0,1,2,5,3}; 	int n = FindIndex(array1,6); 	printf("最多出现了%d次\n" ,n); 	return 0; }31行调用名写错了，应该是FindNum


Question: 请教大神，纯C语言能编写出DLL格式的COM组件吗？

引用 1 楼 turingo 的回复:参考 http://www.west263.com/info/html/chengxusheji/C-C--/20080403/51515.html 我今天忽然点了你这个连接，发现也是 C++ 的，不知道从哪采集来的。

能。com最麻烦的是注册表，其他倒没什么。

谢谢楼上几们，对我很有帮助，虽然看不懂，但是起马有了研究的对象


Question: 请指教，c语言如何打印这类三角形！能力有限，网上没找到这种案例啊！！！

#include "stdio.h" void main() { 	int a[20][20]; 	int i,j,n; 	printf("请输入n："); 	scanf("%d",&n); 	for(i=0;i<n;i++) 		a[i][i]=i+1; 	for(i=1;i<n;i++) 		for(j=1;i-j>=0;j++) 			a[i][i-j]=a[i][i-j+1]+n-j; 	for(i=0;i<n;i++) 		for(j=0;j<=i;j++) 		{ 			printf("%3d",a[i][j]); 			if(i==j)printf("\n"); 		} 	system("pause"); }

学过数组之后写的程序  #include <stdio.h>  main() {   int h,l,n,a[81][81],s=0;   puts("输入");    scanf("%d",&n);   for(l=n;l>=1;l--)     for(h=l;h>=1;h--)       a[h][l]=++s;   for(h=n;h>=1;h--)   {       printf("\n");       for(l=h;l<=n;l++)         printf("%d ",a[h][l]);   } }

#include<stdio.h>  int count(int i) { 	if (i ==1) 		return 1; 	else 		return i+count(i-1); }  void main() {	 	int n,i,j,num,*arr,nest_count=0;  	printf("please input a number:"); 	scanf("%d",&n); 	arr= malloc(sizeof(int)*count(n));   	for(i=1;i<=n;i++) 	{ 		int first = i; 		int nn = n;  		for(j=0;j<i;j++) 		{ 			arr[nest_count] = first; 			nest_count++; 			first = first + (nn--)-1;			 		} 	}  	num=count(n); 	j=1; 	while(j != n+1) 	{ 		num=count(j)-1; 		for(i=0;i<j;i++) 		{ 			printf("%d ",arr[num]); 			num--; 		} 		printf("\n"); 		j++; 	} 	printf("\n");   	free(arr); }

#include<stdio.h>  int h(int a[][6],int j,int i,int s); int l=0; int main() { 	int a[6][6],n,i,j;     scanf("%d",&n); 	j = n; 	a[0][0]=1; 	for(i=0;i<n;++i) 	{ 		if(i==0) h(a,j,i,0); 		else  		{ 			--j; 			h(a,j,i,l); 		} 	} 	for(i = 0;i<n;++i) 	{ 		for(j = 0;j<=i;++j) 		{ 			printf("%d",a[i][j]); 		} 		printf("\n"); 	} 	return 0; }  int h(int a[][6],int j,int i,int s) { 	int x,y; 	if(i==0) 	{ 		 		for(x=1,y=1;x<j;++x,++y) 		{ 			a[x][y]=a[x-1][y-1] + 1; 		} 		l=a[x-1][y-1]; 	} 	else  	{         for(y=0;y<j;++y,++i) 		{ 			if(y==0) a[i][y] = s+1; 			else 			{ 				a[i][y]=a[i-1][y-1] + 1; 			} 		} 		l = a[i-1][y-1];  	} 	return 0; }

看了一下数字，第二行第一个数是从1+行数得到，其它行刚好差1，行内数刚好从前一个数递减 void print_tri(int lev) {     for(auto line=0,st=1;line<lev;++line)     {         for(auto col=0,cur=st,hs=lev-line;col<=line;col++,++hs)         {             cout<<cur<<"\t";             cur -= hs;         }         cout<<endl;         st+=lev-line;     } }


Question: 求高手帮忙写个代码？ 谢谢

我要得分#include<stdio.h>  int main() { 		int state = 0; 		int i; 		char buffer[4]; 		int n; 		scanf("%d",&n); 		sprintf(buffer,"%d",n); 		for(i = 2;i >= 0; --i) 		{ 				if(buffer[i] != '0') 				{ 						state = 1; 				} 				if(state == 1) 						printf("%c",buffer[i]); 		} 		putchar('\n'); 		return 0; }

自己写的话应该不难吧！

引用 2 楼 starytx 的回复:仅供参考，也可以转化为字符串，然后逆序处理。 unsigned int reverseNum(unsigned int n) { 	unsigned int m = n; 	unsigned int k = 0; 	while (m > 0) 	{ 		k *= 10; 		k += m%10; 		m = m/10; 	} 	return k; }+1

貌似初中计算机竞赛题。有什么困难？


Question: 数组无法保存颜色值，里面的元素会自动清零

引用 4 楼 turingo 的回复: 使用数组里面的颜色时，我发现只有将数组定义前加上const才能显示出来，是怎么回事啊，求这位大哥教教

1、你所看到的是0x1f，其实它在内存中确实是0x001f 2、传的时候可以用memcpy  引用 楼主 liaocao2010 的回复:我定义了这样的数组   u16  color_temp[224] = {0}; u16 i = 0;  while(i<224) {    color_temp[i] = 0x001f;    i++; }   问题来了，我要数组每个元素保存的都是0x001f 但是结果它会自动去掉0，保存的都是0x1f，这就没法用了啊 我保存的颜色值要一次性传给显存，如果数组不行，那有其他办法也好。 求高人指点

再补充一个问题，外部调用数组显示颜色的时候，必须在数组前加const，这是为什么，有解决办法么  引用 1 楼 user-3 的回复:0x001f == 0x1f 这两个在u16的内存中是一样的但是我用的时候，必须要用到0x001f  引用 2 楼 zyaiwx 的回复:去掉0有问题吗？去掉0有很大的问题，颜色值是分高低位的，没有0就没有高低位了

去掉0有问题吗？

0x001f == 0x1f 这两个在u16的内存中是一样的


Question: 新人求教啊，字符串查找子字符串的问题

引用 3 楼 turingo 的回复:参考 http://blog.sina.com.cn/s/blog_5f67441501015pyz.html 谢谢帮助

引用 2 楼 zyaiwx 的回复:找两次。要是如果只出现两个，反向查找，一次找到 嘿嘿，显然我是需要找N次。网上查找了一个代码http://blog.csdn.net/arcsinsin/article/details/12162743很不错，期望后面的人看到这个有用。

引用 1 楼 user-3 的回复:先找到第一个，然后在此基础上后移一位再找 char * pFind = strstr(str ,substr); pFind = strstr(pFind+1 ,substr); 方法可行，谢谢

找两次。要是如果只出现两个，反向查找，一次找到


Question: 判定星期几并返回整形

如果你是在 Windows 平台，那么有个最简单的方法： FILETIME ft = { 0 }; // 这里举例为2014年12月1日20:00 // 主要是年月日以及小时最好大于0以确保结果准确 SYSTEMTIME st = { 2014, 12, 0, 1, 20, 0, 0, 0 }; SystemTimeToFileTime(&st, &ft); FileTimeToSystemTime(&ft, &st); // 经过这么一倒腾 st.wDayOfWeek 就包含了星期 // 0 为周日，1~6 为周一到周六

引用 4 楼 ccc212153 的回复:s=yr-1+(int)((yr-1)/4)-(int)((yr-1)/100)+(int)((yr-1)/400)+days;网上常见的一个公式而已，days是该天在这一年中的第几天。也可以用蔡勒公式来计算。关于公式可以搜一下，既然是公式就用就行了，人家推导出来的。 // 计算某年月日是星期几,0:周日，1：周一..... int getWeek(int yr ,int mn ,int day) { 	int M = mn; 	if (mn == 1 || mn == 2)		// 如果是1月或2月，要作为上年的13,14月来处理 	{ 		M += 12; 		yr--;		// 上一年 	} 	int nC = yr/100;	// 世纪数-1（年数前两位） 	int y = yr%100;		// 年数后两位 	int d = day;		// 天 	int W = nC/4 - 2*nC + y + y/4 + (13 * (M+1) / 5) + d - 1 ;	// 蔡勒公式,里边的除法都取整数部分 	return W%7; }

引用 1 楼 starytx 的回复:仅供参考，至于你说的是一周的第几天，自行设置，你可以认为一周从周日开始，也可以从周一开始，本例是从周日开始 int getWeek(int yr ,int mn ,int day) { 	int days = 0; 	int s = 0; 	int mont[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};  	if (yr%4==0||yr%100==0||yr%400==0)  		mont[2]=29; 	else mont[2]=28; 	for (int i=0;i<mn;i++) 		days+=mont[i];  	days+=day;  	s=yr-1+(int)((yr-1)/4)-(int)((yr-1)/100)+(int)((yr-1)/400)+days;  	return s%7; }  int main() { 	int day,mn,yr,days=0,k;  	int mont[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};  	char wek[][9] = { "星期日","星期一","星期二","星期三","星期四","星期五","星期六"}; 	printf("请输入日期 (年-月-日):"); 	scanf("%d-%d-%d",&yr,&mn,&day);  	k = getWeek(yr,mn,day); 	printf("%d-%d-%d 是 %s.",yr,mn,day,wek[k]);  	return 0; }   s=yr-1+(int)((yr-1)/4)-(int)((yr-1)/100)+(int)((yr-1)/400)+days;

s=yr-1+(int)((yr-1)/4)-(int)((yr-1)/100)+(int)((yr-1)/400)+days;  能解释下这句吗？谢谢

UINT DayOfWeek[] = {    LOCALE_SDAYNAME7,   // Sunday    LOCALE_SDAYNAME1,       LOCALE_SDAYNAME2,    LOCALE_SDAYNAME3,    LOCALE_SDAYNAME4,     LOCALE_SDAYNAME5,     LOCALE_SDAYNAME6   // Saturday };  TCHAR strWeekday[256]; CTime time(CTime::GetCurrentTime());   // Initialize CTime with current time ::GetLocaleInfo(LOCALE_USER_DEFAULT,   // Get string for day of the week from system    DayOfWeek[time.GetDayOfWeek()-1],   // Get day of week from CTime    strWeekday, sizeof(strWeekday));  TRACE("%s\n", strWeekday);               // Print out day of the week


Question: 新手提问getchar 函数

getchar 由宏实现：#define getchar() getc(stdin）。getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止（回车字符也放在缓冲区中）.当用户键入回车之后，getchar才开始从stdio流中每次读入一个字符.getchar函数的返回值是用户输入的字符的ASCII码，如出错返回-1，且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符，其他字符会保留在键盘缓存区中，等待后续getchar调用读取.也就是说，后续的getchar调用不会等待用户按键，而直接读取缓冲区中的字符，直到缓冲区中的字符读完为后，才等待用户按键.

getchar每次只从输入缓冲区读取一个字符而已。

getchar()只是读入一个字节

这样理解 你输入的一串数字会被放入一个缓冲区，第一个由于有while，getchar会一直读，直到取完为止，读一个，输出一个


Question: 二维数组，数组名？

数组的问题是最难的

引用 12 楼 Daffodiles 的回复:2.  for(int (*p)[3]=a; p<a+2; p++)   数组名：a，是个指针。 变量：(*p)[3]，也是个指针。  3.  for(int *q=*p; q<*p+3; q++)  变量：*p 取指针所指向对象的值。不过，它的值，还是个指针而已。引用 12 楼 Daffodiles 的回复:2.  for(int (*p)[3]=a; p<a+2; p++)   数组名：a，是个指针。 变量：(*p)[3]，也是个指针。  3.  for(int *q=*p; q<*p+3; q++)  变量：*p 取指针所指向对象的值。不过，它的值，还是个指针而已。错了  你对数组的了解太贫瘠 不懂数组也是一种数据类型  不懂数组和指针之间的类型转换

引用 16 楼 Daffodiles 的回复:知道我所说的东西对你来说太难了  毕竟你水平就这样 1年前在问一级数组一级指针  1年了 终于问二级数组了 难得难得  你是我见过学习C语言 速度最最慢的人 没有之一 而且也是 学得最差的了 白瞎了一把入门书  学得和谭C一样 你是不是看过谭C了?

*p是指针，p是二级指针

你说的都是对的 #include<stdio.h> #include<stdlib.h>  int main() { 		int a[2][3]= {{1,2,3}, 				    	{4,5,6}}; 		for(int (*p)[3] = a; p < a + 2; ++p) 				for(int *q=*p; q < *p + 3; ++q) 						printf("%d\t",*q);  		exit(0); }

程序是用指针遍历数组元素。

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

引用 10 楼 williamhong 的回复:[quote=引用 6 楼 lin5161678 的回复:] [quote=引用 5 楼 user-7 的回复:] 2.使用数组名时，实际上将其自动转换为指向该数组第一个元素的指针。 自动转换 只在特定情况下会发生 不是使用数组名就会发生转换 引用a的类型就是int (*)［3］ a的数据类型就是int[2][3] 而不是 int(*)[3][/quote]  例子中没有自动转换 a的数据类型虽然不是 int(*)[3]，但也不是int[2][3]，因为int[2][3]不是c语言的有效类型，明白意思，但好像写不出来这种类型（也许能写出来可能我不知道） [/quote] 刚才说错了，a的类型是int[2][3]，写法也是int[2][3]

引用 6 楼 lin5161678 的回复:[quote=引用 5 楼 user-7 的回复:] 2.使用数组名时，实际上将其自动转换为指向该数组第一个元素的指针。 自动转换 只在特定情况下会发生 不是使用数组名就会发生转换 引用a的类型就是int (*)［3］ a的数据类型就是int[2][3] 而不是 int(*)[3][/quote]  例子中没有自动转换 a的数据类型虽然不是 int(*)[3]，但也不是int[2][3]，因为int[2][3]不是c语言的有效类型，明白意思，但好像写不出来这种类型（也许能写出来可能我不知道）

谢楼上指点  #include <stdio.h>  int main(){   char * pc;    printf("sizeof pc :%d\n",sizeof(pc));   // 指针的大小 在我这里是 8     int a[2][3]={{1,2,3}, 	       {4,5,6}};         printf("sizeof a :%d   pointer a :%p   pointer of a+1 %p \n",sizeof(a),a,a+1);   printf("sizeof a[1] :%d\n",sizeof(a[1]));    int aa[3][2]={{1,2}, 		{3,4}, 		{5,6}};      printf("sizeof aa :%d   pointer aa :%p   pointer of aa+1 %p \n",sizeof(aa),aa,aa+1);   printf("sizeof aa[1] :%d\n",sizeof(aa[1]));    int ** ppa = a ;      printf("sizeof ppa :%d   pointer ppa :%p   pointer of ppa+1 %p \n",sizeof(ppa),ppa,ppa+1);   printf("sizeof ppa[1] :%d\n",sizeof(ppa[1]));   printf("sizeof **ppa :%d\n",sizeof(**ppa));     char c[] = "ABCD";   char ** ppc = &c ;      printf("sizeof ppc :%d   pointer ppc :%p   pointer of ppc + 1 %p \n",sizeof(ppc),ppc,ppc+1);   printf("sizeof ppc[1] :%d\n",sizeof(ppc[1]));   printf("sizeof **ppc :%d\n",sizeof(**ppc));         for(int (*p)[3]=a; p<a+2; p++){      printf("sizeof p :%d\n",sizeof(p));        printf("sizeof *p :%d\n",sizeof(*p));        for(int *q=*p; q<*p+3; q++){       printf("%d ",*q);     }   } }

仅供参考//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]

这个可以用几行代码测试的吧  还是让代码自己说吧！  只需要几个 sizeof  ++  printf 就足够了  晚上有时间测一下

引用 5 楼 user-7 的回复:2.使用数组名时，实际上将其自动转换为指向该数组第一个元素的指针。 自动转换 只在特定情况下会发生 不是使用数组名就会发生转换 引用a的类型就是int (*)［3］ a的数据类型就是int[2][3] 而不是 int(*)[3]

对于数组，有两个基本概念要清楚： 1.严格地说，C/C++里并没有多维数组，通常所指的多维数组其实就是数组的数组。 2.使用数组名时，实际上将其自动转换为指向该数组第一个元素的指针。  所以，a是一个有两个元素的数组，每个元素又是一个有三个元素的数组。根据上面可知，a也是一个指向有三个整型元素的数组的指针，那么，a的类型就是int (*)［3］，因为［］的优先级比*高，所以声明p的时候要用括号，否则p就变成数组了。  既然p是一个指向int ［3］数组的指针，那么对指针p解引用的*p当然是一个int ［3］的数组。 既然*p是一个数组，那么它同样也是一个指向数组首元素的指针，也就是一个int *。

问题： 1.这个程序，对么？ 单纯讨论语法的话 程序是对的   2.数组名：a，是指针的指针么？ a是数组不是指针 更不是指针的指针   (*p)[3]：也是指针的指针么？ 这个是数组的指针 不是指针的指针  3. C/C++ code  ? 1 for(int *q=*p; q<*p+3; q++)  变量：*p 是个指针，而非指针的指针。对么？ 对


Question: 新手求助

首先说一下别忘了给我分 很简单，k=(++i)+(++i)+(++i);我给你分析一下。 首先：我们知道++n是自加运算，不同于n++，++n直接自身加1不需要临时变量。 其次：k=(++i)+(++i)+(++i);运算的时候从左到右为：           第一步执行第一个++i, 此时所有的i变为4，           第二步 执行第二个++i，此时所有i变为5，           第三步： 执行前两个++i相加！，这两个++i的结果相加之后赋给一个内存中临时变量，此时为10           第四步执行最后一个++i，值为6，第五步：执行上一个内存中临时变量的值与这个6相加。10+6 = 16.

i=6是确定的，k的答案不一定，看编译器了 16就是先做了两个i++之后i=5相加得到10，再加上6, 如果++i 全完成后再加就得到18了 4+5+6也没错，有这种可能


Question: 请教一个PCLint的问题，谢谢！

其实是可以检查出来的，是我看错了错误的行了，这里不会报错误了

lint 还没聪明到能识别出大于等于10时，会return

PClint只是静态检查，在这个函数中i可能大于10，超过数组的界限了，Pclint判断有越界的可能性。可以for (.. i<10..)或者忽略掉此处的这个错误，让pclint忽略此处的这个检查

改为：  for(i = 0; i < 10; i++) {     a[i] = 1; }

void f() {     int a[10] = {0};     int i = 0;     for(i = 0; i < 20; i++)     {         if(i >= 10)         {             return;             break;  //这里加上跳出循环试试         }          a[i] = 1;  //为什么这里还会报661数组越界错误呢，要怎么修改呢？谢谢     } }

lint是静态检查. 话说既然已经知道问题所在,为啥不改改code.   for(i = 0; i < 10; i++) {     a[i] = 1; }


Question: 求助：c语言调用mysql存储过程的问题

这个问题如果去mysql论坛问，更靠谱，我觉得。（真相是我没实际弄过mysql）

函数是这么写的： bool sql_procedure() {        char szSql[64]="call _DBI_Factionlist_FacName('95954',@code)";       if((result!=NULL)        {                   mysql_free_result(result);                   result = NULL;         }        int ret = mysql_real_query(connection , szSql , strlen(szSql));       if(( ret)       {             printf("%s\n",mysql_error(connection));             return false;         }          ret = mysql_query( connection , " SELECT @Code" );          if(ret)          {                  printf("%s\n", mysql_error( connnection ));                   return false;            }             result = mysql_store_result(connnect);            row = mysql_fetch_row(result);           printf("%s\n", row[0]);            return true; }  麻烦你再帮我分析分析

有可能返回的结果集为空 有可能返回的结果集太大（行数太多） 有可能返回的结果集中当前记录的某个字段为NULL 有可能……


Question: 所有传递给函数的参数都是通过传值方式进行的？？

然也。看看产生的汇编就明白了

所有传递给函数的参数都是通过传值方式进行的  YES

是的 所谓传地址 其实也是传值而已

出了C++里的引用，所有参数传递都是这样的：复制一份实参的值，作为副本在函数中使用，所以不会影响实参的值，如果想通过形参改变实参的值，只能传这个值的地址（指针，如果实参是指针，要改变指向，就需要传入指针的地址，也就是指针的指针），因为通过地址（指针）可以改变地址里保存的内容。

c++里面的引用跟地址也比较类似

书里写得不错，但其实也是废话，计算机除了数值运算、传递，还能干什么捏？

是的，地址也是值。  引用 楼主 xialibaran 的回复:所有传递给函数的参数都是通过传值方式进行的？？这件话怎么理解？在《c和指针》这本书150页提到这句话。如图。  最好那句话说的怎么理解？？是不是说地址也终归是值？

在C里面是这样的，C++里还可以传引用。

变量                       变量值 指针变量              指针值

广义上讲都是传值~

地址也是值啊。比如地址：0X00AA  它不就是所谓的“值”么。 只不过这个值和一般的值对编译器来说不同而已。  总的来说，这种经典的书你需要多看几遍，就会有自己的理解，这里说了也不是你真正自己的理解。


Question: 100分求CCF计算机软件能力认证考试历届真题

这个我也找到了，不过只有第一次的。不过还是谢谢！

参考 http://wenku.baidu.com/link?url=KXAjAYDkUOD8IzIqVVK2zgT78F4bE7Env3bYG2Uobq19vVRA9p0_QjBXumgGiCw74dleh8iZ7oywX7JPhlvl76gtlQ_PiHXx3TY70yKzwmW


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

计算机组成原理→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、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

知识点： 运算符的优先级和结合行 布尔值与整型数直接的转换。

根据运算符的结合性，除了三个运算符是从右至左结合的（单目、三目、赋值），其他都是从左至右结合的，所以：if(1000<i<100)等于if(（1000<1)<100),1000<1返回0，if(0<100)为false，

真够闲的！！！

按照顺序执行。<操作符的返回值为bool类型的，为1或者0.所以你的程序肯定执行到if里面了。

按照规则来讲，是不可以这么写的 但是非要研究他，自己可以跟踪调试看看 不管这个条件是真是假，都会执行if下面的语句

何必浪费时间研究没有意义的语句？

if里边不能这么写——1000<i<100 正像二楼所说的 这个知识，谭浩强的书上也有说明的

闲着蛋疼

参见  运算符的结合行

研究如此高端的代码，大有可为啊

1     .file   "t.c"   2     .section    .rodata   3 .LC0:   4     .string "111111111111"   5     .text   6     .globl  main   7     .type   main, @function   8 main:   9     pushl   %ebp  10     movl    %esp, %ebp  11     andl    $-16, %esp  12     subl    $32, %esp  13     movb    $109, 31(%esp)               a=109  14     movl    $.LC0, (%esp)  15     call    puts                                      printf("111111111111\n");    16     movl    $0, %eax  17     leave  18     ret  19     .size   main, .-main  20     .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"  21     .section    .note.GNU-stack,"",@progbits   看看反汇编，根本没有if的相关代码，直接输出1111111。gcc认为1000<i<100是一个无意义的数学表达式，直接给忽略掉了

编译器虽然不会报错（也可能有些版本的编译器会给出warning），但是这段程序无法达到你编程的意义，而且你这个判断的表达式也略奇葩了，存在什么数大于1000然后还小于100的（写反了吧，少年？）。

如果非要看个究竟,看反汇编出来的汇编语言.

1000 < i 结果不是0就是1，总是比100小，最终总是为1（真）。  or  1000 < i && i < 100

想了想应该是这样的：按顺序逐次比较，中间过程中的比较结果只有两种：真1 假0，然后用1或0再次和下一个数进行比较，知道判断结束，根据最后一次的比较真1假0 ，得出最后的输出结果。


Question: UG二次开发，STL模型

我是想遍历所有点，找到脸部正前方方向上的坐标绝对值最大点。感觉也应该可以找到。但是看不到效果。不知道错在哪里了。您有相关代码可以共享吗？我不会写程序。

在足够远处构建平面，使用两实体间最短距离函数，感觉应该可以解决


Question: 音频解码问题

为什么我用官网的压缩工具压缩后出现了下面这个东西

引用 1 楼 zhao4zhong1 的回复:http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=VC%E6%BA%90%E4%BB%A3%E7%A0%81%20g.729&rsv_pq=b7d45aba00008bdb&rsv_t=8e4eLkllsz5RoYorHtsvXcs3FBkEoR71vGmSse74yCVAccmr9Q8Plp3I9VM&rsv_enter=0&rsv_sug3=12&rsv_sug4=205&rsv_sug1=7&inputT=10314  谢谢你，不过我在网上找的源码编译后，对pcm压缩后根本不是g729，也不能对g729解码，而且网上的程序都是一个，可能是我使用的方法不对所以我才来请教的


Question: C语言中字符串截取问题

1楼正解，没分配内存

引用 1 楼 user-2 的回复:strGetRealmBuf 没分配 ？  法克。还真是。我把这个buf换成数组接受就对了。。  							while(*strRealm != 0x22) 							{ 								strGetRealmBuf[count] = *strRealm; 								count++; 								strRealm++; 								//strGetRealmBuf++;

strGetRealmBuf 没分配 ？


Question: 关于函数调用的问题，求帮忙！

函数 数组的参数 会被编译成  指针的 数组的个数情报会丢失的。 即使 实参 传入不同个数的数组也能编译成功的。  比如 int sum(int a[5]) 会被编译成 int sum(int *a);  这种情况下，你即使传入a[3]  也可以的   二维数组也是同样的道理， 第一维的个数会丢失的。


Question: 函数的问题！

#include <stdio.h>  int main(){   unsigned char a = -1;   int b = 0 + a;   printf("%d \n",b);     // 他会输出 255    unsigned int aa = -1;   int bb = 0 + aa;   printf("%d \n",bb);   // 这里会是 －1    int bbb = 4294967295 ;   bbb = bbb * 2;    }  /*          subq	$32, %rsp 	leaq	L_.str(%rip), %rdi 	movb	$-1, -1(%rbp)         movzbl	-1(%rbp), %eax   // 关键的指令在这里 请看 http://www.niwozhi.net/demo_c233_i6798.html         addl	$0, %eax         // 对于unsigned做的扩展是 0扩展   如果是int，也就不需要扩展了         movl	%eax, -8(%rbp)    	movl	-8(%rbp), %esi 	movb	$0, %al 	callq	_printf 	 	leaq	L_.str(%rip), %rdi 	movl	$-1, -12(%rbp) 	movl	-12(%rbp), %esi 	addl	$0, %esi 	movl	%esi, -16(%rbp) 	movl	-16(%rbp), %esi 	movl	%eax, -20(%rbp)         ## 4-byte Spill 	movb	$0, %al 	callq	_printf    // 至于为什么编译器不报错 可能是因为 －1 并没有超出unsigned char的范围，他为什么要报错呢？要报什么样的错呢？    // 就连数组越界他都不报错 你还能指望他计算溢出报错吗？ 或许换成 X 语言的时候就报错了吧！ 再或许你能修改gcc的代码 让他报错！    */

感觉和编译器有关，编译器竟然不报错，也是醉了好值得思考的问题

引用 1 楼 user-10 的回复:-1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1 －1的二进制是FFFFFFFF?不才兄弟我表示不服。

甚至不加强转都可以的： int i1 = -1; unsigned int u1 = 4294967295; int i2 = 4294967295; unsigned int u2 = -1; printf("i1: %d, %u\n", i1, i1); printf("i2: %d, %u\n", i2, i2); printf("u1: %d, %u\n", u1, u1); printf("u2: %d, %u\n", u2, u2);输出结果：i1: -1, 4294967295 i2: -1, 4294967295 u1: -1, 4294967295 u2: -1, 4294967295

对这个函数而言返回值是 unsigned 还是 signed 都不重要，结果的二进制都是 0xFFFFFFFF。int i1 = -1; unsigned int u1 = 4294967295; int i2 = (int)u1; unsigned int u2 = (unsigned int)i1; printf("i1: %d, %u\n", i1, i1); printf("i2: %d, %u\n", i2, i2); printf("u1: %d, %u\n", u1, u1); printf("u2: %d, %u\n", u2, u2);充其量就是强转来强转去的。

引用 15 楼 sholber 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  计算机组成原理→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，有的是16位，有的是32位，如果我信16位的反汇编结果，那是否就是真理呢？该怎么相信呢？[/quote] 没有绝对的真理。只有存在于某个现实中的相对真理。 现实世界中从来就没有未来也不会发生哪怕一次1+1=2  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

引用 14 楼 zhao4zhong1 的回复:电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  计算机组成原理→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，有的是16位，有的是32位，如果我信16位的反汇编结果，那是否就是真理呢？该怎么相信呢？

引用 12 楼 sholber 的回复:[quote=引用 9 楼 nwcfafniw 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 nwcfafniw 的回复:] [quote=引用 5 楼 baidu_23901483 的回复:] [quote=引用 1 楼 user-10 的回复:] -1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.[/quote]  -1对应char依然还是-1，因此对应的16进制为0xffffffff，-1对应unsigned char是255，因此对应的16进制是0x000000ff。程序的输出在逻辑上是没有错的。 如果你想进一步了解编译器的行为，那么只能编译成汇编语言来看了。[/quote]  别的不说，-1对应unsigned char是255，这个可不一定。[/quote] 你的意思是，像-1这样的常量，最后在机器语言中的表现形式有可能不是“OxFFFFFFF”，而是“0XFFFFFFFE”？[/quote]  不，我的意思是，char类型的比特长度可能大于8（按规定是大于等于8）。等于8只是很多系统的典型默认值。  每个C的实现都有自己的定义。从<limits.h>中可以找到当前实现的定义长度：CHAR_BIT。[/quote] 行，多谢指教了。

引用 9 楼 nwcfafniw 的回复:[quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 nwcfafniw 的回复:] [quote=引用 5 楼 baidu_23901483 的回复:] [quote=引用 1 楼 user-10 的回复:] -1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.[/quote]  -1对应char依然还是-1，因此对应的16进制为0xffffffff，-1对应unsigned char是255，因此对应的16进制是0x000000ff。程序的输出在逻辑上是没有错的。 如果你想进一步了解编译器的行为，那么只能编译成汇编语言来看了。[/quote]  别的不说，-1对应unsigned char是255，这个可不一定。[/quote] 你的意思是，像-1这样的常量，最后在机器语言中的表现形式有可能不是“OxFFFFFFF”，而是“0XFFFFFFFE”？[/quote]  不，我的意思是，char类型的比特长度可能大于8（按规定是大于等于8）。等于8只是很多系统的典型默认值。  每个C的实现都有自己的定义。从<limits.h>中可以找到当前实现的定义长度：CHAR_BIT。

编译原理

我很好奇，编译器为什么不给警告呢

引用 8 楼 sholber 的回复:[quote=引用 6 楼 nwcfafniw 的回复:] [quote=引用 5 楼 baidu_23901483 的回复:] [quote=引用 1 楼 user-10 的回复:] -1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.[/quote]  -1对应char依然还是-1，因此对应的16进制为0xffffffff，-1对应unsigned char是255，因此对应的16进制是0x000000ff。程序的输出在逻辑上是没有错的。 如果你想进一步了解编译器的行为，那么只能编译成汇编语言来看了。[/quote]  别的不说，-1对应unsigned char是255，这个可不一定。[/quote] 你的意思是，像-1这样的常量，最后在机器语言中的表现形式有可能不是“OxFFFFFFF”，而是“0XFFFFFFFE”？

引用 6 楼 nwcfafniw 的回复:[quote=引用 5 楼 baidu_23901483 的回复:] [quote=引用 1 楼 user-10 的回复:] -1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.[/quote]  -1对应char依然还是-1，因此对应的16进制为0xffffffff，-1对应unsigned char是255，因此对应的16进制是0x000000ff。程序的输出在逻辑上是没有错的。 如果你想进一步了解编译器的行为，那么只能编译成汇编语言来看了。[/quote]  别的不说，-1对应unsigned char是255，这个可不一定。

引用 1 楼 user-10 的回复:-1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1  谁告诉你-1的二进制，是unsigned的FFFFFFFF？ 你听说过one's complement吗？ 还有，C没说一定要使用two's complement。

引用 1 楼 user-10 的回复:-1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.

楼上说的都对

printf("%u\n",  function()); printf("%d\n",  function()); 对比一下。

引用 5 楼 baidu_23901483 的回复:[quote=引用 1 楼 user-10 的回复:] -1 的二进制  就是  unsigned的 FFFFFFFF的 因为你printf的 带符号整数，所以打印的还是-1char f() { 		return -1; } int main() { 	printf("%x\n",f()); 	printf("%d\n", sizeof(f())); 	return 0; } 为什么输出是ffffffff 和1呢？ 如果返回值类型改成unsigned char 输出变成了 ff 和1.[/quote]  -1对应char依然还是-1，因此对应的16进制为0xffffffff，-1对应unsigned char是255，因此对应的16进制是0x000000ff。程序的输出在逻辑上是没有错的。 如果你想进一步了解编译器的行为，那么只能编译成汇编语言来看了。


Question: C中全局int变量和局部int变量在内存中占多少个字节？

你们老师自己不会教，他的本意是想让你们理解 “变量的存储” 全局变量在静态区，存储地址按照声明的顺序增加。 局部变量存储在栈区，存储地址按照声明的顺序递减。 你只要理解存储在哪里，会按什么样的顺序存储就行了。  你们老师纯属吃饱了撑的非得以为自己是编译器，按照自己想法教，但也不能说他错，算是着重点不分吧。

老师说错了  根本没有这种大小关系

研究这个地址有什么意义呢？真心不懂

x、y的地址相减是得到的结果是00000003的原因在于VS的编译器在DEBUG版的程序的栈的变量之间插入了校验数据，用于检测栈是否被破坏。  http://bbs.pediy.com/showthread.php?p=906375

楼主可知sizeof为何物？？？？？

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

都是sizeof int

替我吐你们老师一脸口水，误人子弟

引用 2 楼 zxh707wk 的回复:不要用变量的地址来算变量的大小 什么意思啊。。。

不要用变量的地址来算变量的大小

这个是编译器优化决定的，没有什么规律的。

尼玛，速度换了正经老师。 生命只有一次啊。

这种老师也是醉了…… 正经的C语言知识讲不清楚，这种无根无据的歪门邪道知识倒是滔滔不绝。

引用 5 楼 zhouchongzxc 的回复:看看所输出的汇编语言代码 应该能够找到答案。 菜鸟不懂汇编语言怎么办。。。

看看所输出的汇编语言代码 应该能够找到答案。

1L已经说的很清楚了，这个是编译器决定的。


Question: bin文件的字库怎么用

引用 3 楼 zhao4zhong1 的回复: 引用 4 楼 sholber 的回复: 引用 2 楼 turingo 的回复:  我周末问的问题，没人答，想不到一上班大家都活跃起来了，多谢各位指教，祝每个人生活都愉快^_^,赵老师和图灵解决了我的疑惑

所谓字库就是字符点阵的集合，你需要知道BIN的格式定义，然后自己查找字符画点即可。 参考我的博文http://blog.csdn.net/turingo/article/details/8191712加深概念。

你没觉出我是在假借喊冤，实际卖老吗？

引用 6 楼 zhao4zhong1 的回复:[quote=引用 4 楼 sholber 的回复:] 赵老师从网上搜完代码，也不看一看，心急火燎上网来贴了，都是抢分闹的。于是出现一个void main () 这个真是本ID在BC++3.1下于94-06-25 14:34:00写的。  ARJ 2.61 BETA SHAREWARE Copyright (c) 1990-98 ARJ Software, Inc. Aug 02 1998 *** This SHAREWARE program is NOT REGISTERED for use in a business, commercial, *** government, or institutional environment except for evaluation purposes.  Processing archive: C.ARJ Archive created: 1996-06-20 19:43:22, modified: 2002-04-12 17:35:02 Filename       Original Compressed Ratio DateTime modified CRC-32   AttrBTPMGVX ------------ ---------- ---------- ----- ----------------- -------- ----------- 16X16.C            2023        817 0.404 94-06-25 14:34:00 99E3D64F A--W B 1G ------------ ---------- ---------- -----     1 files        2023        817 0.404[/quote]  赵老湿也是醉了……不过是开个玩笑，居然也当真了。大家上网来，放轻松嘛。

引用 4 楼 sholber 的回复:赵老师从网上搜完代码，也不看一看，心急火燎上网来贴了，都是抢分闹的。于是出现一个void main () 这个真是本ID在BC++3.1下于94-06-25 14:34:00写的。  ARJ 2.61 BETA SHAREWARE Copyright (c) 1990-98 ARJ Software, Inc. Aug 02 1998 *** This SHAREWARE program is NOT REGISTERED for use in a business, commercial, *** government, or institutional environment except for evaluation purposes.  Processing archive: C.ARJ Archive created: 1996-06-20 19:43:22, modified: 2002-04-12 17:35:02 Filename       Original Compressed Ratio DateTime modified CRC-32   AttrBTPMGVX ------------ ---------- ---------- ----- ----------------- -------- ----------- 16X16.C            2023        817 0.404 94-06-25 14:34:00 99E3D64F A--W B 1G ------------ ---------- ---------- -----     1 files        2023        817 0.404

赵老湿长年活跃在CSDN，实在是不容易。

仅供参考：使用UCDOS的点阵字库HZK16和ASC16 #include <mem.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <graphics.h> const unsigned char bit[8]={128,64,32,16,8,4,2,1}; //-------------------------------------------------------- void dis(xoff,code)     unsigned int xoff,code; {     unsigned char *buffer;     FILE *hzk;     unsigned long offset;     unsigned int q,w;     int x,y,width;      buffer=calloc(32,1);     if ((code&0xFF00)!=0) {         w=(code&0x00FF)-0xA1;         q=((code>>8)&0x00FF)-0xA1;         offset=q*0x5E+w;         offset*=32;         if ((hzk=fopen("HZK16","rb"))==NULL) {             closegraph();             printf("Can not open HZK16\r\n");             exit(1);         }         fseek(hzk,offset,SEEK_SET);         fread(buffer,1,32,hzk);         fclose(hzk);         width=2;     }     else {         if ((hzk=fopen("ASC16","rb"))==NULL) {             closegraph();             printf("Can not open ASC16\r\n");             exit(1);         }         offset=code*16;         fseek(hzk,offset,SEEK_SET);         fread(buffer,1,16,hzk);         fclose(hzk);         width=1;     }     for (y=0;y<16;y++) for (x=0;x<8*width;x++) {         if (buffer[y*width+x/8]&bit[x%8]) putpixel(xoff+x,y,15);     }     free(buffer); } //-------------------------------------------------------- void display(p)     unsigned char *p; {    int i;   unsigned int qw;    i=0;   while (1) {     if (p[i]==0x0D||p[i]==0x1A) break; 	if (p[i]>0xA0) { 		qw=((unsigned int)p[i]<<8)|((unsigned int)p[i+1]&0x00FF); 		dis(8*i,qw); 		i+=2; 	} 	else { 		qw=(unsigned int)p[i]&0x00FF; 		dis(8*i,qw); 		i++; 	}   }  } //-------------------------------------------------------- void main() { 	int gdriver = DETECT, gmode, errorcode; 	long fl; 	FILE *hz; 	unsigned char *p;  	initgraph(&gdriver, &gmode, "c:\\borlandc\\bgi"); 	errorcode = graphresult(); 	if (errorcode != grOk) { 	   printf("Graphics error: %s\n", grapherrormsg(errorcode)); 	   exit(1); 	} 	hz=fopen("hz","rb"); 	fseek(hz,0,SEEK_END); 	fl=ftell(hz); 	p=calloc((int)fl,sizeof(unsigned char)); 	rewind(hz); 	fread(p,1,(int)fl,hz); 	fclose(hz); 	display(p); 	free(p); 	getch(); 	closegraph(); }

哥整过这个，先将汉字转换为对应的GB2312或者Unicode，建立跟BIN文件的对应关系，就可以在LCD显示了


Question: 问两个C语言的题目

看来分数让大家头脑发热啊，别只顾着分数害了别人。

我修改一下find函数的代码。那个函数其实还可以再精练一点，可以只用一个cnt，而不用flag标志： int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0;     while (n --)         if (a [n] == x)             *(cnt ++ ? p : q) = n;     return cnt; }

引用 10 楼 sholber 的回复:如果是别人我就不说啥了……你是版主啊。C语言的美不是完成功能就OK了的。这位高人，首先声明，哥不是此版版主，请看清楚了。再一个，回复是自愿行为，我也没发啥非法内容，求勿喷，再一个，lz的情形很明显就是找作业答案来了，好了，说多了

引用 9 楼 starytx 的回复:仅供参考： int find(int a[] ,int n, int x , int *p ,int *q) { 	int nFlag = -1; 	int nCount = 0; 	for (int i = 0; i != n; ++i) 	{ 		if (a[i] == x) 		{ 			if (nFlag == -1) 			{ 				*p = i; 			} 			nFlag = i; 			nCount++; 		} 	} 	*q = nFlag;  	return nCount; }  int main() { 	int x, c , first , last ; 	int a[10] = {12,34,5,6,87,3,4,23,5,22}; 	printf("请输入要查找的整数值:\n"); 	scanf("%d" ,&x); 	c = find(a ,10 ,x ,&first ,&last); 	printf("要查找的整数值%d出现的次数是%d,首次出现的下标是%d,最后出现的下标是%d:\n" ,x,c ,first ,last); 	return 0; }  如果是别人我就不说啥了……你是版主啊。C语言的美不是完成功能就OK了的。

大牛出没，即刻秒杀，my god

真心谢谢各位的回答了，我是论坛新人，前天和昨天发了两个帖子问了点题目，得到大家这么多回答，对我真的很有帮助，分数不多，能给的我都给大家了，谢谢大家

引用 2 楼 ZHANGJIXIN 的回复:第一题: int find(int a[] ,int n, int x , int *p, int *q) { 	int count = 0; 	bool firstFind = true;  	for(int i=0; i<n; ++i) 	{ 		if(a[i] == x) 		{ 			if(firstFind) 			{ 				*p = i; 				*q = i; 				firstFind = i;  //改成firstFind=false; 				++count; 			} 			else 			{ 				*q = i; 				++count; 			} 		} 	} 	return count; } firstFind = i;  //改成firstFind=false;

满分是朕的，不要抢： #include <stdio.h> #include <stdlib.h>  int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0, flag = 0;     while (n --)         if (a [n] == x)             *(flag ++ ? p : q) = n, cnt ++;     return cnt; }  int main (void) {     int a [] = {1, 2,35, 2, 2, 2, 6, 34, 4, 2, 3, 6};     int p, q;     int c = find(a, sizeof a, 2, &p, &q);     printf("%d, %d, %d", c, p, q); }

满分应该是我的： int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0, flag = 0;     while (n --)         if (a [n] == x)             *(flag ++ ? p : q) = n, cnt ++;     return cnt; }

引用 21 楼 u012436960 的回复:[quote=引用 13 楼 sholber 的回复:] int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0;     while (n --)         if (a [n] == x)             *(cnt ++ ? p : q) = n;     if (cnt == 1) * p = * q;     return cnt; } 你不觉得p q好像反了吗？[/quote]  引用 21 楼 u012436960 的回复:[quote=引用 13 楼 sholber 的回复:] int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0;     while (n --)         if (a [n] == x)             *(cnt ++ ? p : q) = n;     if (cnt == 1) * p = * q;     return cnt; } 你不觉得p q好像反了吗？[/quote] 哦，是我想错了

引用 13 楼 sholber 的回复:int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0;     while (n --)         if (a [n] == x)             *(cnt ++ ? p : q) = n;     if (cnt == 1) * p = * q;     return cnt; } 你不觉得p q好像反了吗？

引用 17 楼 zhao4zhong1 的回复:…… 小心边界条件！ 小心边界条件！  小心边界条件！ 小心边界条件！ ……

引用 13 楼 sholber 的回复:int find (int a [] ,int n, int x , int * p, int * q) {     int cnt = 0;     while (n --)         if (a [n] == x)             *(cnt ++ ? p : q) = n;     if (cnt == 1) * p = * q;     return cnt; }  很简练，厉害~

赵老师出现了，你们还抢什么

…… 小心边界条件！ 小心边界条件！  小心边界条件！ 小心边界条件！ ……

引用 15 楼 robert_chen1988 的回复:你们没发现下标忘记+1了吗？ #include <iostream> using namespace std;  int find(int a[] ,int n, int x , int *p ,int *q);  int main(){  	int a[] = {1,2,3,4,5,6,1,34,1,13}; 	int x, c, first, last; 	cout<<"请输入一个整数值:"; 	cin>>x; 	 	c = find(a, 10, x, &first,&last); 	cout<<c<<"  "<<first<<"  "<<last<<endl;   system("pause"); return 0; }  int find(int a[] ,int n, int x , int *p, int *q) { 	int count = 0; 	bool firstFind = true;  	for(int i=0; i<n; ++i) 	{ 		if(a[i] == x) 		{ 			if(firstFind) 			{ 				*p = i+1; 				*q = i+1; 				firstFind = 0; 				++count; 			} 			else 			{ 				*q = i+1; 				++count; 			} 		} 	} 	return count; } 一个简单的函数find被写得这样复杂，加不加1已经不重要了。这100分俺一定要争。楼主你要是不给非揍你PP

谁和我抢分打断他腿 #include<stdio.h> #include<stdlib.h>  //第一个问题 int find(int a[], int n, int x, int *p,int *q) { 		int num = 0; 		int state = 0; 		for(n = n -1; n>0;--n) 		{ 				if(a[n] == x) 				{ 						num++; 						*p = n; 						if(state == 0) 						{ 								state = 1; 								*q= n; 						} 				} 		} 		return num; }  //第二个问题 int main() { 		int a[10] = {1,2,3,5,6,5,4,8,5,5}; 		int x,c,first,last; 		scanf("%d",&x); 		c= find(a,10,x,&first,&last); 		printf("次数：%d\n",c); 		if(c > 0) 				printf("fisrt:%d\n last:%d\n",first,last); 		exit(0); }


Question: 这段代码为什么是这个结果？

scanf_s 最后一个参数没有提供

引用 1 楼 liaocao2010 的回复:vc++2005/2008中提供了scanf_s(),在最新的VS2013中也提供了scanf_s()。在调用时，必须提供一个数字以表明最多读取多少位字符。 例如 scanf_s("%s",buf,5),表示最多读取4个字符，因为buf[4]要放'\0' scanf_s最后一个参数是缓冲区的大小，表示最多读取n-1个字符.  百度里摘录+1,lz没看函数说明吗

引用 2 楼 zxh707wk 的回复:[quote=引用 1 楼 liaocao2010 的回复:]  vc++2005/2008中提供了scanf_s(),在最新的VS2013中也提供了scanf_s()。在调用时，必须提供一个数字以表明最多读取多少位字符。 例如 scanf_s("%s",buf,5),表示最多读取4个字符，因为buf[4]要放'\0' scanf_s最后一个参数是缓冲区的大小，表示最多读取n-1个字符.  百度里摘录+1,lz没看函数说明吗[/quote]我是沙发，不是楼主


Question: 关于const指针和位操作运算符的问题.

const int a = 10;  int *pa = (int *)&a;  N1570：6.5.4里明确指出，在一个表达式的前面放一个括住的类型名，表达式的值就被转换为那种类型。a的类型是const int；&a的类型是const int *；(int *) & a的类型是int *。 顺便说一下，通过指针修改一个const int是未定义的行为。

楼主，我搜到了你的第一个问题的答案 http://bbs.csdn.net/topics/90085527 对于(int*)强制类型转换，编译器产生一个副本，把a值保存在 副本里。*pa = 10改动的只是内存副本中的内容，a的实际取值还是从常量表里读取

用clang编译 得到的结果也是 9 10  他应该可以解释为  ：  const int a ＝ 10 ；／／ 其实就是 ＃define a 10     所以你用a的时候其实都是10   其实并不是这样，至少clang不是这样。

因为你用的是VC，我用的是gcc，所以以下内容仅供参考  第一个问题： 首先要明确的是，声明为const的局部变量只对编译器有意义，也就是说这里的const仅用于编译时的类型检查，而如果你的程序通过一些取巧的方式来修改这个cosnt的局部变量，程序运行时是不会有任何感知的。接下来回答你的两个小问题 1、因为a是const的，所以 &a 返回的类型是 const int * ，被你强制转换成 int * 后，就能赋给pa了。这种类型不兼容的情况gcc默认只会抛出一个警告。 2、在gcc下，输出的结果是“9 9“。  第二个问题： 有点晕，但你的temp应该初始化为0，而且在while循环内应该是 temp|=(y&1);