Question: Windows编程初学者问题

刚才没显示图，现在看见了，应该这么写：   hwnd = CreateWindow(      TEXT("myexe"),//窗口类名       TEXT("俺的窗口"),       WS_OVERLAPPEDWINDOW,         0,0,600,400,       NULL,NULL,hInstance,NULL);      ShowWindow(hwnd,nShowCmd);      UpdateWindow(hwnd);

引用 6 楼 riderinfo119705 的回复:我点击continue一直出现。break就返回了，编译没有问题啊！  点continue一直出现？啥意思？你是不是在while循环那里打了断点(F9)？或者在myProc打了断点？要是这两个地方有断点，continue是点不完的，因为消息一直有。

引用 5 楼 go_and_see 的回复:[quote=引用 3 楼 riderinfo119705 的回复:] [quote=引用 2 楼 go_and_see 的回复:] 窗口类不能为空，窗口过程也没有，能不失败嘛。 新手，请说大白话，听不懂。就告诉我怎么修改吧！做我师父吧：qq614211648[/quote]  windows窗口程序一般步骤如下： 1、指定窗口样式、指定窗口过程等信息，然后注册窗口类(RegisterClass)。 2、创建窗口。 3、消息循环(while循环)。  少了这三步任意一步，窗口程序就无法正确运行。 你点文件->新建项目->visual c++ -> win32->win32项目，选择目录，对比一下向导生成的代码和你的代码有啥区别就理解了。QQ就不加了，公司不能上QQ。[/quote] 大师，我这会编译通过了，但是程序有问题，注册成功了在showwindow和updatewindow和while那里出了问题看不懂代码如下：#include <Windows.h> LRESULT CALLBACK MyProc( 							HWND hwnd,      // handle to window 							UINT uMsg,      // message identifier 							WPARAM wParam,  // first message parameter 							LPARAM lParam   // second message parameter 							); int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ){ MSG msg; WNDCLASS wndclass; HWND hwnd; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);   wndclass.hCursor=LoadCursor(NULL,IDI_HAND); wndclass.hIcon=LoadIcon(NULL,IDC_APPSTARTING); wndclass.hInstance=hInstance; wndclass.lpfnWndProc=MyProc; wndclass.lpszClassName=TEXT("myexe"); wndclass.lpszMenuName=NULL; wndclass.style=CS_HREDRAW | CS_VREDRAW; if (!RegisterClass(&wndclass)) { 	MessageBox(NULL,TEXT("ERROR!"),TEXT("title"),MB_OK | MB_ICONERROR); 	return 0; }  else { 	MessageBox(NULL,TEXT("ok!"),TEXT("title"),MB_OK | MB_ICONWARNING); } CreateWindow( 			 TEXT("myexe"),//窗口类名 			 TEXT("俺的窗口"), 			 WS_OVERLAPPEDWINDOW,   			 0,0,600,400, 			 NULL,NULL,hInstance,NULL); ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); while (GetMessage(&msg,hwnd,0,0)) { 	TranslateMessage(&msg); 	DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK MyProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){ 	switch(message)   	{   	case WM_DESTROY:   		PostQuitMessage(0);   		return 0;   	}   	return DefWindowProc(hwnd,message,wParam,lParam);    }       之后就出现了这个情况:                               我点击continue一直出现。break就返回了，编译没有问题啊！

引用 3 楼 riderinfo119705 的回复:[quote=引用 2 楼 go_and_see 的回复:] 窗口类不能为空，窗口过程也没有，能不失败嘛。 新手，请说大白话，听不懂。就告诉我怎么修改吧！做我师父吧：qq614211648[/quote]  windows窗口程序一般步骤如下： 1、指定窗口样式、指定窗口过程等信息，然后注册窗口类(RegisterClass)。 2、创建窗口。 3、消息循环(while循环)。  少了这三步任意一步，窗口程序就无法正确运行。 你点文件->新建项目->visual c++ -> win32->win32项目，选择目录，对比一下向导生成的代码和你的代码有啥区别就理解了。QQ就不加了，公司不能上QQ。

引用 楼主 riderinfo119705 的回复:#include <Windows.h> int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ){ WNDCLASS wndclass; MSG msg; HWND hwnd; wndclass.style=CS_HREDRAW|CS_VREDRAW; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndclass.hCursor=IDI_APPLICATION; wndclass.hIcon=IDC_APPSTARTING; wndclass.hInstance=hInstance; wndclass.lpszClassName=NULL; wndclass.lpszMenuName=NULL; if(!RegisterClass(&wndclass)){  	MessageBox(NULL,TEXT("窗口注册失败!"),TEXT("错误"), MB_OK | MB_ICONERROR ) ; 	return 0; }else{ MessageBox(NULL,TEXT("窗口注册成功!"),TEXT("提示"), MB_OK | MB_ICONWARNING);  } CreateWindow(TEXT("mywindow"),TEXT("俺的窗口"), 			  			 WS_OVERLAPPEDWINDOW,       //窗口的风格 			 CW_USEDEFAULT,             //窗口初始显示位置x:使用缺省值 			 CW_USEDEFAULT,             //窗口初始显示位置y:使用缺省值 			 CW_USEDEFAULT,             //窗口的宽度:使用缺省值 			 CW_USEDEFAULT,             //窗口的高度:使用缺省值 			 NULL,                      //父窗口:无 			 NULL,                      //子菜单:无 			 hInstance,                 //该窗口应用程序的实例句柄  			 NULL                       //  			 ); ShowWindow(hwnd,SW_SHOWDEFAULT); UpdateWindow(hwnd); return  0; }为什么总是注册失败，我不写windowproc是我不会一写就出错复制别人的也出错。和不写windowproc有关系吗? 我不懂俄

引用 2 楼 go_and_see 的回复:窗口类不能为空，窗口过程也没有，能不失败嘛。 新手，请说大白话，听不懂。就告诉我怎么修改吧！做我师父吧：qq614211648

窗口类不能为空，窗口过程也没有，能不失败嘛。

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


Question: （新手提问）C语言

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

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

我把你的代码复制运行了下。。。。vc6 环境下的。。。没有报错。。

自己单步调试，很容易就能发现哪里挂了，多半是访问了非法地址


Question: C语言，十佳讲师

样例输出 1 2 3 4


Question: 写字符串数组进入文件中

#include <stdio.h> #include <stdlib.h>  int main() {   FILE *outfile;   char string[256];    outfile=fopen("text.dat","w");   if(outfile==NULL)   {       printf("\nFailed to open the file.\n");       exit(1);   }    while (gets(string) && string[0] != '\0') {     fputs(string,outfile);     fputs("\n",outfile);   }    fclose(outfile);   return 0; }

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

引用 2 楼 z530650681 的回复:while (gets(string) && string[0] != '\0') {     fputs(string,outfile);     fputs("\n",outfile);   } 这段的意思是什么？  fputs(string,outfile);不是全部写入了文件吧，为什么还有  fputs("\n",outfile); 每次循环读入一行，然后写入文件。 gets读到的字符串不包括回车，所以再单独打一个换行


Question: 如何找出n个数的全部子列，并输出

大神果然厉害

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

其实就是输出n位的二进制数。

引用 2 楼 zhao4zhong1 的回复:二进制赵老师，我觉得你是搞底层的

二进制

...好不喜欢写c  你子列就是某一元素有或者没有  你是不是想到了什么


Question: 动态内存分配问题

引用 1 楼 lovesmiles 的回复:不知道说什么。我说不行，你信吗？ 上午一个题目出现的问题，可能我问题没说清，算了吧，我自己查查书吧？，谢谢了

引用 1 楼 lovesmiles 的回复:不知道说什么。我说不行，你信吗？ 不行指的是哪个？

不知道说什么。我说不行，你信吗？


Question: public List btnlist = new List();如何知道btnlist里button的个数

可是btnlist没有size这个属性啊

btnlist.size()


Question: 关于一个综合排序程序的几个小问题 我有些地方看不懂

int main() {     int i;     int rdm[SIZE];     int m[SIZE];     char name[20]  = "Random.txt";     char name1[20] = "BubbleSort.txt";     char name2[20] = "SelectSort.txt";     char name3[20] = "InsertSort.txt";     char name4[20]="Shellsort.txt";     choose();     printf("Start Creating 20000 random number\n");     Random(rdm,SIZE);     printf("Save them in file:Random.txt\n\n");     FileSave(name,rdm,SIZE);     system( "pause" );//如果你弹窗直接关闭的话可以加上这一行代码 }

一: void Copy(int m1[],int m2[],int num) {    int i;    for(i = 0;i < num;i ++)      m1[i] = m2[i];    return; } 这里要复制是因为你每次排序前要把排序内容还原  二:       exchange += 3;这里是3是因为你下面有3次赋值           temp = m[min];           m[min] = m[i];           m[i] = temp;  三:     compare += 2;        exchange ++;       //compare += 2;这里你前面要加注释,要不然就重复了, 比较是(j >= 0) && (m[j] > temp)这两个比较,在上面if里  四: exchange += 1; 这里要看你这个变量是干什么,如果是说数据交换次数的换,1也是对的

你的switch 不仅没把后面的加大括号, 还缺少case单个完后的break;  至于没有输出, 是因为你的输入被封装到choose方法里了, 你没用, 你可以把main拆开,并改成如下的:  void choose() { 	int k; 	printf("please choose 0:all sort  1 SelectSort\2 InsertSort\3 BubbleSort:"); 	scanf("%d",k); 	switch(k) 	{ 	case 0 : 		Copy(m,rdm,SIZE); 		printf("1 Run SelectSort..\n"); 		SelectSort(m,SIZE); 		FileSave(name1,m,SIZE);  		Copy(m,rdm,SIZE); 		printf(" 2 Run InsertSort..\n"); 		InsertSort(m,SIZE); 		FileSave(name2,m,SIZE);  		Copy(m,rdm,SIZE); 		printf("3 Run BubbleSort..\n"); 		BubbleSort(m,SIZE); 		FileSave(name3,m,SIZE);                 break; 	case 1: 		Copy(m,rdm,SIZE); 		printf("1 Run SelectSort..\n"); 		SelectSort(m,SIZE); 		FileSave(name1,m,SIZE);                 break; 	case 2: 		Copy(m,rdm,SIZE); 		printf(" 2 Run InsertSort..\n"); 		InsertSort(m,SIZE); 		FileSave(name2,m,SIZE);                 break; 	case 3: 		Copy(m,rdm,SIZE); 		printf("3 Run BubbleSort..\n"); 		BubbleSort(m,SIZE); 		FileSave(name3,m,SIZE);                 break; 	case 4: 		Copy(m,rdm,SIZE); 		printf("4 Run ShellSort..\n"); 		ShellSort(m,SIZE); 		FileSave(name4,m,SIZE);                 break; 	}  }  int main() { 	int i; 	int rdm[SIZE]; 	int m[SIZE]; 	char name[20]  = "Random.txt"; 	char name1[20] = "BubbleSort.txt"; 	char name2[20] = "SelectSort.txt"; 	char name3[20] = "InsertSort.txt"; 	char name4[20]="Shellsort.txt"; 	choose(); 	printf("Start Creating 20000 random number\n"); 	Random(rdm,SIZE); 	printf("Save them in file:Random.txt\n\n"); 	FileSave(name,rdm,SIZE); }

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

你只是上了一堆代码，没有任何注释的代码，没人有耐心把每块代码都看一看的。 你的switch编译错误，是因为你的switch(k)后面的执行代码，没有用花括号全部括起来。

楼下正解

还有，如何把此程序修改为 可以比较排序耗时并显示 选出 较快的2种方法呢？

把它们括起来以后程序可以编译运行了但是括号里面原本该PRINTF出来的内容都不显示了这是为什么啊？

好的，我以后尽量把代码加上注释。还有，谢谢解答！


Question: struct结构体偏移量

赋值的动作是运行时  偏移量的确定应该是编译时

是固定不变的，和赋值没关系。


Question: socket客户端连接时必须用IP吗？

socket 要将域名转成ip

SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockfd != INVALID_SOCKET) { 	struct sockaddr_in addr = { 0 }; 	addr.sin_family      = AF_INET; 	addr.sin_port        = htons(6000); 	addr.sin_addr.s_addr = inet_addr("111.222.123.123"); 	memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); 	int ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 	if (ret != 0) { 		struct hostent *host = gethostbyname("www.xxx.com"); 		if (host != NULL) { 			addr.sin_addr.s_addr = *(u_long *)*host->h_addr_list; 			ret = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 		} 	} 	if (ret == 0) { 		// ...... 	} 	closesocket(sockfd); }

应该是的吧。。。。。

这，没听说socket什么时候支持过域名了。。。毕竟域名解析是DNS服务器干的事儿。。。我只能说这俩差的有点远。。。


Question: 小白问题

终于弄明白了，改了编码之后要重新输入 ...............


Question: 怎么从调用的函数里面取出参数

顺便问一下两位老师的邮箱，有什么问题还请不吝赐教，感激不尽！！！

多谢赵4老师和mymtom的帮助，小弟向两位致敬！

可以用脚本简单实现的为啥要用程序呀 sed 's/\(.*:\)\(.*\)(\(\([^,()]*,*\)*[^,()]*\)).*/\1 \3/' a.txt | awk -F":" '{n=split($3,a,",");printf("%s %d",$1,n);for(i=1;i<=n;++i){printf(" %s", a[i])}printf("\n");}'

sed 's/\(.*:\)\(.*\)(\(\([^,()]*,*\)*[^,()]*\)).*/\1 \3/' a.txt 这一行shell可以使用C语言来实现吗？如果可以，需要使用到哪些函数呢？

引用 9 楼 mymtom 的回复:$ sed 's/\(.*:\)\(.*\)(\(\([^,()]*,*\)*[^,()]*\)).*/\1 \3/' a.txt /home/cbs/src/file1.c:53: char *a,int b,FILE* fp /home/cbs/src/file2.c:128: a,b,fp /home/cbs/src/file3.c:234: a,b,fp 只能帮你到这里啦，剩下的自己努力吧！  谢谢

怎么把第一行处理后变成第二行的格式呢 第一行 /home/cbs/src/file3.c:234:    if(tmp==store_func(a,b,fp)) 第二行 /home/cbs/src/file3.c  3  a  b  fp 需要用到什么函数？

难者不会，会者不难： //怎么把第一行处理后变成第二行的格式呢 //第一行 /home/cbs/src/file3.c:234:    if(tmp==store_func(a,b,fp)) //第二行 /home/cbs/src/file3.c  3  a  b  fp #include <stdio.h> #include <string.h> char s[256]="/home/cbs/src/file3.c:234:    if(tmp==store_func(a,b,fp))"; char *p,*q,c; char d[256]; char pr[32]; int t,n,r; int main() {     p=strchr(s,':');     if (NULL==p) return 1;     sprintf(d,"%.*s",p-s,s);     while (1) {         q=p+1;         p=strchr(q,'(');         if (NULL==p) break;     }     p=q-1;     if (p[0]!='(') return 2;     t=0;     p++;     q=p;     while (1) {         r=sscanf(p,"%31[^,)]%n",pr,&n);         if (r==1) {             t++;             p+=n;             if (p[0]==')') break;             p++;         } else break;     }     sprintf(d,"%s  %d",d,t);     p=q;     while (1) {         r=sscanf(p,"%31[^,)]%n",pr,&n);         if (r==1) {             sprintf(d,"%s  %s",d,pr);             p+=n;             if (p[0]==')') break;             p++;         } else break;     }     printf("%s\n",d);// /home/cbs/src/file3.c  3  a  b  fp     return 0; }  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

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

引用 6 楼 zhao4zhong1 的回复:2楼代码就是处理的例子。 具体怎么处理？看了一下午还没有明白......

2楼代码就是处理的例子。

引用 3 楼 zhao4zhong1 的回复:再供参考： //NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %32[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8    我是指处理文本问题，你这个程序是文本已经处理好了，直接读入结构体吧？ 我也是要把数据存入结构体，但是前提是要把文本内容处理好。 如题，如何处理好文本内容？

引用 1 楼 user-3 的回复:找括号 逗号划分 能说说具体需要用到C语言中的哪些函数来处理吗？

找括号 逗号划分


Question: MSP430单片机使用低功耗，就出现长时间掉电再上电程序就出现死机状态

建议楼主先熟悉单片机调试器的使用。


Question: 求下一天的日期的程序！

结构体类型定义缺少 分号


Question: MSP430低功耗，出现掉电程序死机状况，我附上代码，现象都写在代码里面了，希望大侠们能帮我分析分析。谢谢

加运行日志或状态信号灯显示。


Question: 需要改一段C代码适应x64

4楼高手。 建议楼主通读include\intrin.h的具体内容。

x64专用：  #include <intrin.h>  int has_CPUID() {     unsigned _int64 flg = __readeflags() ^ 0x200000;     __writeeflags(flg);     return __readeflags() ^ flg ? 1 : 0;      }

使用masm64写成一个函数，然后再链接进来。

我见过的 x64 编译器都不支持内联汇编

vc x64已经不允许你写inline assembly了。


Question: 如何返回第一个非空白字符

while(isspace(ch=getchar()))   ;

自己刚研究出一种 还有没有啊 #include<stdio.h> #include<ctype.h> char get_first(void); int main(void) {    char ch;     ch=get_first(); 	putchar(ch); 	 } char get_first(void) { 	int ch; 	int n;       ch=getchar();      while(n=isspace(ch)?1:0)     	ch=getchar();      	   	while(getchar()!='\n') 	continue; 	return ch; 	 }

我功力還不夠阿


Question: 哪位大哥来帮小弟看看（C 函数原型）

你要先看一下指針就會明白了

是一种数据类型

char是字符类型，char*是字符指针类型。括号中是函数的参数列表。 char *strcpy(char *dst, const char *src); 拷贝src指向的字符串到dst指定的内存处，返回dst。

看二楼


Question: 这么晚了有没有大神在啊？？帮忙看道题啊~~

引用 4 楼 gz_qmc 的回复:  感谢感谢~~好人啊！

为毛都是图片

手头没电脑么？ 搞个循环试一下不就知道了？

你先从2维的试试

求赐教~~


Question: 关于动态库和静态库中同名函数的链接问题

这个明显应该选A。。。不知道是C程序猿整体水平退化了还是回答的人都不是搞C的

今天维护老项目的bug， 发现了这个问题。 3、5楼的前辈说的是对的,  两个动态库各自实现一个同名c函数，编译没问题。但是c没函数重载的概念,  链接的时候前一个会覆盖后一个。

对于答案c我也不觉得有什么错误，这个问题主要是看链接器对于重名的符号的处理。对于两个静态库包含相同的函数（这里只讨论非static修饰的函数），意味着两个静态库包含了重名的符号，那么在同时链接这两个静态库的时候是可以产生链接错误的。我相信在某些版本的链接器上是会这么做的。

为什么我觉得D是错误的. 理论3楼已经讲了. 两个静态库有同名函数, 链接时会出错, 报函数重复定义, 因此C是对的. 两个动态库有同名函数, 动态加载时先加载的优先. (当然如果这两个同名函数完全不一样, 那么调用后一个会变成调用前一个, 导致逻辑错误). 从功能上是允许的, 因此D是错误.

《程序员的自我修养——链接、装载与库》

C是错的，这个我知道。因为公司已有的公共库A中的代码有点问题，然后我把相关代码抽取出来修改后生成B库（接口没变，只是修改了内部的逻辑），然后链接的时候B放在前面，A放在后面，链接器选择的是B中的符号，没出现问题。

以下是在其它地方看到的，你可以参考下       函数可以定义在3个地方1. 程序自身2. 静态库3. 动态库因为静态库是要链进程序的，所以函数定义在程序和静态库可以看成是一样的同名函数出现在程序和静态库中，链接时会报重定义的错误。同名函数出现在动态库中，编译链接都可以通过，但是调用会出问题，会出现覆盖问题。     定义在这3个地方的函数，会调用哪个函数呢？     1. 程序和静态库定义了同名函数，链接报错：重定义     2. 程序或静态库定义的同名函数，会覆盖动态库中定义的函数     3. 动态库中定义的同名函数，先链接覆盖后链接的函数  来源：http://blog.chinaunix.net/uid-26548237-id-3994017.html

就是选c吧!


Question: 拜托了 各位大大  我想用fputs（c，fp）；在终端上向文本文件中输入换行  坐等啊 各位大大们  我就只是想输入个换行 怎么就这么难啊

Windows:Enter,Ctrl+Z,Enter

引用 2 楼 jwj070524 的回复:Windows结束用ctrl-z，Linux结束用ctrl-d  int main() {     int ch;     FILE *fp = fopen("my.txt", "w");     if (NULL == fp) {         fprintf(stderr, "Can't open file\n");         return -1;     }      while (EOF != (ch=fgetc(stdin))) {         fputc(ch, fp);     }     fclose(fp);     return 0; } 貌似只有这个方法了

引用 1 楼 misskissC 的回复:标准输入、输出对应终端设备时通常是行缓冲的。  You can use "while, for" read multi-times.+1


Question: 网络编程中应该有几个接受线程，较为合适？

问题1： iocp就是多个线程在投递io的， 对于sendio，1个socket只由一个线程递交wsasend，不可以多个线程对1个socket去wsasend就可以了，不会乱序 对于recvio，只要保证你wsarecv递交的buf是有序的就可以了，后递交的buf先返回了，需要程序自己控制解包的顺序  问题2： recv，send都是区分socket的，不同的客户端，就是不同的socket，不会出现socket1的recv，收到的却是socket2的数据 但是会出现socket1的recv，先接受到数据的迁移部分，再recv一次接收到后一部分，需要程序自己组装数据

引用 5 楼 u012879806 的回复:[quote=引用 4 楼 lovesmiles 的回复:] 你的问题还是二个客户端的问题，客户端一的数据和客户二的数据本来就没有顺序可言吧？  它们是没有顺序可言  这么说吧， 客户端和服务端都定义了协议。  那么服务端如何保证，完整的收到一个包呢？    2个客户端都发送了数据给服务端，服务端 读取了客户端1的包头，知道 下一次recv 应该收取多少数据，  但是 “下一次recv" 可能收到 客户端2的数据啊。 该怎么办？  我这问题是不是太偏僻，钻牛角尖了吗？  你们平时网络编程，不需要考虑这个问题吗？    [/quote]  你真的连socket编程都没有搞懂。每一个socket都有一个系统缓冲区，每一个recv都要指定从那个socket接收数据。  不同的客户端发送的数据会被系统保存在不同的socket缓冲区里面，根本不会有联系，何来乱序可言？

引用 2 楼 lovesmiles 的回复:同一个socket的数据还是按顺序接收到的，只是接收完之的怎么处理，就要看工作线程怎么同步了。 假如是接收二个socket的数据，乱序有什么关系？本来就是不同的客户端的数据，在那个网络层都没有保证它们的顺序。  问题2：   在堵塞io模型中， 假设有2个客户端发送数据给服务端，服务端只有一个接受线程，  请问; 收到的数据会乱序吗？   比如客户端1 发送了很多数据， 但是服务端某一次只接受了客户端1部分数据， 第2次recv就接受了客户端2的数据。  这种可能性会不会产生？   如果会的话，我如何避免。   求思路解决问题2

推荐你参考下这篇博文http://blog.csdn.net/neicole/article/details/7549497，对IOCP模型不了解。一般嘛创建一个线程池，来一个客户请求就唤醒一个空闲线程去处理

《TCP/IP详解卷一：协议》

scoket跟线程有毛关系呢。    引用 5 楼 u012879806 的回复:[quote=引用 4 楼 lovesmiles 的回复:] 你的问题还是二个客户端的问题，客户端一的数据和客户二的数据本来就没有顺序可言吧？  它们是没有顺序可言  这么说吧， 客户端和服务端都定义了协议。  那么服务端如何保证，完整的收到一个包呢？    2个客户端都发送了数据给服务端，服务端 读取了客户端1的包头，知道 下一次recv 应该收取多少数据，  但是 “下一次recv" 可能收到 客户端2的数据啊。 该怎么办？  我这问题是不是太偏僻，钻牛角尖了吗？  你们平时网络编程，不需要考虑这个问题吗？    [/quote]  既然是2个client，你recieve总是要传2个不同的socket吧，2个client又有毛关系呢

引用 4 楼 lovesmiles 的回复:你的问题还是二个客户端的问题，客户端一的数据和客户二的数据本来就没有顺序可言吧？  它们是没有顺序可言  这么说吧， 客户端和服务端都定义了协议。  那么服务端如何保证，完整的收到一个包呢？    2个客户端都发送了数据给服务端，服务端 读取了客户端1的包头，知道 下一次recv 应该收取多少数据，  但是 “下一次recv" 可能收到 客户端2的数据啊。 该怎么办？  我这问题是不是太偏僻，钻牛角尖了吗？  你们平时网络编程，不需要考虑这个问题吗？


Question: 数据结构里的行编辑程序，总是有错误不能得到答案

引用 2 楼 user-1 的回复:输入的字符串都读到ch里面了，可是这个ch后边也没用到啊，到了LineEdit里面又getchar()，就又要等键盘输入了？ 这个思路有点矛盾。或者不要ch，直接到LineEdit里面读键盘；或者就读了ch，然后把ch作为参数传进LineEdit，然后到LineEdit里就不用读键盘了。谢谢你啊 ，内存的问题解决了。 无限循环的问题也找到了，我用变量c来判断字符是什么，结果循环中的getchar没记录，，c就一直是第一个字符。

IsEmpty好像也有问题，top为什么要加1？这和EmptyStack、InitStack都不一致呀。

引用 楼主 u011385329 的回复:然后用breakpoint一行行的测试发现getchar第一个读到的就是'\n' 内存错误在gettop函数里，应该是因为是空栈，而且没判断条件的原因。 第一个读到的'\n'，就是输入字符串的时候敲的回车。scanf把字符串读到了ch里面，回车留在了缓冲区里被getchar读到了。 GetTop(*s, m);  这个m没初始化是个野指针。建议改成 char m; GetTop(*s, &m);


Question: 求哪位大神帮我看一下下面这段代码出错在哪，它可以编译但运行到一半就报内存使用冲突

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

因为如果用字符的话在我做等值判断时，编译器会报错说无法进行比较。

为什么用ascll数值表示+-*/，这可读性多差啊


引用 1 楼 user-2 的回复:+1，这种情况一般是在 查看 或 视图 选项


我感觉最好使用平台无关的工具  个人意见


Question: glibc下各个目录头文件包含顺序是怎样的？

大的代码库不是这么看的。


Question: 通过指针输出一位数组，求解这是哪里错了，为什么运行不出来

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

*(p+1)中，p+1仅仅得到一个临时的指针对象而已，并没有使p指向后移。

#include"stdio.h" void zhizhen(int*p,int len) {     int i;     for(i=0;i<len;i++)     {         printf("%d ",*(p+i));     }     printf("\n"); } int main(void) {     int a[5]={12,3,41,231,44};     zhizhen(a,5);     return 0; }

printf("%d",*(p+1)); 最后打印有问题，别人都说了

void point(int *p,int len) { int i=0; for(i;i<len;i++) printf("%d",*p++); }

你的指针p在每次循环之后没有指下一个元素啊，改成这样就好了： #include"stdio.h" void zhizhen(int*p,int len) {     int i;     for(i=0;i<len;i++)     {         printf("%d ",*(p++));     }     printf("\n"); } int main(void) {     int a[5]={12,3,41,231,44};     zhizhen(a,5);     return 0; }

难道不应该是 printf("%d",*p); 么？


Question: 求参数 8位数组，4个相加怎么才没有重复的

8个数组 4个一组的相加  具体是怎么分组的？比如8个元素必须全部使用，还是两个分组中最多允许3个相同的元素？

其实只需要一个奇数，剩下的都是偶数就可以了，这样加和中必然有一个奇数有一个偶数。

任取一个基数x, 这8个数取值1, x, x^2, x^3, ..., x^7, 即可. 特别的x=2时就是1楼的答案

1,2,4,8,16,32,64,128 ?

2楼正解，只要两个数之间相差够大即可


Question: C语言socket 连接局域网由于目标机器积极拒绝

目测是多网卡问题造成的，

还有个可能，server所在机器的防火墙是打开的，连接直接被拒绝了

gethostname(Server_name, 128);       hp = gethostbyname(Server_name);           //获取本机名   memset(&sa, 0, sizeof(sa)); //初始化         memcpy(&(sa.sin_addr), hp->h_addr, hp->h_length); //设置服务器的IP地址   把这个地址打印出来看看是不是服务器的ip。 这个函数的返回直不一定是你想要的。

问题可能处在server端的这里： memcpy(&(sa.sin_addr), hp->h_addr, hp->h_length); //设置服务器的IP地址    hp->h_addr其实是hp-> h_addr_list[0]，如果服务端有多个ip，那么你只绑定了一个ip，如果不巧这个ip是个公网ip，那么所有局域网数据都会被这个绑定的socket忽略(哪怕port相同)。 既然是服务器，为什么绑定IP不设置成INADDR_ANY? 这样不管哪个网段收到的请求都能够获得。

调用了，我没有粘贴过来	SOCKET sock1=accept(sock,(SOCKADDR*)&addr[k],&nlen);

服务器端还要调用函数accept


Question: 麻烦各位帮我看看程序，带入数组名和指针的区别

*a="abcdeab"; 会在只读数据区分配8字节的空间, 填写"abcdeab\0" 而a[7]="abcdeab";  分配7字节空间, 填写"abcdeab\0",  其中最后一个字节越界了,写在其他数据内存中.  当初始化其他变量, 例如b[2]="ab";时就会把这个'\0'覆盖掉. b的情况也类似, 因此用数组的结果会是错误的

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

你的a[7]根本放不下"abcdeab"这个字符串啊～它后面还有一个空字符'\0'来表示字符串的结尾，需要a[8]才能放下，不然就不是一个完整的字符串，这样运行起来什么奇葩的事情都有可能发生。

引用 1 楼 bbs2241 的回复:*a="abcdeab"跟a[7]="abcdeab"是不一样的 前面的编译器会自动加个\0,后面的不加 两个都要'\0'。 只有非C风格字符串才会没有'\0'。 比如这种： char s[] = { 'a', 'b', 'c' };

两个定义都有问题。C风格字符串都会在末尾有一个'\0'作为结尾，你7个字符就要申请8个字符的内存。 数组名在有些表达式中会被当作指针来使用，但并不是说它就是一个指针。


Question: 查找  用指针反转字符串 的错误

引用 2 楼 lymymk 的回复:[quote=引用 1 楼 Baoge_leopard 的回复:] temp也有问题  temp 没什么问题吧，，是一字符型啊，，调试也没问题啊。[/quote] 哦！对，我看错了

引用 1 楼 Baoge_leopard 的回复:temp也有问题  temp 没什么问题吧，，是一字符型啊，，调试也没问题啊。

temp也有问题

引用 10 楼 Baoge_leopard 的回复:http://www.cnblogs.com/yezhenhan/archive/2011/10/28/2228083.html 讲的不错，看看  谢谢，，明白了，，

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

引用 7 楼 user-3 的回复:指针的话 s 指向的地址为只读的数据段 $ cat hello.c  int main(int argc, char *argv[]) {         char *s = "hello";          return 0; }  $ gcc -S hello.c $ cat hello.s          .file   "hello.c"         .section        .rodata .LC0:         .string "hello"         .text         .p2align 4,,15 .globl main         .type   main, @function main:         leal    4(%esp), %ecx         andl    $-16, %esp         pushl   -4(%ecx)         pushl   %ebp         movl    %esp, %ebp         pushl   %ecx         subl    $16, %esp         movl    $.LC0, -8(%ebp)         movl    $0, %eax         addl    $16, %esp         popl    %ecx         popl    %ebp         leal    -4(%ecx), %esp         ret         .size   main, .-main         .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"  $    看不懂啊，，，求解释啊

引用 5 楼 Baoge_leopard 的回复:#include<iostream> using namespace std; void reverse_string(char *str) {      char temp,temp1,temp2;      char *string_start=str;      char *string_end=str;            while(*string_end++)            ;            string_end-=2;                  while(string_start<string_end)      {            temp = *string_start; 	            *string_start=*string_end;             *string_end=temp; 		   string_start++; 		   string_end--;                  }       }  int main() { 	char *str = NULL; 	str = (char *)malloc(10); 	strcpy(str,"abcdefg"); 	cout<<str<<endl; 	reverse_string(str); 	cout<<str<<endl; }  这个没问题，可能你的main（）函数中有问题  int main() {     char *string_p="abcdeww";  /*换成string_p[]="abcdeww",则可以     reverse_string(string_p);     printf("%s",string_p); }

引用 4 楼 user-3 的回复:是这样调用的吗？ char *s = "hello"; reverse_string(s); 改成 char s[] = "hello"; reverse_string(s); 就好啦！   为什么用指针 就不行呢


Question: ASCII值为0的对应什么字符啊，我用VC6.0试了下怎么得到的是空格，空格那个不是32吗？

引用 3 楼 u012421456 的回复: 表示‘\0’ 你的程序不妨拿出来看看，建议不要用VC6了 谢谢你的回答，我发现'\0'在VC里输出来就是空格形式表现。。我刚接触C，也不懂用什么，请教下不用VC的话用什么比较好呢？

表示‘\0’ 你的程序不妨拿出来看看，建议不要用VC6了

引用 1 楼 dbzhang800 的回复:你怎么试的，这个才是关键！！  #include <stdio.h> int main() {char a=0; printf("%c",a);}

你怎么试的，这个才是关键！！

有许多人问过这样的问题了——http://bbs.csdn.net/topics/330154077 我个人觉得dev c++、c-free等都不错，我现在就是这个，有时也是用gcc

那只是表象啊，就是NULL


Question: CRC-CTITT程序求详解  菜鸟跪求

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

引用 1 楼 zhao4zhong1 的回复:unsigned short CRC16(unsigned char *buf,int len) {     unsigned short CRC = 0xffffu;     int i,j;      for (i=0;i<len;i++) {         CRC ^= *buf++;         for (j=0;j<8;j++) {             if (CRC & 0x0001u)                 CRC = CRC >> 1^0xA001u;             else                 CRC >>= 1;         }     }      CRC = ((CRC << 8) & 0xFF00u) | ((CRC >> 8) & 0x00FFu);     return CRC; } 介个 赵4老师能讲解下我发的代码不


Question: C语言 一个简单的停车场管理程序，有2 个错 求助，急！

引用 14 楼 runawaysmile 的回复:谢谢！刚开始混论坛~\(≧▽≦)/~没事，慢慢学习！

谢谢！刚开始混论坛~\(≧▽≦)/~

引用 12 楼 runawaysmile 的回复:话说，怎么结贴来着？？在你描述的问题的上方，你的标题上面有深蓝色的按钮，第二个就是结贴。

话说，怎么结贴来着？？

装不上vs就试一下codeblocks，也不大。把flushall()改成getchar()，看看行不行。

你试一下在flushall()的地方换成getchar();

我的电脑安不上VS 不知道为什么。。

删除掉以后可以运行了，但是好奇怪啊，是这样的  我的天，有好多地方出现了无限循环

我用的是C-FREE。

可以了，运行结果好奇怪。。我再看看

楼主的程序错误很多啊，你的代码也没有注释，我就改成可以运行了而已。 #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 2 #define price 0.05  typedef struct time { 	int hour; 	int min; } Time;  typedef struct node { 	char num[10]; 	Time reach; 	Time leave; } CarNode;  typedef struct NODE { 	CarNode *stack[MAX + 1]; 	int top; } SeqStackCar;  typedef struct car { 	CarNode *data; 	struct car *next; } QueueNode;  typedef struct Node { 	QueueNode *head; 	QueueNode *rear; } LinkQueueCar;  void InitStack(SeqStackCar *); int InitQueue(LinkQueueCar *); int Arrival(SeqStackCar *, LinkQueueCar *); void Leave(SeqStackCar *, SeqStackCar *, LinkQueueCar *); void List(SeqStackCar, LinkQueueCar);  void main() { 	SeqStackCar Enter, Temp; 	LinkQueueCar Wait; 	int ch; 	InitStack(&Enter); 	InitStack(&Temp); 	InitQueue(&Wait); 	while (1) 	{ 		printf("\n1.arrival"); 		printf("2.departure"); 		printf("3.show"); 		printf("4.exit\n"); 		while (1) 		{ 			scanf("%d", &ch); 			if (ch >= 1 && ch <= 4)break; 			else printf("\n please choose a number"); 		} 		switch (ch) 		{ 		case 1: 			Arrival(&Enter, &Wait); break; 		case 2: 			Leave(&Enter, &Temp, &Wait); 			break; 		case 3: 			List(Enter, Wait); 			break; 		case 4: 			exit(0); 		default: 			break; 		} 	} }  void InitStack(SeqStackCar *s) { 	int i; 	s->top = 0; 	for (i = 0; i <= MAX; i++) 		s->stack[s->top] = NULL; }  int InitQueue(LinkQueueCar *Q) { 	Q->head = (QueueNode *)malloc(sizeof(QueueNode)); 	if (Q->head != NULL) 	{ 		Q->head->next = NULL; 		Q->rear = Q->head; 		return(1); 	} 	else return(-1); }  void PRINT(CarNode *p, int room) { 	int A1, A2, B1, B2; 	printf("\n please input time of departure:/**:**/"); 	scanf("%d:%d", &(p->leave.hour), &(p->leave.min)); 	printf("\n the number of car is :"); 	puts(p->num); 	printf("\n its time of arrival is :%d:%d", p->reach.hour, p->reach.min); 	printf("time of departure is :%d:%d", p->leave.hour, p->leave.min); 	A1 = p->reach.hour; 	A2 = p->reach.min; 	B1 = p->leave.hour; 	B2 = p->leave.min; 	printf("\n the fee is : %2.1 f dollar", ((B1 - A1) * 60 + (B2 - A2))*price); 	free(p); }  int Arrival(SeqStackCar *Enter, LinkQueueCar *W) { 	CarNode *p; 	QueueNode *t; 	p = (CarNode *)malloc(sizeof(CarNode)); 	flushall(); 	printf("\n please input the number of car :"); 	gets(p->num); 	if (Enter->top<MAX) 	{ 		Enter->top++; 		printf("\n the car is at %d.", Enter->top); 		printf("\n please input the time of arrival:/**:**/"); 			scanf("%d:%d", &(p->reach.hour), &(p->reach.min)); 		Enter->stack[Enter->top] = p; 		return (1); 	} 	else 	{ 		printf("\n it has to wait!"); 			t = (QueueNode *)malloc(sizeof(QueueNode)); 		t->data = p; 		t->next = NULL; 		W->rear->next = t; 		W->rear = t; 		return(1); 	} }  void Leave(SeqStackCar *Enter, SeqStackCar *Temp, LinkQueueCar *W) { 	int i, room; 	CarNode *p, *t; 	QueueNode *q; 	if (Enter->top>0) 	{ 		while (1) 		{ 			printf("\n please input the position of car /1--%d/:,Enter->top"); 				scanf("%d", &room); 			if (room >= 1 && room <= Enter->top) break; 		} 		while (Enter->top>room){ 			Temp->top++; 			Temp->stack[Temp->top] = Enter->stack[Enter->top]; 			Enter->stack[Enter->top] = NULL; 			Enter->top--; 		} 		p = Enter->stack[Enter->top]; 		Enter->stack[Enter->top] = NULL; 		Enter->top--; 		while (Temp->top >= 1) 		{ 			Enter->top++; 			Enter->stack[Enter->top] = Temp->stack[Temp->top]; 			Temp->stack[Temp->top] = NULL; 			Temp->top--; 		} 		PRINT(p, room); 		if ((W->head != W->rear) && Enter->top<MAX) 		{ 			q = W->head->next; 			t = q->data; 			Enter->top++; 			printf("\n car number %s gets into the %d position.", t->num, Enter->top); 			printf("\n please input time right now:/**:**/:"); 			scanf("%d:%d", &(t->reach.hour), &(t->reach.min)); 			W->head->next = q->next; 			if (q == W->rear) 				W->rear = W->head; 			Enter->stack[Enter->top] = t; 			free(q); 		} 		else printf("\n there is no car on the way !~\n"); 	} 	else printf("\n there is no car in the carpark."); }  void List1(SeqStackCar *S) { 	int i; 	if (S->top>0) 	{ 		printf("\n carpark:"); 		printf("\n position /time of arrival/ number\n"); 		for (i = 1; i <= S->top; i++) 		{ 			printf("%d",i); 				printf("%d:%d",S->stack[i]->reach.hour,S->stack[i]->reach.min); 				puts(S->stack[i]->num); 		} 	} 	else printf("\n there is no car in the carpark"); }  void List2(LinkQueueCar *W) { 	QueueNode *p; 	p = W->head->next; 	if (W->head != W->rear) 	{ 		printf("\n the number of car which is waiting is :"); 		while (p != NULL) 		{ 			puts(p->data->num); 			p = p->next; 		} 	} 	else printf("\n there is no car in the way."); }  void List(SeqStackCar S, LinkQueueCar W) { 	int flag, tag; 	flag = 1; 	while (flag) 	{ 		printf("\n plese choose 1 \2\3:"); 		printf("\n 1.carpark \n 2. way 3. return \n"); 		while (1) 		{ 			scanf("%d", &tag); 			if (tag >= 1 || tag <= 3) break; 			else 				printf("\n please choose 1/2/3:"); 		} 		switch (tag) 		{ 		case 1:List(S,W); break; 		case 2:List(S,W); break; 		case 3:flag = 0; break; 		default:break; 		} 	} }

124行：flushall();不行就删掉，我看没有什么影响。

引用 3 楼 runawaysmile 的回复:第124行错误 implicit declaration of function 怎么修改。。就只有这一个错了额你使用什么开发环境？我是在vs2013上运行的，在C-Free上面也报错，但是用法应该没有错，暂时没有在网上找到解决方案。

额，谢谢，不知道为什么会有这么多错啊，我之前只改了一点点然后就出现了很多错。。OTL


Question: 关于C语言中malloc的疑问

在我们调用时，我们不知道里面是如何分配内存可以去看看malloc的实现  不过，平时自己实现内存池的时候，就有很多方案了，得到的地址不是按分配多少决定就很正常了  不如：在申请内存时，多申请一点，前面表示内存大小，或者其他标记....再或者申请的时候，查看池中是否有空闲合适内存等等...  还想到得到连续的地址....  所以得看malloc的实现，“随机分配”一说....

同意二楼，内存是随机分配的，你让 代码改成如下，其地址间距仍然保持不变  #include<stdio.h> #include<stdlib.h> int main() { 	char* s1 = (char *)malloc(sizeof(char)*4); 	char* s2 = (char *)malloc(sizeof(char)*5); 	char* s3 = (char *)malloc(sizeof(char)*10); 	 	printf("sizeof(char)=%ld\n", sizeof(char)); 	printf("s1 = %p\n", s1); 	printf("s2 = %p\n",s2); 	printf("s3 = %p\n", s3);    return 0; }

louzhu ,你实际运行这段代码了吗？

malloc 是随意分配内存的吧

这个和malloc的实现有关吧。  一般内存池会维护各种大小的内存队列。比如16，32，64等， 对于小内存的分配，malloc会直接从对应的最小的队列上面取下一块内存。 比如要分配1个字节的内存，最小的队列是16的话，就在这队列上面取一块下来，所以每块内存之间的地址间隔就是16。 等到16的队列用完了，就会在大的队列，比如32的队列上面取下来。当所有的队列都用完了。 malloc会尝试回收内存，如果还是没有内存，就报错。

参考linux源代码中malloc函数的实现。


Question: 多线程下载软件是如何提高效率的？

就是同时建立多个连接下载同一个文件的不同部分。 所以没必要一定要多线程（单线程用非阻塞socket也可以达到同样目的，只不过多线程每个线程负责一个socket的传输编写代码方便）。

引用 2 楼 taodm 的回复:那都是猴年马月的事啦。 另外，是多任务下载，不是一定就多线程下载 问题是有点老，不过能给点指点吗

那都是猴年马月的事啦。 另外，是多任务下载，不是一定就多线程下载

帮顶，目前需要了解这块知识


Question: 用Source Insight 3.5编辑代码，代码中写了注释，突然不知什么原因，注释变成乱码了.

应该是你编码方式不对 参考http://jingyan.baidu.com/article/ae97a646a5e499bbfc461d54.html

使用Notepad++, 修改成其它字符编码.

可能是二个编辑器同时用,另一个是对比工具，对比工具的编码方式是GB2312, 这个原因造成的.


Question: NULL和0有什么区别啊

引用 7 楼 zilaishuichina 的回复:[quote=引用 6 楼 tyuiop1232 的回复:] [quote=引用 5 楼 zilaishuichina 的回复:] 0是数字，是值 NULL是一个宏，这个宏对应的值是多少是人为规定的，一般规定为0，你看也可以重新规定 谢谢你的回答，我还想问下宏对应的这个0是数字0还是字符0，还是都可以的[/quote]  一般对应的是数字0  如果你要对应字符0，从语法上也是可以的，但是意义就不一样的，数字0和字符0，值是不一样的[/quote] 3q

引用 6 楼 tyuiop1232 的回复:[quote=引用 5 楼 zilaishuichina 的回复:] 0是数字，是值 NULL是一个宏，这个宏对应的值是多少是人为规定的，一般规定为0，你看也可以重新规定 谢谢你的回答，我还想问下宏对应的这个0是数字0还是字符0，还是都可以的[/quote]  一般对应的是数字0  如果你要对应字符0，从语法上也是可以的，但是意义就不一样的，数字0和字符0，值是不一样的

引用 5 楼 zilaishuichina 的回复:0是数字，是值 NULL是一个宏，这个宏对应的值是多少是人为规定的，一般规定为0，你看也可以重新规定 谢谢你的回答，我还想问下宏对应的这个0是数字0还是字符0，还是都可以的

作为一种风格, 很多人不愿意在程序中到处出现未加修饰的0。因此定义了预处理宏NULL,通常是((void *)0).参考：《你必须知道的495个c语言问题》

NULL expands to an implementation-defined null pointer constant C 一般是((void *)0)

A null-pointer constant is either an integral constant expression that evaluates to zero (such as 0 or 0L), or a value of type nullptr_t (such as nullptr). 0是个整形。NULL是个宏定义，也可能是0L（长整形）,也可能是nullptr（C++11里）


Question: 为什么在Xcode下运行会出现内存错误

引用 4 楼 a158337 的回复:两个问题，第一感觉if语句里面的判断条件有问题，不应该是m->buttom==NULL吗你这样写是不是恰恰相反了，第二个感觉不能这么初始化。应该是传递的参数为空，返回值为你现在传递进去的指针类型，然后函数里面重新声明一个所传递的指针类型的变量，来申请内存，如果申请成功，返回这个指针，用这个指针的值给main里面的那个m赋值。  第一个，m->bottom如果为null的话，!m->bottom就是真值了， 第二个，确实要是按你说的写法就不会出我这种错误了，我的m指针还没赋值就直接传进函数了。。 谢谢回答。

函数里的那个m是形参，不能双向传值

引用 2 楼 user-3 的回复:main里面的m是个未经初始化的野指针，不能直接使用。 m=(MazeType)malloc(sizeof(*m)); 啊，谢谢了。 逻辑不严谨，没注意到还犯了这种错误。 多谢指正。

如果你真的要这么写，不该形式也是可以的，不过估计要传递的参数是二阶指针。

再啰嗦两句： 初始化m必须在main里面，在InitStack里面不行，除非改成InitStack(MazeType *m) 另一个办法是在main里面直接把m定义成结构体变量而不是指针

m也需要初始化呀 InitStack函数只是初始化了m->bottom和m->top，但是没初始化m


Question: 为什么我用c语言编写的贪吃蛇游戏运行时会闪退呢

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

#include<stdio.h> #include<time.h> #include<conio.h> #include<stdlib.h> int head=3 ,tail=0; int main() { 	int i,j,k=0;	 	int zuobiao[2][80];	 	long start;	 	int direction=77;	 	int gamespeed;	 	int timeover;	     int change(char qipan[20][80],int zuobiao[2][80],char direction); 	zuobiao[0][tail]=1; 	zuobiao[1][tail]=1; 	zuobiao[0][1]=1; 	zuobiao[1][1]=2; 	zuobiao[0][2]=3; 	zuobiao[0][2]=1; 	zuobiao[1][head]=1; 	zuobiao[1][head]=4; 	char qipan[20][80];//定义棋盘		 	for(i=0;i<20;i++)	     	for(j=0;j<80;j++)			qipan[i][j]=' ';//初始化棋盘		 	for(i=0;i<80;i++)			qipan[0][i]='_';		 	for(i=0;i<20;i++)			qipan[i][0]='|';		 	for(i=0;i<20;i++)			qipan[i][79]='|';		 	for(i=0;i<80;i++)			qipan[19][i]='_';			 	qipan[1][1]=qipan[1][2]=qipan[1][3]='*';//初始化蛇的位置		 	qipan[1][4]='#'; 	printf("This is a game of a SN		AKE.\nGOOD LUCK TO YOU !\n");		 	printf("Input your game speed,please.(e.g.300)\n");			 	scanf("%d",&gamespeed); 	while(direction!='q') 	{ 		system("cls");			 		for(i=0;i<20;i++)//打印出棋盘			 			for(j=0;j<80;j++)		 				printf("%c",qipan[i][j]);		 			timeover=1;		 			start=clock();	 			while(!kbhit()&&(timeover=clock()-start<=gamespeed));	 			if(timeover)	 			{		 				getch();		 				direction=getch();	 			} 			else		 				direction=direction;	 			   if(!(direction==72||direction==80||direction==75||direction==77))		 			   {		 				   return 0;		 				   system("cls");		 				   printf("GAME OVER!\n");	 			   } 			   if(!change(qipan,zuobiao,direction))	 			   {		 				   direction='q';				 				   system("cls");		 				   printf("GAME OVER!\n");	 			   } 	} 	return 0; 	} 	int change(char qipan[20][80],int zuobiao[2][80],char direction) 	{		 		int x,y;	 		if(direction==72)		 			x=zuobiao[0][head]-1;y=zuobiao[1][head];	 		if(direction==80)		 			x=zuobiao[0][head]+1;y=zuobiao[1][head];	 		if(direction==75)		 			x=zuobiao[0][head];y=zuobiao[0][head]-1;		 		if(direction==77)		 			x=zuobiao[0][head];y=zuobiao[1][head]+1;	 		if(x==0||x==18||y==78||y==0)		 			return 0;	 		if(qipan[x][y]!=' ')		 			return 0;	 		qipan[zuobiao[0][tail]][zuobiao[1][tail]]=' ';	 		tail=(tail+1)%80;	 		qipan[zuobiao[0][head]][zuobiao[1][head]]='*';	 		head=(head+1)%80;	 		zuobiao[0][head]=x;		 		zuobiao[1][head]=y;	 		qipan[zuobiao[0][head]][zuobiao[1][head]]='#';	 		return 1; 	}   这是代码，求大牛

你当我们是神啊，代码都没有就问问题

没有程序，谁知道呢。你只能自己调试，一步步，采用注释的办法，比如先注释掉后一半如果还是闪退，问题就在前一半，否则就在后一半找。这样逐渐缩小。闪退原因很多，比如该等待的时候没有等待某个条件完成，初始的时候和结束的时候弄成一样的了不好说


Question: sscanf 的使用

#include <stdio.h>  int main() {   char ch[100] = "%99.4";   gets(ch);    double d;   sscanf(ch, "%*%%lf", &d);   printf("%lf\n", d); }

用一个l就行了     sscanf(&ch[1],"%lf",&d);     printf("%lf\n",d);


Question: EOF是什么东西啊

End-of-File  It is a macro definition of type int that expands into a negative integral constant expression (generally, -1).   It is used as the value returned by several functions in header <cstdio> to indicate that the End-of-File has been reached or to signal some other failure conditions.   It is also used as the value to represent an invalid character.   In C++, this macro corresponds to the value of char_traits<char>::eof().

文件里没有EOF这个东西，它不是表示结束的字符。就是一个信号，读取文件的函数发现文件结束了就会返回这么个值


Question: 关于在vc++中结构体所占内存大小

搜索一下“字节对齐”！

任何类型的起始地址要是类型长度的整数倍，这就是对齐问题

结构体1： struct  最高字节double是8，8字节对齐 { int a; //4字节， 与下面的1 字节可共占8字节 char b; //1字节，和上面的int 共占5个字节，对齐需要补齐3个字节 double c; //8字节 } s1; 结构体2： struct 最高字节double是8，8字节对齐 { int a;//4字节， 下面是double 无法拼凑成小于8的空间，补齐4个字节 double c; //8字节，自身对齐 char b; //1字节  ，上面都已对齐，下面无数据，补齐7个字节 } s2;

对齐问题，老问题了。

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

原则，相邻层能合并补齐则合并（合并后不能超过最大类型字节数，若超过，则各层补）

结构体内分层，以最大字节为标准补齐.

为什么char  b有时按4字节对齐有时8字节对齐   ---------------- 和前面一个类型有关，按上一个大小对齐

为什么char  b有时按4字节对齐有时8字节对齐

字节对齐。。。

结构体1： struct { int a; char b; double c; } s1; 数据对齐如下图 |----------------int----------|char---char---char---char|   4+1+3(后三个char为填充) |---------------------------double---------------------------|  8 所以16B  结构体2： struct { int a; double c; char b; } s2; 数据对齐如下图 |----------------int-----------------|--------------int---------------| 4+4(后一个int为填充) |-------------------------------double-----------------------------|  8 |char---char---char---char---char---char---char--char--|  1+7(后7个char为填充) 所以占24B  可参看：http://pppboy.blog.163.com/blog/static/30203796201082494026399/

struct { int a;  // 4字节 char b;  // 1字节 // 3字节填充，按8对齐 double c; // 8字节 } s1; // 16字节 结构体2： struct { int a; // 4字节 // 4字节填充，按8对齐 double c; // 8字节 char b; // 1字节 // 7字节填充，按8对齐 } s2; // 24字节

搜索一下 alignment and padding

struct Foo {   int a;   char b;   double c; } s1;  struct Bar {   int a;   double c;   char b; } s2;  int main() {   return 0; }  cl.exe /nologo /EHsc /d1reportAllClassLayout demo.cpp   class Foo       size(16):         +---  0      | a  4      | b         | <alignment member> (size=3)  8      | c         +---    class Bar       size(24):         +---  0      | a         | <alignment member> (size=4)  8      | c 16      | b         | <alignment member> (size=7)         +---


Question: 随意输入一个字符串，判断其是否为IP地址。

引用 21 楼 jdqsummer 的回复:各有各的想法很厉害，但是小小的功能何必做的怎么复杂 首先要明白楼主需求，知道输入输出格式 我倒觉得符合需求而且代码简洁的程序才是好程序 工作也是这样，不要把小小的功能写了几百行代码感觉很了不起，那些写了几行代码就能实现的才是大神。 其实楼上多种解法都是有效的，我更倾向于21L的意见。要看LZ想干什么了，需求决定实现。我猜LZ应该是学习用的。学习的时候，我一般喜欢简单容易看懂的代码。而一般编程我都假定用户有一定常识，比如不会输入a.b.c.3这样的“IP”。以上只是我的一点看法，解题答案在其他楼层。

引用 19 楼 xusiwei1236 的回复:[quote=引用 12 楼 FancyMouse 的回复:] [quote=引用 11 楼 xusiwei1236 的回复:] if应该是不等于  int isipv4str(const char *str) { 	int i, a[4]; 	if( sscanf(str, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4 ) 		return 0; 	for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0; 	return 1; }  str="1.1.1.1.1"就能弄挂[/quote] 这个测试数据很好！应该说“错了”，不能说“弄挂”（程序崩溃才能叫挂）  @zhao4zhong1赵老师格式串最后加的"%c"能解决了这个问题，但是不应该判断它的值，而应该是： if( sscanf(str, "%d.%d.%d.%d%c", &a[0], &a[1], &a[2], &a[3], &end) != 4 ) 这样%c的作用就是：判断a[3]后面有没有字符  附测试代码：  #include <stdio.h>  int isipv4str(const char *str) {     int i, a[4]; 	char end;     if( sscanf(str, "%d.%d.%d.%d%c", &a[0], &a[1], &a[2], &a[3], &end) != 4 )         return 0;     for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0;     return 1; }  #define TEST_V4STR(ipstr) printf("isipv4str(\"%s\") : %s\n", ipstr, isipv4str(ipstr) ? "true" : "false")  int main() { 	TEST_V4STR("1.1.1.1"); 	TEST_V4STR("1.1.1.1.1"); 	TEST_V4STR("1.1.1.1.1.1"); 	TEST_V4STR("127.0.0.1"); 	TEST_V4STR("255.255.255.255"); 	TEST_V4STR("255.255.255.256"); 	TEST_V4STR("255.255.255.-1"); 	TEST_V4STR("this.is.a.string");  	return 0; }  [/quote] 弱弱地问一下，你这是“随意输入一个字符串”吗？

IPv4的js方式  function checkIpAddress(strIpAddress) 	{ 		var scount=0;  		var ip = strIpAddress;  		var iplength = ip.length;  		var Letters = "1234567890.";  		for (i=0; i < ip.length; i++)    		{     			var CheckChar = ip.charAt(i);     			if (Letters.indexOf(CheckChar) == -1)     			{  	    		//alert ("IP地址格式不对!!，只能输入数字和“.”,格式为XXX.XXX.XXX.XXX 例如：192.168.0.1");   	    		return false;     			}    		}   		for (var i = 0;i<iplength;i++)    			(ip.substr(i,1)==".")?scount++:scount;  		if(scount!=3)  		{    			//alert ("IP地址格式不对!，只能输入数字和“.”,格式为XXX.XXX.XXX.XXX 例如：192.168.0.1");  	 		return false;  		}   		var first = ip.indexOf(".");  		var last = ip.lastIndexOf(".");  		var str1 = ip.substring(0,first);  		var subip = ip.substring(0,last);  		var sublength = subip.length;  		var second = subip.lastIndexOf(".");  		var str2 = subip.substring(first+1,second);  		var str3 = subip.substring(second+1,sublength);  		var str4 = ip.substring(last+1,iplength);   		if (str1=="" || str2=="" ||str3== "" ||str4 == "")  		{ 			//alert("数字不能为空！格式为XXX.XXX.XXX.XXX 例如：192.168.0.1");  			return false;  		}  		 		if (str1< 0 || str1 >255)  		{ 			//alert ("数字范围为0~255！");  		    return false;  		}  		else if (str2< 0 || str2 >255)  		{ 			//alert ("数字范围为0~255！");  			return false;  		}  		else if (str3< 0 || str3 >255)  		{ 			//alert ("数字范围为0~255！");  			return false;  		}  		else if (str4< 0 || str4 >255)  		{ 			//alert ("数字范围为0~255！");  			return false;  		} 		return true; 	}

引用 12 楼 FancyMouse 的回复:[quote=引用 11 楼 xusiwei1236 的回复:] if应该是不等于  int isipv4str(const char *str) { 	int i, a[4]; 	if( sscanf(str, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4 ) 		return 0; 	for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0; 	return 1; }  str="1.1.1.1.1"就能弄挂[/quote] 这个测试数据很好！应该说“错了”，不能说“弄挂”（程序崩溃才能叫挂）  @zhao4zhong1赵老师格式串最后加的"%c"能解决了这个问题，但是不应该判断它的值，而应该是： if( sscanf(str, "%d.%d.%d.%d%c", &a[0], &a[1], &a[2], &a[3], &end) != 4 ) 这样%c的作用就是：判断a[3]后面有没有字符  附测试代码：  #include <stdio.h>  int isipv4str(const char *str) {     int i, a[4]; 	char end;     if( sscanf(str, "%d.%d.%d.%d%c", &a[0], &a[1], &a[2], &a[3], &end) != 4 )         return 0;     for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0;     return 1; }  #define TEST_V4STR(ipstr) printf("isipv4str(\"%s\") : %s\n", ipstr, isipv4str(ipstr) ? "true" : "false")  int main() { 	TEST_V4STR("1.1.1.1"); 	TEST_V4STR("1.1.1.1.1"); 	TEST_V4STR("1.1.1.1.1.1"); 	TEST_V4STR("127.0.0.1"); 	TEST_V4STR("255.255.255.255"); 	TEST_V4STR("255.255.255.256"); 	TEST_V4STR("255.255.255.-1"); 	TEST_V4STR("this.is.a.string");  	return 0; }

已经有很多大案了！！

grep正则表达式规范 在sed、awk及C语言中用正则表达式

用正则表达式匹配字符串是否为IP地址的C代码：  /*Filename:	regex_in_c.c  *Brife:	use c function to use regex  *Author:	One fish  *Date:		2014.8.12 Tuesday  */ #include <sys/types.h> #include <regex.h> #include <stdio.h> #include <stdlib.h>   int main(void) { 	regex_t		reg; 	char		regex[] = "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"; 	char		str[] = "172.168.13.1"; 	size_t		nmatch = 1; 	regmatch_t	pmatch[1]; 	char		errbuf[100]; 	int		i, re;  	//Compile regex to reg	 	re	= regcomp(®, regex, REG_EXTENDED | REG_NEWLINE); 	if ( 0 != re ) { 		regerror(re, ®, errbuf, 100); 		printf("%s\n", errbuf); 		exit(1); 	}  	//Use reg which compiled from pattern to match substring in whole string str 	re	= regexec(®, str, nmatch, pmatch, 0); 	if (REG_NOMATCH == re) { 		printf("No match\n"); 		exit(1); 	} else if (0 == re) { 		printf("matched:\n"); 		for (i = pmatch[0].rm_so; i < pmatch[0].rm_eo; ++i) { 			putchar(str[i]); 		} 		printf("\n"); 		printf("%d, %d\n", pmatch[0].rm_so, pmatch[0].rm_eo); 	}  	//Free ® used in recomp 	regfree(®); 	return 0; } 编译并执行程序：  gcc  -o  regex_in_c  regex_in_c.c  ./regex_in_c  matched:  172.168.13.1  0,12  当在regcomp函数中的cflags参数中指定REG_NOSUB时nmatch和pmatch参数将会被忽略，不能再将它们的值输出来。

用inet_aton看返回值做判断 不要用inet_addr，具体参见手册

引用 11 楼 xusiwei1236 的回复:if应该是不等于  int isipv4str(const char *str) { 	int i, a[4]; 	if( sscanf(str, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4 ) 		return 0; 	for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0; 	return 1; }  str="1.1.1.1.1"就能弄挂

忘了，这才是当时写的（记得不止两行）  int isipv4str(const char *str) { 	int i, a[4]; 	if( sscanf(str, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) == 4 ) 		return 0; 	for(i=0; i<4; i++) if (a[i] < 0 || a[i] > 255) return 0; 	return 1; }

我被人面过这题，我的解法：  bool isipv4str(const char *str) { 	int a[4]; 	return sscanf(str, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) == 4; }

引用 17 楼 zhao4zhong1 的回复:#include <stdio.h> int main() {     int IP[4];     int i;     char c;      printf("请输入一个ip地址:");fflush(stdout);     while (1) {         rewind(stdin);         if (5==scanf("%d.%d.%d.%d%c",&IP[0],&IP[1],&IP[2],&IP[3],&c)) {             if (0<=IP[0] && IP[0]<=255              && 0<=IP[1] && IP[1]<=255              && 0<=IP[2] && IP[2]<=255              && 0<=IP[3] && IP[3]<=255              && '\n'==c) {                 break;             } else printf("输入的ip地址格式不对!\n请重新输入:\n");         } else printf("输入的ip地址格式不对!\n请重新输入:\n");     }     for (i=0;i<4;i++) {         printf("IP[%d]=%d\n",i,IP[i]);     }     return 0; }  //IPv6地址表示 //IPv6地址为128位长，但通常写作8组，每组为四个十六进制数的形式。例如： //FE80:0000:0000:0000:AAAA:0000:00C2:0002 是一个合法的IPv6地址。 //要是嫌这个地址看起来还是太长，这里还有种办法来缩减其长度，叫做零压缩法。 //如果几个连续段位的值都是0，那么这些0就可以简单的以::来表示，上述地址就可以写成 //FE80::AAAA:0000:00C2:0002。这里要注意的是只能简化连续的段位的0，其前后的0都要保留， //比如FE80的最后的这个0，不能被简化。还有这个只能用一次，在上例中的 //AAAA后面的0000就不能再次简化。当然也可以在AAAA后面使用::，这样的话前面的 //12个0就不能压缩了。这个限制的目的是为了能准确还原被压缩的0.不然就无法确定每个::代表了多少个0. //2001:0DB8:0000:0000:0000:0000:1428:0000 //2001:0DB8:0000:0000:0000::1428:0000 //2001:0DB8:0:0:0:0:1428:0000 //2001:0DB8:0::0:0:1428:0000 //2001:0DB8::1428:0000都是合法的地址，并且他们是等价的。但 //2001:0DB8::1428::是非法的。（因为这样会使得搞不清楚每个压缩中有几个全零的分组） //同时前导的零可以省略，因此： //2001:0DB8:02de::0e13等价于2001:DB8:2de::e13 #include <stdio.h> #include <string.h> char ipv60[]="2001:0DB8:0000:0000:0000:0000:1428:0000"; char ipv61[]="1040::1"; char ipv62[]="fe80::20c:29ff:fe6b:2516"; char ipv63[]="::ffff:c0a8:5909"; unsigned char ip_v6[16]; void show(char *a) {     int i;     printf("%-39s=>",a);     for (i=0;i<16;i++) printf("%02x ",ip_v6[i]);     printf("\n"); } void inet_addr6(char *a) {     char *p;     int n,i,r,k,j;     short s;     k=0;     p=a;     while (1) {         if (*p==':') k++;         p++;         if (*p==0) break;     }     if (a[0]==':') k--;     i=0;     p=a;     while (1) {         r=sscanf(p,"%hx%n",&s,&n);         if (1==r) {             ip_v6[i]=*((unsigned char *)&s+1);             ip_v6[i+1]=*((unsigned char *)(&s));             i+=2;             if (i>=16) break;             p+=n;         } else if (0==r) {             if (p[0]==':') {                 if (p[1]==':') {                     for (j=0;j<(8-k)*2;j++) ip_v6[i+j]=0;                     i+=(8-k)*2;                     if (i>=16) break;                     p+=2;                 } else {                     p++;                 }             } else {                 printf("Format Error [%s]!\n",a);             }         } else break;     } } int main() {     inet_addr6(ipv60);show(ipv60);     inet_addr6(ipv61);show(ipv61);     inet_addr6(ipv62);show(ipv62);     inet_addr6(ipv63);show(ipv63);     return 0; } //2001:0DB8:0000:0000:0000:0000:1428:0000=>20 01 0d b8 00 00 00 00 00 00 00 00 14 28 00 00 //1040::1                                =>10 40 00 00 00 00 00 00 00 00 00 00 00 00 00 01 //fe80::20c:29ff:fe6b:2516               =>fe 80 00 00 00 00 00 00 02 0c 29 ff fe 6b 25 16 //::ffff:c0a8:5909                       =>00 00 00 00 00 00 00 00 00 00 ff ff c0 a8 59 09 // +1

首先你要定义ip地址

獲益良多

楼主，你先要搞清楚什么是正确的ip地址才行哦 192.068.0x1.1是正确的ip地址么？


Question: C语言文件写入乱码

引用 6 楼 flower31857 的回复:[quote=引用 2 楼 baichi4141 的回复:] 字符串和其他初学者遇到的数据类型最大的不同在于：它只存在于概念中，语言中没有字符串这玩意。你可以称放在一起的一堆字符是一个字符串，并用处理字符串的方式去处理这堆字符，你也可以不这么做。 所以用字符指针来接收一个字符串，和用整型变量来接收一个整数，是完全不同的。一个整型变量是独立的，存在它里面的整数只能通过它来改变。而一个指针指向一块内存，这块内存可能被其他指针指向，可能被其他指针修改，甚至可能根本就不属于你！  简单地说，不要使用指向局部变量的指针，这个变量很可能在进入另一个函数时被改变。 准确的说，你可以使用指向任何地方的指针——只要你真的明白这个指针指向什么地方，其数据由谁修改。嗯  是这样，子函数临时开辟的内存已经被释放货征用了   那我该怎么实现[/quote] 最简单的办法， 返回一个结构体实例。  typedef struct tagBuf {   char buf[32]; }Buf;  Buf log() {   Buf buf;   strncpy(buf,  "hello world", sizeof(buf.buf));  return buf; }

1 在main函数中定义数组，将其指针传给log_in函数 2 在log_in函数中malloc，在main函数中用完后free 3 把数组封在一个结构体里，结构体可以直接=  方法有很多，问之前先自己想想，比直接问到答案对你更有帮助

引用 2 楼 baichi4141 的回复:字符串和其他初学者遇到的数据类型最大的不同在于：它只存在于概念中，语言中没有字符串这玩意。你可以称放在一起的一堆字符是一个字符串，并用处理字符串的方式去处理这堆字符，你也可以不这么做。 所以用字符指针来接收一个字符串，和用整型变量来接收一个整数，是完全不同的。一个整型变量是独立的，存在它里面的整数只能通过它来改变。而一个指针指向一块内存，这块内存可能被其他指针指向，可能被其他指针修改，甚至可能根本就不属于你！  简单地说，不要使用指向局部变量的指针，这个变量很可能在进入另一个函数时被改变。 准确的说，你可以使用指向任何地方的指针——只要你真的明白这个指针指向什么地方，其数据由谁修改。嗯  是这样，子函数临时开辟的内存已经被释放货征用了   那我该怎么实现

引用 1 楼 baichi4141 的回复:我在main函数用了一个字符指针us来接收log_in的返回值 用字符数组 要问原因的话，字符指针指向的十有八九是个局部变量，这个局部变量在log_in函数退出后就不再属于你了，而进入printf函数的时候，这个函数征用了这块内存，结果这块内存的数据就发生了变化——只有属于你的内存的数据由你控制，其他的内存你可以读写，别人也可以 如果你不知道一个指针指向的内存何时属于你何时不属于你，就别用指针我好像明白是什么意思了   那段内存在子函数结束后就被征用了 那我该怎么解决呢？貌似字符数组是不能直接用=赋值

目测是 log_in的返回值 lz返回的是一个局部变量  请不要返回一个局部变量的地址

多半返回了栈上变量的指针。


Question: 【求助】求各位帮我看一段代码，找不到问题啊

如果指针参数不应该被修改，就不要在函数中直接操作指针参数，而是赋值给一个临时指针来完成操作。

引用 1 楼 u010963658 的回复:while(*str!='\0')       {         str++; i++; } 这时候while一出来str已经是空了,   p=str+(i-length);自然不是想要的 应该在while之前 const char* pStr = str; p=pStr+(i-length);对啊   while以后  str已经变了  唉  我居然忘了这个


Question: 图的深度优先遍历算法问题

回车被你当边读进去了

scanf("%c",&G->vexs[i]); 把你的换行也读了过去, 在%c前面加个空格就可以过滤换行和空格了 scanf(" %c",&G->vexs[i]);


Question: 关于argc,argv的，注释后面那一段输出for就不会出错，那一段怎了？

引用 1 楼 user-3 的回复:因为第15行写错了      for (i=0;envp[i];++i)  谢谢各位，这例子我是看这里弄的。看来是他那里搞错了。http://www.cnblogs.com/avril/archive/2010/03/22/1691477.html

for(i=0;envp[i]!='\0';++i)或者for(i=0;*(envp+i)!='\0';++i)

因为第15行写错了      for (i=0;envp[i];++i)


Question: 函数中的malloc空间是否要释放

申请的权限给你，就是要你对它的生命期负责

引用 2 楼 caiwei_cs 的回复:[quote=引用 1 楼 user-16 的回复:] 有申请就要释放！ 如果在子函数里面，是不是会像局部变量一样，在函数结束后自动释放呢？ 因为这些空间里面的东西我也不需要了，被系统自动收回也无所谓。[/quote] 自动释放的是在栈上，堆上的资源，自己申请，自己负责回收 不处理就是资源泄露

要释放，不然内存泄漏。

虎头蛇尾是俗人的习惯， 有始有终是君子的操守。

看七楼和九楼

一看明显是学生写的代码，说实话我也写过。工作之后就知道公司对代码要求有多严格，特别是大公司，他们都有自己的一套编码标准叫checklist。代码审核如果上述代码，直接被鄙视，而且影响转正。所以要养成良好的编码习惯，即使是测试程序，也要写规范点。网上也有相关的代码编码标准要求，华为就有一套C语言代码编写标准规范。 我也刚工作两三个月，对编码要求深有体会。

就算会被自动回收也要手动释放，这是一个好习惯，不能一直依赖系统的回收

必须释放 不用考虑 void fun() {     int *p = (int *)malloc(sizeof(int) * 1); }  调用这个函数，当这个函数执行完毕后，p被释放，但p指向的空间没有被释放 想象一下你调用了N次这个函数的结果是什么.....

要释放的，凡是自己申请的内存，就要自己释放。

引用 2 楼 caiwei_cs 的回复:[quote=引用 1 楼 user-16 的回复:] 有申请就要释放！ 如果在子函数里面，是不是会像局部变量一样，在函数结束后自动释放呢？ 因为这些空间里面的东西我也不需要了，被系统自动收回也无所谓。[/quote] 仅仅是你保存动态申请得到的内存地址的局部变量被销毁，但是申请的内存依旧被占用。

如果是开发程序的话一定要释放，平时要养成释放空间的习惯。我老师写链表从来都不释放

在子函数里面动态申请的内存不会自动被系统收回的，因为这些空间在堆里面，而不是栈，平常所说的不能返回指向栈的指针，比如在子函数里面定义一个字符指针，指向常量"hello"因为函数调用完成这部分空间会自动释放，但是堆不会，所以会越积累愈多的，尤其是对这个子函数调用次数非常多就不妙了，申请的内存地址应该保证能够记住或者保证可以找到，为以后的释放做准备。

养成良好的习惯，malloc、calloc和realloc后，内存空间要释放，不释放就会出现内存泄露，写一些小程序到没什么问题发生，假如正式做项目的时候，你的程序必须一直运行，那么一直malloc却不free,一定会出问题的。

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

引用 2 楼 caiwei_cs 的回复:[quote=引用 1 楼 user-16 的回复:] 有申请就要释放！ 如果在子函数里面，是不是会像局部变量一样，在函数结束后自动释放呢？ 因为这些空间里面的东西我也不需要了，被系统自动收回也无所谓。[/quote] 也需要释放的。

有malloc 就得 free 不用思考

引用 1 楼 user-16 的回复:有申请就要释放！ 如果在子函数里面，是不是会像局部变量一样，在函数结束后自动释放呢？ 因为这些空间里面的东西我也不需要了，被系统自动收回也无所谓。

有申请就要释放！


Question: 问if（a++！=b++）的意思

引用 1 楼 aa5566f4 的回复:while(*char!='\0') 請問這段程式碼是否有錯???  额 是whie( *b！=‘\0’) 写快了！

while(*char!='\0') 請問這段程式碼是否有錯???

引用 5 楼 user-3 的回复:char *mat(char *a,char *b){     while(*a!='\0'){         if(*a++!=*b++)   //*a!=*b? a=a+1,b=b+1             return NULL;     }     return b; }   意思是，，（*a++！=*b++）将两个中短的那个全比完，，只要出现不相同的就返回NULL；不知道理解正确么

引用 3 楼 Evankaka 的回复:“ if(*a++!=*b++)”   的意思，，，   首先，我们来看操作符的优先级，++高于* 其次，a,b是指针， 最后，先a++,但这时要注意，*a++表示取指针的内容，但这时取的是*a,,,取完之后a的指针指向+1 同理，b也一样；    判断*a是否等于*b,判断完成之后，不管是相等还是不相等，a,b指针都自加1  然后是，，各自加完后，再比较，，，只要出现（*a++！=*b++）就返回NULL；；是不是啊。。

引用 4 楼 aa5566f4 的回复: #include <stdio.h> char *mat(char *a,char *b); void main() { 	char *test; 	char *_a = "a"; 	char *_b = "b"; 	test = mat(_a, _b); 	printf("%s\n", test); 	 }  char *mat(char *a,char *b) {       	while(*b!='\0')     {           if(*a++!=*b++)  		  return NULL;     }        return b; }   你單步調試就知道為甚麼了吧  看我理解的有没问题，，，就是只有在if（*a++=*b++）才不会返回NULL，，不知道对不对额

引用 10 楼 lymymk 的回复:[quote=引用 9 楼 user-3 的回复:] [quote=引用 8 楼 lymymk 的回复:] [quote=引用 5 楼 user-3 的回复:] char *mat(char *a,char *b){     while(*a!='\0'){         if(*a++!=*b++)   //*a!=*b? a=a+1,b=b+1             return NULL;     }     return b; } [/quote]不能理解为把短的比较完，while循环只对a进行‘\0’末尾的判断，没有对b的判断，比如a长，b短，那么会一直比较下去，如果前面一直匹配，会和存储b之后的内存进行比较（未定义的结果）。[/quote]  那为什么调试后发现，，a比b长，，然后如果是return a 的话，，实际上是，输出a和b比较之后的 长度，，比如：a=“abcdeef”；b=“abc”。。。运行之后 得到的是：return a；结果是：deef[/quote] 就你说的问题来看一下，如果像你那样，当a指向'd‘的时候，b指向’\0'，已经不同，返回的是NULL，但是你是直接对传入的指针操作，所以你来打印a指向字符串，是从你a现在指向的地方一直到'\0'结束。我觉得你本意是这样调用： char* p=mat(a,b);   //p得到NULL

引用 9 楼 user-3 的回复:[quote=引用 8 楼 lymymk 的回复:] [quote=引用 5 楼 user-3 的回复:] char *mat(char *a,char *b){     while(*a!='\0'){         if(*a++!=*b++)   //*a!=*b? a=a+1,b=b+1             return NULL;     }     return b; } [/quote]不能理解为把短的比较完，while循环只对a进行‘\0’末尾的判断，没有对b的判断，比如a长，b短，那么会一直比较下去，如果前面一直匹配，会和存储b之后的内存进行比较（未定义的结果）。[/quote]  那为什么调试后发现，，a比b长，，然后如果是return a 的话，，实际上是，输出a和b比较之后的 长度，，比如：a=“abcdeef”；b=“abc”。。。运行之后 得到的是：return a；结果是：deef

引用 8 楼 lymymk 的回复:[quote=引用 5 楼 user-3 的回复:] char *mat(char *a,char *b){     while(*a!='\0'){         if(*a++!=*b++)   //*a!=*b? a=a+1,b=b+1             return NULL;     }     return b; } [/quote]不能理解为把短的比较完，while循环只对a进行‘\0’末尾的判断，没有对b的判断，比如a长，b短，那么会一直比较下去，如果前面一直匹配，会和存储b之后的内存进行比较（未定义的结果）。


Question: 求助C语言的加密工具

OpenSSL

引用 3 楼 zhao4zhong1 的回复:因为该程序选用的是对称加密算法，所以解密就是对加密过的数据再次加密。对称加密算法

因为该程序选用的是对称加密算法，所以解密就是对加密过的数据再次加密。

引用 1 楼 zhao4zhong1 的回复:仅供参考#pragma comment(lib, "crypt32.lib") #pragma comment(lib, "advapi32.lib") #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define KEYLENGTH  0x00800000 void HandleError(char *s); //-------------------------------------------------------------------- //  These additional #define statements are required. #define ENCRYPT_ALGORITHM CALG_RC4 #define ENCRYPT_BLOCK_SIZE 8 //   Declare the function EncryptFile. The function definition //   follows main. BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword); //-------------------------------------------------------------------- //   Begin main. void main(void) {     CHAR szSource[100];     CHAR szDestination[100];     CHAR szPassword[100];     printf("Encrypt a file. \n\n");     printf("Enter the name of the file to be encrypted: ");     scanf("%s",szSource);     printf("Enter the name of the output file: ");     scanf("%s",szDestination);     printf("Enter the password:");     scanf("%s",szPassword);     //--------------------------------------------------------------------     // Call EncryptFile to do the actual encryption.     if(EncryptFile(szSource, szDestination, szPassword)) {         printf("Encryption of the file %s was a success. \n", szSource);         printf("The encrypted data is in file %s.\n",szDestination);     } else {         HandleError("Error encrypting file!");     } } // End of main //-------------------------------------------------------------------- //   Code for the function EncryptFile called by main. static BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword) //-------------------------------------------------------------------- //   Parameters passed are: //     szSource, the name of the input, a plaintext file. //     szDestination, the name of the output, an encrypted file to be //         created. //     szPassword, the password. {     //--------------------------------------------------------------------     //   Declare and initialize local variables.     FILE *hSource;     FILE *hDestination;     HCRYPTPROV hCryptProv;     HCRYPTKEY hKey;     HCRYPTHASH hHash;     PBYTE pbBuffer;     DWORD dwBlockLen;     DWORD dwBufferLen;     DWORD dwCount;     //--------------------------------------------------------------------     // Open source file.     if(hSource = fopen(szSource,"rb")) {         printf("The source plaintext file, %s, is open. \n", szSource);     } else {         HandleError("Error opening source plaintext file!");     }     //--------------------------------------------------------------------     // Open destination file.     if(hDestination = fopen(szDestination,"wb")) {         printf("Destination file %s is open. \n", szDestination);     } else {         HandleError("Error opening destination ciphertext file!");     }     //以下获得一个CSP句柄     if(CryptAcquireContext(                 &hCryptProv,                 NULL,               //NULL表示使用默认密钥容器，默认密钥容器名                 //为用户登陆名                 NULL,                 PROV_RSA_FULL,                 0)) {         printf("A cryptographic provider has been acquired. \n");     } else {         if(CryptAcquireContext(                     &hCryptProv,                     NULL,                     NULL,                     PROV_RSA_FULL,                     CRYPT_NEWKEYSET))//创建密钥容器         {             //创建密钥容器成功，并得到CSP句柄             printf("A new key container has been created.\n");         } else {             HandleError("Could not create a new key container.\n");         }     }     //--------------------------------------------------------------------     // 创建一个会话密钥（session key）     // 会话密钥也叫对称密钥，用于对称加密算法。     // （注: 一个Session是指从调用函数CryptAcquireContext到调用函数     //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程）     //--------------------------------------------------------------------     // Create a hash object.     if(CryptCreateHash(                 hCryptProv,                 CALG_MD5,                 0,                 0,                 &hHash)) {         printf("A hash object has been created. \n");     } else {         HandleError("Error during CryptCreateHash!\n");     }     //--------------------------------------------------------------------     // 用输入的密码产生一个散列     if(CryptHashData(                 hHash,                 (BYTE *)szPassword,                 strlen(szPassword),                 0)) {         printf("The password has been added to the hash. \n");     } else {         HandleError("Error during CryptHashData. \n");     }     //--------------------------------------------------------------------     // 通过散列生成会话密钥     if(CryptDeriveKey(                 hCryptProv,                 ENCRYPT_ALGORITHM,                 hHash,                 KEYLENGTH,                 &hKey)) {         printf("An encryption key is derived from the password hash. \n");     } else {         HandleError("Error during CryptDeriveKey!\n");     }     //--------------------------------------------------------------------     // Destroy the hash object.     CryptDestroyHash(hHash);     hHash = NULL;     //--------------------------------------------------------------------     //  The session key is now ready.     //--------------------------------------------------------------------     // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的，所以被加密的     // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的     // 数据长度。     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;     //--------------------------------------------------------------------     // Determine the block size. If a block cipher is used,     // it must have room for an extra block.     if(ENCRYPT_BLOCK_SIZE > 1)         dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;     else         dwBufferLen = dwBlockLen;     //--------------------------------------------------------------------     // Allocate memory.     if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {         printf("Memory has been allocated for the buffer. \n");     } else {         HandleError("Out of memory. \n");     }     //--------------------------------------------------------------------     // In a do loop, encrypt the source file and write to the source file.     do {         //--------------------------------------------------------------------         // Read up to dwBlockLen bytes from the source file.         dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);         if(ferror(hSource)) {             HandleError("Error reading plaintext!\n");         }         //--------------------------------------------------------------------         // 加密数据         if(!CryptEncrypt(                     hKey,           //密钥                     0,              //如果数据同时进行散列和加密，这里传入一个                     //散列对象                     feof(hSource),  //如果是最后一个被加密的块，输入TRUE.如果不是输.                     //入FALSE这里通过判断是否到文件尾来决定是否为                     //最后一块。                     0,              //保留                     pbBuffer,       //输入被加密数据，输出加密后的数据                     &dwCount,       //输入被加密数据实际长度，输出加密后数据长度                     dwBufferLen))   //pbBuffer的大小。         {             HandleError("Error during CryptEncrypt. \n");         }         //--------------------------------------------------------------------         // Write data to the destination file.         fwrite(pbBuffer, 1, dwCount, hDestination);         if(ferror(hDestination)) {             HandleError("Error writing ciphertext.");         }     } while(!feof(hSource));     //--------------------------------------------------------------------     //  End the do loop when the last block of the source file has been     //  read, encrypted, and written to the destination file.     //--------------------------------------------------------------------     // Close files.     if(hSource)         fclose(hSource);     if(hDestination)         fclose(hDestination);     //--------------------------------------------------------------------     // Free memory.     if(pbBuffer)         free(pbBuffer);     //--------------------------------------------------------------------     // Destroy session key.     if(hKey)         CryptDestroyKey(hKey);     //--------------------------------------------------------------------     // Destroy hash object.     if(hHash)         CryptDestroyHash(hHash);     //--------------------------------------------------------------------     // Release provider handle.     if(hCryptProv)         CryptReleaseContext(hCryptProv, 0);     return(TRUE); } // End of Encryptfile //-------------------------------------------------------------------- //  This example uses the function HandleError, a simple error //  handling function, to print an error message to the standard error //  (stderr) file and exit the program. //  For most applications, replace this function with one //  that does more extensive error reporting. void HandleError(char *s) {     fprintf(stderr,"An error occurred in running the program. \n");     fprintf(stderr,"%s\n",s);     fprintf(stderr, "Error number %x.\n", GetLastError());     fprintf(stderr, "Program terminating. \n");     exit(1); } // End of HandleError  有完整的解决方案么？此段代码只是加密过程，解密如何实现


Question: calloc 断错误问题

补充一点： 如果我放在linux虚拟机中运行就不会出现，放在嵌入式板子上运行过一段时间就会出现。

引用 9 楼 zxhuser-5 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 嵌入式应用的金科玉律： 初始化时，清理上次异常退出或掉电遗留下来的垃圾数据和垃圾资源、分配本次服务需要的所有资源（内存、文件句柄、连接、……）； 开始服务后，杜绝所有动态资源的分配和释放，轮流使用各资源； 不要也无需优雅地结束服务，拔掉电源即可。噗，拔掉电源即可。。。[/quote] http://bbs.csdn.net/topics/390787357

gcc 的 libc 的 malloc 是支持多线程, 问题在于楼主编译的时候是否指示编译器使用多线程，如果用的是gcc/g++编译多线程程序，需要加上-pthread 参数

引用 4 楼 zhao4zhong1 的回复:嵌入式应用的金科玉律： 初始化时，清理上次异常退出或掉电遗留下来的垃圾数据和垃圾资源、分配本次服务需要的所有资源（内存、文件句柄、连接、……）； 开始服务后，杜绝所有动态资源的分配和释放，轮流使用各资源； 不要也无需优雅地结束服务，拔掉电源即可。噗，拔掉电源即可。。。

引用 7 楼 whiskylife 的回复:[quote=引用 2 楼 wanght99 的回复:] 是不是多线程? 可能是多个线程同时调用内存管理函数了.  造成内存管理数据结构损坏.       是多线程的，内存管理数据结构损坏如何判断与避免呢？可以说说方法吗[/quote]  感觉在malloc和free里莫名其妙地出问题基本上都是这个原因, 有的环境下会出现类似 "double link corrupted"类似的提示. 以我有限了解, 想杜绝这种情况只能避免发生两个线程同时做堆内存操作.因为内存管理函数本身是不可重入的.

引用 2 楼 wanght99 的回复:是不是多线程? 可能是多个线程同时调用内存管理函数了.  造成内存管理数据结构损坏.       是多线程的，内存管理数据结构损坏如何判断与避免呢？可以说说方法吗

引用 3 楼 u010030181 的回复:个人认为： 你分配的内存对于嵌入式板子来说是否有点大？在PC上，由于内存比较大，可能就不会有问题，但嵌入式板子的内存应该比较小，即使是堆上的内存也比较少，你连续分配，再释放……可能就会有很多碎片，而这些碎片可能没有来得及及时整合成一大块，不一定就有一整块那么大的堆内存……所以导致内存分配失败……       确实有点大，但是内存分配失败，表现出来是断错误吗？可不可以从排查的手段入手，说说该如何排查？ 我可以试一下，把内存申请大小变小，看一下效果。

引用 4 楼 zhao4zhong1 的回复:嵌入式应用的金科玉律： 初始化时，清理上次异常退出或掉电遗留下来的垃圾数据和垃圾资源、分配本次服务需要的所有资源（内存、文件句柄、连接、……）； 开始服务后，杜绝所有动态资源的分配和释放，轮流使用各资源； 不要也无需优雅地结束服务，拔掉电源即可。           确实要杜绝出现这种频繁动态的操作内存，但是项目中已经是这样了。要改就要从整个方面来改了。暂时先略过这个。          我想问下，初始化时，清理上次异常退出或掉电遗留下来的垃圾数据和垃圾资源, 这个是如何做到的？


Question: 小弟刚学c，哪个大神帮我看看我这个程序哪错了

scanf("%d" "地址");

引用 2 楼 brookmill 的回复:scanf("%d",&stu[i].chinese); scanf("%d",&stu[i].math); scanf("%d",&stu[i].english); 谢谢，这样弄后就正常了

#include <stdlib.h> #include <stdio.h> #include <conio.h>  #define N 5 struct student { 	char no[9]; 	char name[10]; 	int chinese,math,english;  }stu[N];  int main( ) { 	FILE *fp; 	int i;  	if( ( fp = fopen( "test.txt", "w" ) ) == NULL ) 	{ 		printf( "error\n" ); 		getch( ); 		exit( 1 ); 	} 	for( i = 0; i < N; i++ ) 	{ 		printf( "\n学号 : " ); 		scanf( "%s", stu[i].no ); 		printf( "\n语文 : " ); 		scanf( "%d", stu[i].chinese ); 	printf( "\n姓名 : " ); 	scanf( "%s", stu[i].name ); 	printf( "\n数学 : " ); 	scanf( "%d", stu[i].math ); 	printf( "\n英语:" ); 	scanf( "%d", stu[i].english ); 	fprintf( fp, "%s %s %d %d %d\n", stu[i].no,stu[i].name, stu[i].chinese, stu[i].math, stu[i].english ); 	} 	fclose( fp ); 	return 0; } 两个问题: 1.使用了exit(1),需引入头文件 #include<stdlib.h> 2.main函数需要 return 0

conio.h没用，删掉吧。 main既然是int就该有返回值，最后加上return 0;

先说说怎么个错法呀，不然人家怎么帮你？


Question: socket 多线程写

用写缓存队列，逻辑线程将要写入socket的数据扔入队列，由专门的写socket线程从队列中取出并进行socket写入。队列可以采用信号量进行事件通知。  http://blog.csdn.net/truexf/article/details/38342983

理论上是不应该多线程同时对同一个socket发送数据的，这样加锁必然会影响多线程的效率，一般是由专门的线程负责recv和send，该线程维护一个接受队列和发送队列，将接受队列中的包派发给多个线程，处理完之后将结果放入发送队列

搞个收发缓冲队列。

1楼的主意挺好，应该有一个线程专门负责socket读写操作，这个逻辑上更清晰  当然加锁也是可以的，刚开始学习，从简单的来。 如果是计算密集形的程序，网络发送数据应该不是瓶颈

一个socket只让一个线程读和写。不应该多个线程都能对这个socket进行读或者写。 理由很简单，就像楼主的代码，如果多个线程都要操纵socket，然后用一个锁进行同步。假如send是阻塞的，多个线程同时想往socket写入数据，那么只有其中一个能调用send，其他线程只能被锁住，效率低。如果send是非阻塞的，那么可能发生A线程send一半数据就返回了，然后B线程接着send数据。这样会把数据搞乱的。  应该用一个线程专门负责socket的读和写。其他线程想写数据就把数据放到一个队列里面，然后那个负责socket读写的线程就去读这个队列，读到数据后就send。

仅供参考//循环向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; }


Question: vs2005/2008/2010 的 release编译时间

我在vs2005、2008、2010上每次都是 执行同样的“先clean  再bulid ”

比较重建所有的时间才有意义吧。


Question: 用C语言实现函数

引用 1 楼 cyd54454 的回复:复位的话，只要往该寄存器地址相应的位写值，延时1ms就行。*(volatile unsigned int *)0x6000000 &= ~(1 << 2);delay(1);大概就是这样的。 后面一题的话，自己写了一个，只测了几个简单的案例，仅做参考。思路是这样的：N/M*n(n=0...M)的整数部分刚好是下标号，小数部分是对应下标号的偏移，代码如下： void change_pixel(int old,int new) { 	int i;  	for(i = 0;i <= new;i++) 	{ 		int x = old*i/new; 		float offset = (float)old * i/ new - x;  		printf("Y%d, X%d, %f\n",i,x,offset); 	} }+1，我真不知道


Question: C语言中数据统计疑问？

i没有初始化...  and  printf ("The min is %d,max is %d   %f\n",min,max,(double)sum/i);

引用 5 楼 Idle_ 的回复:[quote=引用 4 楼 pingheng74 的回复:] [quote=引用 3 楼 Idle_ 的回复:] 1. scanf()返回值是成功获取的个数，因为你格式字符串中只有一个“%d”, 因此scanf()扫描到输入缓冲区中第一个非数字时就停止了并且返回了1表示成功获取了一个参数。这样while条件为真，循环继续执行。第二次scanf()时因为缓冲区中仍然有内容而且是数字，所以scanf()继续获取了一个参数，所以循环可以继续执行直到缓冲区中内容都被读完； 这也就是你循环第二次不需要继续输入的原因。  2. 因为你min, max没有初始化，其值是个随机数，因此进过循环后min, max并不能正确设置成你输入的数字，即if(x < min), if(x > max)不满足条件。  MSDN suggests using a different method if you need more accuracy:  To obtain metrics suitable for adjacent strings in layout (for example, when implementing formatted text), use the MeasureCharacterRanges method or one of the MeasureString methods that takes a StringFormat, and pass GenericTypographic. Also, ensure the TextRenderingHint for the Graphics is AntiAlias.   #include <stdio.h>  int main() { 	int i,n,sum=0,min=0,max=0; 	printf ("Please input number:\n"); 	while (scanf("%d",&n)==1) 	{ 		sum+=n; 		if (n<min)  min=n; 		if (n>max)  max=n; 		i++; 	} 	printf ("The min is %d,max is %d    %d\n",min,max,(double)sum/i); 	 } 为啥在这个里面(double)sum/i  输出的值好像是溢出了，咋了？  [/quote]  i没有初始化...[/quote] and  printf ("The min is %d,max is %d    [color=#FF0000]%f[/color]\n",min,max,(double)sum/i);

初始化工作没做好

引用 1 楼 user-6 的回复:max和min没有初始化。scanf好像是在输入缓冲区去读取数据，在你输入1，2，3后，scanf首先读取1，接着再在缓冲区中读取2。你可以搜索以下scanf。+1

引用 4 楼 pingheng74 的回复:[quote=引用 3 楼 Idle_ 的回复:] 1. scanf()返回值是成功获取的个数，因为你格式字符串中只有一个“%d”, 因此scanf()扫描到输入缓冲区中第一个非数字时就停止了并且返回了1表示成功获取了一个参数。这样while条件为真，循环继续执行。第二次scanf()时因为缓冲区中仍然有内容而且是数字，所以scanf()继续获取了一个参数，所以循环可以继续执行直到缓冲区中内容都被读完； 这也就是你循环第二次不需要继续输入的原因。  2. 因为你min, max没有初始化，其值是个随机数，因此进过循环后min, max并不能正确设置成你输入的数字，即if(x < min), if(x > max)不满足条件。  MSDN suggests using a different method if you need more accuracy:  To obtain metrics suitable for adjacent strings in layout (for example, when implementing formatted text), use the MeasureCharacterRanges method or one of the MeasureString methods that takes a StringFormat, and pass GenericTypographic. Also, ensure the TextRenderingHint for the Graphics is AntiAlias.   #include <stdio.h>  int main() { 	int i,n,sum=0,min=0,max=0; 	printf ("Please input number:\n"); 	while (scanf("%d",&n)==1) 	{ 		sum+=n; 		if (n<min)  min=n; 		if (n>max)  max=n; 		i++; 	} 	printf ("The min is %d,max is %d    %d\n",min,max,(double)sum/i); 	 } 为啥在这个里面(double)sum/i  输出的值好像是溢出了，咋了？  [/quote]  i没有初始化...

引用 3 楼 Idle_ 的回复:1. scanf()返回值是成功获取的个数，因为你格式字符串中只有一个“%d”, 因此scanf()扫描到输入缓冲区中第一个非数字时就停止了并且返回了1表示成功获取了一个参数。这样while条件为真，循环继续执行。第二次scanf()时因为缓冲区中仍然有内容而且是数字，所以scanf()继续获取了一个参数，所以循环可以继续执行直到缓冲区中内容都被读完； 这也就是你循环第二次不需要继续输入的原因。  2. 因为你min, max没有初始化，其值是个随机数，因此进过循环后min, max并不能正确设置成你输入的数字，即if(x < min), if(x > max)不满足条件。   #include <stdio.h>  int main() { 	int i,n,sum=0,min=0,max=0; 	printf ("Please input number:\n"); 	while (scanf("%d",&n)==1) 	{ 		sum+=n; 		if (n<min)  min=n; 		if (n>max)  max=n; 		i++; 	} 	printf ("The min is %d,max is %d    %d\n",min,max,(double)sum/i);  } 为啥在这个里面(double)sum/i  输出的值好像是溢出了，咋了？

为啥经常有人这么写 while (scanf("%d",&x)==1) 建议楼主可以去详细的了解scanf的用法


Question: 关于数据结构中的线性表

第一个函数应该是 void initList(List **l){    *l=(List *)malloc(sizeof(List));    (*l)->len=0;  }   第二个函数  l->a[j+1]=l->a[j]; 应该是  l->a[m+1]=l->a[m];


Question: 在Windows8命令行下bison: m4: Invalid argument

我也有这个问题。

引用 2 楼 singlett 的回复:这个说的应该是使用默认安装方式的目录安装的会有空格吧，我使用手动指定安装地址，应该不存在有空格的问题吧。谢谢 你参照哪个链接里说明的方式执行下，看看实际使用的路径是什么。那个问题定位也挺匪夷所思的。

引用 1 楼 truelance 的回复:据说是因为安装时自动加了个快捷方式，实际运行的路径是 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\GnuWin32\Bison 这个路径中有空格  建议的解决方法是 So, if you’re the same way, then this should work for you:  1.Copy C:\GnuWin32 (and subdirs) to a safe location  2.Run the bison uninstall (to remove the entry from the registry)  3.Ensure current C:\GnuWin32 does not exist  4.Ensure C:\ProgramData\Microsoft\Windows\Start Menu\Programs\GnuWin32 does not exist (those true docs will already be saved in the copy we made anyway, that will be restored to C:\GnuWin32)  5.Re-boot computer (because stale registry values will remain and thus a restart is necessary – this I also detected with Procmon)  6.Copy the saved GnuWin32 (and subdirs) back to C:\.  7.Ensure C:\GnuWin32\bin is in the $PATH for Windows.   出处:http://www.chriscalender.com/resolving-the-bison-exe-m4-invalid-argument-error-when-building-mysqlmariadbxtradb-on-windows/  这个说的应该是使用默认安装方式的目录安装的会有空格吧，我使用手动指定安装地址，应该不存在有空格的问题吧。谢谢


Question: 关于C语句显示的问题，请指教

*(ptr++)&=0xff; 相当于：  *ptr = *ptr & 0xff;   // 按位与 ptr++;   // 地址加1

还可以试试把ptr改成int类型： int i; ptr=(int*)data; for(i=0; i<5; i++) { *(ptr++)&=0xff;  // 把4字节int的高24位清0，保留最低8位 } 结果，data里面每4个字节会有3个变成0

每次ptr++，向前移动一个short int的大小。因为short int的大小是两个字节，所以每次ptr++就向前移动2字节。 循环之后，就把data里面原来的20个字节，作为10个short int，每个都把高8位清0，结果就是20个字节里面交错的有一半变成0了

&运算是按位与, 0xff是255, 表示只取最低的8位

*(ptr++)&=0xff;    这句语如何理解 一个2字节的短整数，把它的高8位清0，保留低8位不变。 比如，如果short int s = 0x1234，那么 s &= 0xff 之后 s变成0x34


Question: 字符串c

引用 8 楼 evanbao 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] /*** *strncpy.c - copy at most n characters of string * *       Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved. * *Purpose: *       defines strncpy() - copy at most n characters of string * *******************************************************************************/  #include <cruntime.h> #include <string.h>  /*** *char *strncpy(dest, source, count) - copy at most n characters * *Purpose: *       Copies count characters from the source string to the *       destination.  If count is less than the length of source, *       NO NULL CHARACTER is put onto the end of the copied string. *       If count is greater than the length of sources, dest is padded *       with null characters to length count. * * *Entry: *       char *dest - pointer to destination *       char *source - source string for copy *       unsigned count - max number of characters to copy * *Exit: *       returns dest * *Exceptions: * *******************************************************************************/  char * __cdecl strncpy (         char * dest,         const char * source,         size_t count         ) {         char *start = dest;          while (count && (*dest++ = *source++))    /* copy string */                 count--;          if (count)                              /* pad out with zeroes */                 while (--count)                         *dest++ = '\0';          return(start); }  弱弱的问一下，这个代码可以处理 src和dest内存地址比较靠近情况么？即src+sizeof(count*char)<dst[/quote] 请先弄清楚 copy和move的语义的不同之处： copy的意思是操作完成后，新目标和旧源相同，且旧源内容保持不变； move的意思是操作完成后，新目标和旧源相同，且旧源内容不一定保持不变； 所以根本不存在所谓源和目标内存重叠时可以实现的copy!

for + \0

引用 4 楼 zhao4zhong1 的回复:/*** *strncpy.c - copy at most n characters of string * *       Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved. * *Purpose: *       defines strncpy() - copy at most n characters of string * *******************************************************************************/  #include <cruntime.h> #include <string.h>  /*** *char *strncpy(dest, source, count) - copy at most n characters * *Purpose: *       Copies count characters from the source string to the *       destination.  If count is less than the length of source, *       NO NULL CHARACTER is put onto the end of the copied string. *       If count is greater than the length of sources, dest is padded *       with null characters to length count. * * *Entry: *       char *dest - pointer to destination *       char *source - source string for copy *       unsigned count - max number of characters to copy * *Exit: *       returns dest * *Exceptions: * *******************************************************************************/  char * __cdecl strncpy (         char * dest,         const char * source,         size_t count         ) {         char *start = dest;          while (count && (*dest++ = *source++))    /* copy string */                 count--;          if (count)                              /* pad out with zeroes */                 while (--count)                         *dest++ = '\0';          return(start); }  弱弱的问一下，这个代码可以处理 src和dest内存地址比较靠近情况么？即src+sizeof(count*char)<dst

恩库里面由函数的。strncpy

memmove呀

引用 4 楼 zhao4zhong1 的回复:[/code]赵老你就是积极

引用 2 楼 zxh707wk 的回复:自己写一个，这又不难 揍是，揍是，说的好像一定要帮他写出来似的

自己写一个，这又不难

不要直接用strncpy这个函数


Question: 请问整数显式比较(x>y)和隐式比较(x-y)的区别

课后习题的是对unsigned类型比较的 对signed类型比较不能用减法

感谢大家，在这说明一点，由于是第一次发帖子所以原码本身就有点问题，这点很抱歉，这里提供作者的原码 int cmpint(const void *x, const void *y) { 	if (**(int **)x < **(int **)y) 		return -1; 	else if (**(int **)x > **(int **)y) 		return +1; 	else 		return 0; } 至于为什么是 **(int **) 是因为cmpint主要用于 qsort中, 而需要做排序的是 int *a[]， 所以需要做这种转换

引用 10 楼 FancyMouse 的回复:[quote=引用 1 楼 u010030181 的回复:] [quote=引用 楼主 xccph2410 的回复:] 在c语言接口与实现中，作者的整数比较函数为 int cmpint( const void *x, const void *) 少了个y吧？你这样比较就少了一种相等的情况，你应该加上那就和下面的基本差不多了，下面这种就包含了相等的情况，返回值 <0得出*x < *y, =0得出*x = *y，>0得出*x > *y，当然下面的判断还是存在漏洞的，假如*x是一个很大的正整数,而*y是一个很大的负整数，这样一相减，就会超出int所能表示的范围，但貌似即使超出范围，也不会改变符号位，所以问题也不大，但一般我们也不会去考虑这种问题。[/quote] 为什么你连反例都想到了结论却是错的……溢出以后第一个改变的就是符号位啊。除非保证不会溢出，否则问题非常大。[/quote] 好吧，因为昨天简单测试了一下，发现符号位没有改变，但结果有点奇怪，就没多想……现在想想应该是位数没有达到溢出……

引用 11 楼 Zidane_2014 的回复:第一个没有考虑相等的情况。 第二个可能会产生溢出。  ++

第一个没有考虑相等的情况。 第二个可能会产生溢出。

引用 1 楼 u010030181 的回复:[quote=引用 楼主 xccph2410 的回复:] 在c语言接口与实现中，作者的整数比较函数为 int cmpint( const void *x, const void *) 少了个y吧？你这样比较就少了一种相等的情况，你应该加上那就和下面的基本差不多了，下面这种就包含了相等的情况，返回值 <0得出*x < *y, =0得出*x = *y，>0得出*x > *y，当然下面的判断还是存在漏洞的，假如*x是一个很大的正整数,而*y是一个很大的负整数，这样一相减，就会超出int所能表示的范围，但貌似即使超出范围，也不会改变符号位，所以问题也不大，但一般我们也不会去考虑这种问题。[/quote] 为什么你连反例都想到了结论却是错的……溢出以后第一个改变的就是符号位啊。除非保证不会溢出，否则问题非常大。

C中的compare一般要求：  a == b: 0 a < b : 负数  a  > b: 正数  第一个代码没有处理相等的情况

好精致的代码

引用 1 楼 u010030181 的回复:[quote=引用 楼主 xccph2410 的回复:] 在c语言接口与实现中，作者的整数比较函数为 int cmpint( const void *x, const void *) 少了个y吧？你这样比较就少了一种相等的情况，你应该加上那就和下面的基本差不多了，下面这种就包含了相等的情况，返回值 <0得出*x < *y, =0得出*x = *y，>0得出*x > *y，当然下面的判断还是存在漏洞的，假如*x是一个很大的正整数,而*y是一个很大的负整数，这样一相减，就会超出int所能表示的范围，但貌似即使超出范围，也不会改变符号位，所以问题也不大，但一般我们也不会去考虑这种问题。[/quote]+1，第二种有溢出的可能

引用 3 楼 lovesmiles 的回复:我倒是有个问题，指针变量x做二次**运行是什么意思？  且不说后者的返回值无法是+-1，还可能存在溢出的问题。 根本完成不了函数的作用，谈何效率 返回值什么时候要求只能是 +-1

第一个函数也没有考虑相等的情况，着实蛋疼

你的做法是错的 你没考虑 如果相等 返回多少

个人认为后者效率要高一点。 前者>比较，返回一个整形（其实>就是做个减法)，如果>成立，就返回1。然后还要对这个得到的整形判断，得到判断结果，然后将1返回。如果要执行到else if的语句，还有步骤。 后者直接将相减的结果返回。很有效率。

引用 楼主 xccph2410 的回复:在c语言接口与实现中，作者的整数比较函数为 int cmpint( const void *x, const void *) 少了个y吧？你这样比较就少了一种相等的情况，你应该加上那就和下面的基本差不多了，下面这种就包含了相等的情况，返回值 <0得出*x < *y, =0得出*x = *y，>0得出*x > *y，当然下面的判断还是存在漏洞的，假如*x是一个很大的正整数,而*y是一个很大的负整数，这样一相减，就会超出int所能表示的范围，但貌似即使超出范围，也不会改变符号位，所以问题也不大，但一般我们也不会去考虑这种问题。


Question: C语言中长整型的输出格式是否必须是%ld?

數字要再給大一點吧 = =

我把b值赋予35000  这个值应该超过了 int 范围了吧     但是 还是输出的c值没有问题

只是你赋值太小了，

你输个大于int最大值但小于long最大值的数看看

顶顶顶顶顶顶