Question: 各位大神看看我的C语言WIN32 俄罗斯方块 程序问题在哪。

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

我想问，用什么算法的，以前读书时候，我搞了好久搞不出来

一个控制台版本的俄罗斯方块，仅供参考

最好能调试一下，再有疑问的地方设断点，然后分析为什么没有发生你想要的情况。  所以如果贴的是代码，不是图片的话，别人也可以运行一下，直接看代码有些问题很难发现。

估计大神都吃饭去了吧。自己顶个吧。

新问题出现了 1,.防止左移出借那里 2.防止右移出界那里 3 落到底的块会闪，是定时器的原因吗？4还是hdc的问题，1楼。  谢谢所有大神！ /*=============加好注释了，大神请阅==============*/ #include <windows.h> #include "resource.h" #define ID_TIMER 1 LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wPARAM,LPARAM lParam); void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime); HDC hdc; HWND hwnd; HINSTANCE hins;  void zaokuai();//造块 void luokuai();//落块 void yideweizhi();//一的位置 void zuoyi();//左移 void youyi();//右移 void kuaisuluo();//快速落 BOOL nengluo();//能落不 void bsx();//变实心 void xsshixin();//显示实心  char as[20][10] = { 0 }; //初始化一个游戏界面的数组，20行，10列。 //窗口主函数 int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR pCmdline,int nCmdShow) { 	MSG msg; 	WNDCLASSEX cg; 	cg.cbClsExtra = 0; 	cg.cbWndExtra = 0; 	cg.cbSize = sizeof(WNDCLASSEX); 	cg.hCursor = LoadCursor(NULL,MAKEINTRESOURCE(IDC_NO)); 	cg.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 	cg.hIcon =LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); 	cg.hIconSm = NULL; 	cg.hInstance =hInstance; 	cg.lpfnWndProc = kkk; 	cg.lpszClassName = "HAHAHA"; 	cg.lpszMenuName = NULL; 	cg.style = CS_HREDRAW|CS_VREDRAW; 	  	RegisterClassEx(&cg); 	hwnd = CreateWindow("HAHAHA","俄罗斯",WS_OVERLAPPEDWINDOW,50,50,500,630+8,NULL,NULL,hInstance,NULL); 	ShowWindow(hwnd,nCmdShow); 	hins = hInstance; 	while(GetMessage(&msg,NULL,0,0)) 	{ 		TranslateMessage(&msg); 		DispatchMessage(&msg); 	} 	return 0; } //消息回传函数，定时器写外面了 LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { 	PAINTSTRUCT ps; 	switch(message) 	{ 	case WM_PAINT: 		hdc = BeginPaint(hwnd,&ps); 		SelectObject(hdc,GetStockObject(GRAY_BRUSH)); 		Rectangle(hdc,0,0,300,600);//画游戏界面和下一个块的现实界面 		Rectangle(hdc,320,20,470,170); 		zaokuai();//画块 		EndPaint(hwnd,&ps); 		break; 	case WM_COMMAND: 		switch(wParam) 		{ 		case 1001: 			MessageBox(NULL,"游戏开始！","确认",MB_OK);//开始键，还不能用 			break; 		} 		break; 	case WM_KEYDOWN: 		switch(wParam) 		{ 		case VK_LEFT: 			zuoyi(); 			break; 		case VK_RIGHT: 			youyi(); 			break; 		case VK_DOWN: 			kuaisuluo();//快速落 			break; 		} 		break; 	case WM_CREATE: 		yideweizhi(); 		SetTimer(hwnd,1,600,TimerPro);//设置定时器600ms下落 		CreateWindow("button","START",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,350,400,100,50,hwnd,(HMENU)1001,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		CreateWindow("static","分数：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,190,45,30,hwnd,(HMENU)1002,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		CreateWindow("static","等级：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,240,45,30,hwnd,(HMENU)1003,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		break; 	case WM_CLOSE: 		PostQuitMessage(0); 		KillTimer(hwnd,1); 		KillTimer(hwnd,2); 		break; 	} 	return DefWindowProc(hwnd,message,wParam,lParam); } //定时器消息回传函数 void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime) { 	hdc = GetDC(hwnd); 	SelectObject(hdc,GetStockObject(GRAY_BRUSH)); 	Rectangle(hdc,0,0,300,600); 	Rectangle(hdc,320,20,470,170); 	if(nengluo()) //判断是否能落，不能落则变实心 	{ 		luokuai(); 	} 	else 	{	MessageBeep(-1);//试验用 		bsx(); 	} 	zaokuai();//造块 	xsshixin();//显示实心 	ReleaseDC(hwnd,hdc); } //创建块 void zaokuai() { 	int hang, 		lie; 	char bs[10]; 	for (hang = 0;hang<20;hang++)//遍历所有行和列，如果有1就画出来。 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if (as[hang][lie]) 			{ 				SelectObject(hdc,GetStockObject(WHITE_PEN)); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				SelectObject(hdc,CreateSolidBrush(RGB(255,64,14))); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				 			}							 			 		} 	} }  //一的位置，有1就画一个块，这里是个向下的T型 void yideweizhi() { 	as[0][3] = 0;as[0][4] = 1;as[0][5] = 1;as[0][6] = 1; 	as[1][3] = 0;as[1][4] = 0;as[1][5] = 1;as[1][6] = 0; 	as[2][3] = 0;as[2][4] = 0;as[2][5] = 0;as[2][6] = 0; 	as[3][3] = 0;as[3][4] = 0;as[3][5] = 0;as[3][6] = 0; }  //让快不断下落 void luokuai() { 	int hang, 		lie; 	for (hang = 18;hang>=0;hang--)//遍历所有行和列，如果有1就下落 	{ 		for (lie = 0;lie <=10;lie++) 		{ 			if (1 == as[hang][lie]) 			{ 				as[hang+1][lie] = 1;//行加一实现下落 				as[hang][lie] = 0; 			} 		} 	} }  //左移 void zuoyi()//左移一直按着块向上移的问题解决了，原因是我遍历行的时候for循环是里写的是hang-- { 	int hang, 		lie; 	for (hang = 0;hang<20;hang++)//同上遍历，按下左键调用，有1就列减一 	{ 		for (lie = 1;lie <10;lie++) 		{ 			if (1 == as[hang][lie] && ( 0<lie&&lie<10 ) )//这里出问题了，防止超出左边边界但是继续左移都堆一起了，想不到办法 			{ 				as[hang][lie-1] = 1; 				as[hang][lie] = 0; 			} 		} 	} } //右移 void youyi() { 	int hang, 		lie; 	for (hang = 0;hang<20;hang++)//遍历所有行和列 	{ 		for (lie = 10;lie >=0;lie--) 		{ 			if (1 == as[hang][lie] && ( 0<lie&&lie<=10 ) )//这里出问题了，防止超出右边边界但是继续右移穿越到左边了，思维混乱 			{ 				as[hang][lie+1] = 1;//列加一 				as[hang][lie] = 0; 			} 		} 	} } //快速下落函数 void kuaisuluo() { 	KillTimer(hwnd,1); 	SetTimer(hwnd,2,10,TimerPro);//设置新的定时器2,10毫秒 } //能落不 BOOL nengluo() { 	int lie; 	for (lie = 0;lie <10;lie++)//扫列如果到了19行有1就停止， 	{ 		if ( 1 == as[19][lie] ) 		{ 			MessageBeep(-1);//提示音，试验用 			return FALSE; 		} 	} 	return TRUE;//不能让快到19行停止的问题解决了，原因是我把返回1写到for循环里了。 }  void bsx() //变实心，也就是落到底就置2， { 	int hang, 		lie; 	for (hang = 20;hang>=0;hang--)//遍历所有行和列 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if ( 1 == as[hang][lie] ) 			{ 				as[hang][lie] = 2;//调用时，如果确定不能落则置2， 			} 		} 	} } void xsshixin()//显示实心，把是2的块都画出来 { 	int hang, 		lie; 	for (hang = 20;hang>=0;hang--) 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if ( 2 == as[hang][lie] ) 			{ 				SelectObject(hdc,GetStockObject(WHITE_PEN)); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				SelectObject(hdc,CreateSolidBrush(RGB(255,255,0))); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 			} 		} 	} }

我现在加注释，大神见谅。稍等。

好长啊。。。。

这么长，又没一个注释。。。

我把格式调整一下吧 #include <windows.h> #include "resource.h" #define ID_TIMER 1 LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wPARAM,LPARAM lParam); void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime); HDC hdc ; HWND hwnd ; HINSTANCE hins ;  void zaokuai(); //造块 void luokuai(); //落块 void yideweizhi(); //一的位置 void zuoyi(); //左移 void youyi(); //右移 void kuaisuluo(); //快速落 BOOL nengluo(); //能落不 void bsx(); //变实心 void xsshixin(); //显示实心  char as[20][10]= {     0  } ; int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR pCmdline,int nCmdShow) {     MSG msg ;     WNDCLASSEX cg ;     cg.cbClsExtra=0 ;     cg.cbWndExtra=0 ;     cg.cbSize=sizeof(WNDCLASSEX);     cg.hCursor=LoadCursor(NULL,MAKEINTRESOURCE(IDC_NO));     cg.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);     cg.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));     cg.hIconSm=NULL ;     cg.hInstance=hInstance ;     cg.lpfnWndProc=kkk ;     cg.lpszClassName="HAHAHA" ;     cg.lpszMenuName=NULL ;     cg.style=CS_HREDRAW|CS_VREDRAW ;               RegisterClassEx(&cg);     hwnd=CreateWindow("HAHAHA","俄罗斯",WS_OVERLAPPEDWINDOW,50,50,500,630+8,NULL,NULL,hInstance,NULL);     ShowWindow(hwnd,nCmdShow);     hins=hInstance ;     while(GetMessage(&msg,NULL,0,0))     {         TranslateMessage(&msg);         DispatchMessage(&msg);     }     return 0 ; }  LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) {     PAINTSTRUCT ps ;     switch(message)     {         case WM_PAINT :         hdc=BeginPaint(hwnd,&ps);         SelectObject(hdc,GetStockObject(GRAY_BRUSH));         Rectangle(hdc,0,0,300,600);         Rectangle(hdc,320,20,470,170);         zaokuai();         EndPaint(hwnd,&ps);         break ;         case WM_COMMAND :         switch(wParam)         {             case 1001 :             MessageBox(NULL,"游戏开始！","确认",MB_OK);             break ;         }         break ;         case WM_KEYDOWN :         switch(wParam)         {             case VK_LEFT :             zuoyi();             break ;             case VK_RIGHT :             youyi();             break ;             case VK_DOWN :             kuaisuluo();             break ;         }         break ;         case WM_CREATE :         yideweizhi();         SetTimer(hwnd,1,600,TimerPro);         CreateWindow("button","START",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,350,400,100,50,hwnd,(HMENU)1001,((LPCREATESTRUCT)lParam)->hInstance,NULL);         CreateWindow("static","分数：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,190,45,30,hwnd,(HMENU)1002,((LPCREATESTRUCT)lParam)->hInstance,NULL);         CreateWindow("static","等级：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,240,45,30,hwnd,(HMENU)1003,((LPCREATESTRUCT)lParam)->hInstance,NULL);         break ;         case WM_CLOSE :         PostQuitMessage(0);         KillTimer(hwnd,1);         KillTimer(hwnd,2);         break ;     }     return DefWindowProc(hwnd,message,wParam,lParam); } void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime) {     hdc=GetDC(hwnd);     SelectObject(hdc,GetStockObject(GRAY_BRUSH));     Rectangle(hdc,0,0,300,600);     Rectangle(hdc,320,20,470,170);     if(nengluo())     {         luokuai();     }     else      {         MessageBeep(-1);         bsx();     }     zaokuai();     xsshixin();     ReleaseDC(hwnd,hdc); } void zaokuai() {     int hang,     lie ;     char bs[10];     for(hang=0;hang<20;hang++)     {         for(lie=0;lie<10;lie++)         {             if(as[hang][lie])             {                 SelectObject(hdc,GetStockObject(WHITE_PEN));                 Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30);                 SelectObject(hdc,CreateSolidBrush(RGB(255,64,14)));                 Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30);                              }                      }     } }  void yideweizhi() {     as[0][3]=0 ;     as[0][4]=1 ;     as[0][5]=1 ;     as[0][6]=1 ;     as[1][3]=0 ;     as[1][4]=0 ;     as[1][5]=1 ;     as[1][6]=0 ;     as[2][3]=0 ;     as[2][4]=0 ;     as[2][5]=0 ;     as[2][6]=0 ;     as[3][3]=0 ;     as[3][4]=0 ;     as[3][5]=0 ;     as[3][6]=0 ; }  void luokuai() {     int hang,     lie ;     for(hang=18;hang>=0;hang--)     {         for(lie=0;lie<=10;lie++)         {             if(1==as[hang][lie])             {                 as[hang+1][lie]=1 ;                 as[hang][lie]=0 ;             }         }     } }  void zuoyi() {     int hang,     lie ;     for(hang=18;hang>=0;hang--)     {         for(lie=0;lie<10;lie++)         {             if(1==as[hang][lie])             {                 as[hang][lie-1]=1 ;                 as[hang][lie]=0 ;             }         }     } }  void youyi() {     int hang,     lie ;     for(hang=18;hang>=0;hang--)     {         for(lie=10;lie>=0;lie--)         {             if(1==as[hang][lie])             {                 as[hang][lie+1]=1 ;                 as[hang][lie]=0 ;             }         }     } }  void kuaisuluo() {     KillTimer(hwnd,1);     SetTimer(hwnd,2,10,TimerPro); }  BOOL nengluo() {     int lie ;     for(lie=0;lie<10;lie++)     {         if(1==as[19][lie])         {             MessageBeep(-1);             return FALSE ;         }         else          {             //MessageBeep(-1);             return TRUE ;         }     } }  void bsx() {     int hang,     lie ;     for(hang=20;hang>=0;hang--)     {         for(lie=0;lie<10;lie++)         {             if(1==as[hang][lie])             {                 as[hang][lie]=2 ;             }         }     } } void xsshixin() {     int hang,     lie ;     for(hang=20;hang>=0;hang--)     {         for(lie=0;lie<10;lie++)         {             if(2==as[hang][lie])             {                 SelectObject(hdc,GetStockObject(WHITE_PEN));                 Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30);                 SelectObject(hdc,CreateSolidBrush(RGB(255,255,0)));                 Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30);             }         }     } }

我一开始贴代码发现格式乱了，所以贴的图片，代码如下 #include <windows.h> #include "resource.h" #define ID_TIMER 1 LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wPARAM,LPARAM lParam); void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime); HDC hdc; HWND hwnd; HINSTANCE hins;  void zaokuai();//造块 void luokuai();//落块 void yideweizhi();//一的位置 void zuoyi();//左移 void youyi();//右移 void kuaisuluo();//快速落 BOOL nengluo();//能落不 void bsx();//变实心 void xsshixin();//显示实心  char as[20][10] = { 0 }; int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR pCmdline,int nCmdShow) { 	MSG msg; 	WNDCLASSEX cg; 	cg.cbClsExtra = 0; 	cg.cbWndExtra = 0; 	cg.cbSize = sizeof(WNDCLASSEX); 	cg.hCursor = LoadCursor(NULL,MAKEINTRESOURCE(IDC_NO)); 	cg.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 	cg.hIcon =LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); 	cg.hIconSm = NULL; 	cg.hInstance =hInstance; 	cg.lpfnWndProc = kkk; 	cg.lpszClassName = "HAHAHA"; 	cg.lpszMenuName = NULL; 	cg.style = CS_HREDRAW|CS_VREDRAW; 	  	RegisterClassEx(&cg); 	hwnd = CreateWindow("HAHAHA","俄罗斯",WS_OVERLAPPEDWINDOW,50,50,500,630+8,NULL,NULL,hInstance,NULL); 	ShowWindow(hwnd,nCmdShow); 	hins = hInstance; 	while(GetMessage(&msg,NULL,0,0)) 	{ 		TranslateMessage(&msg); 		DispatchMessage(&msg); 	} 	return 0; }  LRESULT CALLBACK kkk(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { 	PAINTSTRUCT ps; 	switch(message) 	{ 	case WM_PAINT: 		hdc = BeginPaint(hwnd,&ps); 		SelectObject(hdc,GetStockObject(GRAY_BRUSH)); 		Rectangle(hdc,0,0,300,600); 		Rectangle(hdc,320,20,470,170); 		zaokuai(); 		EndPaint(hwnd,&ps); 		break; 	case WM_COMMAND: 		switch(wParam) 		{ 		case 1001: 			MessageBox(NULL,"游戏开始！","确认",MB_OK); 			break; 		} 		break; 	case WM_KEYDOWN: 		switch(wParam) 		{ 		case VK_LEFT: 			zuoyi(); 			break; 		case VK_RIGHT: 			youyi(); 			break; 		case VK_DOWN: 			kuaisuluo(); 			break; 		} 		break; 	case WM_CREATE: 		yideweizhi(); 		SetTimer(hwnd,1,600,TimerPro); 		CreateWindow("button","START",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,350,400,100,50,hwnd,(HMENU)1001,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		CreateWindow("static","分数：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,190,45,30,hwnd,(HMENU)1002,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		CreateWindow("static","等级：",WS_CHILD|WS_VISIBLE|SS_LEFT,350,240,45,30,hwnd,(HMENU)1003,((LPCREATESTRUCT) lParam)->hInstance,NULL); 		break; 	case WM_CLOSE: 		PostQuitMessage(0); 		KillTimer(hwnd,1); 		KillTimer(hwnd,2); 		break; 	} 	return DefWindowProc(hwnd,message,wParam,lParam); } void CALLBACK TimerPro(HWND hwnd,UINT message,UINT TimerId,DWORD nTime) { 	hdc = GetDC(hwnd); 	SelectObject(hdc,GetStockObject(GRAY_BRUSH)); 	Rectangle(hdc,0,0,300,600); 	Rectangle(hdc,320,20,470,170); 	if(nengluo()) 	{ 		luokuai();	 	} 	else 	{	MessageBeep(-1); 		bsx(); 	} 	zaokuai(); 	xsshixin(); 	ReleaseDC(hwnd,hdc); } void zaokuai() { 	int hang, 		lie; 	char bs[10]; 	for (hang = 0;hang<20;hang++) 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if (as[hang][lie]) 			{ 				SelectObject(hdc,GetStockObject(WHITE_PEN)); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				SelectObject(hdc,CreateSolidBrush(RGB(255,64,14))); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				 			}							 			 		} 	} }  void yideweizhi() { 	as[0][3] = 0;as[0][4] = 1;as[0][5] = 1;as[0][6] = 1; 	as[1][3] = 0;as[1][4] = 0;as[1][5] = 1;as[1][6] = 0; 	as[2][3] = 0;as[2][4] = 0;as[2][5] = 0;as[2][6] = 0; 	as[3][3] = 0;as[3][4] = 0;as[3][5] = 0;as[3][6] = 0; }  void luokuai() { 	int hang, 		lie; 	for (hang = 18;hang>=0;hang--) 	{ 		for (lie = 0;lie <=10;lie++) 		{ 			if (1 == as[hang][lie]) 			{ 				as[hang+1][lie] = 1; 				as[hang][lie] = 0; 			} 		} 	} }  void zuoyi() { 	int hang, 		lie; 	for (hang = 18;hang>=0;hang--) 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if (1 == as[hang][lie]) 			{ 				as[hang][lie-1] = 1; 				as[hang][lie] = 0; 			} 		} 	} }  void youyi() { 	int hang, 		lie; 	for (hang = 18;hang>=0;hang--) 	{ 		for (lie = 10;lie >=0;lie--) 		{ 			if (1 == as[hang][lie]) 			{ 				as[hang][lie+1] = 1; 				as[hang][lie] = 0; 			} 		} 	} }  void kuaisuluo() { 	KillTimer(hwnd,1); 	SetTimer(hwnd,2,10,TimerPro); }  BOOL nengluo() { 	int lie; 	for (lie = 0;lie <10;lie++) 	{ 		if ( 1 == as[19][lie] ) 		{ 			MessageBeep(-1); 			return FALSE; 		} 		else 		{			//MessageBeep(-1); 			return TRUE; 		} 	} }  void bsx() { 	int hang, 		lie; 	for (hang = 20;hang>=0;hang--) 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if ( 1 == as[hang][lie] ) 			{ 				as[hang][lie] = 2; 			} 		} 	} } void xsshixin() { 	int hang, 		lie; 	for (hang = 20;hang>=0;hang--) 	{ 		for (lie = 0;lie <10;lie++) 		{ 			if ( 2 == as[hang][lie] ) 			{ 				SelectObject(hdc,GetStockObject(WHITE_PEN)); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 				SelectObject(hdc,CreateSolidBrush(RGB(255,255,0))); 				Rectangle(hdc,lie*30,hang*30,lie*30+30,hang*30+30); 			} 		} 	} }

你直接上图片，我只好说，单步调试看看吧！图片看起来费劲，建议上代码


Question: C内存分配

一般来讲 堆区 栈区 全局区都是在一定的地址范围内

内存分配应该和系统的内存管理有关

函数参数，和函数内临时变量在栈中的地址和和编译器有关.


Question: 求C语言订单处理系统代码框架，大神帮帮忙

自己写啦

编了好久还是有问题

先将订单信息与订单明细建立两个结构体的数据结构。 然后编写处理函数，每一处理都是单独一个函数。


Question: 共享锁出现了个bug，找不到方法修改

引用 7 楼 Idle_ 的回复:[quote=引用 6 楼 u012879787 的回复:] [quote=引用 5 楼 Idle_ 的回复:] 更正一下，为防止减到负数：while( n && n == InterlockedCompareExchange(&IsReadOver, n-1, n) );  牛逼，你对windows底层，了解比较深刻了。  佩服[/quote]  其实开始认为用 if( InterlockedDecrement(&IsReadOver) < 0 ) InterlockedIncrement(&IsReadOver); 就可以达到目的。  后来仔细想了想发觉有漏洞，有造成写一次读超过3次的可能（极端情况下会读取无数次--只要两个线程切换时保持IsReadOver==-1的情况出现即在执行完If判断而未执行InterlockedIncrement时切换线程了），而不是防止出现IsReadOver<0的情况后最多出现写一次读3次（PS: 如果楼主的本来是希望写一次最多读2次的话那么Reader代码的逻辑是有问题的）[/quote]  if( InterlockedDecrement(&IsReadOver) < 0 ) InterlockedIncrement(&IsReadOver);   线程1， 线程2 2个读线程， 来执行这逻辑代码。  线程1， isreadeover由2变为1， 同时，线程2被中断，线程1 继续把1变为0.  此时候，线程2 把把0变成-1， 线程2把-1变成-2.然后线程1可能把-2变成-3. 等等，  都有可能性。   可以说，这代码非常糟糕，很烂。  根源在于：  读线程里的那个while循环  。    最好的法子是:    想有几个读者，就创建几个读者即可。

引用 6 楼 u012879787 的回复:[quote=引用 5 楼 Idle_ 的回复:] 更正一下，为防止减到负数：while( n && n == InterlockedCompareExchange(&IsReadOver, n-1, n) );  牛逼，你对windows底层，了解比较深刻了。  佩服[/quote]  其实开始认为用 if( InterlockedDecrement(&IsReadOver) < 0 ) InterlockedIncrement(&IsReadOver); 就可以达到目的。  后来仔细想了想发觉有漏洞，有造成写一次读超过3次的可能（极端情况下会读取无数次--只要两个线程切换时保持IsReadOver==-1的情况出现即在执行完If判断而未执行InterlockedIncrement时切换线程了），而不是防止出现IsReadOver<0的情况后最多出现写一次读3次（PS: 如果楼主的本来是希望写一次最多读2次的话那么Reader代码的逻辑是有问题的）

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

引用 5 楼 Idle_ 的回复:更正一下，为防止减到负数：while( n && n == InterlockedCompareExchange(&IsReadOver, n-1, n) );  牛逼，你对windows底层，了解比较深刻了。  佩服

有高手知道吗？

引用 3 楼 Idle_ 的回复:将InterlockedDecrement(&IsReadOver);换成： int n = IsReadOver; InterlockedCompareExchange(&IsReadOver, n-1, n); 即可  抱歉，应该用循环以保证能够减一：  do {     n = IsReadOver; } while( n == InterlockedCompareExchange(&IsReadOver, n-1, n) );


Question: 用C语言算打折的衣服

百度下printf，研究下输出格式。内容还是不少的，用于格式化输入还是很有用

做事儿的时候仔细心点总是好的，很多问题都需要自己去找解决办法，代码结果不对，首先静下心来审视一下自己写的代码，每句代表什么意思自己是否真的弄明白了，逻辑是否严密，自己可以先去查资料，实在不行的话再问人。

#include <stdio.h>  int main() { 	int n,sum=0; 	float total=0; 	printf ("Please input a number:\n"); 	scanf ("%d",&n); 	sum=95*n; 	if (sum>300) 	{ 		total=sum*0.85; 		printf ("The price is %.2f\n",total);////////////////////  	} 	else 	{ 		total=sum; 		printf ("The price is %.2f\n",total); 	} 	 	return 0;  } 你啊

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

引用 1 楼 u012421456 的回复:sum是int，你的%f.2??  我改后编程为下面： #include <stdio.h>  int main() { int n,sum=0; float total=0; printf ("Please input a number:\n"); scanf ("%d",&n); sum=95*n; if (sum>300) { total=sum*0.85; printf ("The price is %f.2\n",total); } else { total=sum; printf ("The price is %f.2\n",total); } }   改为这样，为什么结果是不理想？？？请大侠帮忙

应该是输入输出问题

仅供参考 #include <stdio.h>  int main() { 	int sum = 0; 	float total = 0; 	printf("Please input a number:\n"); 	scanf("%d", &sum); 	total = 95.0 * sum; 	if (total > 300.0) 	{ 		total = total*0.85; 	} 	printf("The price is %f.2\n", total); 	return 0; }

如果没理解错的话。。。原意应该是这个吧。。。。 格式问题楼上已经指正 if (sum>300) { total=sum*0.85; printf ("The price is %f.2\n",total);//应该是total，不应该是sum } else { total=sum; printf ("The price is %f.2\n",total);//应该是total，不应该是sum }

printf ("The price is %f.2\n",sum); sum 是int类型

楼主还是输入输出的格式问题啊！


Question: C语言中两点之间距离？

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  double sqrt( double x );

好快~

引用 3 楼 u012421456 的回复:C语言的输入输出都有格式要求，不同格式对应不同数据类型，这点需谨记 楼主这样的问题，其实仔细看看应该可以看出的，学习一门语言，初学时需要多练习，多看书，注意细节，注意全角半角等易错处+1

引用 1 楼 lx458004975 的回复:scanf ("%d%d%d%d",&x1,&x2,&y1,&y2); 改下吧scanf ("%f%f%f%f",&x1,&x2,&y1,&y2);  感谢大侠！


Question: 以下字符数组的定义为什么错误

字符串数组与字符数组..

char 只有分配到一个字符的内存空间，而"C","h","i","n","a"示字符串，在字母后面系统会自动加一个空格符，表示两个字符，所以"C","h","i","n","a"不能用char来存

char c[5]={"C","h","i","n","a"}  应该用‘’单引号，而不是双引号，双引号表示字符串了

目测是lz把字打错了

char c[5]={'c','h','i','n','a'};	//字符数组 char *c1[5]={"C","h","i","n","a"};  //字符串数组  for(int i=0; i<5; i++) { 	printf("%c-%s\n", c[i], c1[i]); }

楼主现在该是酱紫

那书是著名的坑人宝典。

引用 4 楼 yagamil 的回复:[quote=引用 楼主 yagamil 的回复:] char c[5]={"C","h","i","n","a"} 为什么错误的？  我是看的 程序员面试宝典这本书。。。 引用 1 楼 user-11 的回复:'C'是字符， "C"是字符串。 这个应该是正解~~~~~[/quote]  顶一下

引用 楼主 yagamil 的回复:char c[5]={"C","h","i","n","a"} 为什么错误的？  我是看的 程序员面试宝典这本书。。。 引用 1 楼 user-11 的回复:'C'是字符， "C"是字符串。 这个应该是正解~~~~~

还有就是使用字符数组表示字符串，结尾需有一个\0，像你要表示字符串“hello”，数组至少需要6个位置，关于字符串，可以看看这个——http://blog.csdn.net/u012421456/article/details/38645335

如何你没看错的话，那就换一本书吧！

'C'是字符， "C"是字符串。


Question: 关于“resource.h"里的资源文件代码~~~~求解

英语也是一门计算机语言的说。

谢谢！~~~

引用Defines a left-aligned text control. 定义一个左对齐的文本控件。

引用 1 楼 user-3 的回复:http://msdn.microsoft.com/library/office/aa381021.aspx 哥哥，我英语烂啊~~~能解释下不？


Question: 单链表构建问题

引用 7 楼 Kai_gai 的回复:[quote=引用 6 楼 u012549504 的回复:] [quote=引用 5 楼 Kai_gai 的回复:] [quote=引用 4 楼 Kai_gai 的回复:]  #include <stdio.h> #include <stdlib.h>  typedef struct LNode {     int data;     struct LNode *next; } LNode, *LinkList;  LNode *CreateLink(LNode **L, int n) {     LinkList p, head;     int i;      *L = (LNode *)malloc(sizeof(LNode));     (*L)->next = NULL;     (*L)->data = 19;      head = *L;      for (i = 0; i < n; ++i) {         p = (LNode *)malloc(sizeof(LNode));         p->data = i;         p->next = NULL;          head->next = p;         head = p;             }          return *L; }  int main(int argc, char *argv[]) {     LinkList L, p;     CreateLink(&L, 10);      p = L;     while (p) {         printf("%d\n", p->data);         p = p->next;     }      return 0; } 你传入的LNode *L只是一个形式参数，并不能取回你在CreateList中创建的头借点，可以利用二级指针实现[/quote] 有点似懂非懂，有没有哪方面的书或资料可以推荐的..（不是传入指针就会对指针直接操作吗？）[/quote]  传入的指针只是一个形式参数，可以看网易上的一个视频，编程范式，他对c语言指针讲解非常详细。[/quote] 我明白你的意思了。传入的值只是L的一份拷贝，对吧？要取L的地址作为参数传入对吧...

引用 2 楼 Idle_ 的回复:main()中： LinkList L;   -->L位于栈上，内容是随机数，即L是个不知道指向哪里的无效指针 CreatLink(L,10);  -->L被复制到栈上另一个位置作为CreateLink的参数传入CreateLink  CreatLink()中： L = (LinkList)malloc(sizeof(LNode));  L的内容被替换成动态分配的内存首指针，注意，这个L位于栈上传入参数的位置，函数返回时所有传入参数在栈上的数据失效，即你动态分配的内存泄漏  函数返回后main(）中L的内容还是原来那个随机数--不知道指向哪里的无效指针， 随后你循环访问L指向的内容。。。 你运气真好，竟然可以打印两个数程序才死 貌似你讲的最清楚哎！

仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #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-> //

楼上几位说得很对啊， 你改变的只是一个形参。

引用 10 楼 u010539072 的回复:http://pan.baidu.com/s/17yIcQ用的什么编译器？我vc++6.0看了乱码呀[/quote]用记事本打开看看，我这用vs打开没啥问题啊，可能是编码问题，你转一下编码试试

引用 9 楼 zxh707wk 的回复:仅供参考 http://pan.baidu.com/s/17yIcQ用的什么编译器？我vc++6.0看了乱码呀

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

用指针做参数小心点，特别是数组链表这样的，一般只有一小块内存4个字节的

引用 6 楼 u012549504 的回复:[quote=引用 5 楼 Kai_gai 的回复:] [quote=引用 4 楼 Kai_gai 的回复:]  #include <stdio.h> #include <stdlib.h>  typedef struct LNode {     int data;     struct LNode *next; } LNode, *LinkList;  LNode *CreateLink(LNode **L, int n) {     LinkList p, head;     int i;      *L = (LNode *)malloc(sizeof(LNode));     (*L)->next = NULL;     (*L)->data = 19;      head = *L;      for (i = 0; i < n; ++i) {         p = (LNode *)malloc(sizeof(LNode));         p->data = i;         p->next = NULL;          head->next = p;         head = p;             }          return *L; }  int main(int argc, char *argv[]) {     LinkList L, p;     CreateLink(&L, 10);      p = L;     while (p) {         printf("%d\n", p->data);         p = p->next;     }      return 0; } 你传入的LNode *L只是一个形式参数，并不能取回你在CreateList中创建的头借点，可以利用二级指针实现[/quote] 有点似懂非懂，有没有哪方面的书或资料可以推荐的..（不是传入指针就会对指针直接操作吗？）[/quote]  传入的指针只是一个形式参数，可以看网易上的一个视频，编程范式，他对c语言指针讲解非常详细。

引用 5 楼 Kai_gai 的回复:[quote=引用 4 楼 Kai_gai 的回复:]  #include <stdio.h> #include <stdlib.h>  typedef struct LNode {     int data;     struct LNode *next; } LNode, *LinkList;  LNode *CreateLink(LNode **L, int n) {     LinkList p, head;     int i;      *L = (LNode *)malloc(sizeof(LNode));     (*L)->next = NULL;     (*L)->data = 19;      head = *L;      for (i = 0; i < n; ++i) {         p = (LNode *)malloc(sizeof(LNode));         p->data = i;         p->next = NULL;          head->next = p;         head = p;             }          return *L; }  int main(int argc, char *argv[]) {     LinkList L, p;     CreateLink(&L, 10);      p = L;     while (p) {         printf("%d\n", p->data);         p = p->next;     }      return 0; } 你传入的LNode *L只是一个形式参数，并不能取回你在CreateList中创建的头借点，可以利用二级指针实现[/quote] 有点似懂非懂，有没有哪方面的书或资料可以推荐的..（不是传入指针就会对指针直接操作吗？）

引用 4 楼 Kai_gai 的回复: #include <stdio.h> #include <stdlib.h>  typedef struct LNode {     int data;     struct LNode *next; } LNode, *LinkList;  LNode *CreateLink(LNode **L, int n) {     LinkList p, head;     int i;      *L = (LNode *)malloc(sizeof(LNode));     (*L)->next = NULL;     (*L)->data = 19;      head = *L;      for (i = 0; i < n; ++i) {         p = (LNode *)malloc(sizeof(LNode));         p->data = i;         p->next = NULL;          head->next = p;         head = p;             }          return *L; }  int main(int argc, char *argv[]) {     LinkList L, p;     CreateLink(&L, 10);      p = L;     while (p) {         printf("%d\n", p->data);         p = p->next;     }      return 0; } 你传入的LNode *L只是一个形式参数，并不能取回你在CreateList中创建的头借点，可以利用二级指针实现

Head->next = p;   Head = p;  你的头指针指向了倒数第二个了 你应该保存下你的头指针

LNode* CreatLink(LNode*&L,int n)///建立链表


Question: C语言include<> 路径问题

引用 3 楼 q332010372 的回复:可以加绝对路径，如果不加绝对路径，编译器就会根据工程配置里的 include 默认路径去寻找，最后三个是因为这三个头文件是在默认路径下的三个不同的文件夹里面 绝对路径不适合的，遇到问题很麻烦的，写好的项目在别人哪里如何运行？？ 一般都用相对路径的

引用 3 楼 q332010372 的回复:可以加绝对路径，如果不加绝对路径，编译器就会根据工程配置里的 include 默认路径去寻找，最后三个是因为这三个头文件是在默认路径下的三个不同的文件夹里面 其实都在/usr/include 下

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……

相对路径嘛  以Linux为例 #include <errno.h> 实际包含的是 /usr/include/errno.h  #include <sys/ioctl.h> 实际包含的是 /usr/include/sys/ioctl.h

引用 1 楼 cfjtaishan 的回复:后面三个不同的地方时这是三个头文件都在自己独立的目录里。而这些目录和上面的头文件在相同的路径下。所以，需要加上相对路径了。+1


Question: malloc有什么用啊？各位快来帮小弟看一下这段代码。

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

引用 9 楼 u012421456 的回复:引用 3 楼 zxh707wk 的回复:[quote=引用 1 楼 xhw88398569 的回复:] 指针的原因，a.name,和b.name指向的是同一地址+1 你怎么经常性的回复+1啊[/quote]我想说的他都说了，我不+1那干啥

用处可大了呢

引用 3 楼 zxh707wk 的回复:引用 1 楼 xhw88398569 的回复:指针的原因，a.name,和b.name指向的是同一地址+1 你怎么经常性的回复+1啊

刚发现上面给出答案了

引用 4 楼 pingheng74 的回复:[quote=引用 1 楼 xhw88398569 的回复:] 指针的原因，a.name,和b.name指向的是同一地址  既然a.name,和b.name指向的是同一地址，那么为什么a.name和b.name的值不是zhao而是qian？[/quote] 你一开始在这个地址存放的是zhao，后来又存放qian，当然覆盖了 就像你如果令i = 9；后面有一个i= 7；最后i当然是7了

引用 4 楼 pingheng74 的回复:[quote=引用 1 楼 xhw88398569 的回复:] 指针的原因，a.name,和b.name指向的是同一地址  既然a.name,和b.name指向的是同一地址，那么为什么a.name和b.name的值不是zhao而是qian？[/quote] qian是因为后面的是qian，然后两个是同一个地址，就覆盖了，输出来就是那个了，你看看上面那个代码，重开了空间，这样就是两个地址了

加个重载赋值运算符就行了，那个是开空间的，需要用到深拷贝，这里给你，你参考下 #include<stdio.h> #include<stdlib.h> #include<string.h>  struct stu {     char *name, gender;     int score;     /*重载赋值运算符开始*/     stu&operator=(struct stu &b)     {         if (this!=&b)         {             delete name;             name=(char *)malloc(10);             strcpy(name,b.name);         }         return *this;     }     /*重载赋值运算符结束*/ };  int main() {     struct stu a = {NULL, 'm', 290}, b;     a.name = (char *)malloc(10);     strcpy(a.name, "zhao");          b = a;     b.gender = 'f';     b.score = 350;     strcpy(b.name, "qian");          printf("%s, %c, %d\n", a.name, a.gender, a.score);     printf("%s, %c, %d\n", b.name, b.gender, b.score); }

引用 1 楼 xhw88398569 的回复:指针的原因，a.name,和b.name指向的是同一地址  既然a.name,和b.name指向的是同一地址，那么为什么a.name和b.name的值不是zhao而是qian？

应为你用了b = a;百度搜一下“深拷贝，浅拷贝”。。。

指针的原因，a.name,和b.name指向的是同一地址


Question: error C2440: “=”: 无法从“int”转换为“TCHAR [21]”

引用 9 楼 xxsnihao 的回复:。。。。老大 能帮我写下吗 该怎么执行啊 我就像AAA= 我爱你 就可以char *AAA = "我爱你";//char AAA[7] = "我爱你"; if(strcmp(m_strTeleport[tIndex].TelName, AAA == 0)  {      //执行代码  }

引用 2 楼 user-3 的回复:if(strcmp(m_strTeleport[tIndex].TelName, "我爱你") == 0) {     //执行代码 }+1

。。。。老大 能帮我写下吗 该怎么执行啊 我就像AAA= 我爱你 就可以

引用 5 楼 xxsnihao 的回复:如果想把 我爱你 设置成一个变量该怎么弄呢  int AAA = "我爱你"; if(strcmp(m_strTeleport[tIndex].TelName, AAA == 0)  {      //执行代码  }   呵呵这样可以吗int坑定是放不下的，而且不好输出

引用 5 楼 xxsnihao 的回复:如果想把 我爱你 设置成一个变量该怎么弄呢  int AAA = "我爱你"; if(strcmp(m_strTeleport[tIndex].TelName, AAA == 0)  {      //执行代码  }   呵呵这样可以吗一个汉字占两个字节，自己需要多少可以算下，后面记得+1（还有个"\0"）

引用 5 楼 xxsnihao 的回复:如果想把 我爱你 设置成一个变量该怎么弄呢  int AAA = "我爱你"; if(strcmp(m_strTeleport[tIndex].TelName, AAA == 0)  {      //执行代码  }   呵呵这样可以吗char AAA[1024]

非常感谢 论坛的大神些太热心了

引用 2 楼 user-3 的回复:if(strcmp(m_strTeleport[tIndex].TelName, "我爱你") == 0) {     //执行代码 }好方法

我爱你  是文字类型的


Question: C语言 处理数据

//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

引用 3 楼 SUXIN091237 的回复:一楼 我两个字节的校验和位 0x 00 00  如果校验和要是超出了用C语言应该怎么处理 ？ 谢谢  超出部分就没有了  比如0x12345678  变成0x00007856  另外追问请用引用，要不我不看帖子是不知道你有新问题的

将i的2进制的 0-7位 与 8-15位 互换位置  如 0x1234 变为 0x3412


Question: C在什么情况下使用预定义函数

引用 3 楼 zhao4zhong1 的回复:VS IDE中，在不明白的符号上点鼠标右键，选转到定义。+1，这个功能发现挺好用的

楼主最好上个例子

预定义函数是指用宏来实现函数功能吧。  现在C++都是用inline来实现。不推荐用宏了。

说不定在预定义里的其实是C的文件。。。

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

引用 5 楼 Damon_hoo 的回复:这个是百度上的，感觉说的挺好的 1.使用预定义，可以实现函数的移植。 不管在各个种平台上，都可以实现： #define TRUE 1 #define FALSE 0 #define long INT  #define int INT //有的机器int与short的长度相同 #define short SHORT 2.使用预定义可以定义一些简单的函数,且效率很高。因为编译完成替换 #define MIN(a,b) ((a)<(b)?(a):(b)) 3.使用预定义可以防止头文件重复编译。 #ifndef _H_HEAD_H_  #define _H_HEAD_H_ aa  .... //相应的头文件内容 #endif  说的好！

来个例子说说，你说的难道是 ifndef/define/endif？

引用预定义中实现 头文件？


Question: readconsoleinput如何接收中文？

要接收ASCII码很简，读取KeyEvent.uChar.AsciiChar就行,但接收Unicode字符(如汉字)不是简单地读KeyEvent.uChar.UnicodeChar。  其实主要接收的过程了解了就很容易实现，我也是试了很久才知道怎么一回事。有时真不明白，这么简单的事在网上竟然找不到！！  大概过程：按Ctrl＋空格键 启动中文输入法后，输入一个汉字时，会连续两次发送Unicode码。每个Unicode码只是这个汉字的一半，8个位，所以我们直接读取后然后输出是不能正常显示的，而是要经过组合！！嘿嘿。  简单给个代码吧：  用一个循环读取系统消息：  HANDLE hOut;//标准输出句柄  HANDLE hIn;//标准输入句柄  wchar_t wchar;//宽字符，就是unsigned short;  char gchar[3];  string text;//  ........  DWORD res;  INPUT_RECORD InputRec;//存放消息，包括Key和Mouse  KEY_EVENT_RECORD KeyEvent;  MOUSE_EVENT_RECORD MouseEvent;  while(1) // 循环  {  ReadConsoleInput(hIn, &InputRec, 1, &res);  KeyEvent=InputRec.Event.KeyEvent;  MouseEvent=InputRec.Event.MouseEvent;  if (InputRec.EventType == KEY_EVENT)//键盘事件  ReadKeyEvent(KeyEvent);  if (InputRec.EventType == MOUSE_EVENT)//鼠标事件  ReadMouseEvent(MouseEvent);  }  在ReadKeyEvent()函数中接收处理键盘消息  void ReadKeyEvent(KEY_EVENT_RECORD &KeyEvent)  {  ......  if(KeyEvent.bKeyDown){//键盘按下时接收  wchar=KeyEvent.uChar.UnicodeChar;  if(wchar>127){//如果是Unicode码..连续接收两个  if(gchar[0]=='\0'){  gchar[0]=wchar;//Unicode字符的前8位  return;//返回继续接收后8位  }  else {  gchar[1]=wchar;//后8位  gchar[2]='\0';  text+=gchar;//接收到中文  gchar[0]='\0';  //在屏幕输出text  }  }

中文不是KeyEvent


楼主不妨亲自打开include\tchar.h看个究竟。

主要和你工程设置为Unicode有关， CreateFile实际调用的是 CreateFileW   现在一般建议不要使用_T宏来修饰字符串  char 单字节字符串    char *cComName = "COM4"; wchar_t 双字节字符串 wchar_t *cComName = L"COM4";

wchar_t是宽字节字符 char是普通字符 可以参考里面的内容 http://www.cnblogs.com/fire-phoenix/archive/2010/09/04/1818248.html   在使用时最终调用的是 CreateFile((LPCWSTR)portname  就要去protname的名称是wchar_t类型，所以出现了你说的问题。

求指教!!!!!!!!!!


Question: 初学者想问一个C语言的问题

引用 6 楼 chybeyond123456789 的回复:fflush(stdin); 我明白了，读取失败的数据会存到缓冲区，下一次读入的时候自动读取缓冲区的内容，所以不会有从键盘输入内容的机会。那应该还有一个办法解决，就是char ch;  while ((ch = getchar()) != '\n')  putchar(ch);也可以清空缓冲区。谢谢啦

fflush(stdin);

引用 2 楼 lovesmiles 的回复:while ((scanf_s("%d %d", &low, &up)) != 2)这句话决定了必须要输入两个整数 那应该怎么改正呢？

额，改正一下， 如果想继续的话，应该在while循环的最后加continue

在while里面加一个break即可


Question: .exe停止工作

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。 #include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G

#include<stdio.h> #include<stdlib.h> #include <string.h>  typedef struct note { 	int data; 	struct note *left,*right; } BTnode;  BTnode *CreateTree(int Data[],int n) {   	BTnode *root,*current,*parent,*insert; 	int loop;  	//创建根节点 	root=(BTnode *)malloc(sizeof(BTnode)); 	root->data=Data[0]; 	root->left=root->right=NULL; 	current=root;  	for (loop=1;loop<n;++loop) 	{ 		insert=(BTnode *)malloc(sizeof(BTnode)); 		memset(insert, 0, sizeof(BTnode));  		insert->data=Data[loop]; 		insert->left=insert->right=NULL; 		current=root;  		while (current) 		{ 			parent=current;  			if	(current->data > insert->data) 				current=current->left; 			else  				current=current->right; 		}   		if (parent->data > insert->data) 			parent->left=insert; 		else  			parent->right=insert; 	}  	return root; }  void Forder(BTnode *root) {   	if (root) 	{  		printf("%5d",root->data); 		Forder(root->left); 		Forder(root->right); 	} } void Inorder(BTnode *root) {  	if (root)  	{  		Forder(root->left); 		printf("%3d",root->data); 		Forder(root->right); 	} } void FDorder(BTnode *root) {    	if(root) 	{ 		Forder(root->left); 		Forder(root->right); 		printf("%2d",root->data); 	} }  int main(void) {  	int Data[8]={6,4,3,8,2,9,5,7}; 	BTnode *root; 	//创建二叉树 	 	root=CreateTree(Data,8); 	Inorder(root); 	 	printf("\n\n"); 	Forder(root); 	 	printf("\n");  	system("pause"); 	return 0; }  插入那段有问题，先遍历整个二叉树到叶子节点。然后执行插入

只能输出5 6 7

-------------------Configuration: 8 - Win32 Debug-------------------- Compiling... 6.cpp  6.obj - 0 error(s), 0 warning(s)

仔细检查一下看是不是少或多了*什么的，看不出来建议单步调试试试

以调试方式运行程序，看哪行报错。  如果用的是Visual C++，按f5，或者点start debug。


Question: 编译原理、操作系统看哪本书好？

《数据结构（C语言描述）》 《算法精解（C语言描述）》 《编译原理》（红书？） 《30天自制操作系统》 《Windows核心编程》 《深入解析Windows操作系统-Windows Internals》 很高兴楼主认可我这个“模板”。


Question: switch语句结束后加return false是什么意思

函数的返回值，不写有警告。 个人认为是编码规范问题。 例如有一天你把swich删除，就会编译错误了。

当switch条件一条都没有满足时, 就return false.   就是这个意思

主要用DEBUG下没有返回值，其实可以将该句移至DEBUG下。这样看可以更加清楚。

是最后的返回值

那只是一个函数返回值，就像int main最后的return 0一样

函数类型是布尔型，return返回一个false。3楼正解

其实switch中有default已经能把所有情况都处理了 最后一个return是为了消除编译警告吧 如果改成if-else结构就不需要了

意思就是函数默认返回false.   return serialize_hello6(message, ifp);  是返回函数的返回值

引用 3 楼 huoqingna2332 的回复:这下能看清楚了吧，最后那个return false是函数本身的返回值，和switch语句没关系。  [quote=引用 2 楼 huoqingna2332 的回复:]  bool queue_hello(struct hello_message * message, struct interface * ifp)  { #ifdef DEBUG   	OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name); #endif   	switch (olsr_cnf->ip_version)  	{   		case (AF_INET6):    			return serialize_hello6(message, ifp);  		case (AF_INET):   		default:     			return serialize_hello4(message, ifp);  	}  	return false; } [/quote]return false;和return serialize_hello6(message, ifp);  有差别吗？

int foo() { puts("132"); return 0; } puts语句结束后加return 0;是什么意思啊  楼主你体会一下

这下能看清楚了吧，最后那个return false是函数本身的返回值，和switch语句没关系。  引用 2 楼 huoqingna2332 的回复: bool queue_hello(struct hello_message * message, struct interface * ifp)  { #ifdef DEBUG   	OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name); #endif   	switch (olsr_cnf->ip_version)  	{   		case (AF_INET6):    			return serialize_hello6(message, ifp);  		case (AF_INET):   		default:     			return serialize_hello4(message, ifp);  	}  	return false; }

bool queue_hello(struct hello_message * message, struct interface * ifp)  { #ifdef DEBUG   	OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name); #endif   	switch (olsr_cnf->ip_version)  	{   		case (AF_INET6):    			return serialize_hello6(message, ifp);  		case (AF_INET):   		default:     			return serialize_hello4(message, ifp);  	} 	return false; }   这下能看清楚了吧，最后那个return false是函数本身的返回值，和switch语句没关系。


Question: 请告诉我为何输入字母也有输出？

引用 7 楼 Kai_gai 的回复:[quote=引用 5 楼 Heiok 的回复:] [quote=引用 3 楼 Kai_gai 的回复:] val没有初始化，其值是随机的，楼主可以单步调试查看val的值，也可将val打印出来。  多谢各位，int val = 0; 后输入字母就OK了。但不初始化，为何就是2层，我输出val看了也是2.为何不是其他数字？[/quote] 程序在释放内存时，并不会擦除内存中的数据，只是简单的将其标记为可用。你再次运行程序时，它刚好正是你上次使用的那块内存，还未被其他程序使用。你可以等一段时间，在运行看看，它就有可能不是2了。[/quote]  不如你们自己试试？反下我试了两台机器，反复试了各种数字，他就是存2.

引用 5 楼 Heiok 的回复:[quote=引用 3 楼 Kai_gai 的回复:] val没有初始化，其值是随机的，楼主可以单步调试查看val的值，也可将val打印出来。  多谢各位，int val = 0; 后输入字母就OK了。但不初始化，为何就是2层，我输出val看了也是2.为何不是其他数字？[/quote] 程序在释放内存时，并不会擦除内存中的数据，只是简单的将其标记为可用。你再次运行程序时，它刚好正是你上次使用的那块内存，还未被其他程序使用。你可以等一段时间，在运行看看，它就有可能不是2了。

是不是你之前是用2测试的，正确了，然后又用字母再测试。因为字母不是%d的类型，所以没有输入，val的值还是上一个有效输入的值。

引用 3 楼 Kai_gai 的回复:val没有初始化，其值是随机的，楼主可以单步调试查看val的值，也可将val打印出来。  多谢各位，int val = 0; 后输入字母就OK了。但不初始化，为何就是2层，我输出val看了也是2.为何不是其他数字？

新建变量时切记要给变量赋初值

val没有初始化， 也没有正确输入。

因为 val 一直有值  只是你输入字母的时候 val 存储的值是什么没人能确定罢了


Question: C语言求助！！！高分给

仅供参考 按学校名、班名、成绩三级排序 http://pan.baidu.com/s/1ntuNH0X

#include <stdio.h> #include <stdlib.h> #include <string.h> int main () {   char c[1024] = { };   FILE *fp = NULL;   fp = fopen ("file.txt", "r");     printf ("-------print the file ------\n");   while (fgets (c, sizeof (c), fp) != NULL)   {       printf ("%s", c);   }   printf ("\n------------------------------\n");   fclose(fp);   return 0; }  比较简单的代码，*.exe和file.txt要在同一目录。

引用 1 楼 u012421456 的回复:考号排序怎么了，可以把这三个放到结构体中，然后对结构体中的考号进行排序 可以参考一下——http://blog.csdn.net/u012421456/article/details/26170519 其实我不太会的是文件。。

索引是啥，看看几个百科吧——http://www.gfsswy.com/?q=索引


Question: 各位大哥请教一下！！不知道怎么弄了

引用 15 楼 huazi3531919 的回复:连买回教材不到三天，你们就叫我改行，我只是来求解的，各位大哥！ 要不换个编译器吧 dev c++、c-free、gcc什么的

连买回教材不到三天，你们就叫我改行，我只是来求解的，各位大哥！

main()函数前用了void，就不用再return 0了。

引用 13 楼 u014444402 的回复:趁早改行吧，小兄弟。 中肯

趁早改行吧，小兄弟。

楼主3楼的错误5楼已经给出，二楼错误看不出来，编译器报的什么错，拿出来看看

看看这个是否有用http://club.topsage.com/thread-2279554-1-1.html

是兼容性问题，当年我们寝室的胖子为了这个花了一个多礼拜才弄好的，你可以去下载别人已经安装能用的吧，如果只是简单的写程序，你可以使用cfree，这个操作简单，比较容易上手……

引用 3 楼 huazi3531919 的回复:  printf 写错了，还有main函数为void为什么还要return 0？

error说的啥

代码贴出来看看你。。


Question: 关于C中的stdin和stdout自定义出现的问题

引用 1 楼 Idle_ 的回复:你stdin都重定向到串口了，当然输入从串口读了，和键盘没关系   表示解决了，将 static int UartIoGetChar(FILE *stream){     loop_until_bit_is_set(rUCSRA, rRXC);     unsigned char data=rUDR;     return data; }  改为：  static int UartIoGetChar(FILE *stream){ 	loop_until_bit_is_set(rUCSRA, rRXC); 	unsigned char data=rUDR; 	if ((data=='\n')|(data=='\r')|(data=='\0')) return -1; 	return data;   }   就可以成功使用fgets了，但是为什么要这样？？？？不是gets是碰到换行符就结束了吗，为什么一定要把换行符改成EOF才可以？？

引用 1 楼 Idle_ 的回复:你stdin都重定向到串口了，当然输入从串口读了，和键盘没关系 是啊，是从串口读，但是读不了啊，C上课老师也没怎么讲标准输入输出  我的  static int UartIoGetChar(FILE *stream){     loop_until_bit_is_set(rUCSRA, rRXC);     unsigned char data=rUDR;     return data; } 对不对，重定向到这个函数行不行？这个函数就是串口有什么，它就返回什么

引用 1 楼 Idle_ 的回复:你stdin都重定向到串口了，当然输入从串口读了，和键盘没关系 ++

你stdin都重定向到串口了，当然输入从串口读了，和键盘没关系


Question: 定义的数组自己变成指针类型了

有句话叫做，数组名作参数，隐式指针化

无非是关于退化的两点： 函数声明的参数类型，数组形式的声明符会调整为指针； 在特定上下文（例如sizeof和一元&的操作数）以外数组左值转换为指向首个元素的指针值。 VC++？再加一点：不开/Za用了坑爹扩展，&字面量不会得到指向数组的指针。

引用 1 楼 lovesmiles 的回复:数组本来就是指针。 引用 2 楼 lisong694767315 的回复:数组名是指向首元素的指针。 这群瞎扯蛋的怎么混上五个三角形的。 引用 5 楼 u010101009 的回复:数组名是指向首元素的指针的 嫌复读机不够多？

楼上正解

建议搜一下 “数组名 指针”看看两者的联系区别

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

数组名是指向首元素的指针的

数组名和指针类似，但又有些不同——http://blogger.org.cn/blog/more.asp?name=newqiang&id=11178

数组名是指向首元素的指针。

数组本来就是指针。


Question: C/C++中字符串占据空间的计算

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

引用 8 楼 u012421456 的回复:  支持！！！

6，7，8正解。。。

谢谢各位的解释和调试，赵老师有大师的风范，赞一个

引用 9 楼 zhao4zhong1 的回复:"啊";//占几个字节？通常GBK或Unicode占3个，Utf8占4个。 赵老师的指点是很全面的~

说有答案的都是在坑人.这个问题是标准规定的不定义的行为.每个编译器的作者都可以自行决定如何实现字符串常量的存储.比如把字符串存到一个远程数据库,或者存到只读ROM而不是内存里也是可以的.  ISO/IEC 14882:2003 2.13. 2.13. String literals  [...]An ordinary string literal has type “array of n const char” and static storage duration (3.7)  Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation- defined. The effect of attempting to modify a string literal is undefined.  一个可以进行的编译器优化是为str1分配空间之后将str指向str1的第二个字符,这样两个字符串可以共享空间.

\t 和 \0都是转义字符，加上字符传最后的结束符  所以是6，7， 8咯

占空间一个个数不就行了？这样的问题还需要讨论？你是被面试题坑过了，想问strlen和sizeof两个东西运算后的结果吧。

分别是6、7、8 可以写成char str2[] = "\tab\0cde";，然后使用sizeof(str2)进行验证


Question: strlen()返回值的问题

#pragma warning(disable:4996) #include <stdio.h> #include <string.h> int main(void) {     char name[40];     int letters;      scanf("%39s",name);     printf("%d\n",sizeof(name));     letters=strlen(name);     printf("%d\n",letters);      return 0; }

scanf_s("%s",name); 改成 gets(name);不好？

引用 1 楼 lovesmiles 的回复:scanf_s用错了，这个函数的参数你没有设置对。 改成scanf吧。  嗯，我又找了一下，发现scanf_s()确实用错了，我改成scanf_s("%s",name,40)就可以了。

引用 3 楼 zxh707wk 的回复:[quote=引用 1 楼 lovesmiles 的回复:] scanf_s用错了，这个函数的参数你没有设置对。 改成scanf吧。+1，lz是用vs编译代码的吧[/quote]  用的vs2012，用scanf会报错。。。

引用 1 楼 lovesmiles 的回复:scanf_s用错了，这个函数的参数你没有设置对。 改成scanf吧。+1，lz是用vs编译代码的吧

scanf_s用错了，这个函数的参数你没有设置对。 改成scanf吧。


Question: 请教入栈和销毁栈的问题

引用 3 楼 lovesmiles 的回复:[quote=引用 2 楼 zaixiankaifa 的回复:] [quote=引用 1 楼 lovesmiles 的回复:] 第一个问题，你的想法是对的，但不需要加新增的长度，只需将top指回原来的栈顶即可。  p->top=q->base+p->Stack_Size;  第二个问题，你完全搞错了free的用法，一个malloc对应一个free。而不是一个字节free一次。 所以你只需要free一次即可，放在for里面就错了  为什么指回原来栈顶位置呢？ q->top作为栈顶指针应该是在栈的最上方呀，那么就应该是：最低位置的q->base+Stack_Size(原栈顶位置)+STACK_INIT_SIZE(新增空间),难道不是这样么？[/quote]  不对，新增的空间是没有数据的，栈顶在新空间的上面做什么？ 栈顶应该指在最后的一个数据处，当新数据入栈时，栈顶才一步步递增，填满新增的空间。[/quote]  这样说对噢

个人意见 //q->top=q->base+STACK_INIT_SIZE;

引用 2 楼 zaixiankaifa 的回复:[quote=引用 1 楼 lovesmiles 的回复:] 第一个问题，你的想法是对的，但不需要加新增的长度，只需将top指回原来的栈顶即可。  p->top=q->base+p->Stack_Size;  第二个问题，你完全搞错了free的用法，一个malloc对应一个free。而不是一个字节free一次。 所以你只需要free一次即可，放在for里面就错了  为什么指回原来栈顶位置呢？ q->top作为栈顶指针应该是在栈的最上方呀，那么就应该是：最低位置的q->base+Stack_Size(原栈顶位置)+STACK_INIT_SIZE(新增空间),难道不是这样么？[/quote]  不对，新增的空间是没有数据的，栈顶在新空间的上面做什么？ 栈顶应该指在最后的一个数据处，当新数据入栈时，栈顶才一步步递增，填满新增的空间。

引用 1 楼 lovesmiles 的回复:第一个问题，你的想法是对的，但不需要加新增的长度，只需将top指回原来的栈顶即可。  p->top=q->base+p->Stack_Size;  第二个问题，你完全搞错了free的用法，一个malloc对应一个free。而不是一个字节free一次。 所以你只需要free一次即可，放在for里面就错了  为什么指回原来栈顶位置呢？ q->top作为栈顶指针应该是在栈的最上方呀，那么就应该是：最低位置的q->base+Stack_Size(原栈顶位置)+STACK_INIT_SIZE(新增空间),难道不是这样么？


Question: linux下标准io缓冲问题

是这样的，读写操作很多时候都是在虚拟磁盘上操作的。 比如写文件，当你调用write函数之后，你buffer中的内容并不是马上写到文件，而是通过文件系统暂时放在缓存中， 当内存页变赃后才会写到磁盘中，而用fflush想当与跳过这个过程直接写到磁盘中。

When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.

引用 4 楼 wsx199397 的回复:[quote=引用 3 楼 hnwyllmm 的回复:] 很奇怪，我没有看过这本书，也没有见过这样的说法，并且我们操作像Socket（TCP协议时）这种全双工的流时，开两个线程，同时对一个描述字做读写操作 是指的一个线程用于读一个线程用于写吗？在实际应用中我也觉得应该是你说的做法，对socket的io操作是通过什么进行的？应该不会用标准io了吧[/quote] 标准IO也可以，我是直接用标准IO的 既然是全双工的，自然是读写可以同时进行的，就是有缓冲，也是读写缓冲分开的，最典型的就是控制台，也没有见谁用了print再scanf之前刷新一把标准输出的

引用 3 楼 hnwyllmm 的回复:很奇怪，我没有看过这本书，也没有见过这样的说法，并且我们操作像Socket（TCP协议时）这种全双工的流时，开两个线程，同时对一个描述字做读写操作 是指的一个线程用于读一个线程用于写吗？在实际应用中我也觉得应该是你说的做法，对socket的io操作是通过什么进行的？应该不会用标准io了吧

不太懂，顶一下吧

For files open for update (those which include a "+" sign), on which both input and output operations are allowed, the stream shall be flushed (fflush) or repositioned (fseek, fsetpos, rewind) before a reading operation that follows a writing operation. The stream shall be repositioned (fseek, fsetpos, rewind) before a writing operation that follows a reading operation (whenever that operation did not reach the end-of-file 看来对于一个 socket for update，每次在读操作是实现会自动刷新缓冲区，将上次读操作的内容从缓冲区写到socket。而对于一个socket only for write or read,只有我们显示调用上述说的函数或缓冲区满时才写到socket。


Question: 各位 一个问题 最长想了多久 ...

其实停下来是最可怕的，可以找人问下，如果不是特别着急，可以先放着，继续学习，等过段时间回去看，可能就明白了

引用 1 楼 user-10 的回复:  ;; A simple CPS transformer which does proper tail-call and does not ;; duplicate contexts for if-expressions.  ;; author: Yin Wang (yw21@cs.indiana.edu)   (load "pmatch.scm")   (define cps   (lambda (exp)     (letrec         ([trivial? (lambda (x) (memq x '(zero? add1 sub1)))]          [id (lambda (v) v)]          [ctx0 (lambda (v) `(k ,v))]      ; tail context          [fv (let ([n -1])                (lambda ()                  (set! n (+ 1 n))                  (string->symbol (string-append "v" (number->string n)))))]          [cps1           (lambda (exp ctx)             (pmatch exp               [,x (guard (not (pair? x))) (ctx x)]               [(if ,test ,conseq ,alt)                (cps1 test                      (lambda (t)                        (cond                         [(memq ctx (list ctx0 id))                          `(if ,t ,(cps1 conseq ctx) ,(cps1 alt ctx))]                         [else                          (let ([u (fv)])                            `(let ([k (lambda (,u) ,(ctx u))])                               (if ,t ,(cps1 conseq ctx0) ,(cps1 alt ctx0))))])))]               [(lambda (,x) ,body)                (ctx `(lambda (,x k) ,(cps1 body ctx0)))]               [(,op ,a ,b)                (cps1 a (lambda (v1)                          (cps1 b (lambda (v2)                                    (ctx `(,op ,v1 ,v2))))))]               [(,rator ,rand)                (cps1 rator                      (lambda (r)                        (cps1 rand                              (lambda (d)                                (cond                                 [(trivial? r) (ctx `(,r ,d))]                                 [(eq? ctx ctx0) `(,r ,d k)]  ; tail call                                 [else                                  (let ([u (fv)])                                    `(,r ,d (lambda (,u) ,(ctx u))))])))))]))])       (cps1 exp id))))     ;;; tests  ;; var (cps 'x) (cps '(lambda (x) x)) (cps '(lambda (x) (x 1)))   ;; no lambda (will generate identity functions to return to the toplevel) (cps '(if (f x) a b)) (cps '(if x (f a) b))   ;; if stand-alone (tail) (cps '(lambda (x) (if (f x) a b)))   ;; if inside if-test (non-tail) (cps '(lambda (x) (if (if x (f a) b) c d)))   ;; both branches are trivial, should do some more optimizations (cps '(lambda (x) (if (if x (zero? a) b) c d)))   ;; if inside if-branch (tail) (cps '(lambda (x) (if t (if x (f a) b) c)))   ;; if inside if-branch, but again inside another if-test (non-tail) (cps '(lambda (x) (if (if t (if x (f a) b) c) e w)))   ;; if as operand (non-tail) (cps '(lambda (x) (h (if x (f a) b))))   ;; if as operator (non-tail) (cps '(lambda (x) ((if x (f g) h) c)))   ;; why we need more than two names (cps '(((f a) (g b)) ((f c) (g d))))    ;; factorial (define fact-cps   (cps    '(lambda (n)       ((lambda (fact)          ((fact fact) n))        (lambda (fact)          (lambda (n)            (if (zero? n)                1                (* n ((fact fact) (sub1 n))))))))))  ;; print out CPSed function (pretty-print fact-cps) ;; => ;; '(lambda (n k) ;;    ((lambda (fact k) (fact fact (lambda (v0) (v0 n k)))) ;;     (lambda (fact k) ;;       (k ;;        (lambda (n k) ;;          (if (zero? n) ;;            (k 1) ;;            (fact ;;             fact ;;             (lambda (v1) (v1 (sub1 n) (lambda (v2) (k (* n v2)))))))))) ;;     k))   ((eval fact-cps) 5 (lambda (v) v)) ;; => 120    说实话这个代码就足够我看半个月了。   最开始学Java的时候，一个问题思考半个月都太正常了，具体什么问题就不记得了。

引用 4 楼 lovesmiles 的回复:那说明基础的程度还未够看源码的程度。 每天 都能再看懂一些东西 ... 感觉还是有希望的 。。。龟速前进中 ，，

引用 1 楼 user-10 的回复:  ;; A simple CPS transformer which does proper tail-call and does not ;; duplicate contexts for if-expressions.  ;; author: Yin Wang (yw21@cs.indiana.edu)   (load "pmatch.scm")   (define cps   (lambda (exp)     (letrec         ([trivial? (lambda (x) (memq x '(zero? add1 sub1)))]          [id (lambda (v) v)]          [ctx0 (lambda (v) `(k ,v))]      ; tail context          [fv (let ([n -1])                (lambda ()                  (set! n (+ 1 n))                  (string->symbol (string-append "v" (number->string n)))))]          [cps1           (lambda (exp ctx)             (pmatch exp               [,x (guard (not (pair? x))) (ctx x)]               [(if ,test ,conseq ,alt)                (cps1 test                      (lambda (t)                        (cond                         [(memq ctx (list ctx0 id))                          `(if ,t ,(cps1 conseq ctx) ,(cps1 alt ctx))]                         [else                          (let ([u (fv)])                            `(let ([k (lambda (,u) ,(ctx u))])                               (if ,t ,(cps1 conseq ctx0) ,(cps1 alt ctx0))))])))]               [(lambda (,x) ,body)                (ctx `(lambda (,x k) ,(cps1 body ctx0)))]               [(,op ,a ,b)                (cps1 a (lambda (v1)                          (cps1 b (lambda (v2)                                    (ctx `(,op ,v1 ,v2))))))]               [(,rator ,rand)                (cps1 rator                      (lambda (r)                        (cps1 rand                              (lambda (d)                                (cond                                 [(trivial? r) (ctx `(,r ,d))]                                 [(eq? ctx ctx0) `(,r ,d k)]  ; tail call                                 [else                                  (let ([u (fv)])                                    `(,r ,d (lambda (,u) ,(ctx u))))])))))]))])       (cps1 exp id))))     ;;; tests  ;; var (cps 'x) (cps '(lambda (x) x)) (cps '(lambda (x) (x 1)))   ;; no lambda (will generate identity functions to return to the toplevel) (cps '(if (f x) a b)) (cps '(if x (f a) b))   ;; if stand-alone (tail) (cps '(lambda (x) (if (f x) a b)))   ;; if inside if-test (non-tail) (cps '(lambda (x) (if (if x (f a) b) c d)))   ;; both branches are trivial, should do some more optimizations (cps '(lambda (x) (if (if x (zero? a) b) c d)))   ;; if inside if-branch (tail) (cps '(lambda (x) (if t (if x (f a) b) c)))   ;; if inside if-branch, but again inside another if-test (non-tail) (cps '(lambda (x) (if (if t (if x (f a) b) c) e w)))   ;; if as operand (non-tail) (cps '(lambda (x) (h (if x (f a) b))))   ;; if as operator (non-tail) (cps '(lambda (x) ((if x (f g) h) c)))   ;; why we need more than two names (cps '(((f a) (g b)) ((f c) (g d))))    ;; factorial (define fact-cps   (cps    '(lambda (n)       ((lambda (fact)          ((fact fact) n))        (lambda (fact)          (lambda (n)            (if (zero? n)                1                (* n ((fact fact) (sub1 n))))))))))  ;; print out CPSed function (pretty-print fact-cps) ;; => ;; '(lambda (n k) ;;    ((lambda (fact k) (fact fact (lambda (v0) (v0 n k)))) ;;     (lambda (fact k) ;;       (k ;;        (lambda (n k) ;;          (if (zero? n) ;;            (k 1) ;;            (fact ;;             fact ;;             (lambda (v1) (v1 (sub1 n) (lambda (v2) (k (* n v2)))))))))) ;;     k))   ((eval fact-cps) 5 (lambda (v) v)) ;; => 120  比较冷僻的区域 ... 基本上找不到人问

引用 1 楼 user-10 的回复:  ;; A simple CPS transformer which does proper tail-call and does not ;; duplicate contexts for if-expressions.  ;; author: Yin Wang (yw21@cs.indiana.edu)   (load "pmatch.scm")   (define cps   (lambda (exp)     (letrec         ([trivial? (lambda (x) (memq x '(zero? add1 sub1)))]          [id (lambda (v) v)]          [ctx0 (lambda (v) `(k ,v))]      ; tail context          [fv (let ([n -1])                (lambda ()                  (set! n (+ 1 n))                  (string->symbol (string-append "v" (number->string n)))))]          [cps1           (lambda (exp ctx)             (pmatch exp               [,x (guard (not (pair? x))) (ctx x)]               [(if ,test ,conseq ,alt)                (cps1 test                      (lambda (t)                        (cond                         [(memq ctx (list ctx0 id))                          `(if ,t ,(cps1 conseq ctx) ,(cps1 alt ctx))]                         [else                          (let ([u (fv)])                            `(let ([k (lambda (,u) ,(ctx u))])                               (if ,t ,(cps1 conseq ctx0) ,(cps1 alt ctx0))))])))]               [(lambda (,x) ,body)                (ctx `(lambda (,x k) ,(cps1 body ctx0)))]               [(,op ,a ,b)                (cps1 a (lambda (v1)                          (cps1 b (lambda (v2)                                    (ctx `(,op ,v1 ,v2))))))]               [(,rator ,rand)                (cps1 rator                      (lambda (r)                        (cps1 rand                              (lambda (d)                                (cond                                 [(trivial? r) (ctx `(,r ,d))]                                 [(eq? ctx ctx0) `(,r ,d k)]  ; tail call                                 [else                                  (let ([u (fv)])                                    `(,r ,d (lambda (,u) ,(ctx u))))])))))]))])       (cps1 exp id))))     ;;; tests  ;; var (cps 'x) (cps '(lambda (x) x)) (cps '(lambda (x) (x 1)))   ;; no lambda (will generate identity functions to return to the toplevel) (cps '(if (f x) a b)) (cps '(if x (f a) b))   ;; if stand-alone (tail) (cps '(lambda (x) (if (f x) a b)))   ;; if inside if-test (non-tail) (cps '(lambda (x) (if (if x (f a) b) c d)))   ;; both branches are trivial, should do some more optimizations (cps '(lambda (x) (if (if x (zero? a) b) c d)))   ;; if inside if-branch (tail) (cps '(lambda (x) (if t (if x (f a) b) c)))   ;; if inside if-branch, but again inside another if-test (non-tail) (cps '(lambda (x) (if (if t (if x (f a) b) c) e w)))   ;; if as operand (non-tail) (cps '(lambda (x) (h (if x (f a) b))))   ;; if as operator (non-tail) (cps '(lambda (x) ((if x (f g) h) c)))   ;; why we need more than two names (cps '(((f a) (g b)) ((f c) (g d))))    ;; factorial (define fact-cps   (cps    '(lambda (n)       ((lambda (fact)          ((fact fact) n))        (lambda (fact)          (lambda (n)            (if (zero? n)                1                (* n ((fact fact) (sub1 n))))))))))  ;; print out CPSed function (pretty-print fact-cps) ;; => ;; '(lambda (n k) ;;    ((lambda (fact k) (fact fact (lambda (v0) (v0 n k)))) ;;     (lambda (fact k) ;;       (k ;;        (lambda (n k) ;;          (if (zero? n) ;;            (k 1) ;;            (fact ;;             fact ;;             (lambda (v1) (v1 (sub1 n) (lambda (v2) (k (* n v2)))))))))) ;;     k))   ((eval fact-cps) 5 (lambda (v) v)) ;; => 120  我也没看懂 = =

难道没人觉得发错版了么？

一周，我遇到代码比较少

三个月

想了6年，为什么当时选择当程序猿

一口吃不成个胖子

那说明基础的程度还未够看源码的程度。

看这代码，头晕了。。。。

想了十几天，感觉没必要，如果想了好几天想不出来，不如从网上找找别人的经验之谈(个人意见)


Question: 钱币变换问题 //优化问题

不要沉啊，我真的很想知道要怎么优化。。

是的没错。请务必帮我想想改怎么优化，我想了很久还是不懂，所以来问各位大神了

不是说的平行移动吗？还能隔着若干位置跳过去呀。

题目说的不能改变顺序是指你放入的ba不能变成ab

如上图，只要是两个两个配对放入那个空格就可以

调换位置但是不能改变排列顺序，那只能abba..abab -> abbaab..ab啊。

空格和ba调换位置

请问：“相邻的两个非空方格中的钱币可以平行移动到两个相邻的空方格中，但不能改变这两枚钱币的排列顺序。” 那么：     初始：  abba..abab     第一步：abbabaa..b 这是怎么移动的？

没看懂题目的规则。。。

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


Question: gcc的makefile

引用 1 楼 lisong694767315 的回复: obj = main.c my/my.c include/my.h main: $(obj) 	gcc -o main $(obj)    新增一个文件就要改makefile?

搜“跟我一起写makefile”

推荐你用eclipse或者其他编译环境生成一个makefile然后自己改一下

接楼上：  Makefile中以下三行指定源代码、头文件、中间文件的目录  src_dir := src inc_dir := include obj_dir := obj  以下三行是设置编译器参数的 CFLAGS    := -fPIC -Wall -g -DTHREADED -I "/usr/local/include" \                          $(foreach d,$(inc_dir), -I "$d") CPPFLAGS  := -fPIC -Wall -g -DTHREADED -I "/usr/local/include" \                          $(foreach d,$(inc_dir), -I "$d") LDFLAGS   := -L "/usr/local/lib" LOADLIBES := --shared -lzookeeper_mt -lm -lpthread

建议好好的看一下《Managing Projects with GNU Makefile》这本书，有英文版和中文版的。  下面是我的makefile，还算通用，就是写的很复杂。共两个文件，一个是makefile，另外一个是make.rules。两个文件缺一不可，我就是看了上面的书写出来的。另外，再给你一个建议，你可以用cmake，cmake的语法不难，它是自动生成Makefile的工具。  <makefile>  ifdef ComSpec EMPTY     := RM        := del DELIMITER := \$(EMPTY) TARGET    := libzooclient.dll else RM        := rm DELIMITER := / TARGET    := libzooclient.so endif  all: $(TARGET)  src_fmt := *.c *.C *.cc *.CC *.cpp *.cxx src_dir := src inc_dir := include obj_dir := obj  CFLAGS    := -fPIC -Wall -g -DTHREADED -I "/usr/local/include" \ 						 $(foreach d,$(inc_dir), -I "$d") CPPFLAGS  := -fPIC -Wall -g -DTHREADED -I "/usr/local/include" \ 						 $(foreach d,$(inc_dir), -I "$d") LDFLAGS   := -L "/usr/local/lib" LOADLIBES := --shared -lzookeeper_mt -lm -lpthread  # List all sources now. src     := $(foreach d,$(src_dir),\  $(foreach f,$(src_fmt),\   $(if $(wildcard $d/$f),$(eval src+=$(wildcard $d/$f)))))  # Check whether sources contains cxx files. cplusplus := $(filter-out %.c,$(src)) # Check whether builds archive. archive := $(filter %.a,$(TARGET))  include make.rules  ifneq ($(MAKECMDGOALS),"clean") ifneq ($(MAKECMDGOALS),"distclean") # Include dependent files if exist. -include $(addprefix $(obj_dir)/,$(addsuffix .d, $(notdir $(src)))) # Generate compile rules from source to object file. # To "C" files, use gcc, otherwise picking g++. $(foreach f,$(src),\  $(if $(filter %.c,$f),\   $(eval $(call rule-generator-c2o,$(obj_dir),$f)),\   $(eval $(call rule-generator-cxx2o,$(obj_dir),$f)))) # Generate compile rules from object files to executable. # # if source-file(s)-exists #		if target-is-xxx.a #			ar rv $@ $^ #   else if use-c++ #     g++ $^ -o $@ #   else #     gcc $^ -o $@ #		endif # endif $(if $(src),\  $(if $(archive),$(eval $(call archive-target,$(TARGET))),\   $(if $(cplusplus),\    $(eval $(call link-target-cxx,$(TARGET))),\    $(eval $(call link-target-c,$(TARGET))))))  endif endif  prompt_clean := @echo "Nothing to clean." prompt_dclean:= @echo "Nothing to distclean."  objects := $(foreach d,$(obj_dir),\  $(if $(wildcard $d/*.o), $(eval objects+=$(wildcard $d/*.o)))) depends := $(foreach d,$(obj_dir),\  $(if $(wildcard $d/*.d), $(eval depends+=$(wildcard $d/*.d))))  clean_cmd := $(if $(objects)$(depends),\               $(RM) $(objects) $(depends),\               $(prompt_clean)) target := $(if $(wildcard $(TARGET)), $(eval target=$(TARGET))) distclean_cmd := $(if $(objects)$(depends)$(target),\                   $(RM) $(objects) $(depends) $(target),\                   $(prompt_dclean))  clean: 	$(clean_cmd) distclean: 	$(distclean_cmd)  .PHONY: all clean distclean   <make.rules>  # Compiler specific variables. CC         := gcc CXX        := g++ COMPILE.c   = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c COMPILE.cxx = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c LINK.c.o    = $(CC) $(LDFLAGS) $(TARGET_ARCH) LINK.cxx.o  = $(CXX) $(LDFLAGS) $(TARGET_ARCH) AR         := ar ARFLAGS     = rv  # Store all object files while generating rules. allobjects :=  # ******************************** # # ############### C ###############   # $(call depend-generator-c,<target:$1>,<dependfilepath:$2>,<sourcefilepath:$3> # Example: $(call depend-generator,obj/main.c.o,obj/main.c.d,src/main.c) define depend-generator-c $(CC) $(CFLAGS) -MM -MT $1 -MF $2 -MP $3 endef  # Automatic rules from *.c to *.o # $(call rule-generator-c2o,<objdir:$1>,<sourcefilepath:$2>) define rule-generator-c2o allobjects += $1/$(notdir $2).o $1/$(notdir $2).o: $2 	$$(call depend-generator-c,$1/$(notdir $2).o,$1/$(notdir $2).d,$2) 	$(COMPILE.c) $$< -o $$@ endef  # Automatic rules from *.o to executables # $(call link-target-c,<target:$1>) define link-target-c $1: $(allobjects) 	$(LINK.c.o) $$^ $(LDLIBS) $(LOADLIBES) -o $$@ endef  # ******************************** # # ############## C++ ##############  # $(call depend-generator-cxx,<target:$1>,<dependfilename:$2>,<sourcefilename:$3> # Example: $(call depend-generator,obj/main.cxx.o,obj/main.cxx.d,src/main.cxx) define depend-generator-cxx $(CXX) $(CPPFLAGS) -MM -MT $1 -MF $2 -MP $3 endef  # Automatic rules from *.cxx to *.o # $(call rule-generator-cxx2o,<objdir:$1>,<sourcefile:$2>) define rule-generator-cxx2o allobjects += $1/$(notdir $2).o $1/$(notdir $2).o: $2 	$$(call depend-generator-cxx,$1/$(notdir $2).o,$1/$(notdir $2).d,$2) 	$(COMPILE.cxx) $$< -o $$@ endef  # Automatic rules from *.o to executables # $(call link-target-cxx,<target:$1>) define link-target-cxx $1: $(allobjects) 	$(LINK.cxx.o) $$^ $(LDLIBS) $(LOADLIBES) -o $$@ endef  # *********************************** # # ############## Archive ############## # Automatic rule from *.o to archive define archive-target $1: $(allobjects) 	$(AR) $(ARFLAGS) $$@ $$^ endef

试试 GNU Make 的 vpath 指令


Question: 咨询个指针的小白问题：

强制类型转换看看 uint32 ＊p=(uint32 *)0x12345678;

引用 4 楼 sonyex678 的回复:引用 3 楼 derekrose 的回复:[quote=引用 2 楼 sonyex678 的回复:] uint32 i= 0x12345678;  (可变) uint32 ＊p；  想要实现p＝i；这样＊p 就是i变量里寄存器地址中的内容了，但是这种赋值方式编译不允许；    [quote=引用 1 楼 derekrose 的回复:] what is 不允许  编译器说啥[/quote]   Error[Pe513]: a value of type "uint32" cannot be assigned to an entity of type "uint32 *" C:\work\iar projects\code\SimpleGPS\StdDriver\Src\cmd_srv.c 48  [/quote]  什么编译器  你给他强转一下试试？

不行，编译器不知道你的那个地址是否正在使用

引用 3 楼 derekrose 的回复:引用 2 楼 sonyex678 的回复:uint32 i= 0x12345678;  (可变) uint32 ＊p；  想要实现p＝i；这样＊p 就是i变量里寄存器地址中的内容了，但是这种赋值方式编译不允许；    [quote=引用 1 楼 derekrose 的回复:] what is 不允许  编译器说啥[/quote]   Error[Pe513]: a value of type "uint32" cannot be assigned to an entity of type "uint32 *" C:\work\iar projects\code\SimpleGPS\StdDriver\Src\cmd_srv.c 48

引用 2 楼 sonyex678 的回复:uint32 i= 0x12345678;  (可变) uint32 ＊p；  想要实现p＝i；这样＊p 就是i变量里寄存器地址中的内容了，但是这种赋值方式编译不允许；    引用 1 楼 derekrose 的回复:what is 不允许  编译器说啥

what is 不允许


Question: 请问如何将一个char变量转化成一个char字符串？

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

使用的时候char*和 char []是一样的. 比如 char *p = NULL; p = "abcdefg"; cout<<p[2]<<endl; //   按数组方式访问 输出 c  所以你说的两东西, 在大多数使用的地方是相同的.  (但sizeof这样的地方是不同的).

这两个对你来说有什么区别吗

用循环 char数组末尾没有\0，字符串有。

引用 3 楼 zhuyf87 的回复:根据"hello"的字符串长度new一个数组，然后调用字符串拷贝函数或者自己写循环。+1

字符数组表示字符串，最后面需加上一个‘\0’ 关于字符串，可以看看这个——http://blog.csdn.net/u012421456/article/details/38645335

就跟5楼一样就行

char newarr[6]; strcpy(newarr,  arr);

strcpy...

你是说将char*转为char []吗   char* arr = "hello"; char newArr[5]; for (int i=0; i<5; ++i) { 	newArr[i] = *(arr+i); }


Question: 新手 求帮助 uart程序问题

我个人觉得看懂程序最重要的还是以后自己能够应用，所以想要搞懂这些最基本的东西，关于在9楼里提出的问题，希望前辈们帮忙回答下，也可以是像g_ctrlFlag形式的变量，给出自己的见解，或者需要我再提供关于这个程序的相关信息也可以提出来~

已经注释的很清楚了， 看注释就行啦。 变量的话就跳转查看具体定义。

g_ctrlFlag的含义 1.g_ctrlFlag在pic单片机中有固定的某种含义？ 2.ctrl一般表示控制，Flag一般表示标志，那么g是什么含义？ 3.下划线"_"的作用时什么？ 4.g_ctrlFlag.rcvOK的g_ctrlFlag后加一“.”后再加一个标示后又表示什么？

具体到每一句的功能，好多变量不知道是干嘛的，这些变量的名字都能看懂吗？我越看越晕的说~

这上面不是有注释吗？ void uart_fmAnaly(void) {     uint rcvcrc16,sndcrc16 ;     ptagtBBFRAME pfram ;          //接收正确     if(g_ctrlFlag.rcvOk==1)     {         pfram=(ptagtBBFRAME)&g_uartbuf[0];         rcvcrc16=CRC16(g_uartbuf,pfram->dlen-2,0xffff);         //         //查询crc是否正确         if(rcvcrc16==(g_uartbuf[pfram->dlen-2]|g_uartbuf[pfram->dlen-1]<<8))         {             //0x80,主板对打卡板的响应消息             if(pfram->cmd&FRM_MANS_FLAG)             {                 //LED_ON();                 g_ctrlFlag.fmok=1 ;                 //收到正确的响应包             }             else if((pfram->cmd&FRM_MOSI_FLAG)==FRM_MOSI_FLAG)             {                 //0x40,主板到打卡板的消息(做配置，状态查询的一些命令)                 switch(pfram->cmd)                 {                     case M_STATE_CMD :                     //查询串口的状态                     pfram->cmd|=FRM_MANS_FLAG ;                     sndcrc16=CRC16(g_uartbuf,pfram->dlen-2,0xffff);                     #if 1                      uart_sndStr((uchar*)g_uartbuf,5);                     //先把数据体前面的数据发送完成                     uart_sndStr((uchar*)&sndcrc16,2);                     //先把数据体前面的数据发送完成                     #endif                      uart_cfgRst();                     break ;                 }             }             g_ctrlFlag.crdTmEn=FALSE ;             //关闭回复计时             g_cardTM=0x00 ;             g_cardState=CARD_MUTUAL ;             //3,         }         //错误的数据包         //其他类型的错误帧         else          {             g_cardState=CARD_SEEK ;             //0,             uart_cfgRst();         }         g_ctrlFlag.rcvOk=0 ;     } } void uart_cfgRst(void) {     g_rcvpos=0 ;     g_ctrlFlag.rcvOk=0 ;     UART_INT_EN(); }

不太懂，什么是上位机、下位机？

这个是下位机程序吧

2个字 硬看

引用 6 楼 uwillobe 的回复:这些变量是什么含义，看懂的帮忙解释下,谢了！ rcvcrc16 sndcrc16 ptagtBBFRAME g_ctrlFlag.rcvOK g_ctrlFlag.fmOK pfram dlen FRM_MANS_FLAG cmd FRM_MOSI_FLAG uart_cfgRst 不太了解项目只能猜了： rcvcrc16//16位CRC校验，难道是接收到的？ sndcrc16//16位CRC校验，发送的？ ptagtBBFRAME//指向BB框架目标的指针？ g_ctrlFlag.rcvOK//控制位标中的rcvOK标记 g_ctrlFlag.fmOK//控制位标中的fmvOK标记 pfram//指向框架，窗口的指针？ dlen//长度 FRM_MANS_FLAG//人的框架标记 cmd//命令 FRM_MOSI_FLAG//MOSI的框架标记 uart_cfgRst//uart配置Rst不懂是什么意思。


Question: NYOJ 12 喷水装置（二）代码错误

2 1000 6 1 1 4 5

你输入n为1试试


Question: gcc中的语句表达式

宏可能会不止一次地计算它的参数。函数对它的参数只会计算一次，而宏可能会计算两次甚至更多次。如果参数有副作用，多次计算参数的值可能会产生意外的结果。  考虑下面的例子：  #define MAX(x,y)    ((x)>(y) ? (x) :(y))  n = MAX(i++, j);  宏展开以后就是：  n =((i++)>(j)?(i++):(j));   如果i大于j，那么i可能会被（错误地）增加了两次，一次在比较的时候，一次在返回MAX的值的时候，也就是说n被赋予了错误的值。

例子举得不太好，就是类似的意思吧。

i = 1; max(i++, 0); 宏替换之后： ((a) > (b) ? (a) : (b)) ((i++) > (0) ? (i++) : (0)) i自加了2次。

能不能别想这种找抽的问题

个人感觉是为了防止a和b是两个表达式，且其中出现自加或自减这样的操作，进而导致用上面的形式可能会因多次计算而出错，而下面的是先进行了计算，可以肯定三目运算符判断的只是两个数，所以安全 如有错误，欢迎指出


Question: 输出怪怪的，为什么

能否详细描述一下

对了，问一下，你的问题是什么

问题还没解决，换成c++问题消失

输出用%lf

浮点数，如果是双精度，输出时可以用%f，但输入时必须用%lf  循环变量最好不要用浮点数，因为浮点数在这儿无法精确存储

你想用这代码干啥？

scanf那儿要用%lf


Question: 结构体问题

使用引用或者指针来传参，否则值传递只会改变副本，而不会改变原有数据的值。

用指针：#include<stdio.h> #include<stdlib.h>  struct numbers{ 	int apple[5]; 	int boy[4]; 	int cat[3]; 	int dog[2]; 	int egg; };  void initializenumbers(struct numbers* good);  int main(){ 	struct numbers good; 	initializenumbers(&good);  	printf("%d\n", good.egg);      //  	return 0; }  void initializenumbers(struct numbers* good){ 	int a, b, c, d; 	for (a = 0; a < 5; a++){ 		good->apple[a] = 1;  		for (b = 0; b < 4; b++) 			good->boy[b] = good->apple[b] + good->apple[b + 1]; 		for (c = 0; c < 3; c++) 			good->cat[c] = good->boy[c] + good->boy[c + 1]; 		for (d = 0; d < 2; d++) 			good->dog[d] = good->cat[d] + good->cat[d + 1]; 		good->egg = good->dog[0] + good->dog[1]; 		printf("%3d\n", good->egg);                      //这里print出的egg = 16； 	} }


Question: linux c Ftp实现

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

lz你起码得知道自己代码哪里出错了吧，不贴代码谁知道你的quit和bye是什么玩意

上边的那个问题前几天搞定了，目前遇到的问题是我的ftp文件传输的时候怎么断开文件传输，我使用了close和Ctrl+c没用，使用quit或bye的时候导致崩溃。我使用C写的，请问大家这个怎么处理

引用 3 楼 nanjingnew4 的回复:统一编码啊，传递报文的时候使用同一种，如果做不到统一的话那就转换下把，utf8和gbk字节数都不一样，肯定没法比+1

我在linux下用c写的一个ftp客户端，进行下载一个文件的时候可以下载英文的文件，但是中文的文件返回的错误是找不到该文件，就是不能够识别ftp server的中文文件名，我想是本地请求ftp server的时候的编码和ft server的文件名编码不同导致的，ftp server 的编码是gbk，具体不知道该怎么解决这个问题，

具体问题是什么？没说清楚


Question: 求大神指导修改一个小程序，愿意10元话费QB奉上

这个程序是读取LOL游戏 UDP连接的  本身编译的时候提示“命名空间不能直接包含字段或方法之类的成员”第一行第一个词那里    我主要想请大神修改一下  去除读取LOL游戏 UDP连接以外的什么连接服务器功能   并且把生成的结果复制到粘贴板上   10元绝不食言


Question: 写了个读取txt并且统计字符出现次数的程序单运行不了，请大神帮忙看看错在哪里

你确定你要记录文件中的各类字符数？请将你包含的头文件都用上，问题迎刃而解；看看基础去吧。ctype.h头文件：ispunct()判断字符是否为标点符号，isdigit(),判断字符是否为数字，isalnum()判断字符是否为字幕，isupper(),islower(),等等…还有你的for循环只给字符数组的第一个元素复制，并且不断从文件中读取数据，每次一个字符，每次读取的字符都赋给字符数组的第一个元素，并且读文件直到结尾，最终字符数组只有一个元素被赋值，是文件的最后一个字符

string[i] = p； 中的i没有更新

printf("%s",count);错了吧，count是一个int的数组，怎么可以用%s来打印呢  while的语句判断也不能用‘；’来结尾，这样会进入循环中，不能进行赋值  所以，修改了下，试试看吧，  int main(int argc, char *argv[])  { 	FILE *fp = NULL; 	int count[93]; 	 	fp = fopen("device.txt", "rb"); 	while(!feof(fp)/*string[c] != '\0'*/); 	{ 		count[fgetc(fp) - ' ']++; 	} 	fclose(fp); 	printf("%d\n", count); 	return 0; }

这样？ #include<stdio.h> #include<string.h>   int main() {    FILE* fp = fopen("script.txt", "rb");    int count[93] = {0};    while ( !feof(fp));    {    		count[fgetc(fp)-' ']++;    }     printf("%s", count)： }


Question: 关于printf和wprintf的问题，请赐教！

非常感谢 mujiok2003，结贴！

引用 5 楼 cqruan 的回复:[quote=引用 3 楼 mujiok2003 的回复:] 不要混用 char 和 wchar_t 版本的流操作函数，否则会导致这些函数运行异常 试试#include <stdio.h> #include <wchar.h> #include <locale.h> int main(int argc,char* argv[]) {  	setlocale(LC_CTYPE,"zh_CN.UTF-8"); 	char *str="中国上海"; 	printf("%s\n",str);   	wchar_t *wcstr=L"北京您好"; 	printf("wide char string:%ls\n",wcstr);  	return 0; }  非常感谢，测试的时候程序没有崩溃，呵呵，就是输出不了正确的结果。 我就是想知道原因是啥？  追问一个问题：对于wprintf，网上有人说是最终都转换成了ANSI字符集来进行输出到终端或控制台的（本论坛上找到的），但有的说是CRT时转换成了setlocale设置的locale字符集，到底那一个说的正确？谢谢！    [/quote] 后面那个更准确。msvc CRT  wint_t __cdecl _fputwc_nolock (         wchar_t ch,         FILE *str         ) {         if (!(str->_flag & _IOSTRG))         {             if (_textmode_safe(_fileno(str)) == __IOINFO_TM_UTF16LE                     || _textmode_safe(_fileno(str)) == __IOINFO_TM_UTF8)             {                 /* binary (Unicode) mode */                 if ( (str->_cnt -= sizeof(wchar_t)) >= 0 ) {                     return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch));                 } else {                     return (wint_t) _flswbuf(ch, str);                 }             }             else if ((_osfile_safe(_fileno(str)) & FTEXT))             {                 int size, i;                 char mbc[MB_LEN_MAX];                  /* text (multi-byte) mode */                 if (wctomb_s(&size, mbc, MB_LEN_MAX, ch) != 0) // 这里会根据转换为locale相关的mb                 {                         /*                          * Conversion failed; errno is set by wctomb_s;                          * we return WEOF to indicate failure.                          */                         return WEOF;                 }                 for ( i = 0; i < size; i++)                 {                         if (_putc_nolock(mbc[i], str) == EOF)                                 return WEOF;                 }                 return (wint_t)(0xffff & ch);             }         }         /* binary (Unicode) mode */         if ( (str->_cnt -= sizeof(wchar_t)) >= 0 )                 return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch));         else                 return (wint_t) _flswbuf(ch, str); }  #undef putwc  wint_t __cdecl putwc (         wchar_t ch,         FILE *str         ) {         return fputwc(ch, str); }

引用 5 楼 cqruan 的回复:[quote=引用 3 楼 mujiok2003 的回复:] 不要混用 char 和 wchar_t 版本的流操作函数，否则会导致这些函数运行异常 试试#include <stdio.h> #include <wchar.h> #include <locale.h> int main(int argc,char* argv[]) {  	setlocale(LC_CTYPE,"zh_CN.UTF-8"); 	char *str="中国上海"; 	printf("%s\n",str);   	wchar_t *wcstr=L"北京您好"; 	printf("wide char string:%ls\n",wcstr);  	return 0; }  非常感谢，测试的时候程序没有崩溃，呵呵，就是输出不了正确的结果。 我就是想知道原因是啥？  追问一个问题：对于wprintf，网上有人说是最终都转换成了ANSI字符集来进行输出到终端或控制台的（本论坛上找到的），但有的说是CRT时转换成了setlocale设置的locale字符集，到底那一个说的正确？谢谢！    [/quote] 这两个不矛盾的。locale可以设置为ansi(比如zh_CN.gbk),或者unicode(比如zh_CN.utf8)

引用 3 楼 mujiok2003 的回复:不要混用 char 和 wchar_t 版本的流操作函数，否则会导致这些函数运行异常 试试#include <stdio.h> #include <wchar.h> #include <locale.h> int main(int argc,char* argv[]) {  	setlocale(LC_CTYPE,"zh_CN.UTF-8"); 	char *str="中国上海"; 	printf("%s\n",str);   	wchar_t *wcstr=L"北京您好"; 	printf("wide char string:%ls\n",wcstr);  	return 0; }  非常感谢，测试的时候程序没有崩溃，呵呵，就是输出不了正确的结果。 我就是想知道原因是啥？  追问一个问题：对于wprintf，网上有人说是最终都转换成了ANSI字符集来进行输出到终端或控制台的（本论坛上找到的），但有的说是CRT时转换成了setlocale设置的locale字符集，到底那一个说的正确？谢谢！

把代码文件保存为UTF-8的编码格式就可以编译了，我的这个是在liunx下测试的。

额，这个跟编译器有关吧，我在VC++6.0下正常运行，但在cfree中这段代码wchar_t *wcstr=L"北京您好";都编译不了……换成英文就行！


Question: 求助， execve函数无法编译

char* strProcess[] = {"new", (char *) NULL}; execve("new", strProcess, environ);

引用 3 楼 godbreak 的回复:[quote=引用 2 楼 u012879806 的回复:] [quote=引用 1 楼 godbreak 的回复:] 1. 应该是extern char **envrion;不加extern，envirion是一个局部变量，指针的值是脏的； 2. exec系列函数，无论是vector（execv×）还是list（execl×），参数表（argv）都要求至少包含一个字符指针，且以空指针结束——（char *）NULL。习惯上，参数表的第一个参数就是exec函数的第一个参数； 3. 很多Linux系统的实现会忽视参数表的第一个参数，但并不是每个类Unix系统都这样； 4. 关于搜索文件名，我只知道一个命令——find，eg: find ./ -name hello。更多信息参阅man find。   全局变量？   什么意思？   为什么是脏的？  变量不要定义吗  全局变量，只申明，你不觉得奇怪吗？  所以我改成局部变量。  [/quote] 因为char **environ在头文件中以全局变量的形式声明且定义了。不加extern，相当于在内部作用域中屏蔽了外部作用域的environ，成为一个新定义的变量。而局部变量不初始化，其值是不确定的。 如果这样说还不明白，你应该去看C的语法书了。[/quote]   理解了， 这个变量，是linux的头文件里有，  我还以为是随便命名的呢。   可是这个还是无法编译： extern char** environ;  char* strProcess[] =""; execve("new", &strProcess, environ); //无法编译  提示：  ./test.cpp:41:36: error: cannot convert ‘char (*)[1]’ to ‘char* const*’ for argument ‘2’ to ‘int execve(const char*, char* const*, char* const*)’ make: *** [test.o] Error 1

引用 2 楼 u012879806 的回复:[quote=引用 1 楼 godbreak 的回复:] 1. 应该是extern char **envrion;不加extern，envirion是一个局部变量，指针的值是脏的； 2. exec系列函数，无论是vector（execv×）还是list（execl×），参数表（argv）都要求至少包含一个字符指针，且以空指针结束——（char *）NULL。习惯上，参数表的第一个参数就是exec函数的第一个参数； 3. 很多Linux系统的实现会忽视参数表的第一个参数，但并不是每个类Unix系统都这样； 4. 关于搜索文件名，我只知道一个命令——find，eg: find ./ -name hello。更多信息参阅man find。   全局变量？   什么意思？   为什么是脏的？  变量不要定义吗  全局变量，只申明，你不觉得奇怪吗？  所以我改成局部变量。  [/quote] 因为char **environ在头文件中以全局变量的形式声明且定义了。不加extern，相当于在内部作用域中屏蔽了外部作用域的environ，成为一个新定义的变量。而局部变量不初始化，其值是不确定的。 如果这样说还不明白，你应该去看C的语法书了。

引用 1 楼 godbreak 的回复:1. 应该是extern char **envrion;不加extern，envirion是一个局部变量，指针的值是脏的； 2. exec系列函数，无论是vector（execv×）还是list（execl×），参数表（argv）都要求至少包含一个字符指针，且以空指针结束——（char *）NULL。习惯上，参数表的第一个参数就是exec函数的第一个参数； 3. 很多Linux系统的实现会忽视参数表的第一个参数，但并不是每个类Unix系统都这样； 4. 关于搜索文件名，我只知道一个命令——find，eg: find ./ -name hello。更多信息参阅man find。   全局变量？   什么意思？   为什么是脏的？  变量不要定义吗  全局变量，只申明，你不觉得奇怪吗？  所以我改成局部变量。


Question: 新手问题

引用 8 楼 u014539580 的回复:[quote=引用 6 楼 cfjtaishan 的回复:] struct information  { char uid[20];    //注意结构体对齐 char name[10]; char sex; };  ?这两种有什么区别呢，我用sizeof算出来的都是31啊[/quote] 嗯，是的。因为这三个结构体成员的类型都是char类型的。

引用 5 楼 jwj070524 的回复:[quote=引用 2 楼 u014539580 的回复:] [quote=引用 1 楼 jwj070524 的回复:]  if( fprintf(fp,"%s %s %c\n",xu.name,xu.uid,xu.sex) )   return 0;  这写错了吧，fprintf返回输出的字符数，如果没错，返回非0，然后就直接return了，fp中缓存的数据还没刷到文件上呢  非常感谢，的确是这的问题，但是对这个fprint还是没了解清楚，为什么fprint的返回值都有了，fp的数据还没到文件上，计算机内部具体是怎么工作的，能详细说一下吗？非常感谢！@jwj070524[/quote]  因为FILE类型内部有缓冲的，缓冲就是预先获取一块内存，比如1KB，4KB，留着，当你用fprintf时，首先将数据写到缓冲上，就是直接写到内存上，之所以不直接写到文件是因为写文件很费时（相对于写内存）。接着当缓冲写满时，自动将数据一次性写到文件上。当然了，关闭文件的话fclose函数会自动将缓冲区中的数据刷到文件。所以如果你打开文件写入数据的话，一定要记得fclose，否则缓冲没写满，程序退出，文件上可能什么都没有。[/quote]   太好了刚刚需要这个提示！

引用 6 楼 cfjtaishan 的回复:struct information  { char uid[20];    //注意结构体对齐 char name[10]; char sex; };  ?这两种有什么区别呢，我用sizeof算出来的都是31啊

引用 2 楼 u014539580 的回复:[quote=引用 1 楼 jwj070524 的回复:]  if( fprintf(fp,"%s %s %c\n",xu.name,xu.uid,xu.sex) )   return 0;  这写错了吧，fprintf返回输出的字符数，如果没错，返回非0，然后就直接return了，fp中缓存的数据还没刷到文件上呢  非常感谢，的确是这的问题，但是对这个fprint还是没了解清楚，为什么fprint的返回值都有了，fp的数据还没到文件上，计算机内部具体是怎么工作的，能详细说一下吗？非常感谢！@jwj070524[/quote]  因为FILE类型内部有缓冲的，缓冲就是预先获取一块内存，比如1KB，4KB，留着，当你用fprintf时，首先将数据写到缓冲上，就是直接写到内存上，之所以不直接写到文件是因为写文件很费时（相对于写内存）。接着当缓冲写满时，自动将数据一次性写到文件上。当然了，关闭文件的话fclose函数会自动将缓冲区中的数据刷到文件。所以如果你打开文件写入数据的话，一定要记得fclose，否则缓冲没写满，程序退出，文件上可能什么都没有。

fprintf, fwprintf Print formatted data to a stream.  int fprintf( FILE *stream, const char *format [, argument ]...);  int fwprintf( FILE *stream, const wchar_t *format [, argument ]...);  Function Required Header Compatibility  fprintf <stdio.h> ANSI, Win 95, Win NT  fwprintf <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  fprintf returns the number of bytes written. fwprintf returns the number of wide characters written. Each of these functions returns a negative value instead when an output error occurs.   Parameters  stream  Pointer to FILE structure  format  Format-control string  argument  Optional arguments  Remarks  fprintf formats and prints a series of characters and values to the output stream. Each function argument (if any) is converted and output according to the corresponding format specification in format. For fprintf, the format argument has the same syntax and use that it has in printf.  fwprintf is a wide-character version of fprintf; in fwprintf, format is a wide-character string. These functions behave identically otherwise.   Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _ftprintf fprintf fprintf fwprintf    For more information, see Format Specifcations.  Example  /* FPRINTF.C: This program uses fprintf to format various  * data and print it to the file named FPRINTF.OUT. It  * then displays FPRINTF.OUT on the screen using the system  * function to invoke the operating-system TYPE command.  */  #include <stdio.h> #include <process.h>  FILE *stream;  void main( void ) {    int    i = 10;    double fp = 1.5;    char   s[] = "this is a string";    char   c = '\n';     stream = fopen( "fprintf.out", "w" );    fprintf( stream, "%s%c", s, c );    fprintf( stream, "%d\n", i );    fprintf( stream, "%f\n", fp );    fclose( stream );    system( "type fprintf.out" ); }   Output  this is a string 10 1.500000   Stream I/O Routines  See Also   _cprintf, fscanf, sprintf

fprintf返回的是成功写入文件的字节数。

引用 1 楼 jwj070524 的回复: if( fprintf(fp,"%s %s %c\n",xu.name,xu.uid,xu.sex) )   return 0;  这写错了吧，fprintf返回输出的字符数，如果没错，返回非0，然后就直接return了，fp中缓存的数据还没刷到文件上呢  非常感谢，的确是这的问题，但是对这个fprint还是没了解清楚，为什么fprint的返回值都有了，fp的数据还没到文件上，计算机内部具体是怎么工作的，能详细说一下吗？非常感谢！@jwj070524


Question: 求助两个程序题

char *p; null也去掉

getmemory删掉也是可以的

引用 13 楼 oQianQu 的回复:[quote=引用 4 楼 xhsemaill 的回复:] #include <cstdio> #include<cstdlib> #include<cstring> void GetMemory(char* &p) { 	p = (char *)malloc(100); } int main() { 	char *str = NULL; 	GetMemory(str); 	strcpy(str, "hello world"); 	printf(str); 	return 0; }  用到了C++中的引用 谢谢你的回答！代码放在c++下是可以运行的，但是c语言不行，因为头文件不对，可是我不知道应该添加哪些头文件呢？12楼有类似的解决方案，但是也不完善。你看看还有什么办法？谢谢你~[/quote]  c语言貌似没有引用这个概念

引用 4 楼 xhsemaill 的回复:#include <cstdio> #include<cstdlib> #include<cstring> void GetMemory(char* &p) { 	p = (char *)malloc(100); } int main() { 	char *str = NULL; 	GetMemory(str); 	strcpy(str, "hello world"); 	printf(str); 	return 0; }  用到了C++中的引用 谢谢你的回答！代码放在c++下是可以运行的，但是c语言不行，因为头文件不对，可是我不知道应该添加哪些头文件呢？12楼有类似的解决方案，但是也不完善。你看看还有什么办法？谢谢你~

引用 1 楼 cstdingjw 的回复:Q1: 当b<=0时, 返回值不确定;  Q2: 代码如下: #include <stdio.h> #include <stdlib.h> void GetMemory(char* &p){ p = (char *)malloc(100); } void main(){ char *str = NULL; GetMemory(str); strcpy(str, "hello world"); free(str); printf(str); } 谢谢你的回答，我以为代码这样写也是可以的，但是就是报错了，见截图。你看还有没有什么建议？

引用 5 楼 Evankaka 的回复:第二个应该这个写才是，用指向指针的指针 #include <stdio.h> void GetMemory(char **p){ *p = (char *)malloc(100); } void main(){ char *str = NULL; GetMemory(&str); strcpy(str, "hello world"); printf(str); free(str)///记得加！ }  void GetMemory(char *p) ///虽说能改变p指针指向的内容，即*p,但它实际上还是按值传递，只不过传递的是地址，相当于生成了地址p的一个复本_p,,然后*_p就能相应的改变*p的内容，因为它们的地址是一样的，但是我们在按值传递中学过，形参变，不会改变实参，要注意，这里的形参指的是地址，也就是说，你改变了_p指针的地址，_p申请了新的内存,但是p是实参，它没变化。所以你每调用这个函数一次，它就发生一次内存泄露。用指向指针的指针，这时就可以了。。。 谢谢你的回答，你的方案是可行的，但是我比较想要一个用引用传递的方式解决问题的方案，你看能不能再给点建议？

引用 9 楼 gojoy_x13 的回复:c是函数f中的局部变量，运行时f中的局部变量保持在临时栈中，所以return c 是不规范的吧~~ +1 Q1：当这个函数调用结束后，局部对象的生命期随函数的结束而结束。 建议多了解一下函数、生命期

引用 2 楼 q3733353520 的回复:Q1:  如果b不满足条件c,就不会初始化.  Q2:纠错下代码先  #include <stdio.h>  void GetMemory(char *p) { 	p = (char *)malloc(100); } void main() { 	char *str = NULL; 	GetMemory(str); 	strcpy(str, "hello world"); 	printf("%s\n",str); }    然后p申请的堆内存,随着其被回收,应该也被系统回收了,所以str根就没申请到堆内存.  呵呵，其它的不说，p被收回不收回和堆内存被收回有什么关系？堆内存不主动free都不会被收回。少年，你要多看看书了。

看楼主的代码和问题，感觉楼主需要先看书等资料，看不明白，想不明白了可以再来问 printf(str);？

基础问题，看看指针，以及函数参数

c初始值未定


Question: 关于程序功能实现的效率问题？

啊是南京话？可以先读取文件大小，可以一次性分配内存，然后写个函数一次性读取好了。

大一就有这觉悟了！厉害厉害，好好走下去吧 不要需要考虑太复杂的情况，随着学习的深入，后面的知识将会很好的解决你现在的问题，

引用 1 楼 FancyMouse 的回复:>在实际生活中，“帐户名”.txt中的数据会很庞大 实际生活中用不到你的系统。别关心不存在的需求。 >我也没法判断哪一种更合适？ 能跑小数据就行。你现在即使关心大规模也很难把事情搞对，甚至连什么是大规模数据下需要关心的问题都不一定对。一步一步来。 >为了解决文件操作里的一个bug，我用了两天时间，花了大概将近六个小时 你才大一。有道理，我好像有点好高骛远了，还是打好基础。

刚考完高考的我不解释。。。


Question: Linux Opencv编译提示找不到list

因为list是c++的头文件，而你编译的源文件是c程序，改成cpp就可以了

在#include <opencv2/opencv.hpp>外加上#ifdef __cplusplus .. #endif

确实用g++编译就可以通过的～～

我找到解决办法了，虽然不知道为什么，但是用g++编译通过了

留个联系方式吧qq279510616，如果看到的话可以交流下，多谢了

你好，你这个问题解决了吗？我这也碰到了这个问题


Question: 求大神讲解下这段代码的意思。

# include <stdio.h>  int main() { 	int a; 	char * h=" - o x \n";    	 	int m[90] = {0};      // -  等于  0； 	m[40] = m[50] = 1;    // o  等于  1； 	m[41] = m[49] = 2;    // x  等于  2； 	                      // \n 等于  3；  	for(int i = 0; i < 10; m[a] = 3)   //一行9个, 等于3 其实就是换行。 	{                                 // 这相当于是一个 二维数组  m[9][9]; 		a = i++ * 9; 	} 	 	for(int j = 9; j < 82; ++j)       // j= 9 ,相当于 m[0][9];  这9个格子就不显示了。 	{ 		printf("%.2s", &h[m[j]*2]);  // 关键就在这里，"%.2s" 是如何把 0.1.2.3 转换成 - o x \n 的 	}                                 	 	return 0; }

代码功能不明白，还是代码语法不明白？

在等大神的同时把写代码的人打死吧。

看了一点，头晕脑胀，不想看了

#include <stdio.h>  int p,t,a,d,c,v,i,m[90]={0},s,r[]={-10,-9,-8,-1,1,8,9,10}; void k(){if(m[p]==0) for(i=0;i<8;i++){                  for(c=0,v=p+r[i];m[v]==3-t;v+=r[i])                      c++;                  if(c&&m[v]==t){                     a+=c;v=p;                     if(d)                     do m[v]=t,v+=r[i];                   while(m[v]!=t);                   }                   }          } char*h=" - o x\n";  int main(){     for(i=1,m[41]=m[49]=2;i<10;m[i++*9]=3)     m[40]=m[50]=t=s=1;        for(;;a=d=0){         for(p=9;p<82;++p)k(),           printf("%.2s",&h[m[p]*2]);           if(a)           for(d=a=s=p=8;a==8;k())t-2?(scanf("%d %d",&p,&i),p+=i*9):++p;else if(s)s=0,printf("pass");           else            break;         t=3-t;}     return 0; }

把变量都定义成了全局的，第一次见  楼主哪里不明白？

绳命布洗，啥铁布紫！

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

语法看不懂。。。。。

不知LZ从哪里搞来的,真心难


Question: linux新手，关于mmap

sizeof(int) 32位下 就是4字节长。 如果你希望结果是0 1 2 3那么你需要写成p[0]=0x33323130;  这个int是一次写入4字节的，并不是分4次每次写1个字节，小端cpu的话写入的4字节代表的int就是低位在前高位在后

引用 1 楼 Idle_ 的回复:p[0]=和*p=是一回事。 而且结果没错。 因为你p定的是int *，所以p[0]=0x30313233是写一个int到内存，写了4字节，按小端存储就是3 2 1 0. 是30先压进寨里才在后面吗？ 要写成p[0]=0123 效果一样吗？ 另外为什么一个常量占4字节，有类似资料吗