Question: 把这个C++代码改成C语言的。

我用vs2005 加上#include "stdlib.h" 就可以运行

编译出来没问题啊 //#include"iostream" #include"stdio.h" #include"time.h" #include"malloc.h" #define M 20 #define N 20 //堆栈结构 typedef struct node  {     int row ;     //行     int col ;     //列     struct node*next ; } Mlink ; Mlink*stack ; //定义一个栈 int backup[M+2][N+2]; //备份数组  /*********************************建立迷宫矩阵**************************/   //建立迷宫 void create(int maze[][N+2]) {     int i,j,flag ;     srand((unsigned)time(NULL));     //以时间产生随机种子     for(i=0;i<=M+1;i++)     for(j=0;j<=N+1;j++)     maze[i][j]=1 ;     //将四周置为1     for(i=1;i<=M;i++)     for(j=1;j<=N;j++)     {         maze[i][j]=0 ;         //初始化矩阵         backup[i][j]=0 ;         //初始化备份矩阵     }     printf("建立迷宫矩阵(选择1或者2)：\n1,手动建立\n2,自动建立\n请输入您的选择：\n");     scanf("%d",&flag);     //手动建立迷宫     if(flag==1)     {         printf("手动建立迷宫矩阵(0表示可通1表示障碍):\n");         for(i=1;i<=M;i++)         for(j=1;j<=N;j++)         scanf("%d",&maze[i][j]);     }               if(flag==2)     {         //自动建立迷宫         int c,i1,j1 ;         for(c=1;c<=M*N;c++)         {             //矩阵初始为“0”，随机选择位置赋予一个随机的0或1，             i1=(int)(rand()%M)+1 ;             j1=(int)(rand()%N)+1 ;             maze[i1][j1]=(int)(rand()%2);             //随机矩阵 按照王教授的要求这样可以产生更多的“0”即通路         }         printf("自动生成中……\n");         system("pause");     }     for(i=1;i<=M;i++)     for(j=1;j<=N;j++)     backup[i][j]=maze[i][j];     //备份数组矩阵 } /***************************华丽的分割线*******************************/   /********************************打印迷宫矩阵*****************/ void prin(int maze[][N+2]) {     int i,j ;     printf("迷宫矩阵如下(0可通)：\n  ");     int z ;     //在矩阵上方标明列号     for(z=1;z<=N;z++)     {         if(z<10)         printf("%d ",z);         else          printf("%d",z);     }     for(i=1;i<=M;i++)     {         printf("\n");         if(i<10)printf("%d ",i);         //矩阵左方标明行号         else printf("%d",i);         for(j=1;j<=N;j++)         printf("%d ",maze[i][j]);     }     printf("\n迷宫图形如下(白色可通)：\n");     printf("  ");     //在图形上方标明列号     for(z=1;z<=N;z++)     {         if(z<10)         printf("%d ",z);         else          printf("%d",z);     }     for(i=1;i<=M;i++)     {         printf("\n");         if(i<10)printf("%d ",i);         //矩阵左方标明行号         else printf("%d",i);         for(j=1;j<=N;j++)         {             if(maze[i][j]==0)printf("*");             if(maze[i][j]==1)printf("#");         }     }      } /*******************************分割线***************************/    int Mazepath(int maze[][N+2],int x1,int x2,int y1,int y2) {     Mlink*p ;     if(maze[x1][y1]==0)     {         p=(Mlink*)malloc(sizeof(Mlink));         p->row=x1 ;         p->col=y1 ;         p->next=NULL ;         stack=p ;         //将入口放入堆栈         maze[stack->row][stack->col]=1 ;         //标志入口已访问         //未找到出口并且堆栈不空         while((!(stack->row==NULL&&stack->col==NULL))&&(!(stack->row==x2&&stack->col==y2)))         {             //下面位置可通             if(maze[stack->row][stack->col+1]==0)             {                 p=(Mlink*)malloc(sizeof(Mlink));                 p->row=stack->row ;                 p->col=stack->col+1 ;                 p->next=stack ;                 //入栈                 stack=p ;                 maze[stack->row][stack->col]=1 ;                 //标记已访问             }             //上面可通             else if(maze[stack->row][stack->col-1]==0)             {                 p=(Mlink*)malloc(sizeof(Mlink));                 p->row=stack->row ;                 p->col=stack->col-1 ;                 p->next=stack ;                 //入栈                 stack=p ;                 maze[stack->row][stack->col]=1 ;                 //标记已访问                              }             //右面可通             else if(maze[stack->row+1][stack->col]==0)             {                 p=(Mlink*)malloc(sizeof(Mlink));                 p->row=stack->row+1 ;                 p->col=stack->col ;                 p->next=stack ;                 //入栈                 stack=p ;                 maze[stack->row][stack->col]=1 ;                 //标记已访问             }             //左面可通             else if(maze[stack->row-1][stack->col]==0)             {                 p=(Mlink*)malloc(sizeof(Mlink));                 p->row=stack->row-1 ;                 p->col=stack->col ;                 p->next=stack ;                 //入栈                 stack=p ;                 maze[stack->row][stack->col]=1 ;                 //标记已访问             }             //不可通 返回上一点             else              {                 if(stack->next!=NULL)                 {                     //堆栈里布置一个顶点则出栈并返回循环                     p=stack ;                     stack=stack->next ;                     //出栈                     free(p);                     //释放空间                 }                 //堆栈里只有一个顶点即入口，此时若释放空间出栈会使循环                 else                  {                     //控制语句无法比较（因为stack->col,stack->row都已不存在，)                     stack->row=NULL ;                     stack->col=NULL ;                     stack->next=NULL ;                 }             }                      }         if(stack->row==x2&&stack->col==y2)return(1);         else return(0);              }     else return(0); }  /****************************输出坐标通路*******************/ void printonglu1() {     Mlink*q ;     printf("其中的一条通道为：\n");     q=stack ;     printf("出口<--");     while(q!=NULL)     {         printf("(%d%3d)<--",q->row,q->col);         q=q->next ;     }     printf("入口\n"); } /*******************************分割线**********************/   /**********************输出图形通路**************************/  //2时输出↑，3时输出←，4时输出→，5时输出↓  void printonglu2() {     printf("图形通路如下：\n");     int z ;     printf("  ");     //图形上方标明列号     for(z=1;z<=N;z++)     {         if(z<10)         printf("%d ",z);         else          printf("%d",z);     }     int i,j ;     Mlink*p ;     p=stack ;     backup[p->row][p->col]=6 ;     while(p->next!=NULL)     {         if(p->next->col!=NULL)         {             if(p->row>p->next->row)backup[p->next->row][p->next->col]=5 ;             //下一节点在下             else if(p->row<p->next->row)backup[p->next->row][p->next->col]=2 ;             //下一节点在上             else if(p->col>p->next->col)backup[p->next->row][p->next->col]=4 ;             //下一节点在右             else backup[p->next->row][p->next->col]=3 ;             //下一节点在左         }         else ;         p=p->next ;     }     for(i=1;i<=M;i++)     {         printf("\n");         if(i<10)printf("%d ",i);         //图形左方标明行号         else printf("%d",i);         for(j=1;j<=N;j++)         {             if(backup[i][j]==0)printf("*");             if(backup[i][j]==1)printf("#");             if(backup[i][j]==2)printf("↑");             if(backup[i][j]==3)printf("←");             if(backup[i][j]==4)printf("→");             if(backup[i][j]==5)printf("↓");             if(backup[i][j]==6)printf("=");         }     } } int main() {     system("color f0");     //背景该为白色     int k=1 ;     int maze[M+2][N+2];     //迷宫矩阵     create(maze);     //建立迷宫          int abc[M+2][N+2],p,q ;     //备份数组以重复使用迷宫     for(p=0;p<=M+2;p++)     for(q=0;q<=N+2;q++)     abc[p][q]=maze[p][q];     while(k!=0)     {         int x,x1,x2,y1,y2 ;         prin(maze);         //打印迷宫矩阵         printf("\n输入迷宫入口：\n");         scanf("%d%d",&x1,&y1);         printf("输入迷宫出口：\n");         scanf("%d%d",&x2,&y2);         x=Mazepath(maze,x1,x2,y1,y2);         //迷宫可通         if(x==1)         {             printonglu1();             //打印坐标通路             printonglu2();             //打印图形通路             printf("\n");         }         else printf("无通路！\n");         //不可通         for(p=0;p<=M+2;p++)         for(q=0;q<=N+2;q++)         {             backup[p][q]=abc[p][q];             maze[p][q]=abc[p][q];         }         printf("输入0结束:\n");         scanf("%d",&k);     } }  就是有5个警告

我刚试了试，VC6和VS005都不行，我的上个图片用的是C-Free5.0，我这儿VC6加上#include<stdlib.h>也不行，VC6现在已经落后了啊 楼主可以试试在你那儿，加上#include<stdlib.h>这个头文件试试

引用 6 楼 u012421456 的回复: 我这里能运行，不知道楼主什么编译器  VC6

而且是后缀为.c的C程序

我这里能运行，不知道楼主什么编译器

把  引用 4 楼 u012421456 的回复:[quote=引用 3 楼 u012421456 的回复:] 是同一楼， 接着运行程序看看吧！本来就是个C程序[/quote]  这个程序只能用 .CPP 才能运行。但需要.c 运行。按照你说的改了 没有用。 没有学过C语言。希望哪位大神帮忙改一下。真的可以再发出来吧。是来送分的，因为很急。拜托了 (┬＿┬)

引用 3 楼 u012421456 的回复: 是同一楼， 接着运行程序看看吧！本来就是个C程序

同楼上， 楼主到底看程序了没有啊，不是只看了第一行代码吧？ 把第一行注释掉，然后把第48行的int去掉

来送分的

目测这本来就是C


Question: 动态数组堆栈问题

assert的意思就是"断言" 即程序执行到这里我断定它是这个条件,或者必需要满足这个条件.  所以assert(stack_size > 0);  的意思就是:   程序执行到这里,stack_size必需大于0, 否则就报错.

为什么不直接使用_alloca呢？ _alloca Allocates memory on the stack.  void *_alloca( size_t size );  Routine Required Header Compatibility  _alloca <malloc.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  The _alloca routine returns a void pointer to the allocated space, which is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than char, use a type cast on the return value. A stack overflow exception is generated if the space cannot be allocated.  Parameter  size  Bytes to be allocated from stack  Remarks  _alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function exits. Therefore, do not pass the pointer value returned by _alloca as an argument to free.  There are restrictions to explicitly calling _alloca in an exception handler (EH). EH routines that run on x86-class processors operate in their own memory “frame”: They perform their tasks in memory space that is not based on the current location of the stack pointer of the enclosing function. The most common implementations include Windows NT structured exception handling (SEH) and C++ catch clause expressions. Therefore, explicitly calling _alloca in any of the following scenarios results in program failure during the return to the calling EH routine:   Windows NT SEH exception filter expression:  __except ( alloca() )   Windows NT SEH final exception handler:  __finally { alloca() }   C++ EH catch clause expression  However, _alloca can be called directly from within an EH routine or from an application-supplied callback that gets invoked by one of the EH scenarios listed above.   Memory Allocation Routines  See Also   calloc, malloc, realloc

断言assert里边的表达式是你希望或者断定他为真，如果为假说明验证失败。所以很正常

引用 3 楼 qjedward 的回复:[quote=引用 2 楼 heronism 的回复:] 请问第68行为什么是stack_size > 0，而不是stack_size <= 0  ？ ——有什么问题，stack_size > 0表示这个栈是有实际内容的，assert里的表达式是要求为真程序才继续往下跑的。  那第61行的assert(stack_size > 0);  为什么不是stack_size = 0？它不是is_empty 函数吗？堆栈为空，不是stack_size = 0 吗？[/quote] 拜托好好看看你的代码吧，别人看一眼就能明白，你自己压根就没好好看。好好想想你说的“堆栈为空，不是stack_size = 0 吗？”有什么依据

assert(stack_size > 0]);  这是一条断言，是在调试阶段比较常用的方式。如果参数为假则直接退出，对于查找问题效率较高。

引用 2 楼 heronism 的回复:请问第68行为什么是stack_size > 0，而不是stack_size <= 0  ？ ——有什么问题，stack_size > 0表示这个栈是有实际内容的，assert里的表达式是要求为真程序才继续往下跑的。  那第61行的assert(stack_size > 0);  为什么不是stack_size = 0？它不是is_empty 函数吗？堆栈为空，不是stack_size = 0 吗？

自己查一下 assert的用法就明白了。


Question: 怎么在c语言中用socket的方式调用webservice？？

跟webservice无关，跟socket编程有关。 如果放着webservice的库不用，那么还是先从socket的编程的基本内容开始吧。

引用 1 楼 user-6 的回复:先会如何用 http 交谈, 剩下的就是拼接 soap 文档了.  是发送一段http报文过去吗？？？

百度gsoap。

用soapui工具来转换成需要的头文件和源文件  直接掉生成的接口

引用 4 楼 robertbo 的回复:可以实现，先connect sockaddr_in server; 	if (m_bSockConnected)  	{ 		return TRUE; 	} 	server.sin_addr.s_addr	= inet_addr(m_szHost); 	server.sin_family		= AF_INET; 	server.sin_port			= htons((UINT)m_nPort);  	if(connect(m_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) 	{ 		m_bSockConnected = FALSE; 		m_nLastErrorNo = WSAGetLastError(); 		MessageBox(0, "请检网络和服务器", "网络连接错误", 0); 		return FALSE;  	} 	else 	{ 		m_bSockConnected = TRUE; 	}  	int timeout=30; 	setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(int)); 然后再发送url char requestHeader[1024]= {0}; 	char nBuf[36]			= {0}; 	strcpy(requestHeader, "PUT "); 	strcat(requestHeader, szUrl); 	strcat(requestHeader, "&Content-Length="); 	_ui64toa(contentLength + 8, nBuf,10); //额外加了传输完成头的长度是8 strlen(SEND_END_STRING) 	strcat(requestHeader, nBuf); 	strcat(requestHeader, "&FileCount="); 	ltoa(fileCount,nBuf, 10); 	strcat(requestHeader, nBuf); 	strcat(requestHeader," HTTP/1.1\r\nContent-Length: "); 	_ui64toa(contentLength + 8, nBuf, 10); 	strcat(requestHeader,nBuf); 	strcat(requestHeader,"\r\nHost: "); 	strcat(requestHeader,m_szHost); 	strcat(requestHeader,":"); 	itoa(m_nPort,nBuf,10); 	strcat(requestHeader,nBuf); 	strcat(requestHeader,"\r\nAccept: */*;\r\nAccept-Encoding: gzip,deflate\r\nKeep-Alive: 60000\r\nConnection: keep-alive\r\n\r\n"); 	//MessageBox(0, requestHeader, "info", 0); 	char * szUTF8 = NULL; 	BOOL	bRet  = FALSE; 	bRet = CCharTransLib::EncodeToUTF8(requestHeader,&szUTF8); 	if (bRet) 	{ 		if ( (int)strlen(szUTF8) != send(m_socket, szUTF8, strlen(szUTF8), 0)) 		{ 			m_nLastErrorNo = GetLastError(); 			bRet = FALSE; 		} 		if (szUTF8) 		{ 			delete []szUTF8; 			szUTF8 = NULL; 		} 	} 以上是从我工程里面摘的，可能有些变量楼主编译不过去，但基本思想就是这样的  如果我用http get的方式发送报文，服务端返回的内容是怎么样的呢？？我还没弄懂怎么解析返回报文。

建议楼主先学会使用抓包软件比如wireshark

先会如何用 http 交谈, 剩下的就是拼接 soap 文档了.


Question: 有人用c语言写过计算md5的么

恩恩，好用，好用 你也下吧

百度上有现成的代码

仅供参考#include <stdio.h> #include <math.h> #include <string.h> #include <memory.h> const unsigned int s[4][4]={{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}}; const unsigned long t[64]={//t[i]=4294967296*fabs(sin(i+1));  0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,  0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,  0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,  0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,  0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,  0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,  0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,  0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 }; const int serial[64]={  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,  1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,  5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,  0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 }; void func(unsigned long& a,           unsigned long b,           unsigned long c,           unsigned long d,           unsigned long M,           unsigned long t,           int s,           int turn) {     unsigned long temp;     switch(turn) {     case 0:         temp=(b&c)|((~b)&d);         break;     case 1:         temp=(d&b)|((~d)&c);         break;     case 2:         temp=b^c^d;         break;     case 3:         temp=c^(b|(~d));         break;     }     temp+=M+t+a;     _asm {         mov ecx,s         rol temp,cl     }     a=b+temp; } void MD512(const unsigned long M[16],unsigned long hash[4]) {     int i,j,index=0;     for (i=0;i<4;i++)         for (j=0;j<4;j++) {             func(hash[0],hash[1],hash[2],hash[3],M[serial[index]],t[index],s[i][0],i);             index++;             func(hash[3],hash[0],hash[1],hash[2],M[serial[index]],t[index],s[i][1],i);             index++;             func(hash[2],hash[3],hash[0],hash[1],M[serial[index]],t[index],s[i][2],i);             index++;             func(hash[1],hash[2],hash[3],hash[0],M[serial[index]],t[index],s[i][3],i);             index++;         } }  void MD5(char* M,int nLen,unsigned long output[4]) {     int i,j;     unsigned long Hash[4]={0x67452301,0xefcdab89,0x98badcfe,0x10325476};     unsigned long hash[4];      //填充     __int64 BitsLen=nLen*8;     int oldlen=nLen;     while(nLen%64!=56) {         M[nLen++]=0;     }     M[oldlen]=0x80u;     *(__int64*)(M+nLen)=BitsLen;     nLen+=8;      //开始处理分组     for (i=0;i<nLen;i+=64) {         memcpy(hash,Hash,sizeof(long)*4);         MD512((const unsigned long*)&M[i],hash);//处理512bits分组         for (j=0;j<4;j++)             Hash[j]+=hash[j];     }      //处理输出。     for (i=0;i<4;i++)         for (j=3;j>=0;j--) {             *((char*)(output+i)+j)=*((char*)(Hash+i)+3-j);         } } int main() {     int i;     char szMessage[1000]={0};     printf("input a string:\n>>>");     scanf("%s",szMessage);     unsigned long output[4];     MD5(szMessage,strlen(szMessage),output);     for (i=0;i<4;i++)         printf("%08lx",output[i]);     printf("\n");     return 0; }


Question: 大神们，有关步进电机和直流电机的问题，在线等？？

引用 1 楼 user-5 的回复:lz确定这是属于c、c++板块的问题？  这位姑娘  我看了你11年的帖子跟踪到这里来的， 近况怎么样？

引用 楼主 Happy_5201314 的回复:这里不懂，为什么PWM_TEME_H会等于80，PWM_TEME_L会等于20？？我计算的结果是PWM_TEME_H = 20，PWM_TEME_L = 80？？ 占空比是指高电平在一个周期之内所占的时间比率。  底下那几个问题 第一，两个if的判断条件实际上是等价的，估计程序写错了，注释也写反了 第二，估计加速键和减速键分别对应着PWM_TEME_H的++和--，所以如果在操作之后发现结果超出了允许范围，就要--和++恢复成操作前的数值 第三，高电平时间+低电平时间=总时间，所以低电平时间=总时间-高电平时间，如果连这你要问，那我觉得你不是新手，你是不想动手

你在电脑上写了一个程序，跑起来很顺畅 然后我跟你说，请你把这个程序移植到电视机上 你觉得此时露出什么表情比较好？  步进电机和直流电机的原理不同，硬件不同，所以软件也完全不同 步进电机每一个脉冲都会使内部磁场旋转一个步距角，所以脉冲数决定了角度，发脉冲的频率也就决定了速度 直流电机的输入功率对应其转速，调节电压和占空比都会改变实际输入的功率，至于脉冲频率不重要 你要是有能力让你家电视机运行你的电脑程序，你就可以用控制直流电机的程序来控制步进电机

小弟，是新手啊？跪求大神帮忙解决？？

步进电机和一般直流电机的驱动方式是完全不同的，PWM不适用于步进电机。

提醒：小心“空回误差”。

lz确定这是属于c、c++板块的问题？


Question: tcp 长连接检测客户端异常退出  keepalive使用

心跳包原理：  1、自行实现的心跳包，一般是发送一段简短的报文  2、tcp协议栈自带的keepalive心跳包，重发一个已经发送过的字节，有触发时间（即一段时间无通信后）

keepalive是tcp协议栈提供的心跳包（保活）机制  以windows平台上已建立的连接为例：  用户进程（非服务）被杀死，tcp协议栈将异常断开连接，另一方可以获得通知，如recv返回-1  用户进程退出且未调用closesocket，另一方可以获得通知  系统关机（正常的），另一方可以获得通知  系统关机（异常的），另一方不一定可以获得通知  系统断电，另一方无法获得通知  网络突然故障（例如网线被拔掉），另一方无法获得通知  由此可见，断电和断网时，对方无法获得通知，recv将一直阻塞直到永远。keepalive主要就是为了应对这种情况，若干保活包不能送达，对方即认为连接丢失。

引用 14 楼 zhao4zhong1 的回复:不要在另外一个线程中或定时器回调函数中直接调用send函数发送心跳包，要在另外一个线程或定时器回调函数中将待发送心跳包插入一个待发送数据包FIFO队列中。 原来专管调用send函数发送数据的那个线程（如果没有就需要专门创建此线程），只管从待发送数据包FIFO队列中逐个取出数据包调用send函数发送。  否则会出现类似 发送方发送：发送数据的那个线程send(人多)，发送数据的那个线程send(病少)，另一个线程中或定时器回调函数中send(心跳)，发送数据的那个线程send(财富) 接收方接收：recv(人多病心跳)recv(少财富) 这样的错误！   多线程FIFO队列参考这个：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }    表示没怎么看懂。。使用心跳包是不是会改变协议？ 比如说TCP 的数据部分原来是char data[0]。 现在可能要改写成   typedef struct _t_msg {     unsigned int type;    //用来标记是否是心跳包     char data[0]; }tMsg;  而且客户端的数据部分也要是这个格式。。

引用 21 楼 u012889234 的回复:[quote=引用 20 楼 mujiok2003 的回复:] 服务器可以主动断开一段时间内没有通讯的连接， 虽然粗暴，但是很实用。   心跳包以下缺点：   1. 加大服务器的通讯量，会恶化网络更差的情况。  2. 客户端需要响应心跳， 客户、服务器之间耦合性更强。  太粗暴不好吧！！！！万一别人没有想要端开，结果你给关了。。[/quote] 粗暴是相对的， 时间你可以自己调整。 心跳包也会有误杀的情况。

引用 20 楼 mujiok2003 的回复:服务器可以主动断开一段时间内没有通讯的连接， 虽然粗暴，但是很实用。   心跳包以下缺点：   1. 加大服务器的通讯量，会恶化网络更差的情况。  2. 客户端需要响应心跳， 客户、服务器之间耦合性更强。  太粗暴不好吧！！！！万一别人没有想要端开，结果你给关了。。

有没一个例子啊。。。我定时向客户端发心跳包，通过send的返回值还是recv的返回值判断。 recv的返回值好像对异常退出没有处理啊？     貌似是说异常退出发不出来FIN包。。    while (1)   {       if ((connectfd = accept(listenfd, (struct sockaddr *)&cliaddr,    (socklen_t *)& sin_size)) == -1)          {                   perror("Accept() error-");                 continue;           }           nrecv = recv(sockfd, recvbuf, MAXDATASIZE, 0);  	if(nrecv < 0) 	{ 	            if( errno == EAGAIN || errno == EWOULDBLOCK)                     { 			continue;                    }                    else                    {         	         //..... 客户端应用程序退出		  	         }       }       if (nrecv == 0)         {             //  客户端主动断线        }         else        {                  // 正常通信         }           close(listenfd); }

用自行实现的心跳包，和协议无关且可根据自己实际需要灵活配置。 别用tcp协议栈自带的keepalive心跳包。

SO_KEEPALIVE 的检测时间可能达到 2 个小时，不适合用来判断客户端是否掉线 不过，通常情况下，客户端进程退出，客户端进程崩溃，操作系统正常关闭等等服务器都可以收到通知的。只有客户端操作系统异常崩溃的情况下服务器无法得知，需要用心跳包来检测。 而客户端断网，中间路由器崩溃造成网络不通等等，即使不处理也说得通，因为这些情况都是可以在稍后恢复的。

推荐自己发送心跳包， 具体实现可以使用时间轮（time wheel)

心跳包这样做可以吗？？？   BOOL InitThreads() {         if(pthread_create(&MyParam.CheckConnectedId, NULL, CheckConnectedThread, NULL))     {         write_log(LOG_SYS_ERR, "\nCreate CheckConnectedThread Failure!");         return FALSE;     }      return TRUE; }  void * CheckConnectedThread(void * para) {     sleep(MyParam.user_tmout);   //300秒     int i = 0;     int len = 0;      char buf[] = "hello client!";     int sockfd = -1;     for(i = 0; i < FD_SETSIZE; i++)     {         if((sockfd = MyMrTb.client6[i].fd) < 0)            {                continue;         }         send(sockfd, buf, strlen(buf), 0);          //......怎么判断是否断线     } }

引用 6 楼 u012889234 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 不要迷信和使用keepalive 要使用心跳包 心跳包怎么使用用的啊！！！ 开启一个线程吗？   比如我要没5分钟检测一次。就是向所有的客户端发送心跳包，没有回应就表示已异常断开了吗?  [/quote] 所谓心跳包的意思就是在应用层甲方和乙方自己定义一个特殊的数据包，内容比如为“（甲当前时间）甲：人在吗？”，由甲方定期比如每5分钟发送给乙方，乙方收到后，发送“（甲当前时间）甲：人在吗？＋（乙当前时间）乙：在呢。”给甲方。 甲方收到乙方的对应回应，即确定此时连接可用；甲方连续多次比如三次在设定时间内比如10秒未收到乙方的对应回应，即确定此时连接已不可用，启动每隔比如15秒重新和乙方建立连接，重新连接多次比如10次不成功，想办法比如电邮、短信、报警……通知运维人员。

引用 5 楼 zhao4zhong1 的回复:不要迷信和使用keepalive 要使用心跳包 心跳包怎么使用用的啊！！！ 开启一个线程吗？   比如我要没5分钟检测一次。就是向所有的客户端发送心跳包，没有回应就表示已异常断开了吗?

不要迷信和使用keepalive 要使用心跳包

主要问题是第一个？？？还未得到回复！！

引用 9 楼 zhao4zhong1 的回复:不要用多线程或定时器回调直接发送心跳包，要用多线程或定时器回调将待发送心跳包插入一个待发送数据包FIFO队列中。 发送线程只管从待发送数据包FIFO队列中逐个取出数据包发送。  否则会出现类似 send(人多)，send(病少)，另一个线程或定时器回调发送(心跳)，send(财富) recv(人多病心跳)recv(少财富) 这样的错误！  什么意思？？ 是------比如有一个客户端成功连接时就给它创建一个循环定时器，让它定时发送。。   typedef  struct _t_mnode4  tMnode4; struct _t_mnode4 {    // ............     tTimer  *       t_time_id;     //定时器ID    //........... };    inline tMnode4 * AddMrUserv4tcpTb(tMnode4 * pMrnode) {    // ................................................... //  创建用户TCP长连接检查机制，若已与MR服务器断线，则关闭该TCP socket //create_ctimer 创建循环定时器函数 //MyMrTb.user_timerID   定时器组ID //MyParam.user_tmout  定时时长 300秒 //pMrnode  传给回调函数的参数 //&pMrnode->t_time_id  用来获得返回的定时器 //MrUserv4tcp_Tm_out   回调函数            create_ctimer(MyMrTb.user_timerID, MyParam.user_tmout, pMrnode, &pMrnode->t_time_id, MrUserv4tcp_Tm_out);  //............................... }  //回调函数 void MrUserv4tcp_Tm_out(void * para, tTimer * tid) {     tMnode4 *   pMnode4 = NULL;     int         sockfd = 0;     char        buf[64] = "IsAlive";     int         len = 0;     pMnode4 = (tMnode4 *)para;     if(!pMnode4)     {         kill_timer(tid);         return ;     }     sockfd = pMnode4->sockfd;     len = send(sockfd, buf, strlen(buf), 0);     if(len <= 0)    //用户异常断线     {         // 删除用户信息     } }    这么做吗？

[quote=引用 9 楼 zhao4zhong1 的回复:] 不要用多线程或定时器回调直接发送心跳包，要用多线程或定时器回调将待发送心跳包插入一个待发送数据包FIFO队列中。 发送线程只管从待发送数据包FIFO队列中逐个取出数据包发送。  否则会出现类似 send(人多)，send(病少)，另一个线程或定时器回调发送(心跳)，send(财富) recv(人多病心跳)recv(少财富) 这样的错误！ [/quote 什么意思？？ 是------比如有一个客户端成功连接时就给它创建一个循环定时器，让它定时发送。。  typedef  struct _t_mnode4  tMnode4; struct _t_mnode4 {    // ............     tTimer  *       t_time_id;     //定时器ID    //........... };    inline tMnode4 * AddMrUserv4tcpTb(tMnode4 * pMrnode) {    // ................................................... //  创建用户TCP长连接检查机制，若已与MR服务器断线，则关闭该TCP socket //create_ctimer 创建循环定时器函数 //MyMrTb.user_timerID   定时器组ID //MyParam.user_tmout  定时时长 300秒 //pMrnode  传给回调函数的参数 //&pMrnode->t_time_id  用来获得返回的定时器 //MrUserv4tcp_Tm_out   回调函数            create_ctimer(MyMrTb.user_timerID, MyParam.user_tmout, pMrnode, &pMrnode->t_time_id, MrUserv4tcp_Tm_out);  //............................... }  //回调函数 void MrUserv4tcp_Tm_out(void * para, tTimer * tid) {     tMnode4 *   pMnode4 = NULL;     int         sockfd = 0;     char        buf[64] = "IsAlive";     int         len = 0;     pMnode4 = (tMnode4 *)para;     if(!pMnode4)     {         kill_timer(tid);         return ;     }     sockfd = pMnode4->sockfd;     len = send(sockfd, buf, strlen(buf), 0);     if(len <= 0)    //用户异常断线     {         // 删除用户信息     } }   是这个做法吗？？

TCP不允许传输0字节，recv函数接收到0字节，就表示对方主动断开


Question: 关于ASCII的问题

只有可视字符才能正常显示：  32～126(共95个)是字符(32是空格），其中48～57为0到9十个阿拉伯数字 65～90为26个大写英文字母，97～122号为26个小写英文字母，其余为一些标点符号、运算符号等。   引用 楼主 syj52417 的回复:为什么我的计算机识别不了一些ASCII中的字符  int x=1; printf("%c",x);  这样就可以输出ASCII为1的字符，当x变成其他值比方说 x=251，字符应该是个    勾 ，为什么控制台输出只显示个问号，这是为什么？

引用 5 楼 baichi4141 的回复:简单的说，ASCII码的有效数值是1～127，大于等于128的数在ASCII码中没有对应字符，不管你的程序中显示出来的使什么玩意，都跟ASCII码表无关 补充一句：某些编译器的ASCII码值是0~255的，比如win-tc 某些编译器的ASCII码值是-128~127的，比如vc、cfree、gcc

引用 楼主 syj52417 的回复:为什么我的计算机识别不了一些ASCII中的字符  int x=1; printf("%c",x);  这样就可以输出ASCII为1的字符，当x变成其他值比方说 x=251，字符应该是个    勾 ，为什么控制台输出只显示个问号，这是为什么？  将x赋值为65，你就知道了。顺便了解下：哪些是可显示字符，哪里不是!!

引用 楼主 syj52417 的回复:为什么我的计算机识别不了一些ASCII中的字符  int x=1; printf("%c",x);  这样就可以输出ASCII为1的字符，当x变成其他值比方说 x=251，字符应该是个    勾 ，为什么控制台输出只显示个问号，这是为什么？ ASCII码表，不可显示字符，用的是示意符号表示，并不是那个字符可以在屏幕上那样显示。

#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> wchar_t a2w[256]={ 0x0020,0x263a,0x263b,0x2665,0x2666,0x2663,0x2660,0x2022, 0x25d8,0x25cb,0x25d9,0x2642,0x2640,0x266a,0x266b,0x263c, 0x25ba,0x25c4,0x2195,0x203c,0x00b6,0x00a7,0x25ac,0x21a8, 0x2191,0x2193,0x2192,0x2190,0x221f,0x2194,0x25b2,0x25bc, 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x2302, 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, 0x00e9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, 0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00ff, }; extern "C" HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     wchar_t ws[256];     unsigned char s[256];     int i;       system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(16,  0, 0, 0, 0, 0, 0, 0, 0           , 0, 0, 0, 0, "Lucida Console");     SelectObject(hdc,hfont);     TextOutW(hdc,10,10,L"你好",2);     for (i=0;i<256;i++) s[i]=i;     for (i=0;i<256;i++) ws[i]=a2w[s[i]];     TextOutW(hdc,10, 40,ws    ,32);     TextOutW(hdc,10, 80,ws+ 32,32);     TextOutW(hdc,10,120,ws+ 64,32);     TextOutW(hdc,10,160,ws+ 96,32);     TextOutW(hdc,10,200,ws+128,32);     TextOutW(hdc,10,240,ws+160,32);     TextOutW(hdc,10,280,ws+192,32);     TextOutW(hdc,10,320,ws+224,32);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }


Question: DES加密的C语言实现过程中，最后一步居然出错，数组有关！！

static void RotateL(const int input[28],int output[28], int loop)//秘钥循环左移 { 	int i; 	if(loop==1) 	{ 		int temp=input[0]; 		for(i=0;i<27;i++) 			output[i]=input[i+1]; 		output[27]=temp; 	} 	else 	{ 		int temp=input[0]; 		int temp_1=input[1]; 		for(i=0;i<26;i++) 			output[i]=input[i+2]; 		output[26]=temp; 		output[27]=temp_1; 	} }; 你的错误在这里。。。好难查找的错误！！！

引用 3 楼 shen_wei 的回复:input[i+1]*8+input[i+2]*4+input[i+3]*2+input[i+4] 数组越界了！！！ i = 12  i + 4 = 16  但是input[16]不越界啊 input[]是48的。

《算法精解（C语言描述）》随书代码中似乎有现成的des代码。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。  重点检查函数参数传递


Question: 利用显示页和编辑页交替变化实验动画效果，为何程序运行后，看不到动画效果？

仅供参考#include <graphics.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos.h> #include <conio.h> #include <time.h> #include <math.h> time_t t; char timestr1[30];//DDD MMM dd hh:mm:ss YYYY char timestr2[30];//DDD MMM dd hh:mm:ss YYYY char hhmmss[9]; int graphdriver,graphmode,page; int i,xo,yo,r0,r1,r2,r3,r4,r5,r6,r7; int x1,y1,x2,y2; int hh,mm,ss; double c,s; int xasp,yasp; void main() {     xo=60;yo=60;     r0=5; //轴     r1=20;//时针     r2=36;//分针     r3=45;//秒针     r4=50;//时刻度     r5=53;//分刻度     r6=55;//刻度外     r7=59;//表盘     graphdriver=VGA;     graphmode=VGAMED;     initgraph(&graphdriver,&graphmode,"D:\\BC\\BGI");     getaspectratio(&xasp, &yasp);     page=0;     timestr2[0]=0;     while (1) {         if (kbhit()) break;         time(&t);         strcpy(timestr1,ctime(&t));         if (strcmp(timestr1,timestr2)) {             strcpy(timestr2,timestr1);             hh=atoi(timestr2+11);             mm=atoi(timestr2+14);             ss=atoi(timestr2+17);             setvisualpage(page);             setactivepage(1-page);             cleardevice();             sprintf(hhmmss,"%02d:%02d:%02d",hh,mm,ss);             outtextxy(28,0,hhmmss);             pieslice(xo,yo,0,360,r0);             circle(xo,yo,r7);             for (i=0;i<60;i++) {                 c=cos(i*6*3.14159265/180);                 s=sin(i*6*3.14159265/180)*xasp/yasp;                 if (0==(i%5)) {                     x1=xo+r4*c;                     y1=yo+r4*s;                 } else {                     x1=xo+r5*c;                     y1=yo+r5*s;                 }                 x2=xo+r6*c;                 y2=yo+r6*s;                 line(x1,y1,x2,y2);                 if (((hh%12)*5+mm/12+45)%60==i) {                     x2=xo+r1*c;                     y2=yo+r1*s;                     setlinestyle(0,-1,3);                     line(xo,yo,x2,y2);                     setlinestyle(0,-1,1);                 }                 if ((mm+45)%60==i) {                     x2=xo+r2*c;                     y2=yo+r2*s;                     setlinestyle(0,-1,3);                     line(xo,yo,x2,y2);                     setlinestyle(0,-1,1);                 }                 if ((ss+45)%60==i) {                     x2=xo+r3*c;                     y2=yo+r3*s;                     line(xo,yo,x2,y2);                 }             }             page=1-page;         }         delay(100);     }     getch();     closegraph(); }

引用 4 楼 yerssa 的回复:[quote=引用 3 楼 user-2 的回复:] [quote=引用 2 楼 yerssa 的回复:] [quote=引用 1 楼 user-2 的回复:] 页面交换需要，要延时的 画出来也许很快，那样就看不到中间结果了 那怎么才能看到动画效果呢？程序需要改哪里？[/quote] TC有delay 函数，和 Windows Sleep效果一致，  不然自己用定时器，实现之，需要操作硬件 用outportb 设置定时器时间间隔，并且需要设置中断向量。 在中断响应函数里，做计数。轮询该计数，就可以了[/quote] 恩，看到动画效果了，但还有个问题，就是为什么生成的.EXE文件，双击后，只是一个窗口一闪而过，其它什么也看不到呢？[/quote] windows下控制台，现在就这样，你最后加一个延时，或者getchar();之类的把它画面停住，就可以了。  另外TC的画图程序，在XP下运行不一定成功，在Win98下是可以的  可以尝试，在虚拟机中，DOS下运行。

引用 3 楼 user-2 的回复:[quote=引用 2 楼 yerssa 的回复:] [quote=引用 1 楼 user-2 的回复:] 页面交换需要，要延时的 画出来也许很快，那样就看不到中间结果了 那怎么才能看到动画效果呢？程序需要改哪里？[/quote] TC有delay 函数，和 Windows Sleep效果一致，  不然自己用定时器，实现之，需要操作硬件 用outportb 设置定时器时间间隔，并且需要设置中断向量。 在中断响应函数里，做计数。轮询该计数，就可以了[/quote] 恩，看到动画效果了，但还有个问题，就是为什么生成的.EXE文件，双击后，只是一个窗口一闪而过，其它什么也看不到呢？

引用 2 楼 yerssa 的回复:[quote=引用 1 楼 user-2 的回复:] 页面交换需要，要延时的 画出来也许很快，那样就看不到中间结果了 那怎么才能看到动画效果呢？程序需要改哪里？[/quote] TC有delay 函数，和 Windows Sleep效果一致，  不然自己用定时器，实现之，需要操作硬件 用outportb 设置定时器时间间隔，并且需要设置中断向量。 在中断响应函数里，做计数。轮询该计数，就可以了

引用 1 楼 user-2 的回复:页面交换需要，要延时的 画出来也许很快，那样就看不到中间结果了 那怎么才能看到动画效果呢？程序需要改哪里？

页面交换需要，要延时的 画出来也许很快，那样就看不到中间结果了


Question: 怎么扫描指定的点

引用 8 楼 u010095851 的回复:引用 7 楼 zjq9931 的回复:[quote=引用 6 楼 u010095851 的回复:] [quote=引用 5 楼 zjq9931 的回复:] [quote=引用 3 楼 u010095851 的回复:] 我再问一下，那怎么弄可以使上面这些点按顺序五个五个都遍历到呢  [quote=引用 1 楼 zjq9931 的回复:] for(i=1, j=0; i<ix,j<iy; i++,j++) 不太明白5个5个遍历是什么意思，能否细说？[/quote]  就是（1,0），（2,1），（3,2），（4,3），（5,4）一组，（2,1），（3,2），（4,3），（5,4），（6,5）一组，每五个一组以此类推得到这些点的值[/quote]   int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      scanxy(ix,ix-1);      scanxy(ix+1,ix);      scanxy(ix+2,ix+1);      scanxy(ix+3,ix+2);      scanxy(ix+4,ix+3); }  或者  int check(x, y) {     for(i=0; i<5; i++)     {         scanxy(x+i, y+i);     } } int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      check(ix,ix-1); } [/quote]  scanxy是自己写的函数吗？[/quote] 是的。

引用 7 楼 zjq9931 的回复:引用 6 楼 u010095851 的回复:[quote=引用 5 楼 zjq9931 的回复:] [quote=引用 3 楼 u010095851 的回复:] 我再问一下，那怎么弄可以使上面这些点按顺序五个五个都遍历到呢  [quote=引用 1 楼 zjq9931 的回复:] for(i=1, j=0; i<ix,j<iy; i++,j++) 不太明白5个5个遍历是什么意思，能否细说？[/quote]  就是（1,0），（2,1），（3,2），（4,3），（5,4）一组，（2,1），（3,2），（4,3），（5,4），（6,5）一组，每五个一组以此类推得到这些点的值[/quote]   int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      scanxy(ix,ix-1);      scanxy(ix+1,ix);      scanxy(ix+2,ix+1);      scanxy(ix+3,ix+2);      scanxy(ix+4,ix+3); }  或者  int check(x, y) {     for(i=0; i<5; i++)     {         scanxy(x+i, y+i);     } } int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      check(ix,ix-1); } [/quote]  scanxy是自己写的函数吗？

引用 6 楼 u010095851 的回复:引用 5 楼 zjq9931 的回复:[quote=引用 3 楼 u010095851 的回复:] 我再问一下，那怎么弄可以使上面这些点按顺序五个五个都遍历到呢  [quote=引用 1 楼 zjq9931 的回复:] for(i=1, j=0; i<ix,j<iy; i++,j++) 不太明白5个5个遍历是什么意思，能否细说？[/quote]  就是（1,0），（2,1），（3,2），（4,3），（5,4）一组，（2,1），（3,2），（4,3），（5,4），（6,5）一组，每五个一组以此类推得到这些点的值[/quote]   int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      scanxy(ix,ix-1);      scanxy(ix+1,ix);      scanxy(ix+2,ix+1);      scanxy(ix+3,ix+2);      scanxy(ix+4,ix+3); }  或者  int check(x, y) {     for(i=0; i<5; i++)     {         scanxy(x+i, y+i);     } } int ix; for(ix=1; ix<18-4; ix++)  //看你前面写的最后是18 {      check(ix,ix-1); }

引用 5 楼 zjq9931 的回复:引用 3 楼 u010095851 的回复:我再问一下，那怎么弄可以使上面这些点按顺序五个五个都遍历到呢  [quote=引用 1 楼 zjq9931 的回复:] for(i=1, j=0; i<ix,j<iy; i++,j++) 不太明白5个5个遍历是什么意思，能否细说？[/quote]  就是（1,0），（2,1），（3,2），（4,3），（5,4）一组，（2,1），（3,2），（4,3），（5,4），（6,5）一组，每五个一组以此类推得到这些点的值

引用 3 楼 u010095851 的回复:我再问一下，那怎么弄可以使上面这些点按顺序五个五个都遍历到呢  引用 1 楼 zjq9931 的回复:for(i=1, j=0; i<ix,j<iy; i++,j++) 不太明白5个5个遍历是什么意思，能否细说？

引用 2 楼 zhao4zhong1 的回复:for (int x=1; x<=18;x++) scanxy(x,x-1); 赵老师 谢谢您的回答  我楼上还有一个问题

for (int x=1; x<=18;x++) scanxy(x,x-1);

for(i=1, j=0; i<ix,j<iy; i++,j++)


Question: 如何学习算法

为什么要有数据结构这个东东？ 因为要将现实世界或者抽象理论中的各种数据保存在计算机外存（光盘、硬盘、U盘……）或内存（ROM、RAM、SRAM……）里面的二进制字节数组中。 然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。至于具体如何处理就是所谓算法。

《算法导论》好像太深奥了，，不太适合入门啊············

可以按照上图，一步步学，至于书籍，我觉得楼上的说的可以

以前看到的一张图片

比如算1+2+...+10000 你写个循环真的加，就是暴力 如果你会公式，就是算法

有问题多到csdn论坛来问吧

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

《算法导论》 《The Algorithm Design Manual 2Ed》

一张A4白纸，一支笔足以

google v_july_v博客


Question: 新手求助，显示“Judge”: 重定义；不同的基类型

你是不是把这个函数现在头文件里。然后被2个源文件引用了

你所贴的代码段没有Judge重定义的问题，请仔细检查其它代码段。

怎样使用它的？


Question: 关于C语言return语句的一些疑问

计算机组成原理→DOS命令→汇编语言→C语言（不包括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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 6 楼 mujiok2003 的回复:char s1[]="123"; char s2[]="456"; my_strcpy_end(s1,s2); 但是我发现我这么调用的话好像那个return语句没起到什么作用啊，所以我想问下大家，return语句到底有什么作用？它返回的值究竟去了哪里？   返回值一般放入EAX寄存器。 因为你的例子中，你没有“接收”返回值，所以被丢弃了。 ++  引用 2 楼 u013697891 的回复:返回至不是应该这么用吗 int  a(){ ........... return b;} main(){ int c; c=a();} ++  函数调用是个表达式，称为函数调用表达式。 任何表达式，加上一个分号，就成为一个表达式语句。  单独的函数调用语句是个表达式，这个表达式的值，没有使用，所以被忽略。 任何其他表达式也是如此 例如： int a=10; a; // 表达式语句，值为 a（也就是10，如果赋值给别的表达式），该值没使用，被忽略。 a= 20;// 赋值表达式 哲理有3个表达式  a,20 ,a=20  //1） a 20   a是左值表达式。20是右值表达式 //2） a=20  是个赋值表达式 ，值为a(也就是20，如果赋值给别的表达式) 被忽略 //3）副作用是a 的值变成20，完成赋值。

1. 你的函数中f1未使用，不需要这个变量 2. 函数的逻辑有问题，你这是要覆盖原来的字符 3. 你未测试函数参数的有效性 4. 你的return goal-1;逻辑上不准确，至少是return f1; 5. 你my_strcpy_end(s1,s2);调用是有问题的，s1的长度是在编译后确定了的，如果s2很长，会造成s1溢出 6. 你调用函数时不使用变量接收函数的返回值，它的返回值就被抛弃了，相当于(void *)my_strcpy_end(s1,s2);

记得书上说return值返回到Main函数

这里二楼说的很详细——http://bbs.bccn.net/thread-308356-1-1.html


Question: 百度的c语言写的2048代码，求大神看看那里错误了不能运行呢

恩恩  好的 这是个好方法，但是我都不知道错在那里呢。谢谢lz

那为啥只报了有2个错误呢，求大神帮帮忙改一下下呢~~o(>_<)o ~~

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

错误一大堆。。。。 最开始的错误是：int add(int n); 后面多了分号，但改完这个之后，又有一大堆。


Question: 纯API 超链接...

引用 1 楼 user-1 的回复:Resource.h  #define	DLG_MAIN	   1000 #define	IDC_WEBPAGE 1101 #define	IDC_EMAIL   1102  Hyperlink.rc  #include	<Winres.h> #include "Resource.h"  DLG_MAIN	DIALOGEX 160, 160, 236, 185 STYLE		DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION		"对话框模板" FONT		9, "宋体" BEGIN	    CONTROL         "Goto Replace",IDC_WEBPAGE,                     "SysLink",WS_TABSTOP,25,85,174,10    CONTROL         "Goto E-Mail",IDC_EMAIL,                     "SysLink",WS_TABSTOP,25,55,174,10    CONTROL		   "",-1,"Static",SS_ETCHEDHORZ,7,155,222,1    DEFPUSHBUTTON	"退出",IDOK,177,163,50,14 END  ID_ICON ICON "bulbs.ico"  Hyperlink.c  #define STRICT   #include <Windows.h> #include <tchar.h>   #include <commctrl.h> #include <Shellapi.h> #include "Resource.h"  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib")  //#pragma comment(lib, "comctl32.lib") #pragma comment(lib, "Shell32.lib")  #pragma comment(linker, "/subsystem:windows,5.1.2600 /entry:WinMainCRTStartup")   // 设置入口地址   INT_PTR CALLBACK AboutDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam);  int WINAPI _tWinMain(HINSTANCE hInstance,                      HINSTANCE hPrevInstance,                      LPTSTR szCmdLine,                      INT iCmdShow) {    DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, AboutDlgProc,0);    return 0;    //InitCommonControls(); }  INT_PTR CALLBACK AboutDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) {    switch (umsg)    {    case WM_INITDIALOG:        SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(GetModuleHandle(NULL), TEXT("ID_ICON")));       break;     case WM_COMMAND:       if (IDOK == LOWORD(wParam))          EndDialog(hwnd, 0);       return TRUE;     case WM_CLOSE:       EndDialog(hwnd, 0);       return TRUE;     case WM_NOTIFY:       {          LPNMHDR pnmhdr = (LPNMHDR)lParam;          switch (pnmhdr->code)           {          case NM_CLICK:          case NM_RETURN:             {                if (pnmhdr->idFrom == IDC_WEBPAGE)                 {                   ShellExecute(hwnd, TEXT("open"), TEXT("http://www.flos-freeware.ch"), NULL, NULL, SW_SHOWNORMAL);                }                else if (pnmhdr->idFrom == IDC_EMAIL)                 {                   ShellExecute(hwnd, TEXT("open"), TEXT("mailto:florian.balmer@gmail.com"), NULL, NULL, SW_SHOWNORMAL);                }             }             break;           }       }       return TRUE;    }    return FALSE;     } 好吧...先谢谢2L的朋友啦..


Question: win7下，malloc失败！求高手解决！

内存碎片吧，可能。

应该是没有连续的200M的内存空间，或者腾不出这么大的空间吧。楼主这是要做什么一下子需要申请这么多空间，不可以分批多次申请吗？

最好的破解方法是： 在程序初始化时分配程序主循环中将要用到的所有内存 在程序主循环中不再释放和动态分配内存 在程序退出时释放所有分配的内存（也可不释放而让操作系统自动释放）  内存如果不够大，可改用： 内存映射文件 或 用文件读写模拟内存读写（参考_lseeki64函数）

使用范例： TMymems  Pubmems ; //全局变量 内存池 申请： char *p = (char *)Pubmems.Getmem(newsize); 释放  Pubmems.freemem(p);  当系统内存紧张时   Pubmems.freememNoUse(),释放空闲的内存块 当系统退出时   Pubmems.freememAll(),释放全部内存块

//一个内存块 TMymemBlock {  char *fmem ;   unsigned int fsize;  bool Use ;  friend class TMymems;    public :     void *Getmem(int newsize)     {          if(fsize < newsize)           {             fsize = newsize ;              if(fmem) delete fmem ;              fmem = new char[newsize];        }        Use = true ;         return fmem ;       }      void freemem()     {         if(fmem) delete fmem ;         fmem = NULL ;          fsize = 0 ;          Use = false ;      }    TMymemBlock() fmem(NULL) , fsize(0),Use(false) {} }; //TMymems 管理多个不连续的内存块，形成内存池。 TMymems {   std::vector<TMymemBlock>  mems ;  typedef   std::vector<TMymemBlock>::iterator TMymemItem ;  TMymemItem  Findmem(int size) //查找最适合的空闲内存块供使用   {     TMymemItem  pItem = mems.end() ;     unsigned int dt = -1 ;       for(TMymemItem  p =mems .begin() ; p != mems.end() ; ++p )      {           if( ! p->Use )           {              unsigned int tmp = (p->fsize > size) ?  (p->fsize - size)  : -1;               if(tmp  == 0  )                  return p;              else if(tmp < dt )                 {dt = tmp ;  pItem = p ;}              else if( pItem == mems.end() )                 pItem = p ;           }        }     if( pItem  == mems.end() || (mems.size() < 100 ) ) //预留100个内存块,这个可以依据自己的项目来设定，以得到最好性能         {mems.push_back(TMymemBlock());   pItem =  mems.end();}     return pItem ;   } public :     void *Getmem(int newsize)     {         TMymemItem p =  Findmem(newsize)         return p->Getmem(newsize);       }      void freemem(void *p)     {         for(TMymemItem  p =mems .begin() ; p != mems.end() ; ++p )           if(p->fmem == char(*)p )              {p->Use = false ; break ; }     }      void freememNoUse(); //这里不写了      void freememAll(); //这里不写了 } (上面是随手写的) 类似这样的一个简单的机制，就可以应付简单频繁申请释放内存的问题。当然，这个简单的机制，只是适合才用。 小项目，用这样小的定制内存池机制，性能会更好。

有什么好用的内存池么？求大神给推荐一下。。

用内存池撒 ，或者简单点：自己先申请好所有要用的内存

引用 3 楼 pz239 的回复:我估计也是内存碎片问题 ，因为程序在运行中需要频繁的分配、释放大块的内存。。  不知 有何破解方法。。？ 像你这样的频繁的分配释放，需要使用内存池。不能这样一直申请释放 简单讲，就是申请几个内存块，放在那儿拿着用，而不要真正释放掉。

内存碎片问题。 说明现在虚拟地址空间中没有连续的200M可以申请了 和你剩余空间大小无关。而严重的依赖于内存分配的算法。这个算法是运行时库做的。估计设计的不太好吧。。

有图有真相：  最下面显示无法分配内存   可用内存几乎用完，存在大量的备用内存，却无法使用。。。


Question: 关于while 和switch 混合型问题求详解

你可以这样 #include <stdio.h> int main() { 	char c; 	while (1) 	{ 		printf("h\n"); 		switch (c=getchar()); 		printf("%d\n",c); 	} 	return 0; } 看输出的数值是多少，再参照ASCII码去看就知道了

单步调试一下，看看两次都是什么字符

getchar会在你按回车之后把输入的字符接收，你按下的回车也会当做一个字符接收的

引用 1 楼 zxh707wk 的回复:getchar()会把回车也当做输入来接收的关键是不知道为啥会有输出h那

getchar()会把回车也当做输入来接收的


Question: 包含了头文件stdio.h，还是报错显示printf未声明，怎么回事啊，求助！！！

#pragma comment(lib, "Ws2_32.lib") 是加载静态库的意思。

#include <winsock.h>     WORD wVersionRequested;     WSADATA wsaData;     wVersionRequested=MAKEWORD(2,2);     WSAStartup(wVersionRequested,&wsaData); //...     WSACleanup();

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

引用 8 楼 mujiok2003 的回复:来搞笑的吗？  - =， 没注意，但我改过来以后还是不行，不能建立套接字 这是怎么回事啊

初学者都这样啦。我当初也是这种错误找了好久。拼写错误而已。

哈哈，这个有点意思

来搞笑的吗？

如果是VC的话，装个visual assist 一般这种函数都不会打错的。

error: 'pritnf' was not declared in this scope

printf 打错了。。。

三个printf，t和n的顺序反了

close函数加上# include <unistd.h>

在补充说一句，这段代码在cygwin上可以运行，但是我放到vc里面就出了这bug了， windows下socket编程难道有什么不一样的地方？？


Question: C语言画简单的心电图；

如果是我，直接用一个数组记录每个点的坐标。

我也没画过，给个思路。  你要知道这个“心”的图形函数，然后再画出来。最好用现成的库，否则得自己处理选择点和反走样。问问你身边用MATLAB的同学

牛人啊！


Question: 怎么用C语言编写一个程序修改器（修改指定程序的内容）

内存搜索、修改器（附VC6源码） http://bbs.csdn.net/topics/390312862


Question: C语言写的俄罗斯方块，附源码

我下载为什么是404？

楼主，能否发一份源码，我想学习一下，谢谢！

《Visual C++ 游戏开发经典案例详解》 第12章 俄罗斯方块游戏项目开发

学习了，谢谢分享

《Visual C++ 游戏开发经典案例详解》

大神在你的源码中怎样修改才能使得在运行图中显示名字

刘xx，你暴露了

我也写了一个，界面比楼主的好看一点

考虑做一个AI不？

支持一下，我一直想自己写，但还没有写过。 这次要写一下。

学习了，谢谢分享

什么情况呢

支持一下。支持一下。

我也没办法运行 在错误中修正了一下可以了 以下提供projact VS2012  http://pan.baidu.com/s/1qW9DPhy

厉害

hao de  好的

学习了，谢谢分享

好，等待2.0版升级彩色啊。 我好多年没玩了，以前DOS的年代是双手同时操作键盘玩超高速，后来手机什么的没意思，太慢

有适当的说明就好了，有助于大家的理解


Question: 项目如何寻找

感觉java的项目比较容易找，c和c++的比较难找。。

写OS　写编译器

如果要做项目的话，那就比较大了，不如做一些小的功能实现，虽然小，但也能练习基础知识，同时也比较容易完成，占用的时间比较少一些。再说了，大学里还有其他的学科需要学习。 建议：比较小的功能比如：简单的学生管理系统；字符串查找解析等等；

直接在论坛找啊，谁要做什么就帮他做，最实际最有价值的了

参与开源社区吧

搜网络教程“学OpenGL编3D游戏”。

去找一些开源项目跟，又有价值又有锻炼。

去实验室找 去找兼职，实习


Question: gcc 编译 .c 文件出错

gcc -I include/ -fno-builtin -o kernel/start.o kernel/start.c

自己装一个呗，别说不会装

引用 1 楼 hnwyllmm 的回复:limpc.so，这个链接库在我的电脑上都找不到，我用的Linux内核是3.13，gcc版本4.8.2，看楼主编译的文件名字应该是内核文件，楼主的编译器是不是不适合编译内核？我看这个链接库应该是编译器用的 我的是 gcc4.8.2   内核好像是3.10.17    我估计是linux发行版太古老 好多软件版本没更新

引用 2 楼 u013776377 的回复:[quote=引用 1 楼 hnwyllmm 的回复:] limpc.so，这个链接库在我的电脑上都找不到，我用的Linux内核是3.13，gcc版本4.8.2，看楼主编译的文件名字应该是内核文件，楼主的编译器是不是不适合编译内核？我看这个链接库应该是编译器用的 我的是 gcc4.8.2   内核好像是3.10.17    我估计是linux发行版太古老 好多软件版本没更新 [/quote] 好吧，楼主请教内核模块的人吧


Question: 用c语言可以调用音乐文件播放吗  ?

#define _UNICODE #define UNICODE #include <Windows.h> #include <tchar.h> #include <Mmsystem.h>  #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib") #pragma comment(lib, "winmm.lib")  #pragma comment(linker, "/subsystem:windows,5.1.2600")  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  BOOL WINAPI SetWindowCenter(HWND hwnd) {    UINT uFlags;    RECT stRect = { 0 };     INT x = GetSystemMetrics(SM_CXSCREEN);       INT y = GetSystemMetrics(SM_CYSCREEN);     GetWindowRect(hwnd, &stRect); // 获取窗口当前的位置     __asm    {       pushad       mov eax, stRect.right       sub eax, stRect.left     ; eax保存的是窗口的宽度       mov ebx, x       sub ebx, eax       shr ebx, 1       mov stRect.left, ebx     ; 窗口左上角x坐际 = (屏幕宽 - 窗口宽) / 2       mov eax, stRect.bottom       sub eax, stRect.top      ; eax保存的是窗口的高度       mov ebx, y       sub ebx, eax       shr ebx, 1       mov stRect.top, ebx      ; 窗口左上角y坐际 = (屏幕高 - 窗口高) / 2       popad    }     uFlags = SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW;    // 宽度和高度参数为零时则保持原样不变    return SetWindowPos(hwnd, NULL, stRect.left, stRect.top, 0, 0, uFlags); // 重新设置窗口的位置 }  int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow) {    static TCHAR szAppName[] = TEXT("HelloWin");    HWND         hwnd;    MSG          msg;    WNDCLASS     wndclass;        RtlZeroMemory(&wndclass, sizeof(wndclass));    wndclass.style         = CS_HREDRAW | CS_VREDRAW;    wndclass.lpfnWndProc   = WndProc;    //wndclass.cbClsExtra    = 0;    //wndclass.cbWndExtra    = 0;    wndclass.hInstance     = hInstance;    //wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION); //#define IDI_APPLICATION MAKEINTRESOURCE(32512)    //wndclass.hIcon         = LoadIcon(NULL, MAKEINTRESOURCE(32512));    wndclass.hIcon         = LoadIcon(NULL, TEXT("#32512"));    wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    wndclass.lpszMenuName  = NULL;    wndclass.lpszClassName = szAppName;        if (!RegisterClass(&wndclass))    {       MessageBox(NULL,                   TEXT("This program requires Windows NT series!"),                   szAppName,                  MB_ICONERROR);       return 0;    }            hwnd = CreateWindowEx(WS_EX_TOOLWINDOW,         // A tool window does not appear in the task bar or in the window that appears when the user presses ALT+TAB.                        szAppName,                  // window class name                        TEXT("The Hello Program"),  // window caption                        WS_OVERLAPPEDWINDOW,        // window style                        10,//CW_USEDEFAULT,              // initial x position                        200,//CW_USEDEFAULT,              // initial y position                        320,//CW_USEDEFAULT,              // initial x size                        320,//CW_USEDEFAULT,              // initial y size                        NULL,                       // parent window handle                        NULL,                       // window menu handle                        hInstance,                  // program instance handle                        NULL);                      // creation parameters     SetWindowCenter(hwnd);    ShowWindow(hwnd, SW_SHOW);    UpdateWindow(hwnd);          {       BOOL bRet;       while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)       {          if (bRet == -1)           {             MessageBox(NULL,                         TEXT("GetMessage Error."),                         szAppName,                        MB_ICONERROR);             return -1;           }           else           {             TranslateMessage(&msg);             DispatchMessage(&msg);           }       }    }        return msg.wParam; }  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    HDC         hdc;    PAINTSTRUCT ps;    RECT        rect;        switch (message)    {       case WM_CREATE:          PlaySound(TEXT("Hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);          return 0L;              case WM_PAINT:          hdc = BeginPaint(hwnd, &ps);                 GetClientRect(hwnd, &rect);          DrawText(hdc, TEXT("Hello, Windows 98!"), -1, &rect,                   DT_SINGLELINE | DT_CENTER | DT_VCENTER);          EndPaint(hwnd, &ps);          return 0L;              case WM_DESTROY:          PostQuitMessage(0);          return 0L;    }    return DefWindowProc(hwnd, message, wParam, lParam); }

vc6  完美调用

就是，linux下编程和windows下编程还是有不少差异的

肯定可以啊

这个是windows的API, 只能在windows下使用, 怎么能有gcc

playsound可以播放wav格式的文件。  如果要播放mp3格式的音乐文件，只能用其他api了。

搞定了  用vc6.0


Question: void *fun和  (void *)fun 的区别

一楼正解啊。

引用 1 楼 oYinGui1 的回复:后者是强制转换。前者没看太明白，如果是void *fun();那就是返回值为void *类型的函数。。  大大看看这个帖子http://bbs.csdn.net/topics/390811403


Question: 急求指教，C语言编程出错（ Cannot open include file: 'head.h': ）

head.h 是自己写的，就在头文件中指明路径，比如 #include ‘/home/desktop/……/head.h’

还是放同一目录吧

要放在同一目录下 find.c 和 head.h

吧head.h和c放一个目录下

/*head.h*/ #ifndef FIRST #include<stdlib.h> #include<stdio.h> #include<string.h> struct patient { char id[10]; char name[10]; char sex[10]; char casehist[200]; int callnum[12]; struct patient *next; }; int flag; void search(struct patient *temp); void listall(struct patient *temp); struct patient *insert(struct patient *head,struct patient *rear); void modify(struct patient *temp); struct patient *load(struct patient *head); void save(struct patient *head); #define FIRST #endif  这段另存为 head.h 文件


Question: 零基础学C语言先看哪本书好啊？

谭浩强的C语言，另外自己上网找教学视频，多敲代码才是真的

看书可以看谭浩强的，也可以看《C primer》 网上视频有小甲鱼和郝斌都讲得挺好的！

0基础学C语言还是看视频比较好

0基础就别选C语言作为入门语言了。 python、lua 》》 java 、C#

《C primer》

百度 C语言教程， 有简版的


Question: 请问windows怎么用exec()和fork(),如果不能那用什么函数可以达到同样的效果

引用 2 楼 Intel0011 的回复:推荐《Windows核心编程》这本书，里面有详细讲解 于我心有戚戚焉。

你不需要fork

推荐《Windows核心编程》这本书，里面有详细讲解

CRT有_exec。对应的API是CreateProcess。  windows没有fork对应的API。 参考Porting from UNIX to Win32


Question: 零基础学C语言先看哪本书好啊？

先下载Win-TC，然后参考C:\Win-TC\tcstudy.chm

引用 16 楼 lin5161678 的回复:[quote=引用 12 楼 u013697891 的回复:] [quote=引用 6 楼 xiaobai_dream 的回复:] 新手推荐《C Primer Plus》 谭浩强的那本书说实话，不推荐。 我就是看的谭书[/quote]那就快停下 [/quote] 完了，八个月前就看完了

引用 12 楼 u013697891 的回复:[quote=引用 6 楼 xiaobai_dream 的回复:] 新手推荐《C Primer Plus》 谭浩强的那本书说实话，不推荐。 我就是看的谭书[/quote]那就快停下

the c programming language!!

我推荐你去看 郝斌老师的 视屏， 他讲的真心不错， 如果需要可以密我：245913495

引用 6 楼 xiaobai_dream 的回复:新手推荐《C Primer Plus》 谭浩强的那本书说实话，不推荐。 我就是看的谭书

《C Primer Plus》

1.《C Primer Plus》 2.《C语言程序设计现代方法 》-->这个相当好

《C语言程序设计现代方法 》 如果穿越时光，我就给自己学这本

《C Primer Plus》

C程序设计 学校一般都用这个吧

新手推荐《C Primer Plus》 谭浩强的那本书说实话，不推荐。

c程序设计语言

这个好像不少人都问过了啊  http://www.baidu.com/baidu?word=零基础学C语言先看哪本书好&ie=utf-8

C primer plus 不错， 基本编程还是靠实践，多敲代码。

听很多老鸟说谭浩强的看多了不好


Question: 关于C语言static方法先声明后定义的问题

没人回复，坐沙发等


Question: 一个申请的国外老师出的题目，关于用C模拟排队系统的

引用 4 楼 buyong 的回复:编程实现这个公式把？能用数学库么？能用的话找找开源库，直接搞定 应该不行的吧，这玩意看起来好像信号与系统里面的东西，好像要用傅里叶展开的吧……高数忘得差不多了。

编程实现这个公式把？能用数学库么？能用的话找找开源库，直接搞定

看不到图吗，我发一下原题

说的太少了，不明白题目是干啥的？楼主的问题是什么


Question: 新手求教。谭浩强C程序语言软件下载win8

不同的计算机操作系统有不同的编译器，Unix，Linux，windows，都是不同的。  我以一个高一C新手，被谭浩强的书折磨俩月，的苦逼学生党的身份告诉lz，零基础学C看那本书，真心不明智！我估计你也是看的云里雾里。还是看看我在一楼说的那本书吧。那本书考二级证或许看看。太误导新人了。

如果零基础，看谭浩强的c程序设计，这不是明智的选择。建议lz看C Primer Plus 第五版（人民电邮出版社）谭浩强的C程序设计写的太过笼统，不适合新人看，我一开始看了一段时间，没有学到什么。他的书比较注重算法。  你从书本厚度上，就大致应该知道，哪个对C介绍的详细。


Question: 求各路高手来看看！linux下的readline问题

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

prompt初始化或改成NULL


Question: u8*指针赋值出错

问题是：指针使用前未初始化。使用malloc即可。

static void test(u8 *src)  {        u8 *tmp;        u8 buf[2];   tmp=(u8 *)buf;  *tmp= 0xFFu;//等价于buf[0]=0xFFu;  *tmp++ = 0xFDu;//等价于buf[1]=0xFDu;          tmp = src; ｝

不知道你断到哪句了，函数一开始的tmp指针没有初始化，你调用 *tmp = 0xFF 程序没挂掉算是运气的。


Question: 'b'在内存中占几个字节？

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

引用 38 楼 lin5161678 的回复:[quote=引用 37 楼 gz_qmc 的回复:] "B"在内存中占2个字节 因为""就自动化成char组类型,而且不论多少都在末尾加0  'b'等同于立即数98 在内存中所占字节和机器位数有关系 也就是说 在16位机器上, 立即数占2字节 在32位机器上, 立即数占4字节  char  x = 'b'; 是先确定了x的空间为1字节,再给他强制赋予一个数据而已 还有疑虑的你们可以在机器上试一下 char  x=1234; 1234是个立即数 但通过赋值后强制把1234的所占空间掐断了 所以 char x='b' 等价于 char x=98   在16位机器上等价于  char x=0x0062; 在32位机器上等价于  char x=0x00000062;     'b'占据多少内存 和 多少位机器 没有关系  'b'是int 而int 占据多大内存由编译器决定   别误导别人 [/quote]  实际上楼上说的不错，我记得c++没有标准说一个int占多少个字节，完全是由编译器所决定的，vc6.0一个int是两个字节，vs2010是四个字节，遇到这种问题直接在编译器中sizeof看大小就好

引用 49 楼 fefe82 的回复:[quote=引用 10 楼 lin5161678 的回复:] [quote=引用 9 楼 zxh707wk 的回复:] 这段转换规则和 'b'是什么类型毫无关系  不同类型转换为同一个类型  那么  sizeof 'b'  这里 不同类型分别指的是什么类型 谁是类型A 谁是类型B ?? [/quote]  sizeof 之后，所有这些转换都不发生。[/quote]你回复错了人

引用 54 楼 Z_R_Z_798205 的回复:'b' 是一个 int 型,"B" 是一个指针错了 "B"是一个数组 不是指针

'b' 是一个 int 型,"B" 是一个指针

引用 51 楼 u010370871 的回复:[quote=引用 38 楼 lin5161678 的回复:] [quote=引用 37 楼 gz_qmc 的回复:] 'b'等同于立即数98 在内存中所占字节和机器位数有关系 也就是说 在16位机器上, 立即数占2字节 在32位机器上, 立即数占4字节  'b'占据多少内存 和 多少位机器 没有关系  'b'是int 而int 占据多大内存由编译器决定   别误导别人 [/quote] [/quote] 我反驳的是这段话 楼上认为int 占用多少内存是由机器位数决定 实际上 如你所说 是有编译器决定的

引用 10 楼 lin5161678 的回复:[quote=引用 9 楼 zxh707wk 的回复:] 这段转换规则和 'b'是什么类型毫无关系  不同类型转换为同一个类型  那么  sizeof 'b'  这里 不同类型分别指的是什么类型 谁是类型A 谁是类型B ?? [/quote]  sizeof 之后，所有这些转换都不发生。

大小写是一样的，8个bit加颜色属性8个bit所以共16个bit，你是写驱动吗？

搞单片机的路过 37楼的说法似乎有道理 我用8位单片机  sizeof(‘b') 竟然是 1     但单片机int 型占2字节 不知道单片机是不是不一样  32位单片机  就跟你们说的一样了 手上没16位的，没得试

引用 6 楼 u013929023 的回复:你可以在编译器里用sizeof()函数看一下就行  呵呵，sizeof可不是函数哦，小朋友

引用 2 楼 taodm 的回复:C语言里，'b'占和int一样的字节，因为它就是int类型的。 C++里，占和char一样的字节，因为它是char类型的。 这是C和C++的重要区别之一。 建议换本好点的教材，这些基本知识都应该写在上面的。+1

引用 43 楼 u013470052 的回复:'b'一个。"b"两个。 别听那个乱说，老谭害人不浅。错了 'b'不是一个字节 他的数据类型是 int

'b'一个。"b"两个。 别听那个乱说，老谭害人不浅。

引用 13 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括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对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

引用 2 楼 taodm 的回复:C语言里，'b'占和int一样的字节，因为它就是int类型的。 C++里，占和char一样的字节，因为它是char类型的。 这是C和C++的重要区别之一。 建议换本好点的教材，这些基本知识都应该写在上面的。 学习了

楼主你手残吗？ sizeof("A") sizeof("a") sizeof("Z") sizeof("z") sizeof('A') sizeof('a') sizeof(L"a"); sizeof(L'a'); 你自己去实验吧，我说完你也记不住

先把测试写出来，gcc编译通过，运行结果在注释  #include <stdio.h>  int main() { 	char a = 'a'; 	printf("%d\n", sizeof(int)); //4 	printf("%d\n", sizeof(char));//1 	printf("%d\n", sizeof a);//1 	printf("%d\n", sizeof 'a');//4 	printf("%d\n", sizeof "a");//2 	return 0; }

引用 34 楼 zxcvbnm0014 的回复:[quote=引用 2 楼 taodm 的回复:] C语言里，'b'占和int一样的字节，因为它就是int类型的。 C++里，占和char一样的字节，因为它是char类型的。 这是C和C++的重要区别之一。 建议换本好点的教材，这些基本知识都应该写在上面的。 不要误导新人，int在16位系统占2字节，在32位系统占4字节。char占一个字节，字符串有个结束符标志，可以说是占2个字节。[/quote] 人家好像没有说int占多少字节吧，那么激动做什么

引用 37 楼 gz_qmc 的回复:"B"在内存中占2个字节 因为""就自动化成char组类型,而且不论多少都在末尾加0  'b'等同于立即数98 在内存中所占字节和机器位数有关系 也就是说 在16位机器上, 立即数占2字节 在32位机器上, 立即数占4字节  char  x = 'b'; 是先确定了x的空间为1字节,再给他强制赋予一个数据而已 还有疑虑的你们可以在机器上试一下 char  x=1234; 1234是个立即数 但通过赋值后强制把1234的所占空间掐断了 所以 char x='b' 等价于 char x=98   在16位机器上等价于  char x=0x0062; 在32位机器上等价于  char x=0x00000062;     'b'占据多少内存 和 多少位机器 没有关系  'b'是int 而int 占据多大内存由编译器决定   别误导别人


Question: 求大神，谭浩强的c语言第四版第一章的练习题第6题怎么做。

谢谢大家给我的回答

这种问题不应该自己想么？这题都问别人，请问还有什么问题是lz能自己想出来的呢？

方法一运行截图：  方法二运行截图：  方法三运行截图：

引用 楼主 qq_16539597 的回复:求大神，谭浩强的c语言第四版第一章的练习题第6题怎么做。 方法一： #include<stdio.h> int main() { 	int max(int x,int y,int z);/*函数声明*/ 	int a,b,c,M;/*定义三个整型变量abc和存放最大值变量M*/ 	printf("请键盘输入三个整型数据：\n"); 	scanf("%d%d%d",&a,&b,&c);/*键盘输入三个整型数据*/ 	M=max(a,b,c);/*传递a，b，c三个参数到函数max里。*/ 	printf("%d,%d,%d的最大值为：\n%d\n",a,b,c,M);/*打印出最大值*/ 	return 0; } /*自定义名称为max的函数,函数返回值类型整型，参数传递三个整型数据*/ int max(int x,int y,int z)  { 	int w,t;/*定义局部变量w，t*/ 	if(x>y)w=x;/*如果x的值大于y，就把x的值赋值给w；*/ 	else w=y;/*否则x的值小于或者等于y，就把y的值赋值给w*/ 	if(w<z)/*如果前两个数的最大值w小于z的值，那么将执行下列代码*/ 	{  		/*下列代码便于你理解，这么给你解释*/ 		t=w;/* w中的水放到空杯子t中。*/ 		w=z;/*z中的水放到空杯子w中*/ 		z=t;/*t中的水放到z杯子中。*/ 	} 	return (w);//返回三个数的最大值*/ } 方法二： 上面代码也可以这么写 #include<stdio.h> /*自定义名称为max的函数,函数返回值类型整型，参数传递三个整型数据*/ int max(int x,int y,int z)  { 	int w,t;/*定义局部变量w，t*/ 	if(x>y)w=x;/*如果x的值大于y，就把x的值赋值给w；*/ 	else w=y;/*否则x的值小于或者等于y，就把y的值赋值给w*/ 	if(w<z)/*如果前两个数的最大值w小于z的值，那么将执行下列代码*/ 	{  		/*下列代码便于你理解，这么给你解释*/ 		t=w;/* w中的水放到空杯子t中。*/ 		w=z;/*z中的水放到空杯子w中*/ 		z=t;/*t中的水放到z杯子中。*/ 	} 	return (w);//返回三个数的最大值*/ } int main() { 	int a,b,c,M;/*定义三个整型变量abc和存放最大值变量M*/ 	printf("请键盘输入三个整型数据：\n"); 	scanf("%d%d%d",&a,&b,&c);/*键盘输入三个整型数据*/ 	M=max(a,b,c);/*传递a，b，c三个参数到函数max里。*/ 	printf("%d,%d,%d的最大值为：\n%d\n",a,b,c,M);/*打印出最大值*/ 	return 0; } 方法三： #include<stdio.h> int main() { 	int a,b,c,M,t;/*定义三个整型变量abc和存放最大值变量M*/ 	printf("请键盘输入三个整型数据：\n"); 	scanf("%d%d%d",&a,&b,&c);/*键盘输入三个整型数据*/ 	if(a>b) 		M=a; 	else  		M=b; 	if(M<c) 	{ 				/*下列代码便于你理解，这么给你解释*/ 		t=M;/* m中的水放到空杯子t中。*/ 		M=c;/*z中的水放到空杯子w中*/ 		c=t;/*t中的水放到z杯子中。*/ 	} 	printf("三个数的最大值为：\n%d\n",M);/*打印出最大值*/ 	return 0; }

引用 1 楼 user-6 的回复:求最大值 a与b比较，找出大的 把大的赋给a， a再与c比较，输出大的

不好意思！回复错了

看书可以看谭浩强的，也可以看《C primer》 网上视频有小甲鱼和郝斌都讲得挺好的！

这个程序怎么写：比较a,b,c的较大者，写出过程最好了

引用 2 楼 fox_liucx 的回复:题目你都不贴出来，难道让大家去翻书找题？ 就是，而且还是直接伸手要答案  http://bbs.csdn.net/topics/390623576

题目你都不贴出来，难道让大家去翻书找题？

求最大值 a与b比较，找出大的 把大的赋给a， a再与c比较，输出大的


Question: opencv cvSaveImage保存图像问题！！急急急啊！！

你的问题在于不知道怎么使文件名可变是吧？可以这么做：   int idx=0;    char adr[128]={0};   sprintf(adr, "E:/Notemp/%d_imgNo_temp.jpg", ++idx);   cvSaveImage(adr, imgNo );  文件名为%d_imgNo_temp.jpg,%d部分会被后面idx的值填充。当然前提是要E：/Notemp/ 这个文件夹是存在的，不然会出错。

请问楼主的问题是怎么解决的？我也有类似的问题，总是报错

定义一个 char imgname[80][100]用来存储文件名,不过这应该是一个二维数组，每一行代表一个路径，然后一个指针指向这个路径，执行完之后指针自加1指向下一行，不过要把库里面的*filename类型改成非常量（就是把const去掉），希望能帮到你。

用imwrite()函数

lz问题解决了没，我遇到和你一样的问题。

目测你的.太多了。

引用 5 楼 user-7 的回复:[quote=引用 4 楼 wo252518553 的回复:] 我知道了，因为cvSaveImage不能创建不存在的文件夹。。。。。搞了一整天白忙活了。。。。 很少API会自动创建一个文件夹的。[/quote] 恰好今天看到了： MakeSureDirectoryPathExists The MakeSureDirectoryPathExists function creates all the directories in the specified DirPath, beginning with the root.  BOOL MakeSureDirectoryPathExists(   IN LPSTR DirPath   );   Parameters DirPath  Pointer to a null-terminated string that specifies a valid path name. If the final component of the path is a directory, not a filename, the string must end with a backslash (\) character.  Return Values If the function succeeds, the return value is TRUE.  If the function fails, the return value is FALSE. To retrieve extended error information, call GetLastError.  Remarks Each directory specified is created, if it does not already exist. If only some of the directories are created, the function will return FALSE.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.   Windows CE: Unsupported.   Header: Declared in imagehlp.h.   Import Library: Use imagehlp.lib.  See Also PE Image Helper (ImageHlp) Overview, ImageHlp General Functions

引用 4 楼 wo252518553 的回复:我知道了，因为cvSaveImage不能创建不存在的文件夹。。。。。搞了一整天白忙活了。。。。 很少API会自动创建一个文件夹的。

引用 1 楼 zhao4zhong1 的回复:cvSaveImage("d:\\img\\a\\result1.jpg”,img);求大神指导啊……

请问，如果我定义一个 char imgname[80]用来存储文件名，然后再用strcat（“路径A”，imgname） 最后cvSaveImage（“路径A”，Img）可以吗？  其实是这样的，这个imgname文件名是 file\img.jpg 所以strcat以后新的路径就是\.....\...\img.jpg  ，然后我再把最后的.jpg删掉就变成\.....\...\img 接下来strcat（“\.....\...\img”，“\imgggggg.jpg”） 这样我想要的路径基本就是\.....\...\img\imgggggg.jpg  最后用cvSaveImage（“\.....\...\img\imgggggg.jpg”，img） 这么做对吗？可是总是存不上呢？？？而且我想生成的img文件夹也没有生成，什么变化都没有，这是怎么回事？求指导！！


Question: SWU 求助

long int ftell ( FILE * stream ); Get current position in stream Returns the current value of the position indicator of the stream.  For binary streams, this is the number of bytes from the beginning of the file.  For text streams, the numerical value may not be meaningful but can still be used to restore the position to the same position later using fseek (if there are characters put back using ungetc still pending of being read, the behavior is undefined).

楼上说得不错。 不过我觉得没机会判断文件头吧？主要的问题还是文件尾。

文件尾是 feof 可以判断 文件头可以试着用 ftell 看返回值是否为0


Question: win32 C RegisterClass失败

WNDCLASS wndcls;改成 WNDCLASS wndcls = {}; 不然你那样的代码，这wndcls里面好几个成员都是无效值。。。

引用 1 楼 M173475237 的回复:问题解决了...WNDCLASS赋值有问题 40分,,,免费送出去

问题解决了...WNDCLASS赋值有问题


Question: 题挺难，求助各位大神

引用 5 楼 zhao4zhong1 的回复:两个或多个弹孔不完全重叠呢？ http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1430276010019_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E9%9F%A6%E6%81%A9%E5%9B%BE

参考步骤写的提示还不错，就按照指示搜索查阅资料解决

这个题连个模型都没有，怎么写程序，感觉像是论述题

你好，我想问一下这个问题得到解决了吗，我也想解决这个问题，急求啊！

如果两个弹孔重叠了，怎么算？呵呵......

C语言可以调用函数，MATLAP不让。。求各位大神给点力

。。。。。图片就是那两个图片。。。

跪求个程序，我们老师不让我们调用函数，跪求啊。

这道题快折磨死小弟了。求救啊。。。

不要这么说啊。

我觉得出题的老师有点脑残。

说实话你们说的大多数小弟都不懂。。。

各位不好意思啊。下午上课了，只需要看B图，B图的单孔已经标注出来了啊

参考步骤都出来了，就这么干吧，步骤1和步骤3可以确定弹孔位置，这个确定算法是重点，只要这个确定了，剩下的就都不是问题了。 （3）	检测出每个弹孔的圆心，作为鉴别打靶的环数，可采用质心算法 （1）	检测出b图中所有弹孔的位置，可采用背景建模的方法，或者霍夫变换。

lz这是要被调戏了的节奏

两个或多个弹孔不完全重叠呢？

（1） 直接相减吧，b-a，然后二值化 （2） 参照opencv的cvFindContours()，或者MATLAB的bwlabel() （3） 每个弹孔区域用质心法...（搜一下公式） （4） hough变换（参照opencv 的cvHoughCircles）可以得到一系列同心圆，各质心到圆心的距离... （5） ......  如果是要求所有的算法自己实现，那你确实需要花点时间，如果可用现成的，那应该很好做

引用 1 楼 91program 的回复:如果两个弹孔重叠了，怎么算？呵呵......算脱靶啊

引用 1 楼 91program 的回复:如果两个弹孔重叠了，怎么算？呵呵...... 说到重点了！


Question: 二分法算法时间复杂度分析

自己顶...................

感谢！结贴!!

T(N) =O(f(N)) 的精确表示是 对于任意大的N，N是自然数。。。。           任意大的意思是，如果有机若干N不满足，并且此后所有都满足，忽略这些不满足的 有 T(N) <= c * f(N)  c是个常数 在这里用 T(N)=O(f(N))，表示分析的结果是忽略 c 的

注意这里是算法分析，不是实际计算 算法分析，考虑的情况比实际计算（执行）复杂，不可能完全精确计数。 你这里一个具体的数据，把问题简单化，片面化了，所以不具有代表性。  如果这得需要精确检测，你需要所有合乎要求的数据都拿来测试，一一检测 此外，注意算法分析，不是精确计数。。它分析的是数量级。 一般来说,算法分析的结果多半是这样的： T(N) =O(f(N))  基本上是以下几种数据中的一个，有时候也会用O(n^(1/3)),O(n^(4/3)) 这样的 表示。  O(1)<O(log(n))<O(log*(n))<n<O (nlog(n))<O(n^2)<O(n^k) ; k>2

这是考虑算法，还是实际统计，算法复杂度，本来就不可能绝对准确， 只是按照某种方式估计的大概复杂度 你的常数和例子中的并不一致，注意at most log(n - 1) + 2. at most 至多，就是说不会超过，你这里是 High - Low: 8   High - Low: 3 High - Low: 0 High - Low: -1 共4步 4  < log2(8)+2 =3+2 =5  满足 4<=5 的要求，所以这个思路没有错误

自己定!!!!!!!!!!!!!!!!!!!

引用 2 楼 user-1 的回复:64, 32, 16, 8, 4, 2, 1, 0, -1            7，6， 5， 4， 3， 2，1 红色部分就是+2          int result = binarySear(a, 0, 9); 	System.out.print("binarySear() result: "+result);  	public static int binarySear(int[] A, int X, int N){ 		int Low, Mid, High; 		Low = Mid = 0; 		High = N-1; 		while (Low <= High) { 			System.out.print("High - Low: "+(High - Low)); 			System.out.print("\n"); 			Mid = (Low + High)/2; 			if(A[Mid] < X) 				Low = Mid + 1; 			else if (A[Mid] > X)  				High = Mid - 1; 			else  				return Mid; 			 		} 		System.out.print("High - Low: "+(High - Low)); 		System.out.print("\n"); 		return -1; 	}   输出结果:  High - Low: 8 High - Low: 3 High - Low: 0 High - Low: -1 binarySear() result: -1   根据算法在计算器上的计算结果:  >>> math.log2(8)+2 5.0   这样测试来看的话，Log(n-1)+2是不准的


Question: 如何判断算法所消耗的时间。

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  VC6企业版：   Run the Profiler from the Development Environment Home |  Overview |  Details  Feature Only in Professional and Enterprise Editions   Profiling is supported only in Visual C++ Professional and Enterprise Editions. For more information, see Visual C++ Editions.  The development environment will profile the active project’s target. To profile more than one project, you should use custom batch files; see Profiling Multiple .DLL and .EXE Files for more information.  See Select Code to Profile for information on how to specify which code shall be profiled.  To run the profiler from the development environment  On the Build menu, choose Profile to display the Profile dialog box, as shown in the figure below.  In the Profile Type box, click one of the following option buttons:  Function Timing   Function Coverage   Line Coverage   Merge   Use Custom and the Custom Settings text box to run a batch file that contains profiler commands. See Run the Profiler from the Command Line for information on why you might want to batch and execute your own profiler commands. See Running a Custom Batch File for more information on specifying a batch file from the development environment.   Advanced settings is where you can specify PREP Phase I options.  Click OK.  Profile Dialog Box    Note   If you haven’t built your current project with profiling enabled, an error message lets you know that you need to rebuild your project. See Enable Profiling for more information.

1. 算法复杂度分析: big O 2. 操作系统API，查看进程所花费的用户时间，系统时间等， linux time 就可以了。 3 自己计时，误差太大（跟运行环境有关）

运行前取个time值，运行完成后再取一个值，两者时间差不就是了么?


Question: 求助，为什么同样的代码在code blocks里面会有ERROR， vc却下正常

谢谢各位了，那本书不错，打算好好看看。

你可以先看这本书，有什么不明白的再找别的书看

引用 13 楼 zhao4zhong1 的回复:[quote=引用 12 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 11 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c  [/quote]  谢谢赵4老师 我想请教一下您，我想了解一个程序是怎么运行起来的，就是怎么从代码到exe文件的。 我现在还是搞不清出动态链接和静态链接。 请问有没有什么书讲这方面知识讲的很透彻的，我想去看看。 [/quote] 《程序员的自我修养——链接、装载与库》[/quote]  还有一个问题，就是我包含了stdio.h但是头文件里面并没有printf的实现，只用printf的声明 那我我编译运行这段代码的时候，printf的实现是从哪里来的？我并没有把printf.c这个文件和我编译的那个文件放在同一个文件夹中啊[/quote] 看了《程序员的自我修养——链接、装载与库》这本书你就会明白了。[/quote]  赵老师，看这本书需不需要别的什么基础知识啊？比如编译原理什么的。 如果需要能给我说说吗？？

itoa不是标准的C函数啊， 建议不要用。

摒弃itoa,atoi 使用sprintf,sscanf

摒弃itoa,aoti 使用sprintf,sscanf

引用 1 楼 user-6 的回复:itoa是广泛应用的非标准C语言扩展函数。由于它不是标准C语言函数，所以不能在所有的编译器中使用。但是，大多数的编译器（如Windows上的）通常在<stdlib.h>头文件中包含这个函数。 vc和codeblocks使用的编译器不同。  确实是编译器设置问题- =,已经弄好了，thx

code blocks可以设置使用哪种编译器的吧，楼主用的可能是gcc，到设置里面把编译器改成MSVC之类的实试试。

VC6太古老了吧。。。有些东西cb不能过，vc6.0可以过，那就是vc6.0的问题了。

引用 12 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c  [/quote]  谢谢赵4老师 我想请教一下您，我想了解一个程序是怎么运行起来的，就是怎么从代码到exe文件的。 我现在还是搞不清出动态链接和静态链接。 请问有没有什么书讲这方面知识讲的很透彻的，我想去看看。 [/quote] 《程序员的自我修养——链接、装载与库》[/quote]  还有一个问题，就是我包含了stdio.h但是头文件里面并没有printf的实现，只用printf的声明 那我我编译运行这段代码的时候，printf的实现是从哪里来的？我并没有把printf.c这个文件和我编译的那个文件放在同一个文件夹中啊[/quote] 看了《程序员的自我修养——链接、装载与库》这本书你就会明白了。

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c  [/quote]  谢谢赵4老师 我想请教一下您，我想了解一个程序是怎么运行起来的，就是怎么从代码到exe文件的。 我现在还是搞不清出动态链接和静态链接。 请问有没有什么书讲这方面知识讲的很透彻的，我想去看看。 [/quote] 《程序员的自我修养——链接、装载与库》[/quote]  还有一个问题，就是我包含了stdio.h但是头文件里面并没有printf的实现，只用printf的声明 那我我编译运行这段代码的时候，printf的实现是从哪里来的？我并没有把printf.c这个文件和我编译的那个文件放在同一个文件夹中啊

引用 10 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c  [/quote]  谢谢赵4老师 我想请教一下您，我想了解一个程序是怎么运行起来的，就是怎么从代码到exe文件的。 我现在还是搞不清出动态链接和静态链接。 请问有没有什么书讲这方面知识讲的很透彻的，我想去看看。 [/quote] 《程序员的自我修养——链接、装载与库》

引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 Zzy_ZhangZeyu_ 的回复:] [quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c  [/quote]  谢谢赵4老师 我想请教一下您，我想了解一个程序是怎么运行起来的，就是怎么从代码到exe文件的。 我现在还是搞不清出动态链接和静态链接。 请问有没有什么书讲这方面知识讲的很透彻的，我想去看看。

引用 8 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 7 楼 mymtom 的回复:] itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习 [/quote] C:\Program Files\Borland\CBuilder6\Source\Rtl\Source\io\printf.c C:\Microsoft SDK\src\crt\printf.c C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\src\crt\printf.c C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\PRINTF.C C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c

引用 7 楼 mymtom 的回复:itoa不是标准的C函数啊， 建议不要用。  请问我在哪里能找到c库函数的实现源码？？ 我想看看学习学习


Question: 我写了一c primer plus 第九章的一个旅馆收费系统的函数，编译时错误为：未定义函数pow(),请帮我看看

Ubuntu系统上怎么运行这个

我没有在/lib/下找到libm.a文件，怎么安装

难道数学库丢了？ 楼主看看/usr/lib/libm.a这个文件在吗? 如果有这个文件，那很可能是链接路径的设置有问题

我gcc版本4.8.2.我按你说的编译了，还是不行。

楼主，gcc命令行里不要加头文件，应该是 gcc hotel.c hotel_fun.c 或者gcc -lm hotel.c hotel_fun.c 把hotel.h去掉

奇怪，我刚在cygwin和ubuntu上都试了，都可以直接编译链接成功，不用-lm 可我明明记得以前需要加-lm的呀 难道是最近的gcc都自动链接数学库了？ 楼主的gcc什么版本？我的是4.8.2和4.6.3

gcc -lm hotel.c ......


Question: DLL 函数

串口通讯可以直接发命令码。。。

引用 楼主 wangmin_0522 的回复:在学习关于射频卡的读写操作。我这里有个厂家给的函数说明，看不懂，求解： void Wake_Up(unsigned char * PassWord) 功能      ： 唤醒休眠的卡片；  参数      ：*PassWORD  ： 四个字节的卡片数码；  命令码    ： 　　　　AA BB , len1 len2 , 00 00 , 03 20 , Pw1 Pw2 Pw3 Pw4 ,xor  　　　　Sample ：aa bb , 09 00 ,00 00 ,03 20 , 77 77 77 77 , 23 Respond : aa bb len1 len2 , 00 00 , 01 20 , Status ,xor (请参考返回数据格式  这个参数不是很理解。 还有命令码。有知道的 可以教下吗？  说的不够清楚,可以直接找厂家咨询下

这类设备一般是用某种通信控制的，所谓通信，就是两边互发纯数据，根据数据的内容和格式来判断对方想干什么 从楼主给的例子中可以看出，【唤醒休眠的卡片】这个功能，需要电脑给读卡器发送“AA BB , len1 len2 , 00 00 , 03 20 , Pw1 Pw2 Pw3 Pw4 ,xor ”这么一串数据 结合Sample来看，前两个字节是0xAA和0xBB,第三第四个字节是后续数据的字节数，低位在前高位在后，第五第六个字节都是0，第七到第十个字节是密码（pw即password），第十一个字节是前面一部分字节的按位异或结果用来校验是否有数据错误 Wake_Up这个函数从函数说明来看，需要你输入一个指针，指针指向四个字节的密码，函数的功能就是直接把输入的这四个字节复制到上面这一串数据中然后把整串发送出去 如果只是单纯用厂家提供的控制函数，可以不必关心命令码的内容，但如果你想要理解设备具体是怎么工作的，甚至不用厂家提供的DLL自己开发一个控制模块，就需要你了解它的通信方式和通信协议，所谓通信协议，就是两边互发的那一串一串数据中每一个字节都用来代表什么意义


Question: 求助，新手求助，哪位大神可以帮我写一下这个程序，用c语言

引用 1 楼 qq_16514969 的回复:急急急！，求助啊 你急也没用啊 作业这种东西得靠自己啊 这会你得培养成一个习惯，就是想要得到必须付出。别人跟你又不熟，凭什么无缘无故帮你写作业？只因为你急？

急急急！，求助啊


Question: 关于 win32 api CreateProcess 的使用

CreateProcess The CreateProcess function creates a new process and its primary thread. The new process executes the specified executable file.   BOOL CreateProcess(   LPCTSTR lpApplicationName,                          // pointer to name of executable module   LPTSTR lpCommandLine,  // pointer to command line string   LPSECURITY_ATTRIBUTES lpProcessAttributes,  // process security attributes   LPSECURITY_ATTRIBUTES lpThreadAttributes,   // thread security attributes   BOOL bInheritHandles,  // handle inheritance flag   DWORD dwCreationFlags, // creation flags   LPVOID lpEnvironment,  // pointer to new environment block   LPCTSTR lpCurrentDirectory,   // pointer to current directory name   LPSTARTUPINFO lpStartupInfo,  // pointer to STARTUPINFO   LPPROCESS_INFORMATION lpProcessInformation  // pointer to PROCESS_INFORMATION );   Parameters lpApplicationName  Pointer to a null-terminated string that specifies the module to execute.  The string can specify the full path and filename of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification.   The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string. If you are using a long filename that contains a space, use quoted strings to indicate where the filename ends and the arguments begin, otherwise, the filename is ambiguous. For example, consider the string "c:\program files\sub dir\program name". This string can be interpreted in a number of ways. The system tries the possibilities in the following order:   c:\program.exe files\sub dir\program name c:\program files\sub.exe dir\program name c:\program files\sub dir\program.exe name c:\program files\sub dir\program name.exe   The specified module can be a Win32-based application. It can be some other type of module (for example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer.   lpCommandLine  Pointer to a null-terminated string that specifies the command line to execute. The system adds a null character to the command line, trimming the string if necessary, to indicate which file was actually used.  The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.   If both lpApplicationName and lpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can use GetCommandLine to retrieve the entire command line. C runtime processes can use the argc and argv arguments.   If lpApplicationName is NULL, the first white space-delimited token of the command line specifies the module name. If you are using a long filename that contains a space, use quoted strings to indicate where the filename ends and the arguments begin (see the explanation for the lpApplicationName parameter). If the filename does not contain an extension, .EXE is assumed. If the filename ends in a period (.) with no extension, or the filename contains a path, .EXE is not appended. If the filename does not contain a directory path, the system searches for the executable file in the following sequence:   The directory from which the application loaded.  The current directory for the parent process.  Windows 95 and Windows 98: The Windows system directory. Use theGetSystemDirectory function to get the path of this directory. Windows NT: The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is SYSTEM32.   Windows NT: The 16-bit Windows system directory. There is no Win32 function that obtains the path of this directory, but it is searched. The name of this directory is SYSTEM.  The Windows directory. Use theGetWindowsDirectory function to get the path of this directory.  The directories that are listed in the PATH environment variable.  If the process to be created is an MS-DOS - based or 16-bit Windows-based application, lpCommandLine should be a full command line in which the first element is the application name. Because this also works well for Win32-based applications, it is the most robust way to set lpCommandLine.    lpEnvironment  Pointer to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.  An environment block consists of a null-terminated block of null-terminated strings. Each string is in the form:   name=value    Because the equal sign is used as a separator, it must not be used in the name of an environment variable.   If an application provides an environment block, rather than passing NULL for this parameter, the current directory information of the system drives is not automatically propagated to the new process. For a discussion of this situation and how to handle it, see the following Remarks section.   An environment block can contain Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains Unicode characters, the dwCreationFlags field's CREATE_UNICODE_ENVIRONMENT flag will be set. If the block contains ANSI characters, that flag will be clear.   Note that an ANSI environment block is terminated by two zero bytes: one for the last string, one more to terminate the block. A Unicode environment block is terminated by four zero bytes: two for the last string, two more to terminate the block.   lpCurrentDirectory  Pointer to a null-terminated string that specifies the current drive and directory for the child process. The string must be a full path and filename that includes a drive letter. If this parameter is NULL, the new process is created with the same current drive and directory as the calling process. This option is provided primarily for shells that need to start an application and specify its initial drive and working directory.  lpStartupInfo  Pointer to a STARTUPINFO structure that specifies how the main window for the new process should appear.  lpProcessInformation  Pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.  Return Values If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError.   Remarks The CreateProcess function is used to run a new program. The WinExec and LoadModule functions are still available, but they are implemented as calls to CreateProcess.   The process is assigned a 32-bit process identifier. The identifier is valid until the process terminates. It can be used to identify the process, or specified in the OpenProcess function to open a handle to the process. The initial thread in the process is also assigned a 32-bit thread identifier. The identifier is valid until the thread terminates and can be used to uniquely identify the thread within the system. These identifiers are returned in the PROCESS_INFORMATION structure.   When specifying an application name in the lpApplicationName or lpCommandLine strings, it doesn't matter whether the application name includes the filename extension, with one exception: an MS-DOS – based or Windows-based application whose filename extension is .COM must include the .COM extension.   The calling thread can use the WaitForInputIdle function to wait until the new process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronization between parent and child processes, because CreateProcess returns without waiting for the new process to finish its initialization. For example, the creating process would use WaitForInputIdle before trying to find a window associated with the new process.   The preferred way to shut down a process is by using the ExitProcess function, because this function notifies all dynamic-link libraries (DLLs) attached to the process of the approaching termination. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread calls ExitProcess, other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs).   ExitProcess, ExitThread, CreateThread, CreateRemoteThread, and a process that is starting (as the result of a call by CreateProcess) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means the following restrictions hold:   During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.  Only one thread in a process can be in a DLL initialization or detach routine at a time.  The ExitProcess function does not return until no threads are in their DLL initialization or detach routines.  The created process remains in the system until all threads within the process have terminated and all handles to the process and any of its threads have been closed through calls to CloseHandle. The handles for both the process and the main thread must be closed through calls to CloseHandle. If these handles are not needed, it is best to close them immediately after the process is created.   When the last thread in a process terminates, the following events occur:   The current directory specified by the lpcurrentDirectory parameter is the current directory for the child process. The current directory specified in item 2 under the lpCommandLine parameter is the current directory for the parent process.

引用 3 楼 wang0635 的回复:char ExeName[] = {"C:\\MySQL\\MySQL Server 5.1\\bin"}, 可执行文件名呢？   那是后改过的，加上执行文件名一样不行

引用 1 楼 zhao4zhong1 的回复:你注释掉的system行不行，如果行，将system的内容写到一个临时批处理文件比如tmp.bat中，然后 WinExec("cmd.exe /c tmp.bat",SW_HIDE); remove("tmp.bat"); 我注释掉的那段可以，但是我想用 CreateProcess ，因为 CreateProcess 灵活性高一些


Question: 想写个贪吃蛇

怎么老是弹出垃圾网页？我们域名被盗了吗？

我主要想知道图形界面怎么实现，我用的codeblocks

引用 8 楼 wenbo228228 的回复:我主要想知道图形界面怎么实现，我用的codeblocks  http://www.oschina.net/code/snippet_945741_20644

楼主可以参考这个帖子里的代码，不过是linux里的，也是用C语言写的。 http://bbs.csdn.net/topics/350080780

我直接在dos窗口用字符输出的。。。 代码仅供参考哦（使用多线程） main.c #define WIN32_LEAN_AND_MEAN  #include <stdio.h> #include <stdlib.h> #include <windows.h> #include "snake.h"  int main() {     HANDLE hThrd;     DWORD threadId;     flage=4;     time_interval=10;     hThrd=CreateThread(NULL,0,snake,(LPVOID)0,0,&threadId);     for(;;)     {         switch(getch())         {         case 224:             switch(getch())             {             case 72:                 if(flage!=2&&flage>0)                 {                     flage=1;                 }                 break;             case 80:                 if(flage!=1&&flage>0)                 {                     flage=2;                 }                 break;             case 75:                 if(flage!=4&&flage>0)                 {                     flage=3;                 }                 break;             case 77:                 if(flage!=3&&flage>0)                 {                     flage=4;                 }                 break;             }             break;         case 32:             flage=-flage;             break;         case 'w':             if(time_interval<200)             {                 time_interval=time_interval+1;             }             break;         case 'e':             if(time_interval>1)             {                 time_interval=time_interval-1;             }             break;         }         Sleep(100);     }     getchar();     return 0; }   snake.c //#define WIN32_LEAN_AND_MEAN #define HEIGHT 20 #define WIDE 76 #define ICO "*"  int flage; int time_interval;  struct node {     int x;     int y;     struct node* next; };  void getpos(HANDLE hOut,COORD *pos) {     CONSOLE_SCREEN_BUFFER_INFO info;     GetConsoleScreenBufferInfo( hOut , &info );     *pos = info.dwCursorPosition; } void gotopos(HANDLE hOut,COORD pos) {     SetConsoleCursorPosition(hOut, pos); }  void put_logo() {     int i;     for(i=0; i<8; i++)     {         printf("\n");     }     for(i=0; i<35; i++)     {         printf(" ");     }     printf("snake");     Sleep(2000);     system("cls"); }  void start_map() {     int i;     int j;     for(i=0; i<HEIGHT+3; i++)     {         for(j=0; j<WIDE+3; j++)         {             if(i==0||i==HEIGHT+2)             {                 printf("=");             }             else if(j==0||j==WIDE+2)             {                 printf("|");             }             else             {                 printf(" ");             }         }         printf("\n");     } }  struct node* clear_last(HANDLE hOut,COORD pos,struct node* p,int x,int y) {     pos.X = p->x;     pos.Y = p->y;     gotopos(hOut,pos);     printf(" ");     p->x=x;     p->y=y;     return p->next; }  int check_ways(struct node* q,int x,int y,int len) {     int i;     if(x<1||x>WIDE+1)     {         return 1;     }     if(y<1||y>HEIGHT+1)     {         return 1;     }     for(i=0; i<len; i++)     {         if(q->x==x&&q->y==y)         {             return 1;         }         q=q->next;     }     return 0; }  DWORD WINAPI  snake() {     struct node snakes;     struct node* head;     struct node* p;     struct node* q;     HANDLE hOut;     COORD pos;     int i;     int len;     len=10;     snakes.x=1;     snakes.y=1;     snakes.next=NULL;     pos.X=snakes.x;     pos.Y=snakes.y;     start_map();     hOut = GetStdHandle(STD_OUTPUT_HANDLE);     gotopos(hOut,pos);     head=p=q=malloc(sizeof(struct node));     p->x=snakes.x++;     p->y=snakes.y;     printf(ICO);     p->next=q;     for(i=0; i<len-1; i++)     {         q=p;         p=malloc(sizeof(struct node));         p->x=snakes.x++;         p->y=snakes.y;         printf(ICO);         p->next=head;         q->next=p;     }     printf(ICO);     snakes.x=snakes.x-1;     p=head;     for(;; Sleep(time_interval*50))     {         switch(flage)         {         case 1:             snakes.y--;             break;         case 2:             snakes.y++;             break;         case 3:             snakes.x--;             break;         case 4:             snakes.x++;             break;         default :             goto _NEXT;             break;         }         if(check_ways(head,snakes.x,snakes.y,len))         {             goto _END;         }         p=clear_last(hOut,pos,p,snakes.x,snakes.y);         pos.X=snakes.x;         pos.Y=snakes.y;         gotopos(hOut,pos);         printf(ICO);         printf("\b"); _NEXT:         ;     } _END:     ;     pos.X=25;     pos.Y=10;     gotopos(hOut,pos);     printf("game over!you have %d long snakes\b",len); }   snake.h #include "snake.c"  void put_logo(); void getpos(HANDLE hOut,COORD *pos); void gotopos(HANDLE hOut,COORD pos); DWORD WINAPI  snake();

就c的话，turbo c其实是有图形界面的，只不过你不知道而已，而且很简单。 再者，你可以用win32开发，不需要用mfc,win32贪吃蛇 可以参考着个(随便找的。)http://download.csdn.net/detail/qq752923276/4562794

在百度搜“VC 贪吃蛇”

这个不太难只要知道相关的函数，比如随机，比如光标。。。。。

C游戏编程从入门到精通   这本书不知道讲的什么 可以看下是否适合    看windows编程   一般都是这个

自己搜一个源码，然后调试学系


Question: 文件操作 fwrite

引用 6 楼 wenbo228228 的回复:[quote=引用 1 楼 Automation_dmu 的回复:] "w"(只写) 为输出打开一个文本文件 Student的头4个字节是一个int， 小端机器的内存就是 0x17 0x00 0x00 0x00,  显然作为文本，这些是乱码。 那怎么做才不出现乱码？ [/quote]这个不是乱码，windows的记事本会将二进制数据按字符显示，你可以将这个int转化为字符串，然后再存储

怎么最近老是弹出垃圾网页？管理员管一下诶！

引用 1 楼 Automation_dmu 的回复:"w"(只写) 为输出打开一个文本文件 Student的头4个字节是一个int， 小端机器的内存就是 0x17 0x00 0x00 0x00,  显然作为文本，这些是乱码。 那怎么做才不出现乱码？

我仅仅是想知道怎么做才可以把数据写入目标文件，而不是在文件中出现乱码，其他深层次的原因不深究了，实在没有这个精力

我觉得这个设计的内容挺广泛的，楼主过度深究这个问题只是想弄明白其中的道理吗，我觉有些道理还是不要太明白的好

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

你可以使用UltraEdit等工具查看文本的16进制数据，应该就明白了


Question: 一道 static 的题

C语言中static的作用 http://blog.csdn.net/xuzhouweihao/article/details/27534779  static的作用，讲的很透彻。

引用 4 楼 pengxn 的回复:还是运算的顺序问题 ，  return(fact( )*(i+1));  return((i+1)*fact( )); 楼上正解，这个跟乘号操作符的左右操作数的计算顺序有关，标准并未规定乘号操作符左右操作数的计算顺序，编译器可以先计算左操作数，也可以先计算右操作数，程序中最好不要依赖这种编译器自定义行为。 乘号表达式只有一个序列点，在同一个序列点中多次写变量或者既写变量又读变量的值会导致未定义行为。 你的这个式子中先计算fact()这个操作数，然后一直计算到当i为0的时候开始回归，此时最里层fact()返回1，而（i+1)也是1，得到上一层的fact()为1；此时因为i是静态变量，回归的时候值仍旧为1，因此最后结果为1 如果修改成（i+1)*fact()可以得到想要的结果，因为先计算的是（i+1),但是最好不要依赖这种编译器特定行为。求阶乘的递归算法参考3楼。

递归有两个阶段，一个是递推阶段，一个是回归阶段。 递推阶段很好理解，就是在fact中再次使用fact，一直到终止条件。 回归阶段呢，就是从终止的函数开始，一层一层地回归，直到回到你主函数调用的那一层。 问题就在于你使用了函数内部的静态变量，当你递推到i为0，嗯，这时计算机知道递推到顶了，要开始回归，即求解。这时，i为0，回归又不会使他增加，那么每一层回归都执行了if(i==0)的语句，每一层都返回1，直到最后得到1的函数结果输出。 如果你要达成阶乘的递归函数目的，就应该把每一层的标志换为函数参数：#include "stdio.h"  int fact(int n) { 	if (n == 0) return 1; 	else 		return(fact(n - 1)*n); } int main() { 	printf("%d\n", fact(5)); 	return 0; }

引用 楼主 u013985488 的回复:#include "stdio.h"  int fact( )  {  	static int i=5;  	if(i==0) return 1;      else  	{ 	i--; 	return(fact( )*(i+1));  	}  }  int main( )  {  	printf("%d\n",fact());      return 0; }   输出是1，我不理解了  搞清楚static关键字就知道为啥了

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