Question: 高手啊，老鸟来帮我看看这代码怎么没有输出结果

还差一级接口的调用呢？

#include<stdio.h> int main(void) {   int i=0,sum=0;   for(;i<=100;i++)     {        sum+=i;     }       printf("%d\n",sum);   return 0; }

引用 5 楼 u010629326 的回复:   是我2了，加不加都行，我刚开始看到这种情况了，以为是需要加的，但是后面一想貌似函数名也能表示首地址。查资料发现这两种表达都行。 答案已经有朋友给出了，确实是没有调用输出函数。对于你这一题，我个人查看的方法：主函数中的p->AB();的返回值类型是func_AB*的，但是真正的打印函数是void类型的，返回值类型完全不一样，沿着结构体找下去会发现p->AB()只是指向的是一个已经初始化了的func_AB类型的结构体，并没有调用结构体中是输出函数。可能你的注释导致了一些误解。至于内存泄露的问题确实是需要后面优化的

int main() {                 factory_t *p = func_sel('A');//匹配函数                 if(p)                 {                                 p->AB()->factory_AB();//调用函数显示结果                                 p->CD()->factory_CD();//调用函数显示结果                 }                 return 0; }

引用 1 楼 user-7 的回复:factory_t *p = func_sel('A');//匹配函数                 if(p)                 {                                 p->AB()->factory_AB();//调用函数显示结果                                 p->CD()->factory_CD();//调用函数显示结果                 }                 //内存释放呢？？？？？？？？？？？ 小程序，  引用 4 楼 theskyisblue 的回复:func_AB* func_a(void)//产品Ａ { 				func_AB* pa = (func_AB*)malloc(sizeof(func_AB)); 				pa->factory_AB = &factory_A;  //这里还有取址 				return pa; } func_AB* func_b(void) { 				func_AB* pb = (func_AB*)malloc(sizeof(func_AB)); 				pb->factory_AB = factory_B;  //怎么到了后面全没了 				return pb; } func_CD* func_c(void) { 				func_CD* pc = (func_CD*)malloc(sizeof(func_CD)); 				pc->factory_CD = factory_C; 				return pc; } func_CD* func_d(void) { 				func_CD* pd = (func_CD*)malloc(sizeof(func_CD)); 				pd->factory_CD = factory_D; 				return pd; } factory_t* func_sel(char name)//自定义组合 { 				factory_t* f = (factory_t*)malloc(sizeof(factory_t)); 				if( name == 'A') 				{ 								f->AB = func_a;  //这里应该都需要取地址吧 								f->CD = func_c; 				} 				else 				{ 								f->AB = func_b; 								f->CD = func_d; 				} 				return f; } 				 int main() { 				factory_t *p = func_sel('A');//匹配函数 				if(p) 				{ 								p->AB();//调用函数显示结果 								p->CD();//调用函数显示结果 				} 				return 0; }[/code][/quote] 谢谢你的回复，可是当我加上了＆，一样输不出结果，我下载个软件调试调试，谢谢回复

你只是赋值了函数指针，并没有执行输出的这几个函数嘛  预知程序如何执行，可以单步运行跟踪

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


Question: hdu1003Runtime Error (ACCESS_VIOLATION)

能不能通俗点比如想法有问题还是哪一步代码有问题

运行出错时点中中断，通过调用堆栈、变量窗口等观察分析原因

Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 195914    Accepted Submission(s): 45729   Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.    Input The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).    Output For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.    Sample Input 2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5   Sample Output Case 1: 14 1 4  Case 2: 7 1 6


Question: 求大神帮忙 LeetCode two sum c语言问题

int * ret = malloc(sizeof(int) * 2); ret[0] = index1; ret[1] = index2; return ret;

注释的意思应该是，返回值必须放在一个数组，这个数组的空间要动态开辟，且假定主函数中已经释放malloc开辟的内存。

返回的通过malloc分配的, 看起来这代码没有返回 专门去看了一下题目好像没有要求, 要快一点可以排序或者hash

这种 n^2 的方法肯定过不去 lc 时间限制的。 引用 楼主 qq_31933059 的回复:还有，我也不理解注释中的： * Note: The returned array must be malloced, assume caller calls free(). 这句是什么意思 lc 说的是返回的指针应该指向一个数组，包含两个元素。这个数组由你在函数内分配，然后由 oj 负责 free。


Question: 4个字节16进制数转换成十进制浮点数

char p[4] = { 0x1e,0x0d,0xa8,0x3c }; 	float* f = (float*)p; 	//之后*f将是0.0205140673 	//之后可以直接判断*f是否大于0.0f来分别正负

float类型内存表示 请阅读 IEEE 754-2008 国际标准。计算机按此标准存放float数据。 数据传输和存放，涉及字节流序列。小端码和大端码 字节序列不同。

#include <stdio.h> int main(void) {      float a=0.0f; 	unsigned char * b = (unsigned char*)&a; 	char c[4] = {0x1e,0x0d,0xa8,0x3c};      int i = 0;     //printf("b1:%d\n",b);     for(i = 0; i<4; i++){ 		b[i] = (unsigned char)c[i]; 	} 	//printf("b2:%d\n",*b); 	printf("结果为：\n");     printf("%f\n", a);     //printf("a:%d\n",a); }

浮点数格式 http://bbs.csdn.net/topics/390676437


Question: C++怎么提取时间信息 2016/1/21

int nYear,nMonth,nDay; sscanf("2016/1/21","%d/%d/%d/",&nYear,&nMonth,&nDay);

参考：  #include <stdio.h> #include <string.h> int main(void) { 	char date[] = "2016 1 21"; 	int r, d; 	char *p = strtok(date, " "); 	printf("%s\n", p); 	while (1) { 		if (NULL == (p =  strtok(NULL, " "))) break; 		printf("%s\n", p); 	} 	return 0; } //2016 //1 //21


Question: c如何在枚举和变量间建立key value 关系

引用 7 楼 u012560967 的回复:[quote=引用 3 楼 u012560967 的回复:]  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？[/quote] 就算你写30000个case，没准仍然比map效率高。

引用 12 楼 u012560967 的回复:[quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？[/quote]  #define FIELD_OFFSET(type, field)    ((LONG)(LONG_PTR)&(((type *)0)->field))  type结构体类型名，field该结构体中的成员名字

引用 9 楼 paschen 的回复:[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？

不要低估编译器生成Release版switch语句时选择优化算法的智商。 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  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、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

引用 7 楼 u012560967 的回复:[quote=引用 3 楼 u012560967 的回复:]  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？[/quote] Why not !? char* TransOperType(int nOperType) {     switch (nOperType) {     case OPER_UNKNOWN:              return "UNKNOWN";     case OPER_PLAY:                 return "PLAY";     case OPER_RECORD:               return "RECORD";     case OPER_GETDIG:               return "GETDIG";     case OPER_ACCEPTCALL:           return "ACCEPTCALL";     case OPER_ANSWERCALL:           return "ANSWERCALL";     case OPER_MAKECALL:             return "MAKECALL";     case OPER_DROPCALL:             return "DROPCALL";     case OPER_SETBILLING:           return "SETBILLING";     case OPER_SENDMOREINFO:         return "SENDMOREINFO";     case OPER_DLCACHE:              return "DLCACHE";     case OPER_DLMEM:                return "DLMEM";     case OPER_STOPCH:               return "STOPCH";     case OPER_PUTEVT:               return "PUTEVT";     case OPER_SYSNOTIFY:            return "SYSNOTIFY";     case OPER_CST:                  return "CST";     case OPER_GETTRCOUNT:           return "GETTRCOUNT";     case OPER_XOIP_SETRESATTR:      return "OPER_XOIP_SETRESATTR";     case OPER_XOIP_GETRESATTR:      return "OPER_XOIP_GETRESATTR";     case OPER_XOIP_GETSSINFO:       return "OPER_XOIP_GETSSINFO";     case OPER_XOIP_STARTMEDIA:      return "OPER_XOIP_STARTMEDIA";     case OPER_XOIP_STOP:            return "OPER_XOIP_STOP";     case OPER_XOIP_SENDDIGITS:      return "OPER_XOIP_SENDDIGITS";     case OPER_XOIP_ENABLEEVENT:     return "OPER_XOIP_ENABLEEVENT";     case OPER_XOIP_DISABLEEVENT:    return "OPER_XOIP_DISABLEEVENT";     case OPER_XOIP_RECEIVEDIGITS:   return "OPER_XOIP_RECEIVEDIGITS";     case OPER_XOIP_SENDRFC2833:     return "OPER_XOIP_SENDRFC2833";     case OPER_SENDCPG:              return "OPER_SENDCPG";     case OPER_CALLPROCEEDING:       return "OPER_CALLPROCEEDING";     case OPER_CALLPROGRESS:         return "OPER_CALLPROGRESS";     case OPER_SETUPACK:             return "OPER_SETUPACK";     case OPER_SIP_SENDREINVITE:     return "OPER_SIP_SENDREINVITE";     case OPER_SIP_SENDREINVITEACK:  return "OPER_SIP_SENDREINVITEACK";     case OPER_SIP_SENDREGISTER:     return "OPER_SIP_SENDREGISTER";     case OPER_XOIP_SWITCH_VF:       return "OPER_XOIP_SWITCH_VF";     case OPER_SIP_SENDINFO:         return "OPER_SIP_SENDINFO";     case OPER_SIP_SENDINFOACK:      return "OPER_SIP_SENDINFOACK";     case OPER_NR_SCROUTE:           return "OPER_NR_SCROUTE";     case OPER_NR_SCUNROUTE:         return "OPER_NR_SCUNROUTE";     case OPER_SIP_SENDREGISTERACK:  return "OPER_SIP_SENDREGISTERACK";     case OPER_SIP_SENDTRYING:       return "OPER_SIP_SENDTRYING";     case OPER_DT_SETTSSIG:          return "OPER_DT_SETTSSIG";     case OPER_DT_GETTSSIG:          return "OPER_DT_GETTSSIG";     case OPER_SIP_SENDSUBSCRIBE:    return "OPER_SIP_SENDSUBSCRIBE";     case OPER_SIP_SENDNOTIFYACK:    return "OPER_SIP_SENDNOTIFYACK";     case OPER_GETCONFENERGY:        return "OPER_GETCONFENERGY";     case OPER_ESTCONF:              return "OPER_ESTCONF";     case OPER_ADDCONF:              return "OPER_ADDCONF";     case OPER_REMCONF:              return "OPER_REMCONF";     case OPER_DELCONF:              return "OPER_DELCONF";     case OPER_SETCDE:               return "OPER_SETCDE ";     case OPER_ESTCONF_EX:           return "OPER_ESTCONF_EX";     case OPER_ADDCONF_EX:           return "OPER_ADDCONF_EX";     case OPER_REMCONF_EX:           return "OPER_REMCONF_EX";     case OPER_SETCDE_EX:            return "OPER_SETCDE_EX";     case OPER_SETLMASKEX:           return "OPER_SETLMASKEX";     case OPER_SS7_SENDEXT:          return "OPER_SS7_SENDEXT";     case OPER_FXS_SEND:             return "OPER_FXS_SEND";     case OPER_FXS_RECV:             return "OPER_FXS_RECV";     case OPER_MO_SETHOOK:           return "OPER_MO_SETHOOK";     case OPER_MO_DIAL:              return "OPER_MO_DIAL";     case OPER_MS_GENRING:           return "OPER_MS_GENRING";     case OPER_MS_WTRING:            return "OPER_MS_WTRING";     case OPER_AG_SENDTONE:          return "OPER_AG_SENDTONE";     case OPER_RECVFSK:              return "OPER_RECVFSK";     case OPER_SENDFSK:              return "OPER_SENDFSK";     case OPER_SIP_RECVUPDATE:       return "OPER_SIP_RECVUPDATE";     case OPER_SIP_SENDUPDATE:       return "OPER_SIP_SENDUPDATE";     case OPER_SIP_RECVUPDATEACK:    return "OPER_SIP_RECVUPDATEACK";     case OPER_SIP_SENDUPDATEACK:    return "OPER_SIP_SENDUPDATEACK";     case OPER_SIP_RECVACK:          return "OPER_SIP_RECVACK";     case OPER_SIP_SENDACK:          return "OPER_SIP_SENDACK";     case OPER_SIP_RECVPRACK:        return "OPER_SIP_RECVPRACK";     case OPER_SIP_SENDPRACK:        return "OPER_SIP_SENDPRACK";     case OPER_SIP_SENDPRACKACK:     return "OPER_SIP_SENDPRACKACK";     case OPER_SIP_RECVPRACKACK:     return "OPER_SIP_RECVPRACKACK";     default: break;     }     return "UNKNOWN"; }

引用 2 楼 paschen 的回复:建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数

引用 3 楼 u012560967 的回复: void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } } 写错了个地方。。。 另， 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。赵老师的意思就是，我写300多个case是可以的么？？

void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr)/sizeof(M); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } }

swith case  这个世界上唯一不变的就是变化。请拥抱变化。

引用 4 楼 u012560967 的回复:[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系 谢谢，这样的确是我需要的，但是用偏移量会不会有危险，结构体在内存中的地址是不是因为内存对齐导致不连续，如果使用这样的方法，需要注意什么呢，需不需要对结构体成员位置进行调整呢？[/quote] sorry，忘问了一句，这样写的话，是不是每次需要变更结构体的时候，都需要变更对应的枚举吧。

引用 2 楼 paschen 的回复:建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系 谢谢，这样的确是我需要的，但是用偏移量会不会有危险，结构体在内存中的地址是不是因为内存对齐导致不连续，如果使用这样的方法，需要注意什么呢，需不需要对结构体成员位置进行调整呢？

引用 1 楼 user-3 的回复:如果结构体中的变量长度都相同，可以使用偏移量直接赋值 谢谢1楼的回答，用偏移量赋值的确是我期望的那样，但是由于结构体中成员类型有不同，所以需要用3楼的方法建立一个枚举或者数组记录对应成员位置，由于我之前用的Enum E {A,B,C,D,E,F,G,H,I,J,K...... }为协议中的ID值，所以需要建立一个 typedef struct Map {    int id;    int addr; }M; Enum E {A,B,C,D,E,F,G,H,I,J,K...... } Enum Ad {   ONE = 0,TWO = 4... }; M arr[1000] = { {A, ONE}, {B, TWO}, {C,THREE}... };  当我用的时候  void setParam(u16 uiParamId, u8* pParam) {    for（int i =0; i < sizeof(arr); ++i）   {     if(uiParamId = arr[i].id)     {       * (pMTParamSetting+arr[i].addr) = pParam;     }   } }

引用 13 楼 paschen 的回复:[quote=引用 12 楼 u012560967 的回复:] [quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系  C语言结构体没问题，另外可以通过一个宏求得偏移量，而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦，可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组，如何通过id（而非地址）进行赋值和访问呢？ 引用 6 楼 zhao4zhong1 的回复:swith case  这个世界上唯一不变的就是变化。请拥抱变化。 谢谢，说的很对，这个帖子就是单纯的想对结构体成员赋值进行理解，只有用不同途径完成相同功能，理解的才能更深刻不是么？[/quote]  #define FIELD_OFFSET(type, field)    ((LONG)(LONG_PTR)&(((type *)0)->field))  type结构体类型名，field该结构体中的成员名字[/quote] 不错不错，多谢指教了~也感谢1楼和一直都语重心长的赵老师~

建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系

如果结构体中的变量长度都相同，可以使用偏移量直接赋值


Question: windows编程开发 C语言描述 使用listview和treeview实现资源管理器

引用 1 楼 wzwwql 的回复:MFC些的要不要求发邮箱873857547@qq.com

MFC些的要不要

#由Windows版移至C语言#


Question: 用结构体建立链表，为什么输出一个链表，就自动结束运行了？

引用 7 楼 why444216978 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 why444216978 的回复:] [quote=引用 4 楼 paschen 的回复:] 加一个getchar(); 接收回车产生的'\n'   	while (c == 'Y' || c == 'y') 	{ 		getchar(); //接收回车产生的'\n' 		head = AppendNode(head); 		DispLink(head);      //显示当前链表各结点信息 		printf("Do you want to append a new node(Y/N)?"); 		scanf("%c", &c); 		i++; 	}      还是不行[/quote]  自己加断点单步调试分析原因 [/quote]   codeblocks怎么加断点分布调试啊。。。百度了好久百度不出来[/quote]  http://www.shangxueba.com/jingyan/1837645.html

引用 6 楼 paschen 的回复:[quote=引用 5 楼 why444216978 的回复:] [quote=引用 4 楼 paschen 的回复:] 加一个getchar(); 接收回车产生的'\n'   	while (c == 'Y' || c == 'y') 	{ 		getchar(); //接收回车产生的'\n' 		head = AppendNode(head); 		DispLink(head);      //显示当前链表各结点信息 		printf("Do you want to append a new node(Y/N)?"); 		scanf("%c", &c); 		i++; 	}      还是不行[/quote]  自己加断点单步调试分析原因 [/quote]   codeblocks怎么加断点分布调试啊。。。百度了好久百度不出来

引用 5 楼 why444216978 的回复:[quote=引用 4 楼 paschen 的回复:] 加一个getchar(); 接收回车产生的'\n'   	while (c == 'Y' || c == 'y') 	{ 		getchar(); //接收回车产生的'\n' 		head = AppendNode(head); 		DispLink(head);      //显示当前链表各结点信息 		printf("Do you want to append a new node(Y/N)?"); 		scanf("%c", &c); 		i++; 	}      还是不行[/quote]  自己加断点单步调试分析原因

引用 4 楼 paschen 的回复:加一个getchar(); 接收回车产生的'\n'   	while (c == 'Y' || c == 'y') 	{ 		getchar(); //接收回车产生的'\n' 		head = AppendNode(head); 		DispLink(head);      //显示当前链表各结点信息 		printf("Do you want to append a new node(Y/N)?"); 		scanf("%c", &c); 		i++; 	}      还是不行

引用 1 楼 Z_R_Z_798205 的回复:head 没有分配内存 不对啊。。。每次循环都动态分配内存了  运行的时候  是显示第二次   Do you want to append a new node(Y/N)?   的时候 他结束运行，  如果是没有分配内存的话，应该直接就退出了吧。。。。

引用 1 楼 Z_R_Z_798205 的回复:head 没有分配内存 在 struct Link *AppendNode(struct Link *head)这个函数里   每循环一次分配一次么？ 分配的大小是多大啊

head 没有分配内存


Question: 大家帮忙看个二级指针使用的问题

我的函数中,应该怎么使用这个**str呢. 我有点不清楚.多谢大家.

char str [] = "class[0]"; test_func (& str); 如果一元&运算符的操作数属于类型T，则&T的结果类型是指向T的指针。 str的类型是数组char []，故& str的类型是指向数组的指针char (*) []。  PS：一元&运算符的操作数必须是左值，且它的结果不是左值。因此 &str合法而&&str不合法。

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  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

引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  str是数组，不是指针！

引用 11 楼 theskyisblue 的回复:[quote=引用 9 楼 winner8080 的回复:] [quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  str并不是指针，只是数组名，并不真用内存空间，因此作为  引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  赵四老师已经给出了答案，test_func函数也需要进行一些修改，主要问题在于str是数组名，取址之后真心不能当做二级指针用，二级指针保存的是一级指针的地址，而str是没有地址的[/quote] 多谢多谢. test_func一开始我是写对的了.后面实在搞不定了就改成现在这个样子了. 看来问题就是你分析的这样,我调用的地方给错了. 再次感谢各位.

引用 8 楼 zhao4zhong1 的回复:#include <stdio.h> int test_func(char **str) {     char *p = NULL;     char *q = NULL;      printf("%s(), line = %d, str = %s \n", "test_func", __LINE__, *str);//test_func(), line = 6, str = class[0]     for (p = *str, q = *str; *p != '\0'; p++)         if (*p != '[' && *p != ']')             *q++ = *p;     *q = *p;     return 0; } int main() {     char str[] = "class[0]";     char *pstr=&str[0];     test_func(&pstr);     printf("%s",str);//class0     return 0; } 多谢赵4老师. 在调用的地方,我用&str为什么不行呢, 单独用个指针char *pstr=&str[0]; 然后再取pstr的地址,这个我理解 就是不理解&str不是二级指针吗 然后试着用&&str,结果编译报错说str未定义.

引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  str并不是指针，只是数组名，并不真用内存空间，因此作为  引用 9 楼 winner8080 的回复:[quote=引用 6 楼 paschen 的回复:] [quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢[/quote]  赵四老师已经给出了答案，test_func函数也需要进行一些修改，主要问题在于str是数组名，取址之后真心不能当做二级指针用，二级指针保存的是一级指针的地址，而str是没有地址的

char str[] = "class[0]";       test_func(&str);       我刚刚试过了，这样就是不行的，加个指针char *p=str; test_func(&p)；就可以了，说明指针和数组还是不一样        数组名代表首地址，但是数组名并不是变量，并不真正占据内存空间，因此对数组名取地址作为实参传入函数的做法并不合适， 因为函数的形参是一个二次指针，二次指针必须要指向一次指针，二次指针的值为指向的一次指针的地址，而数组名是没有地址的。 此外test_func函数的for循环中中，你将二次指针str直接赋值给一次指针p这样肯定也是有问题的。第8行那里，应该是*str吧！

引用 6 楼 paschen 的回复:[quote=引用 5 楼 winner8080 的回复:] [quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**[/quote] str是一个指针,那么&str,这样取地址,不就是二级指针了吗 请大侠解惑.多谢啊 我应该怎么写呢

引用 5 楼 winner8080 的回复:[quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote] 你这句话是想干嘛？ printf("%s(), line = %d, str = %s \n", __func__, __LINE__, &(*str)); __func__, __LINE__又是什么？

引用 5 楼 winner8080 的回复:[quote=引用 3 楼 user-5 的回复:] 实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢[/quote]  char str[] = "class[0]"; &str的类型并不是char**

引用 2 楼 paschen 的回复:*str 类型就是char* 我直接打印 printf("%s", *str);这样就死机了.

引用 3 楼 user-5 的回复:实现这个功能为什么要用二级指针呢？ 大侠能给个建议或者小例子吗 多谢

实现这个功能为什么要用二级指针呢？

*str 类型就是char*


Question: 菜鸟求助！急盼解答！

提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

各位大神，能否给个C版本（不是C++版本）的答案？谢谢各路大神的配合！

#include <iostream> #include<string> using namespace std;  void print_x(char x,int m,int n){ 	while(m!=0){ 		cout<<"\t"; 		m--; 	} 	cout<<x; 	while(n!=0){ 		cout<<"\t"; 		n--; 	} } void number_x(int num,char char_num){ 	int ix=0,var=num-1; 	for(;var!=0;var--,ix++){ 		print_x((char_num-var),ix,var); 		print_x((char_num-var),var,ix); 		cout<<endl; 	} 	print_x((char_num-var),ix,var); 	cout<<endl; 	ix=1,var=num-2; 	for(;var>=0;var--,ix++){ 		print_x((char_num-ix),var,ix); 		print_x((char_num-ix),ix,var); 		cout<<endl; 	} } int main(){ 	char x;int num; 	cout<<"请输入一个数字，ctr+z结束"<<endl; 	cin>>num; 	cout<<"请输入一个字母,ctr+z结束"<<endl; 	cin>>x; 	cout<<"结果是"<<endl; 	number_x(num,x); 	system("pause"); }


Question: vs2010编译没有错误，运行会显示Unable to start program的问题。

DLL需要有宿主EXE才能运行

在MSDN里面搜“调试DLL”

dll文件不能独立运行

你编译的是一个库文件，不是一个可执行程序。

看我的工程文件，这就是一个正常的工程，是因为这个工程就是用来生成.DLL文件的，所以不能第二次运行吗？


Question: C语言排序问题

仅供参考：//随机产生100000000个取值范围为[0～2的32次方减1]的数据， //然后让用户输入一个数据，判断用户输入的数据是不是包含在前面随机产生的数据中。 //要求：当用户输入完成后，必须在1毫秒(千分之一秒)之内完成判断。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <malloc.h> long int i; unsigned long ul; unsigned long *d; unsigned long ulrand(void) {     return (      (((unsigned long)rand()<<24)&0xFF000000ul)     |(((unsigned long)rand()<<12)&0x00FFF000ul)     |(((unsigned long)rand()    )&0x00000FFFul)); } void main() {     d=(unsigned long *)calloc(1<<(32-5),sizeof(unsigned long));     if (NULL==d) {         printf("Can not calloc(%d,%d)!\n",1<<(32-5),sizeof(unsigned long));         return;     }     srand(time(NULL));     for (i=0;i<100000000;i++) {         while (1) {             ul=ulrand();             if (0==(d[ul>>5]&(1lu<<(ul%32)))) {                 d[ul>>5]|=1<<(ul%32);                 break;             }         }         if (0==i%1000000) printf("%09d,%10lu\n",i,ul);     }     while (1) {         printf("\nInput a number:");         fflush(stdout);         rewind(stdin);         if (1==scanf("%lu",&ul)) break;     }     if (d[ul>>5]&(1<<(ul%32))) printf("Include.\n"    );     else                       printf("Not include.\n");     free(d); } //000000000,2135468533 //001000000,2465805973 //002000000,3844079964 //003000000,1883232874 //004000000,1204697784 //005000000,4050838287 //006000000,3802081245 //007000000,1586042671 //008000000,3119931368 //009000000, 251096899 //010000000,3491239701 //011000000,3365323844 //012000000,2191846708 //013000000,1879478195 //014000000,1112631457 //015000000,1927301519 //016000000,1717332861 //017000000,2922278240 //018000000, 694854106 //019000000, 273255526 //020000000, 398518467 //021000000,3270756812 //022000000,1500289424 //023000000,1502241936 //024000000,1770380660 //025000000,3668842116 //026000000,3255869879 //027000000,1299184024 //028000000,1072990028 //029000000, 242094712 //030000000,3789344297 //031000000,2599365925 //032000000, 962754138 //033000000,2055075654 //034000000,4083452879 //035000000, 489250842 //036000000, 611455230 //037000000, 277350616 //038000000,1597410795 //039000000,3224173662 //040000000,2291446877 //041000000,2546280575 //042000000,2509145642 //043000000,2371773252 //044000000, 635555963 //045000000,2674538666 //046000000,4253690312 //047000000,2675755514 //048000000,1269320296 //049000000,3172516920 //050000000,1430265210 //051000000, 196156173 //052000000,2470825669 //053000000,2536750977 //054000000,1182829949 //055000000,3202826434 //056000000,2263336265 //057000000, 313302924 //058000000,3630264578 //059000000,1154892716 //060000000,2985304230 //061000000,1252204837 //062000000,1292076720 //063000000, 242249250 //064000000,3999999961 //065000000, 431166416 //066000000,1366947236 //067000000,1414387330 //068000000,2143784481 //069000000,3242175409 //070000000,4158065163 //071000000,1425449573 //072000000,2493600232 //073000000,1316783455 //074000000,3723170478 //075000000,3064111466 //076000000, 408557403 //077000000,3722586955 //078000000,3801652651 //079000000,3788160154 //080000000,3329440047 //081000000,1408976868 //082000000, 471838899 //083000000,2145198260 //084000000,3781081738 //085000000,3439027738 //086000000,1150808750 //087000000,2782578638 //088000000,  85604584 //089000000,2704078162 //090000000, 584840269 //091000000,3854577719 //092000000,2823653537 //093000000, 797877025 //094000000,2248017755 //095000000,1787038685 //096000000,2816548567 //097000000, 489107494 //098000000, 911680090 //099000000,3677777147 // //Input a number:3677777147 //Include.

使用位图。参考：http://blog.csdn.net/justaipanda/article/details/8016249

位图法 http://blog.csdn.net/zhangxiangdavaid/article/details/38589359

位图法，参考：  #include <stdio.h> char arr[1000000]; int i, d, n; int main(void){ 	//初始化 	for (i = 0; i < 1000000; i++) { 		arr[i] = '0'; 	} 	//读入数据 	scanf("%d", &n); 	for (i = 0; i < n; i++) { 		scanf("%d", &d); 		arr[500000 + d] = '1'; 	} 	//输出 	for (i = 0; i < 1000000; i++) { 		if (arr[i] == '1') { 			printf("%d ", i - 500000); 		} 	} 	printf("\nend\n"); 	return 0; } //5 //5 1 3 2 4 // 1 2 3 4 5 //end

这个明显是 bitmap 啊  伪代码：  char arr[] = {0};  for (..) {    fscanf("%d", &a);    arr[a+500000] = 1; }  for (i = 0 .. 1000000) {    if (arr[i] == 1)       printf ("%d ", i-500000); } printf("\n");


Question: 使用Code Blocks调试C语言程序的问题

摒弃单步调试。  有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： //循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

学会使用GDB

跟踪不到可以加日志 默默地问一句，楼主的断点处是在循环内吗？

然而问题在于我进行单步调试的时候，把断点设在这个函数后时，这个函数是能够被调用的，而直接运行的时候不行。我觉得并不在于GDB的使用形式的问题吧。

Code Blocks本身没有调试能力，它是后台调用GDB调试的。 说错了的话，请楼下Code Blocks大神拍砖。

并不是在循环体内，是一个函数调用的前后，通过单步调试时该函数可以正常工作。


Question: linux下如何判断文件被占用

引用 2 楼 zhao4zhong1 的回复:独占打开失败即被占用。我觉得。 如果已经被其他进程采用非独占的方式打开了，这个就没有用了。

java中没有独占打开linux中的文件的方法，有人知道怎么才能在java代码中独占打开文件吗？

引用 2 楼 zhao4zhong1 的回复:独占打开失败即被占用。我觉得。  赵老师，linux上怎么独占打开文件？目前没有找到合适方式。

最后还是用lsof判断文件夹，然后使用脚本过滤筛选出未被占用的文件。。。。。。没时间看lsof的源代码，应该有底层接口判断方法

拷贝之前用flock()锁住，拷贝玩用flock()解锁。

额，我整理了下这方面的资料，linux下是没有直接的api或者对应的标识符来判断文件是否被占用，因为难以保证其他的进程对文件的操作，linux下没有对文件做这方面的功能；所以必须在业务层自己判断： 1.独占方式打开失败 2.文件锁--建议锁锁文件失败 3.文件内容hash，2s钟后比对失败  目前只想到了上述3中方法判断。。。。

返回打开文件的状态。

独占打开失败即被占用。我觉得。

刚刚又想到一个思路，linux所有非正常关闭的文件都会有一个以swp结尾的备份文件，可以判断该文件是否存在来判断文件的状态，但是这个方法比较取巧，还是想知道有没有对应的api或者对应的状态标识符来获得文件是否被占用？


Question: 这个问题困扰了我很久，请各位大神帮忙

听1楼筒子的 7楼说的好热闹

看看啦。。。。。

引用 7 楼 gwbzx 的回复:任何的技巧或方式都是为解决问题而衍生的，如果解决不了现实中的问题所有的努力都是狗屁 ，大学生或是教授级别解决不了问题的人同样会被淘汰！ 佛说：苦难面前众生平等！ 恐龙灭绝了，因为它被自己的屁熏死了，苍蝇活到了现在，因为它有吃不完的大便。  任何如今看似规模宏大的大型企业都是由当初的苍蝇般的臭虫活过来的，只应为他们只吃大便 ，如果你想统一天下，请吃大便吧！！

EOF定义为-1，所以只是一般输入字符或者回车的话是无法跳出循环的。可以用0XA(即enter键)判断输入是否结束，作为跳出循环的依据。

是想统计输入了多少个字符吧，不过每次按回车，还会多产生一个'\n'

EOF用来标识文件尾，windows中头文件可能是这样定义的#define EOF -1 你可以printf("EOF = %d",EOF); 查看EOF具体的值； 而当getchar从键盘获取输入的时候，一般是检测到回车结束 ，所以getchar最后一个读取的是''\n' ASCII值为10，所以getchar最后一个获取到的值是10，10 != -1 所以又会进入循环体，导致死循环。 但如果把输入重定向到文件的话getchar就能读取到标识结束符的EOF,你可以把以上代码编译为160121.exe， 然后cmd下进入其所在目录，运行160121.exe< 160121.txt，其中160121.txt是一个包含有限文本的文档。 而如果你是要从键盘获取到输入，判断条件可以改为getchar() != '\n'

printf("%ld\n", nc);

在ws下按楼上的方式输入结束符~

Enter、Ctrl+Z、Enter


Question: 【请问】如果不加锁，修改基本类型的数据在多线程下安全吗？

引用 2 楼 mLee79 的回复:如果 a 在 4字节边界对齐， 现在能见到的32位及以上的处理器上不会， 但是会出现一些线程读出 0xCCDDEEFF 同时另一些线程读出 0x01020304 的情况。  要避免这种情况， 需要刷新各核心的高速缓存 比如加  lock 前缀啊， 用 ldrex 啥的指令啊什么的。。。  你提到一个条件，就是“ 4字节边界对齐”。 如果是1字节对齐，那么就有可能出现只修改部分字节的情况，是吗？

基本类型（值类型）应该不会出现读到只修改部分的情况

不安全

引用 3 楼 HeBanBei 的回复:[quote=引用 2 楼 mLee79 的回复:] 如果 a 在 4字节边界对齐， 现在能见到的32位及以上的处理器上不会， 但是会出现一些线程读出 0xCCDDEEFF 同时另一些线程读出 0x01020304 的情况。  要避免这种情况， 需要刷新各核心的高速缓存 比如加  lock 前缀啊， 用 ldrex 啥的指令啊什么的。。。  你提到一个条件，就是“ 4字节边界对齐”。 如果是1字节对齐，那么就有可能出现只修改部分字节的情况，是吗？[/quote]  没4字节对齐是未定义行为， 在很多RISC的处理器上会直接crash， 在单CPU的 x86 处理器上应该能正常工作， 在多CPU的 x86  SMP上即使加了 lock 前缀也是未定义行为， 有可能会读到部分修改的值。

不安全。  编译器如何处理的代码，与 CPU 如何处理得到的指令，都会带来潜在的危险。


Question: c语言的小钢琴游戏问题

为什么该论坛禁止我发超过50字？

引用 9 楼 qq_33758085 的回复:钢琴.exe - 1 error(s), 0 warning(s) 引用 10 楼 qq_33758085 的回复:你编译的效果是怎样的？  可以编译，1 error 是什么，你麻烦发完整啊

你编译的效果是怎样的？

钢琴.exe - 1 error(s), 0 warning(s)

引用 7 楼 qq_33758085 的回复:#include<stdio.h> #include<process.h> #include<windows.h> #include<Mmsystem.h> #pragma comment (lib,"Winmm.lib") /* *隐藏控制台光标 */ void HideTheCursor() { 	CONSOLE_CURSOR_INFO cciCursor; 	HANDLE hstdOut =GetStdHandle(STD_OUTPUT_HANDLE);  	if(GetConsoleCursorInfo(hstdOut,&cciCursor)) 	{ 		cciCursor.bVisible=FALSE; 		SetConsoleCursorInfo(hstdOut,&cciCursor); 	} } /* *播放线程 */ unsigned _stdcall thread_play(LPVOID lpParam) { 	char sz_command[126]={0}; 	char sz_cur_play[32]={0};  	/*打开mp3文件*/ 	sprintf(sz_command,"open \"key\\%c.mp3\"alias key_%c",(WORD)lpParam,(WORD)lpParam);     mciSendString(sz_command,0,0,0);  	/*播放*/ 	sprintf(sz_command,"play %s",sz_cur_play); 	mciSendString(sz_command,0,0,0);  	/*3秒后关闭*/ 	Sleep(3000); 	sprintf(sz_command,"close %s",sz_cur_play); 	mciSendString(sz_command,0,0,0);  	return 0; }  main() { 	/*输入标准句柄*/ HANDLE h_console_in;  	/*输入记录*/ 	INPUT_RECORD input_rec; 	DWORD res;  	/*线程句柄*/ 	HANDLE h_thread_play=INVALID_HANDLE_VALUE; 	unsigned id_thread_play; 	printf("欢迎来到键盘钢琴！！\n\n");  	HideTheCursor();  	/* 获取标准输入句柄，并设置为接受输入*/ 	h_console_in=GetStdHandle(STD_INPUT_HANDLE); 	SetConsoleMode(h_console_in,ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);  	while (1) 	{  	/*读取一个输入*/ 	ReadConsoleInput(h_console_in,&input_rec,1,&res);  	/*刷新输入缓冲区*/ 	FlushConsoleInputBuffer(h_console_in);  	/*输入事件为按键输入，且按键按下时*/ 	if (input_rec.EventType==KEY_EVENT && input_rec.Event.KeyEvent.bKeyDown==TRUE) 	{ 	/*输入的是A~Z之间的按键*/ 		if (input_rec.Event.KeyEvent.wVirtualKeyCode >='A' 			&& input_rec.Event.KeyEvent.wVirtualKeyCode<='Z') 		{ 	/*将当前按键作为参数，开线程*/ 			h_thread_play=(HANDLE)_beginthreadex(NULL,0,&thread_play, 				(void *)input_rec.Event.KeyEvent.wVirtualKeyCode,0,&id_thread_play);    		} 	}  	} }  可以正常编译，你说的错误什么，给出错误提示

引用 15 楼 qq_33758085 的回复:可以编译了，但是怎么用呢？  你得自己看代码啊，而且从你代码看，你目录下需要有他需要的几个mp3文件

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

引用 12 楼 qq_33758085 的回复:--------------------Configuration: 钢琴 - Win32 Debug-------------------- Compiling... 钢琴.cpp F:\C语言\钢琴.cpp(81) : error C2065: '_beginthreadex' : undeclared identifier F:\C语言\钢琴.cpp(87) : warning C4508: 'main' : function should return a value; 'void' return type assumed 执行 cl.exe 时出错.  钢琴.exe - 1 error(s), 0 warning(s)  前面加上#include <process.h>

可以编译了，但是怎么用呢？

Skipping... (no relevant changes detected)

#include "stdio.h" #include "process.h" #include "windows.h" #include "Mmsystem.h" #pragma comment (lib,"Winmm.lib") /* *隐藏控制台光标 */ void HideTheCursor() { 	CONSOLE_CURSOR_INFO cciCursor; 	HANDLE hStdOut =GetStdHandle(STD_OUTPUT_HANDLE);  	if(GetConsoleCursorInfo(hStdOut,&cciCursor)) 	{ 		cciCursor.bVisible=FALSE; 		SetConsoleCursorInfo(hStdOut,&cciCursor); 	} } /* *播放线程 */ unsigned _stdcall thread_play(LPVOID lpParam) { 	char sz_command[126]={0}; 	char sz_cur_play[32]={0};  	/*打开mp3文件*/ 	sprintf(sz_command,"open \"key\\%c.mp3\"alias key_%c",(WORD)lpParam,(WORD)lpParam); 	mciSendString(sz_command,0,0,0);  	/*播放*/ 	sprintf(sz_command,"play %s",sz_cur_play); 	mciSendString(sz_command,0,0,0);  	/*3秒后关闭*/ 	Sleep(3000); 	sprintf(sz_command,"close %s",sz_cur_play); 	mciSendString(sz_command,0,0,0);  	return 0; }  void main() { 	/*输入标准句柄*/ 	HANDLE h_console_in;  	/*输入记录*/ 	INPUT_RECORD input_rec; 	DWORD res;  	/*线程句柄*/ 	HANDLE h_thread_play=INVALID_HANDLE_VALUE; 	unsigned id_thread_play; 	printf("欢迎来到键盘钢琴！！\n\n");  	HideTheCursor();  	/* 获取标准输入句柄，并设置为接受输入*/ 	h_console_in=GetStdHandle(STD_INPUT_HANDLE); 	SetConsoleMode(h_console_in,ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);  	while (1) 	{  		/*读取一个输入*/ 		ReadConsoleInput(h_console_in,&input_rec,1,&res);  		/*刷新输入缓冲区*/ 		FlushConsoleInputBuffer(h_console_in);  		/*输入事件为按键输入，且按键按下时*/ 		if (input_rec.EventType==KEY_EVENT && input_rec.Event.KeyEvent.bKeyDown==TRUE) 		{ 			/*输入的是A~Z之间的按键*/ 			if (input_rec.Event.KeyEvent.wVirtualKeyCode >='A'&& input_rec.Event.KeyEvent.wVirtualKeyCode<='Z') 				{ 					/*将当前按键作为参数，开线程*/ 					h_thread_play=(HANDLE ) _beginthreadex(NULL,0,&thread_play, 					(void *)input_rec.Event.KeyEvent.wVirtualKeyCode,0,&id_thread_play); 				} 		} 		 	} }

注意大小写，不是 hStdOut ， 而是hstdOut 注意字母l与数字1，不是1pParam，而是lpParam 同理misSendString 拼错了

有意思，多年以前玩过一个DOS下的弹钢琴，好像是有界面的，就是一条一条的类似琴键。忘了是光盘里的还是从哪个同学软盘拷来的，毕业后无聊做了个小游戏下载的静态个人主页（记得好像是51.net的个人主页空间），用56K的猫找遍网络，找不到那个DOS弹钢琴了。因为经历了一些转折，最初玩电脑时的一些美好的小游戏小软件后来又找回来很多，可惜个人主页没有几个月就被关闭无法访问了，还交了3年的钱好像。

引用 4 楼 qq_33758085 的回复:改了还是显示有错，能不能发 验证过 的代码过来？  你把你改好的代码发上来，帮你看下

改了还是显示有错，能不能发 验证过 的代码过来？


Question: c语言如何将一个十进制负整数转换成四字节的十六进制？？？

引用 2 楼 paschen的回复:http://blog.chinaunix.net/uid-20776242-id-1846735.html 这个链接打不开，是怎么回事

可以用一个uint8_t的指针指向这个int整数，然后挨个printf %x,如果你真需要四个字节显示的话

#include "stdio.h" int main(){ 	int a;     printf("输入一个整数：\n");     scanf("%d",&a); 	printf("十六进制输出为：\n");     printf("0x%hhx\n", a);     return 0;  }

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


Question: getchar这个函数是会等待用户输入但是又会继续循环吗？

仅供参考：#include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }

你怎么知道是回到13行让你输入数据，而不是一直卡在getchar让你输入？   问题一：%d是无法读取走scanf输入结束后的换行符的，因为类型不匹配，%d要读取的是整形的数，读取到换行符这个非整形的字符之后就不读了，并且不会清除换行符，因此换行符一直存在缓冲区里面。所以程序下面使用了getchar去读走这个换行符   问题二：如果输入的是-10，那么确实如你所想，if中的getchar把缓冲区中的换行符读取走了之后，下面的while中的getchar是会一直卡在那里等你输入的，不过不是你说的那样能调回13行，而是getchar的效果，一直等你输入换行符之后才能结束本次循环回到13行，不信你在13行前面加个printf提示。    对本程序的建议：14行  15行那里，把day>=0和getchar=='\n'互相换下。如果不满足，不会getchar了。

你运行一下不就知道了吗！

你写得太复杂！


Question: 代码没有写错，总是提示debug assertion failed是什么原因

我找到原因了，谢谢

遇到问题点中断，然后通过调用堆栈、变量窗口等观察分析原因 代码没写错只是编译没有错误，运行时仍然可能有错误 实在检查不出把代码发上来

原因是，你觉得没写错，但是实际上确实写错了。


Question: linux下的read系统调用，什么时候，会返回0或者负数

比如对方把 socket 关了。

查MSDN是Windows程序员必须掌握的技能之一。 查man是Linux程序员必须掌握的技能之一。

看man page http://man7.org/linux/man-pages/man2/read.2.html

引用 8 楼 user-5 的回复:收到fin返回0，错误返回-1。错误信息看strerror(errno)，Interrupted system call是系统中断，不是真正的错误，直接continue继续read。  返回-1， 系统调用被中断，说明有信号产生 ,  错误码是einter， 确实可以继续调用read， 不需要重新建立socket。    返回0，是fin，已经和web服务器断开连接了。

引用 2 楼 zhangxiangDavaid 的回复:read返回读到的字节数 返回0，表明读到了文件结尾； 返回-1，表明出错。  把socket等同于文件。  帮忙看看5楼

引用 5 楼 u012879787 的回复:[quote=引用 4 楼 fefe82 的回复:] 比如对方把 socket 关了。 我打印了错误码，发现read return  -1的时候，strerror(errno)后提示：  Interrupted system call，  我这个程序是一个web压力测试源码，难道网站服务器，检测到我做压力测试，就强制关闭我的系统调用？  凭什么关闭，它什么理由？  我是压力腾讯的新闻网站，试试我的压力测试代码。  第2个问题： read return 0的时候 ， strerror(errno)提示success。   百思不得其解，按照1的说法，返回0，则说明已经到了文件尾部，数据都取出了，所以是成功，  我晕，这个解释，不能让人满意吧，你自己想想， 套接字我没有做任何设置，没有数据，就返回0！！！  我的理解是，没有数据， 就堵塞，这才对！！！毕竟是我没有套接字设置过属性嘛。不是吗？    [/quote]  第2个问题： read return 0的时候 ， strerror(errno)提示success。   百思不得其解，按照1楼的说法，

引用 4 楼 fefe82 的回复:比如对方把 socket 关了。 我打印了错误码，发现read return  -1的时候，strerror(errno)后提示：  Interrupted system call，  我这个程序是一个web压力测试源码，难道网站服务器，检测到我做压力测试，就强制关闭我的系统调用？  凭什么关闭，它什么理由？  我是压力腾讯的新闻网站，试试我的压力测试代码。  第2个问题： read return 0的时候 ， strerror(errno)提示success。   百思不得其解，按照1的说法，返回0，则说明已经到了文件尾部，数据都取出了，所以是成功，  我晕，这个解释，不能让人满意吧，你自己想想， 套接字我没有做任何设置，没有数据，就返回0！！！  我的理解是，没有数据， 就堵塞，这才对！！！毕竟是我没有套接字设置过属性嘛。不是吗？


引用 3 楼 paschen 的回复:doses[3] 被编译器理解成 *(doses + 3) 3[doses] 被编译器理解成 *(3 + doses) 所以是一样的  http://blog.csdn.net/paschen/article/details/47315449  我刚好结帖了，没有给到分，抱歉。

C语言中，数组和下标可以互换，这是由数组下标的指针定义决定的，由于存在加法交换律，只要一个是指针，另一个是整型就行，而无关顺序，doses[3]等价于3[doses]，等价于*(doses+3)，等价于*(3+doses)。只要知道有这么回事就行，不推荐3[doses]这种写法。

这是语法糖 http://blog.csdn.net/zhangxiangdavaid/article/details/38085743


Question: 求解C语言一道基础题

1<=x<=2. 很明显的一个错误

不能连续比较吧

真的是基础没学好啊，while (1 <= x <= 2); 这写，没有哪里这么教你的吧 把基础书籍再看一遍的好

引用 6 楼 zhao4zhong1 的回复:哪几种语言有对一个数据连续比较的用法？我想知道。 lisp 如：(< 1 2 3 4 5)

其实就是人脑在比较数字大小的时候也是拆成两部分分别比较的，更何况机器呢==

没有语言能够进行连续比较吧

哪几种语言有对一个数据连续比较的用法？我想知道。

C语言中没有对一个数据连续比较的用法，所以使用逻辑运算符对数据进行比较

1 <= x <= 2 被程序理解成了 1<=x 得到的bool值（0或1）来比较是否小于2，显然变成了死循环 应该写成 x >= 1 && x <= 2

那while (1 <= x <= 2)  是指x>=1 || x<= 2吗？？？？

不只C语言，好多语言中都没有1 <= x <= 2这种写法，而是要用逻辑与代替，比如1 <= x && x <= 2

修改如下：  #include <stdio.h> #include <stdlib.h> int main() { 	int x, y; 	x = 3; 	do 	{ 		y = x--; 		if (!y) { printf("x"); continue; } 		printf("#"); 	} while (1 <= x && x <= 2); //while (1 <= x <= 2);  	return 0; } //###


Question: 求历年c语言课程设计（自己做的，任何内容）谢谢了，复制给我一个

提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

这个最好是自己动手写写，大有裨益。如果实在不知道怎么写，可以从网上百度一个，一般这种网上都是有的，但是自己一定要看懂

最好新颖一点的，独特，比如一个同学给自己家洗衣店做的一个系统，实用，新颖


Question: visual studio 2015 scanf_s

\n  空格和制表符，是空白符。 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符。 只有输入一个非空白符的时候才能终止scanf的输入。

谢谢，受教啦

scanf_s("%d\n",&n);  改成 scanf_s("%d",&n);


Question: 求a%b,数都非常大，怎么解决

引用 4 楼 hxiaohai 的回复:我突然看到，你的是long long 类型的，.0输出控制符是对浮点型的，long long 是长长整型，是没有小数位的，那就是这里的问题了。谢谢

仅供参考：#include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }

引用 2 楼 hxiaohai 的回复:printf("%.0lld\n",x1); 其他代码没错，问题出在.0处，输不出0。 printf("%lld\n",x1); 这样能输出0但其他有小数位。 原因和修改方法我再去百度看看  直接去掉.0测试了一下，结果竟然正好符合输出样例

没看懂你的输入，scanf("%s %lld", s, &m);是不是少了个逗号呢


Question: 后根遍历与后序遍历区别是什么呢···

树后根遍历的顺序和中序遍历顺序是一样的，后根遍历是从做到右，不是字面的意思

树后根遍历的顺序和中序遍历顺序是一样的，后根遍历是从做到右，不是字面的意思

引用 5 楼 zhao4zhong1 的回复:[quote=引用 3 楼 jjaisgm 的回复:] [quote=引用 2 楼 ghx287524027 的回复:] 这没什么区别啊，只是一个别名而已，原理是一样的   那帮我看一下这道题： 树的后根遍历序列等同于该树对应的二叉树的（     ) A.先序遍历序列 B.中序遍历序列 C.后序遍历序列[/quote] C[/quote]    昨天下午的考试考了这道题·····，我按照那本练习册给的答案选了B······哎······

引用 3 楼 jjaisgm 的回复:[quote=引用 2 楼 ghx287524027 的回复:] 这没什么区别啊，只是一个别名而已，原理是一样的   那帮我看一下这道题： 树的后根遍历序列等同于该树对应的二叉树的（     ) A.先序遍历序列 B.中序遍历序列 C.后序遍历序列[/quote] C

无区别 二叉树的各种遍历： http://blog.csdn.net/zhangxiangdavaid/article/details/37115355

引用 2 楼 ghx287524027 的回复:这没什么区别啊，只是一个别名而已，原理是一样的   那帮我看一下这道题： 树的后根遍历序列等同于该树对应的二叉树的（     ) A.先序遍历序列 B.中序遍历序列 C.后序遍历序列

这没什么区别啊，只是一个别名而已，原理是一样的

名字不同。 后序遍历（LRD）是二叉树遍历的一种，也叫做后根遍历、后序周游，可记做左右。 http://baike.baidu.com/link?url=3HC3f_Vs74RtCYB6l2RCOplmKVuVzZa0v5gys8II59ZOTJGkGD6BhUkxMZTlVtvY3pi5Z8doM7btjayeSHThtK


Question: strcpy函数的问题

先弄清楚copy和move的语义： copy的语义是操作结束后，新目的的内容和旧源的内容一致，且保证旧源的内容不变。 move的语义是操作结束后，新目的的内容和旧源的内容一致，但不保证旧源的内容不变。 于是乎，当操作的内存重叠时，无论如何也不可能实现copy！

好问题，楼上已经解答了， 以后注意就行、

引用 3 楼 z878669112的回复:刚才查了下重叠时strcpy的不确定性，在执行这段代码时，实际上是一次性复制4个字节，所以输出为aabcd。这种说法是否正确呢？ 既然已经是不确定的，你再分析为什么得到这个结果也没有意义了，在你这里是这个结果，在别人那里也许就不是这个结果，也或许根本就执行不了，所以不能因为结果去分析原因

引用 3 楼 z878669112 的回复:刚才查了下重叠时strcpy的不确定性，在执行这段代码时，实际上是一次性复制4个字节，所以输出为aabcd。这种说法是否正确呢？  没明白你说的一次性是什么意思，不确定表示可能得到任意结果，包括你希望得到的与不希望得到的

如1楼所说，当内存重叠时strcpy()的行为不确定，你可以用memcpy（），这个的内存块是可以重叠的

https://msdn.microsoft.com/en-us/library/kk6xf663.aspx  MSDN上已经说了，如果复制源和目的字符串有重叠，行为不确定  The strcpy function copies strSource, including the terminating null character, to the location that's specified by strDestination. The behavior of strcpy is undefined if the source and destination strings overlap.


Question: 谁能帮我看看哪里出问题了

fscanf每次是从fp指向的位置（也就是文件开始处）读取五个数，所以每次输出的结果都是一样的。要想继续往下读取，需要在每次读取后重新设置文件流指针的位置（也就是下次开始读取的位置）。可以利用fseek()进行设置。原型如下： int fseek( FILE *stream, long offset, int origin );   第一个参数stream为文件指针   第二个参数offset为偏移量，整数表示正向偏移，负数表示负向偏移   第三个参数origin设定从文件的哪里开始偏移,可能取值为：SEEK_CUR、 SEEK_END 或 SEEK_SET   SEEK_SET： 文件开头   SEEK_CUR： 当前位置   SEEK_END： 文件结尾

因为你fscanf只读取了五个数呀

一直都是读取文件内的前五个数，而不是接着向下读取


Question: 不确定个数的界面制作问题。。求教

引用 8 楼 user-2 的回复:[quote=引用 6 楼 q1306436808 的回复:] 。。想当于每次改文件或更新文件内容都要再改下代码么，，能不能有其他方法实现改变文件内容，不用加代码，运行时菜单自动也随着改变  不需要加代码啊，你不会用循环啊，读到什么显示什么不就行了！ 建议先去把基础打好！[/quote]  。。我自己玩出来了，，谢谢你啊

引用 8 楼 user-2 的回复:[quote=引用 6 楼 q1306436808 的回复:] 。。想当于每次改文件或更新文件内容都要再改下代码么，，能不能有其他方法实现改变文件内容，不用加代码，运行时菜单自动也随着改变  不需要加代码啊，你不会用循环啊，读到什么显示什么不就行了！ 建议先去把基础打好！[/quote]  就是不会用这个循坏啊，，switch肯定不行，我也试了for循环，不会玩啊

想的太多了太美了不如不想怀抱初心直接做。

引用 6 楼 q1306436808 的回复:。。想当于每次改文件或更新文件内容都要再改下代码么，，能不能有其他方法实现改变文件内容，不用加代码，运行时菜单自动也随着改变  不需要加代码啊，你不会用循环啊，读到什么显示什么不就行了！ 建议先去把基础打好！

引用 3 楼 user-2 的回复:[quote=引用 2 楼 q1306436808 的回复:] 能不能举个例。。  void showmenu(char**p, int n) { 	for(int i = 0; i < n; ++i) 		printf(p[i]); }  int main() { 	char*p[100] = {"1、XXX\n", "2、YYY\n"}; 	int n = 2; //现在有两个菜单项 	showmenu(p, n);  	printf("\n\n");  	//现在加上一个菜单 	p[n++] = "3、ZZZ\n"; 	showmenu(p, n);  	return 0; } [/quote] 再次求教啊，，我不想用这个方法。

引用 4 楼 q1306436808 的回复:这个懂了，，但我是要根据文件里的内容做，我那个菜单要将这个文件的学校列出来，然后选对应的序号得到相应的信息，这个学校个数可以随意改变。。 	int i,count; 	FILE *fpp; 	fpp = fopen("school.txt","w"); 	if(fpp == NULL){ 		printf("文件打开失败\n"); 	}  	 	printf("请输入参赛学校个数:"); 	scanf("%d",&count); 	fprintf(fpp,"%d\n",count); 	printf("\n"); 	 	for(i=0; i<count; i++){ 		printf("请输入第%d个学校的名称:",i+1); 		scanf("%s",s[i].name); 		fprintf(fpp,"%s\n",s[i].name); 	} 	fclose(fpp);  一样的，学会举一反三，你要添加一个菜单就在添加一个字符串

引用 2 楼 q1306436808 的回复:能不能举个例。。  void showmenu(char**p, int n) { 	for(int i = 0; i < n; ++i) 		printf(p[i]); }  int main() { 	char*p[100] = {"1、XXX\n", "2、YYY\n"}; 	int n = 2; //现在有两个菜单项 	showmenu(p, n);  	printf("\n\n");  	//现在加上一个菜单 	p[n++] = "3、ZZZ\n"; 	showmenu(p, n);  	return 0; }

能不能举个例。。

把菜单项放到一个字符指针数组中，每次循环显示所有的，需要添加菜单时就在字符指针数组中再添加一个


Question: 二级指针的自增问题.

如果p是单纯的二级指针char**p，那么p+1是增加1个sizeof(char*)即1个指针所占字节数4， 而(*p)+1 只是增加sizeof(char)即1个字节。  这种二级指针跟数组指针如char (*p)[N]是有区别的，此时p指向的是一维数组，p+1就是增加sizeof(char) * N，而(*p)+1依旧是增加sizeof(char)即1个字节。  简单说一个二维数组char a[M][N]，数组名a就是一个常量一维数组指针char (* const a)[N]，a+1就是增加sizeof(char) * N

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

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  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、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

二维数组 int a[][size]     a+1   增加的是 sizeof(int)*size

引用 1楼user-8 的回复:因为p和*p存放的都是地址，而**p存放的是char，所以p++加了4；*p++加了1是char*还是char[]  ？

同意。 引用 4 楼 paschen 的回复:对于T* t  增加的是sizeof(T) 所以： 第一个增加sizeof(char*) 第二个增加sizeof(char) 观察一把：  int main(void)//52 { 	char *strs[] = { 		"David", 		"zx", 	}; 	char **p = strs; 	printf("p=%x,p+1=%x\n", p, p + 1); 	printf("*p=%x,*p+1=%x\n", *p, *p + 1); 	return 0; } //p=18f7fc,p+1=18f800 //*p=fece74,*p+1=fece75

对于 T *p; ，p + 1 增加 sizeof(T)。  char **p; p +1 增加 sizeof(char *) 。(*p) + 1 对 *p 增加 sizeof (char)

指针+1的效果和指针类型有关，char**类型的指针用来指向字符串数组，即这样使用char**p={"abc","d""efgh"}; 首先是p，p的指针类型可以称作字符串数组指针。也就是p指向一个数组，数组元素为字符串。开始时，p指向第一个字符串即“abc”，这也是字符串数组的第一个元素（整个字符串是一个元素）。那p+1就应该指向第二个元素即“d”，从中可以看出增加了几个字节，还可以看出这个增加的长度是不确定的（和第一个字符串长度有关）。 然后就是*p，它的指针类型可以称作字符串指针。也就是它也指向一个数组，但这个数组里放的是字符。当p指向“abc”时，*p就指向 ‘a’，而(*p)++应该指向第二个字符即‘b’，也就是增加了一个字节


Question: 很简单的程序，怎么运行后卡死，求帮忙分析~

卡在 While 循环了，你在 for(j=2....)那里的break，只是退出了 for(j=2....) 层的循环，并没有退出While循环，所以一直在 i=2 时的while循环中卡住。

#include<stdio.h> int main() { 	int i, j, k = 1, h=0,m; 	for (i = 1; i <= 1000; i++) 	{ 		m=i; 		while (1) 		{ 			if (m == 1) 				break; 			for (j = 2; j <= m; j++) 			{ 				if (m%j == 0) 				{ 					m = m / j; 					k += j; 					break; 				} 			} 		} 		if (k == i) 		{ 			printf("%d\t", i); 			h++; 			if (h>5) 			{ 				printf("\n"); 				h = 0; 			} 		} 		k=1;  	} 	return 0; }       貌似i值没有判断好，还忘记给k值置1。给了一个中间变量m，break能跳出来的，谢谢楼上帮忙~写代码太粗心惹。

引用 6 楼 qq_28061217 的回复:但是我上面还有一个break啊~上面那个break是当为1的时候才跳出的，如果i不是1就不起作用了

但是我上面还有一个break啊~

while循环没有跳出来，后面的一个break只是跳出了for循环，while没有结束

循环一直出不来，单步跟踪一下就知程序实际怎么走的了

能具体说说是哪条语句开始陷入死循环了吗~

不是卡死，是陷入了死循环

附上程序： #include<stdio.h> int main() { 	int i, j, k = 1, h = 0; 	for (i = 1; i <= 1000; i++) 	{ 		while (1) 		{ 			if (i == 1) 				break; 			for (j = 2; j <= i; j++) 			{ 				if (i%j == 0) 				{ 					i = i / j; 					k += j; 					break; 				} 			} 		} 		if (k == i) 		{ 			printf("%d\t", i); 			h++; 			if (h>5) 			{ 				printf("\n"); 				h = 0; 			} 		}  	} 	return 0; }


Question: 数据类型互相定义，先有鸡还是先有蛋？

引用 10 楼 sholber 的回复:[quote=引用 9 楼 paschen 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在[/quote]  可别狡辩了。你把声明当成语句还有理了？ 还有，就你那个例子问题也是大大的。如下例所示，有没有DECL，程序的效果是不同滴。 struct s {char c;};            //DECL  void f (void) {     typedef struct s * ps;     struct s {float f;}; } 虚心一点，不是谁都愿意指出你的错误。 [/quote]  如果注释掉DECL ps使用的是float f的结构，不注释则是上边char c的结构，学习了，不过还是不太懂typedef的时候到底是如何寻找结构s的，是优先向前找，如果前面没有再向后找吗？

引用 14 楼 zhao4zhong1 的回复:先有一种能描述鸡和蛋以及未来所有概念的语言 先有一种能指向鸡和蛋以及未来所有概念的指针 赵老师总是这么高屋建瓴

引用 12 楼 sholber 的回复:[quote=引用 11 楼 paschen 的回复:] [quote=引用 10 楼 sholber 的回复:] [quote=引用 9 楼 paschen 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在[/quote]  可别狡辩了。你把声明当成语句还有理了？ 还有，就你那个例子问题也是大大的。如下例所示，有没有DECL，程序的效果是不同滴。 struct s {char c;};            //DECL  void f (void) {     typedef struct s * ps;     struct s {float f;}; } 虚心一点，不是谁都愿意指出你的错误。 [/quote]  我想你误解我意思了，我只是说可以这样写而已 你给的例子在f函数中有没定义效果当然是不同的，或许你给的例子更有说服力 函数f中的ps表示的是struct s {float f;}指针，而不是全局中在前面的那个 typedef优先在所在的名字空间下寻找，而且也仅在同名称空间中可见的范围内有效[/quote]  不，typedef没有优先在当前块内寻找的说法。 就上例而言，pf的类型并不是指向struct s {float f;}的指针，而是指向struct s {char c;}的指针。[/quote]  是的，我 这句说错了

引用 11 楼 paschen 的回复:[quote=引用 10 楼 sholber 的回复:] [quote=引用 9 楼 paschen 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在[/quote]  可别狡辩了。你把声明当成语句还有理了？ 还有，就你那个例子问题也是大大的。如下例所示，有没有DECL，程序的效果是不同滴。 struct s {char c;};            //DECL  void f (void) {     typedef struct s * ps;     struct s {float f;}; } 虚心一点，不是谁都愿意指出你的错误。 [/quote]  我想你误解我意思了，我只是说可以这样写而已 你给的例子在f函数中有没定义效果当然是不同的，或许你给的例子更有说服力 函数f中的ps表示的是struct s {float f;}指针，而不是全局中在前面的那个 typedef优先在所在的名字空间下寻找，而且也仅在同名称空间中可见的范围内有效[/quote]  不，typedef没有优先在当前块内寻找的说法。 就上例而言，pf的类型并不是指向struct s {float f;}的指针，而是指向struct s {char c;}的指针。

引用 10 楼 sholber 的回复:[quote=引用 9 楼 paschen 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在[/quote]  可别狡辩了。你把声明当成语句还有理了？ 还有，就你那个例子问题也是大大的。如下例所示，有没有DECL，程序的效果是不同滴。 struct s {char c;};            //DECL  void f (void) {     typedef struct s * ps;     struct s {float f;}; } 虚心一点，不是谁都愿意指出你的错误。 [/quote]  我想你误解我意思了，我只是说可以这样写而已 你给的例子在f函数中有没定义效果当然是不同的，或许你给的例子更有说服力 函数f中的ps表示的是struct s {float f;}指针，而不是全局中在前面的那个 typedef优先在所在的名字空间下寻找，而且也仅在同名称空间中可见的范围内有效

引用 9 楼 paschen 的回复:[quote=引用 8 楼 sholber 的回复:] [quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在[/quote]  可别狡辩了。你把声明当成语句还有理了？ 还有，就你那个例子问题也是大大的。如下例所示，有没有DECL，程序的效果是不同滴。 struct s {char c;};            //DECL  void f (void) {     typedef struct s * ps;     struct s {float f;}; } 虚心一点，不是谁都愿意指出你的错误。

引用 8 楼 sholber 的回复:[quote=引用 6 楼 paschen 的回复:] 下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。[/quote]  你没见过不代表不存在

引用 6 楼 paschen 的回复:下面语句 A定义在typedef之后，仍然是可以的   typedef struct A* Task;  struct A {  };   首先，没见过这样的“语句”； 其次，这两个struct A是否一样，是否为同一结构类型，还取决于上下文，你没说清楚。

引用 1 楼 user-5 的回复:这个有点链表的意味。比如： typedef struct ugl_node     {     struct ugl_node *pNext;     struct ugl_node *pPrev;     struct ugl_list *pList;     } UGL_NODE; 哪怕还没有声明struct ugl_node，也照样可以使用struct ugl_node *pNext。因为编译器完全可以识别出这是指向结构体的指针，但是只有定义了结构体ugl_node之后，才可以进行解引用操作如*pNext，即pNext的用处是极度受限的。不过只要struct ugl_node的定义完成（遇到对应的右大括号），这样的限制也就消失，在后面的代码中完全可以正常的使用……  这种回答是自信过头了。

这种定义是合法的，你也可以写成：   typedef struct TaskData { void (*handler)(struct TaskData*, MessageId, Message); } TaskData;

顶一顶，希望有更浅显的解释

如果嵌套类型的使用，递归定义，导致size无法确定了，就会有逻辑问题。 但使用指针是没有问题的，因为32位下指针总是4个字节的，大小确定，无歧义。

引用 1 楼 user-5 的回复:这个有点链表的意味。比如： typedef struct ugl_node     {     struct ugl_node *pNext;     struct ugl_node *pPrev;     struct ugl_list *pList;     } UGL_NODE; 哪怕还没有声明struct ugl_node，也照样可以使用struct ugl_node *pNext。因为编译器完全可以识别出这是指向结构体的指针，但是只有定义了结构体ugl_node之后，才可以进行解引用操作如*pNext，即pNext的用处是极度受限的。不过只要struct ugl_node的定义完成（遇到对应的右大括号），这样的限制也就消失，在后面的代码中完全可以正常的使用…… 链表是用自己定义自己，这个是用别人定义自己，而别人又是用自己去定义的，好像有点不一样，我再体会一下。。


Question: C 关于结构的问题。。

。。是的我知道了，谢谢各位了

没有问题、没有问题、没有问题……

这个定义没有问题，不知你是哪出问题了

光看这个是没有错误的，错误的地方不在这里

如果你程序中有man_project .NAme类似的程序会出现这种错误 换为man_project ->NAme

只有这点代码吗？这里是不应该报错的


Question: 关于while的一个问题，很基础

答案错了，是个死循环，如果写成while(k==10) k--; 那么就是执行一次

引用 7 楼 zhangxiangDavaid 的回复:[quote=引用 6 楼 zhangxiangDavaid 的回复:] [quote=引用 5 楼 legal_high 的回复:] [quote=引用 4 楼 zhangxiangDavaid 的回复:]  while(k  = 10; k--; );  以上这种while写法可以循环10次 ou，不好意思没打好是k=10;while(k=1) k--;[/quote] 你的写法显然是无限循环[/quote] 因为循环条件k=1，一直都是true[/quote] en 我也是这么觉得 但是答案是循环一次 看来有可能是答案错了

引用 5 楼 legal_high 的回复:[quote=引用 4 楼 zhangxiangDavaid 的回复:]  while(k  = 10; k--; );  以上这种while写法可以循环10次 ou，不好意思没打好是k=10;while(k=1) k--;[/quote] 你的写法显然是无限循环

引用 6 楼 zhangxiangDavaid 的回复:[quote=引用 5 楼 legal_high 的回复:] [quote=引用 4 楼 zhangxiangDavaid 的回复:]  while(k  = 10; k--; );  以上这种while写法可以循环10次 ou，不好意思没打好是k=10;while(k=1) k--;[/quote] 你的写法显然是无限循环[/quote] 因为循环条件k=1，一直都是true

引用 4 楼 zhangxiangDavaid 的回复: while(k  = 10; k--; );  以上这种while写法可以循环10次 ou，不好意思没打好是k=10;while(k=1) k--;

能过，但是printf不出的

这个能编译过嘛 ...

引用 1 楼 user-3 的回复:这个能编译过嘛 ... 能过，但是printf不出的


Question: 求详解，谢谢！

#include <stdio.h> int a=13,b=5;	        //程序中并没有用到，所以可以删除 int max(int x,int y)	              { return x>y?x:y;       //返回x和y较大的一个数，重点是? :运算符，可搜索了解 } void main() {                             //局部变量和全局变量、函数同名时，局部变量覆盖其他 int a=18;                                      int b=7;	 printf("max=%d\n",max(a,b));   //此时传递的是main函数私有变量ab }

如果楼主打算访问的是全局变量，可以这样写：  printf("max=%d\n",max1(::a,::b));

局部变量直接覆盖了全局变量

重点理解全局变量和局部变量

楼上说的很好，自己在电脑上调试一下就知道了！我想你想问的是为什么会这样，建议你找本书看看，系统的学习一下，不然就算别人给你讲了，你还是一知半解！

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

覆盖只是现象，变量查找规则才是本质。


Question: 链表的尾插法一定需要声明头指针以及另外两个指针吗???能不能把这段代码中的s指针去掉

假设头结点Head已经建好，并且 genNode(data);返回新创建的节点，数据为data;不初始化next指针。 input();返回 输入数据 isValid(data) 返回数据是否有效 头插法   Head ->next =NULL; data =input(); while(isValid(data)){  p=genNode(data); p->next =Head->next; Head->next =p; data =input(); } 尾插法  Head ->next =NULL; p = Head; data =input(); while(isValid(data)){ p->next  = genNode(data); p = p->next; p->next  = NULL; data =input(); }

不论头插法，尾插法，都不需要额外的指针。 不过如何实现，看你自己想怎么做。

在还没有正确实现功能之前，临时变量越多逻辑越清晰。

插入节点总是找到待插位置的前驱。


Question: 添加上能算正负数相加的程序

单向链表实现加、减、乘 http://blog.csdn.net/zhangxiangdavaid/article/details/31032251


Question: PAT乙级——1002 数字分类 (C/C++)一直报错，请大神指点

引用 9 楼 jianjiu7 的回复:[quote=引用 8 楼 u013575812 的回复:] 输出第四类的数是 楼主您的代码是这样的： printf("%.1lf ",A4); 改为这样： printf("%.1lf ",A4/a4);  因为是要求平均数。  再试试。应该可以AC了。谢谢，原来在这。。。[/quote] 恩恩 没事没事 简单的小问题难免会出错 这种题多注意一下细节应该就没什么  加油~

引用 8 楼 u013575812 的回复:输出第四类的数是 楼主您的代码是这样的： printf("%.1lf ",A4); 改为这样： printf("%.1lf ",A4/a4);  因为是要求平均数。  再试试。应该可以AC了。谢谢，原来在这。。。

#include<stdio.h> int main() {     int n,i;     int num;     int A1=0,A2=0,A3=0,A5=0;     double A4=0.0;     int a1=0,a2=0,a3=0,a4=0,a5=0;     int ibus=1; 	printf("请输入数字个数：\n");     scanf("%d",&n); 	printf("请输入数字：\n");     for(i=0;i<n;i++)     {         scanf("%d",&num);         int r = num%5;         if(r==0&&num%2==0)         {             a1++;             A1+=num;         }        else if(r==1)         {             a2++;             A2+=ibus*num;             ibus=-ibus;         }        else if(r==2)         {             a3++;             A3++;         }       else if(r==3)         {             a4++;             A4+=num;         }         else if(r==4)         {             a5++;             if(num>A5)                 A5=num;         }     } 	printf("结果如下：\n");     if(a1!=0)        printf("A1=%d \n",A1);     else         printf("A1=N  \n");     if(a2!=0)        printf("A2=%d  \n",A2);     else         printf("A2=N  \n");     if(a3!=0)        printf("A3=%d  \n",A3);     else         printf("A3=N  \n");     if(a4!=0)        printf("A4=%.1lf  \n",A4/a4);     else         printf("A4=N  \n");     if(a5!=0)        printf("A5=%d \n",A5);     else         printf("A4=N \n");     return 0; }

没报错啊，只是输出结果和你说的不一样

没人评论你敢信？？？？？？

楼主你好，不知测试用例报错时是否有给出测试用例。 若有 可以贴出来一起讨论下。

引用 5 楼 zhangxiangDavaid 的回复:貌似木有问题~但是在刷pat时，pat系统总是报错，看了别人的代码思想也差不多，就是能完全通过，唉，想不懂

貌似木有问题~

引用 2 楼 ghx287524027 的回复:不是，在编译器上不报错，但结果不对，在pat上系统报错，想不出来错在哪 没报错啊，只是输出结果和你说的不一样


Question: while的问题 很基础 刚刚的没打清楚不好意思

引用 2 楼 paschen 的回复:答案错了，是个死循环，如果写成while(k==10) k--; 那么就是执行一次 ok谢谢啊

无限次、无限次、无限次……


Question: 请教各位大神关于数据结构 图 的问题

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

还有那个遍历，，那个递归调用没搞懂

从基础概念看起： 图论基础 http://blog.csdn.net/zhangxiangdavaid/article/details/37915329

不知道你想知道什么？


Question: 有没有人做过OPNET和VS的联合仿真啊？

想请教您一些问题~

你好，请问您联合仿真成功了吗？、我最近也在做这个方向

注释掉不可以，因为用到了这个头文件。请问您做过OPNET和VS的联合仿真吗？

注释掉试试


Question: 声明在一个文件里，定义在一个文件，调用在一个文件。咋还错误

谢谢大家，已经解决啦，用双引号就可以了、真心谢谢

把两部分代码贴出来看看吧

换个函数名试下， max可能和其他宏重名了

你max的cpp里包含了max的头文件吗？

看下错误提示~


Question: 敲回车后一闪而过 这是为啥啊 VS2010

最“正宗”的方法是： 开始、运行、cmd、确定 cd /d 你的exe程序所在盘符和目录 你的exe程序

添加头文件#include<stdlib.h> 在main函数最后添加system("pause");

调试时记得下断点~

引用 4 楼 user-6 的回复:[quote=引用 3 楼 ghx287524027 的回复:] [quote=引用 2 楼 user-6 的回复:] 在最后加上getchar()，不然程序运行完就退出了，或者用Ctrl+F5运行程序   #include <stdio.h> void main() { 	int score; 	printf("输入成绩"); 	scanf("%d",&score); 	getchar(); 	if(score>100) 		printf("数值错误从新输入");  	//return 0; 	getchar(); }   即使再加一个getchar()，应该和原来的程序也没有多大区别吧，只不过是一次输入变两次输入了[/quote]  他代码里的getchar是为了接收掉'\n'，我的是等待观看最后结果，不是同一个意思！[/quote]  恩，可以达到这个目的，就是看他想实现什么功能了。

#include <stdio.h> #Iinclude<windows.h> void main() {  int score; printf("输入成绩"); scanf("%d",&score); getchar(); if(score>100) printf("数值错误从新输入"); system("pause");  }

引用 3 楼 ghx287524027 的回复:[quote=引用 2 楼 user-6 的回复:] 在最后加上getchar()，不然程序运行完就退出了，或者用Ctrl+F5运行程序   #include <stdio.h> void main() { 	int score; 	printf("输入成绩"); 	scanf("%d",&score); 	getchar(); 	if(score>100) 		printf("数值错误从新输入");  	//return 0; 	getchar(); }   即使再加一个getchar()，应该和原来的程序也没有多大区别吧，只不过是一次输入变两次输入了[/quote]  他代码里的getchar是为了接收掉'\n'，我的是等待观看最后结果，不是同一个意思！

引用 2 楼 user-6 的回复:在最后加上getchar()，不然程序运行完就退出了，或者用Ctrl+F5运行程序   #include <stdio.h> void main() { 	int score; 	printf("输入成绩"); 	scanf("%d",&score); 	getchar(); 	if(score>100) 		printf("数值错误从新输入");  	//return 0; 	getchar(); }   即使再加一个getchar()，应该和原来的程序也没有多大区别吧，只不过是一次输入变两次输入了

不明白你说的一闪而过是什么意思，


Question: 一个统计学生的c，编译没报错，运行错误。

/*这是一个查询学生成绩的程序，查询数学，英语，语文，计算并算出总成绩*/ /*首先，显示输入学生人数，然后显示输入各科成绩，最后按照学号排序输出各科 成绩。最后计算并显示出各科成绩的平均值，最大值，最小值*/ /*在main函数中既有printf1函数，scanf函数，printf2函数,arg函数，min函数 max函数*/ void input(double s[][4], int n); void output(double s[][4], int n); double max1(double s[][4], int n, int i); double min1(double s[][4], int n, int i); double avg(double s[][4], int n, int i); int main() { 	int i, number; 	double grade[100][4]; 	char pro[4][10] = { "数学", "英语", "语文", "总成绩" }; 	printf("请输入学生的人数:"); 	scanf("%d", &number); 	input(grade, number); 	output(grade, number); 	for (i = 0; i <= 4; ++i)//这里数组越界了 	{ 		printf("%s最高成绩为%.2f\n", pro[i], max1(grade, number, i)); 		printf("%s最低成绩为%.2f\n", pro[i], min1(grade, number, i));//多了一个%s 		printf("%s平均成绩为%.2f\n", pro[i], avg(grade, number, i)); 		printf("\n"); 	} 	return 0; }  void input(double s[][4], int n) { 	printf("输入学生的成绩按照（高数，英语，c语言的次序输入)\n"); 	/*转义字符*/ 	int i; 	int a, b, c; 	printf("%d\n", n); 	for (i = 0; i<n; i++) 	{ 		//scanf("%f %f %f", &a, &b, &c);//没加& 		//s[i][0] = a; 		//s[i][1] = b; 		//s[i][2] = c; 		scanf("%lf %lf %lf", &s[i][0], &s[i][1], &s[i][2]);//没加& 		s[i][3] = s[i][2] + s[i][1] + s[i][0]; 	} 	printf("%d\n", i); } void output(double s[][4], int n) { 	printf("输入的学生成绩为：\n"); 	printf("学号\t高数\t英语\tc语言\t总分\n"); 	int i; 	for (i = 0; i<n; i++) 	{ 		printf("%d\t%.1lf\t%.1lf\t%.1lf\t%.1lf\n", i, s[i][0], s[i][1], s[i][2], s[i][3]);//多了一个反斜杠 	} } double max1(double s[][4], int n, int j) { 	double m = s[0][j]; 	int i; 	for (i = 1; i<n; i++) 	if (m<s[i][j]) 		m = s[i][j]; 	return m; } double min1(double s[][4], int n, int j) { 	double m = s[0][j]; 	int i; 	for (i = 1; i<n; i++) 	if (m > s[i][j]) 		m = s[i][j]; 	return m; } double avg(double s[][4], int n, int j) { 	double sum = s[0][j]; 	int i; 	for (i = 1; i<n; i++) 		sum += s[i][j]; 	return sum / n; } 帮楼主改了改，有问题的地方都添加了注释。楼主可以参考

一些细节上面的错误，取地址符号，if语句的判断条件，循环的次数导致溢出 我也是初学，这只是个人看法，不一定正确，供参考

#include<stdio.h>  /*这是一个查询学生成绩的程序，查询数学，英语，语文，计算并算出总成绩*/  /*首先，显示输入学生人数，然后显示输入各科成绩，最后按照学号排序输出各科  成绩。最后计算并显示出各科成绩的平均值，最大值，最小值*/  /*在main函数中既有printf1函数，scanf函数，printf2函数,arg函数，min函数  max函数*/  void input(double s[][4],int n);  void output(double s[][4],int n); double max(double s[][4],int n,int i);   double min(double s[][4],int n,int i); double avg(double s[][4],int n,int i);  int main()  { 	int i,number; 	double grade[100][4]; 	char pro[4][10]={"数学","英语","语文","总成绩"}; 	printf("请输入学生的人数:") ; 	scanf("%d",&number); 	input(grade,number); 	output(grade,number); 	for(i=0;i<4;++i) 	{ 		printf("%s最高成绩为%.2f",pro[i],max(grade,number,i)); 		printf("%s最低成绩为%.2f",pro[i],min(grade,number,i)); 		printf("%s平均成绩为%.2f",pro[i],avg(grade,number,i)); 		printf("\n"); 	} 	return 0; }  void input(double s[][4],int n) { 	printf("输入学生的成绩按照(高数，英语，语文的次序输入)\n"); 	/*转义字符*/  	int i; 	for(i=0;i<n;i++) 	{ 		scanf("%lf %lf %lf",&s[i][0],&s[i][1],&s[i][2]); 		s[i][3]=s[i][2]+s[i][1]+s[i][0]; 	} } void output(double s[][4],int n) { 	printf("输入的学生成绩为：\n"); 	printf("学号\t高数\t英语\t语文\t总分\n"); 	int i; 	for(i=0;i<n;i++) 	{ 		printf("%d\t%.1lf\t%.1lf\t%.1lf\t%.1lf\n",i+1,s[i][0],s[i][1],s[i][2],s[i][3]); 	} } double max(double s[][4],int n,int j) { 	double m=s[0][j]; 	int i; 	for(i=1;i<n;i++) 	{ 		if(m<s[i][j]) 			m=s[i][j]; 	} 	return m; } double min(double s[][4],int n,int j) { 	double m=s[0][j]; 	int i; 	for(i=1;i<n;i++) 	{ 		if(m>s[i][j]) 			m=s[i][j]; 	} 	return m; } double avg(double s[][4],int n,int j) { 	double sum= s[0][j]; 	int i; 	for(i=1;i<n;i++) 		sum+=s[i][j]; 	return sum/n; }

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

编译没报错说明没有语法错误，但是运行时又出错了，说明是程序的逻辑错误，调试一下看看

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];

引用 7 楼 qq_26440903 的回复:[quote=引用 3 楼 ghx287524027的回复:]input()函数中scanf("%1f %1f %1f",&s[i][0],&s[i][1],s[i][2]);“,s[i][2]”缺少取地址符号，所以会报越界错误。 另外，局部变量定义时最好进行赋值，否则其值是不固定的。 我改了，编译没问题，可是运行他说学生别成绩.exe已经停止运行[/quote]  在调试时运行，出错点中断，然后通过调用堆栈、变量窗口等观察分析原因

引用 3 楼 ghx287524027的回复:input()函数中scanf("%1f %1f %1f",&s[i][0],&s[i][1],s[i][2]);“,s[i][2]”缺少取地址符号，所以会报越界错误。 另外，局部变量定义时最好进行赋值，否则其值是不固定的。 我改了，编译没问题，可是运行他说学生别成绩.exe已经停止运行

引用 2 楼 虚空大鸟的回复:引用 1楼我是你的主体 的回复:哪里出问题了呢？，谢谢你的pro初始化有问题，还有你运行时报的什么错 学生成绩.exe停止运行。

少了个& scanf("%1f %1f %1f",&s[i][0],&s[i][1],&s[i][2]);

修改如下：  #include <stdio.h> /*这是一个查询学生成绩的程序，查询数学，英语，语文，计算并算出总成绩*/ /*首先，显示输入学生人数，然后显示输入各科成绩，最后按照学号排序输出各科 成绩。最后计算并显示出各科成绩的平均值，最大值，最小值*/ /*在main函数中既有printf1函数，scanf函数，printf2函数,arg函数，min函数 max函数*/ void input(double s[][4], int n); void output(double s[][4], int n); double max(double s[][4], int n, int i); double min(double s[][4], int n, int i); double avg(double s[][4], int n, int i); int main() { 	int i, number; 	double grade[100][4]; 	char pro[4][10] = { "数学","英语","语文","总成绩" }; 	printf("请输入学生的人数:"); 	scanf("%d", &number); 	input(grade, number); 	output(grade, number); 	for (i = 0; i <= 4; ++i) 	{ 		printf("%s最高成绩为%.2f", pro[i], max(grade, number, i)); 		printf("%s最低成绩为%.2f", min(grade, number, i)); 		printf("%s平均成绩为%.2f", avg(grade, number, i)); 		printf("\n"); 	} 	return 0; } void input(double s[][4], int n) { 	printf("输入学生的成绩按照(高数，英语，c语言的次序输入)\n"); 	/*转义字符*/ 	int i; 	for (i = 0; i<n; i++) 	{ 		//scanf("%1f %1f %1f", &s[i][0], &s[i][1], s[i][2]); 		scanf("%1f%1f%1f", &s[i][0], &s[i][1], &s[i][2]);     //zx 		s[i][3] = s[i][2] + s[i][1] + s[i][0]; 	} } void output(double s[][4], int n) { 	printf("输入的学生成绩为：\n"); 	printf("学号\t高数\t英语\tc语言\t总分\n"); 	int i; 	for (i = 0; i<n; i++) 	{ 		printf("%d\t%.1lf\t%.1lf\t%.1lf\t%.1lf\n", i, s[i][0], s[i][1], s[i][2], s[i][3]); 	} } double max(double s[][4], int n, int j) { 	double m = s[0][j]; 	int i; 	for (i = 1; i < n; i++) 		if (m < s[i][j]) 			m = s[i][j]; 	return m; } double min(double s[][4], int n, int j) { 	double m = s[0][j]; 	int i; 	for (i = 1; i < n; i++) 		//if (m + s[i][j]) 		if (m > s[i][j])   //zx 			m = s[i][j]; 	return m; } double avg(double s[][4], int n, int j) { 	double sum = s[0][j]; 	int i; 	for (i = 1; i < n; i++) 		sum += s[i][j]; 	return sum / n; }

哪里出问题了呢？，谢谢


Question: 如何利用C语言打开本地的软件

system, _wsystem Execute a command.  int system( const char *command );  int _wsystem( const wchar_t *command );  Routine Required Header Compatibility  system <process.h> or <stdlib.h> ANSI, Win 95, Win NT  _wsystem <process.h> or <stdlib.h> or <wchar.h> 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  If command is NULL and the command interpreter is found, the function returns a nonzero value. If the command interpreter is not found, it returns 0 and sets errno to ENOENT. If command is not NULL, system returns the value that is returned by the command interpreter. It returns the value 0 only if the command interpreter returns the value 0. A return value of – 1 indicates an error, and errno is set to one of the following values:  E2BIG  Argument list (which is system-dependent) is too big.  ENOENT  Command interpreter cannot be found.  ENOEXEC  Command-interpreter file has invalid format and is not executable.  ENOMEM  Not enough memory is available to execute command; or available memory has been corrupted; or invalid block exists, indicating that process making call was not allocated properly.  Parameter  command  Command to be executed  Remarks  The system function passes command to the command interpreter, which executes the string as an operating-system command. system refers to the COMSPEC and PATH environment variables that locate the command-interpreter file (the file named CMD.EXE in Windows NT). If command is NULL, the function simply checks to see whether the command interpreter exists.  You must explicitly flush (using fflush or _flushall) or close any stream before calling system.  _wsystem is a wide-character version of system; the command argument to _wsystem 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  _tsystem system system _wsystem    Example  /* SYSTEM.C: This program uses  * system to TYPE its source file.  */  #include <process.h>  void main( void ) {    system( "type system.c" ); }   Output  /* SYSTEM.C: This program uses  * system to TYPE its source file.  */ #include <process.h> void main( void ) {    system( "type system.c" ); }   Process and Environment Control Routines  See Also   _exec Functions, exit, _flushall, _spawn Functions

CreateProcess

CreateProcess需要自己对文件类型做处理。 ShellExecute可以打开任何类型的文件格式。。

WinExec、ShellExecute和CreateProcess,这3个函数都能做到

https://msdn.microsoft.com/zh-cn/library/ms682425%28v=vs.85%29.aspx  里面有解释有例子

CreateProcess怎么用的


Question: 函数名和函数指针有什么不同吗？

函数指针多用于回调函数

一个是常量，一个是变量，其它的，也就没什么了

引用 3 楼 qq_27874423 的回复:[quote=引用 2 楼 ghx287524027 的回复:] func1是一个指针函数，即返回值为指针类型的函数。此处应正确区分函数指针与指针函数 。。这个我知道[/quote] 首先，定义int* func1(){}说明func1()是个函数，其返回值类型为int*，故func1()是指针函数；定义int* (*func2)(){}说明func2是一个指向函数的指针，姑且假设其指向的函数为func3()，所以int* (*func2)(){}可以改写为int* (func3)(){}，类比func1()，说明func3()是一个返回指针的指针函数。而int cmp(const void* a,const void* b)仅仅是一个返回值为int类型的函数而已，只不过其形参为指针常量，与func1、func2没有必然的关系。

引用 2 楼 ghx287524027 的回复:func1是一个指针函数，即返回值为指针类型的函数。此处应正确区分函数指针与指针函数 。。这个我知道

函数名可以退化成函数指针 函数名你不可能重新修改一个地址，但函数指针可以 不要把数组名然当指针，同样不要把函数名当指针


Question: 数组名和指针有什么不同？

数组不是指针 ，数组和指针只有作为函数行参的时候编译器才将两者视为一样的，因为编译器都会将数组的操作转换成对指针的操作，其他地方数组是数组，指针是指针

数组名和指针的关系，是在表达式中体现的。 sizeof运算符，是个编译期运算符，这个运算符作用于数组名， 是求数组的占用内存单元的数量 这个表达式是个常量表达式（有些实现支持变量定义数组的大小，这种实现中不是常量表达式） 另外一处，就是 &运算符和数组名构成的表达式，这个表达式中， &a表示数组a的地址，而不是数组名作为指针的地址   程序中并没有储存表示数组首地址的指针。 取到的不是指针的地址。  C++中，函数的数组引用参数，可以匹配数组， 所以C++中数组名，表达式中，就表现为指针，数组全体对象，两种不同形态。 C中，就没有这么复杂，除了 sizeof(a) ，&a 中表示数组全体对象外，别的表达式中，通常表现为指针

编译器会自动把数组的首地址传递过去，但数组和指针还是有区别的

谢谢各位的帮助，我结贴了。

引用 6 楼 ghx287524027 的回复:虽然在效果上数组名可以等同于指向数组的指针，但是在本质上它和实际的指针是有区别的。首先，数组名只是一个符号，系统不会为它分配任何空间。其次，数组名是一个常量，它不能作为左值进行运算（自增和自减也是不允许的）。而实际指针没有这方面的限制。 这样，多谢。

引用 4 楼 user-5 的回复:数组名不是指针！！ 说数组名是指针的都是错的 你从sizeof就发现他们的不同了 数组名和指针的联系是数组名可以退化成指针（退化后数组大小就丢失了），反之不成立 谢谢！ 我也看了另外一个帖子： http://bbs.csdn.net/topics/390800454 觉得大体明白了明白了它们并不是同样的东西。 应该要结贴了。

引用 1 楼 csdn1223537114 的回复:ss1是指针类型，ss2是数组类型，直接填数组名编译器会把数组首地址传过去~~ 意思就是它们两个完全是两种类型吗？ 但是数组名不就是一个指向数组第一个元素的指针吗？

ss1是指针类型，ss2是数组类型，直接填数组名编译器会把数组首地址传过去~~

sizeof数组返回的是数组的里面元素的字节数


Question: 函数中的字符常量，这段代码为什么会运行出错？

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  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对应的汇编并单步执行观察相应内存和寄存器变化。）  其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

printf()在stdio.h中定义，所以要加一句#include "stdio.h"，另外，如果你返回0的话，会提示无法将int转为char*，所以还需要明白你这段代码想实现什么功能。

您的函数不是返回指针么，return 0是什么鬼，而且和楼上说的一样，不要返回局部指针

Char p[] = “hello world”;  以上这句代码，并不是字符串常量。 以下这句才是  Char *p = “hello world”;  其实  Char p[] = “hello world”; 等价于 Char p[12] = “hello world”;

不确定 不要返回局部变量指针 你返回一个指向局部数组的指针，函数结束后，内存就销毁了，所以行为是不确定的


Question: OpenSSL中生成的RSA密钥对能够通用吗

引用PEM_read_RSA_pubkey ----- public key  //try this  pem_read_rsapublickey---- rsa public key  谢谢，确实是这个的原因，现在真的解决了。  生成公钥的时候使用PEM_write_RSA_PUBKEY函数，生成的公钥就能够用Crypto++来进行加密，相对应的，读取公钥的时候使用PEM_read_RSA_PUBKEY函数同样能够使用Crypto++的库生成的公钥进行加密  可以结贴啦~

引用请精确描述问题，到底是怎么回事？  首先                  1. 每个库都有自己的格式， 密钥也如此， 比如你用openssl生成一密钥对， 然后其公约加密，然后把密钥和私钥给crypto++。 请问这种能解密吗？  如果不能解密，原因是什么？是crypto++不能识别私钥格式？  同理，crypto++用自己生成公约加密后，把私钥丢给openssl，openssl无法解密？  2.          如果第一点我猜对了，那么请看下面，如果没有猜对，请不要看。  密钥都是数字，那么是否可以通过bignum之类的接口，把密钥的数字提出来，把数字（密钥）给对方。  这样避免，不同的格式，无法解密的问题。  数字给的对方的时候，再把数字转换为 所要求的密钥格式。  其实问题很简单，就是Crypto++生成的公钥，我使用OpenSSL提供的读取公钥函数无法识别，根本就获取不到公钥。。。我就发现Crypto++生成的公钥长度和我用OpenSSL生成的公钥长度是不一样的（我上面已将粘出来了，明显不一样长的说 = =!），我现在就不知道为什么这两个库生成的公钥会不一样长？是什么原因造成的？有没有什么解决办法？谢谢啦~

引用 12 楼 u012224760 的回复:引用看了下， cryptopp 支持 DER 编码的 RSA PUBKEY, 支持 PKCS#8 编码的 RSA 私钥， 这些是 ASN1, PKCS 标准所规定的， 完全木有任何的的问题。 这个我也看了，在一个英文网站上看到了，我感觉Crypto++生成的密钥是没有问题的，我觉得就是我用PEM_write_bio_RSAPublicKey()这个函数提取出来的公钥长度有问题，但是并不知道问题在哪？    PEM_read_RSA_pubkey ----- public key  //try this  pem_read_rsapublickey---- rsa public key

引用还有密钥的格式问题，  你用openssl生成密钥对，会看到，密钥的前面有----public rsa ---- 之类的字眼吧。  crypto++ 有没有？ crypto++ 是没有，但是我发现并不只是这个问题，我把crypto++生成密钥格式变成与openssl的一样的话还是不行，感觉最离谱的是，不单纯是格式不同，整个密钥的长度都差不少 这个是openssl生成的公钥长度： MEgCQQDEg++2FXqzMrcwIqvnjr7CsqGgSAW2X9W9FJv3sZ9H/vOmNrS3KMXwZaZfJheM/jfF4ExuoDAZUhdhvM5D6uHVAgMBAAE= 这个是crypto++生成公钥长度： MFowDQYJKoZIhvcNAQEBBQADSQAwRgJBALld1AnfrvHKZ6oIFmKw6XFwpDC67kImYvFLumsPyMhR33KtsAcULSO7JIxH0g8pZli++LkDrp9XrAD8289dYT8CARE= 除去openssl那些格式，且都是512密钥长度，实在是不知道这是为什么？有没有什么解决办法

引用 楼主 u012224760 的回复:我之前用的Crypto++的库写的C++的RSA密钥生成工具以及加解密工具，但是现在需要使用C语言来实现RSA加解密，我就又使用了OpenSSL的库来实现，问题是现在OpenSSL的加解密没有办法使用之前Crypto++库生成密钥，按道理来讲，RSA算法都是一样的，可是为什么密钥不能通用呢？是什么原因？有没有解决的办法呢？请各位大神指教！  密钥长度，  还有算法的padding 不一样，  都会失败

引用 8 楼 u012224760 的回复:引用padding， 明文需要padding  楼主做实验：  将简单明文， 比如123，  用2个密钥库加密后，试试结果是否一样，  先不要管长的明文。 刚刚搞错了，加密长度其实也是一样的 crypto++库 I05DbaBzRA0AaiBaL9Do7hhyIQLs8yaArlYgvdw++pa6Ju0Q56ovKswaNc0oQfXy7T/kEN0+Np7z8mxApkwHNjIE+pWESMAABBO3GH4uNEZkmtvf3aos6cqvhF48kMUy4SHI1HSkAqqDEHyRXYENCkO9w0K6sW73A9O2wzVK6Dw= （123使用1024长度的密钥加密的结果） openssl库 I05DbaBzRA0AaiBaL9Do7hhyIQLs8yaArlYgvdw++pa6Ju0Q56ovKswaNc0oQfXy7T/kEN0+Np7z8mxApkwHNjIE+pWESMAABBO3GH4uNEZkmtvf3aos6cqvhF48kMUy4SHI1HSkAqqDEHyRXYENCkO9w0K6sW73A9O2wzVK6Dw= （123使用1024长度的密钥加密的结果） 我的问题不是密文不能通用，而是密钥不能通用，crypto++生成的密钥长度和openssl生成的密钥长度不一致，但是分别都可以正常进行加解密的，我想知道这是什么原因造成？有没有解决办法？  请精确描述问题，到底是怎么回事？  首先                  1. 每个库都有自己的格式， 密钥也如此， 比如你用openssl生成一密钥对， 然后其公约加密，然后把密钥和私钥给crypto++。 请问这种能解密吗？  如果不能解密，原因是什么？是crypto++不能识别私钥格式？  同理，crypto++用自己生成公约加密后，把私钥丢给openssl，openssl无法解密？  2.          如果第一点我猜对了，那么请看下面，如果没有猜对，请不要看。  密钥都是数字，那么是否可以通过bignum之类的接口，把密钥的数字提出来，把数字（密钥）给对方。  这样避免，不同的格式，无法解密的问题。  数字给的对方的时候，再把数字转换为 所要求的密钥格式。

引用padding， 明文需要padding  楼主做实验：  将简单明文， 比如123，  用2个密钥库加密后，试试结果是否一样，  先不要管长的明文。 加密出来的结果肯定是不一样的啊，相同的库，相同的密钥，相同的内容，每次加密得到的密文都是不一样的，长度的话确实不同，是这样的： crypto++库 ivQqC7jPaTVquKsbZcdVKB2V0K5znnUc9BEwKjHFPMuF9k5VokgzUxnBBqOZvimcuyITgE6N TPc/dz2hevneXj5AhybNja2x8oz9FJ4BJLiphskMfLZAfo2EmY1+IZC9VVk5yCCdNG/4uhvm f6QLHKfx1Nh/A24KG0DSsw2ytEQ=     （123使用512长度的密钥加密的结果） openssl库 G0OcYhXVnf+BlMxn0jGaE4Bb19jwuKM7H0AUhT6XAnRXCKWtKtZi2Ztyaj45wJKvF+KI5sDePSFmvmG/MFo1Yg== （123使用512长度的密钥加密的结果） 这个长度不同是与padding有关吗？得到的密钥的长度不同，是不是也和这个有关系呢？

应该有地方配置密钥长度的。


Question: 参数传递时，实参只能是数组，不能是指针，这是为什么呢？？？

引用 10 楼 paschen 的回复:[quote=引用 9 楼 daa20 的回复:] 退化成指针，，与直接用指针有什么区别呢  [quote=引用 6 楼 paschen 的回复:] [quote=引用 4 楼 daa20 的回复:] [quote=引用 1 楼 paschen 的回复:] char* 的话是让这个指针指向常量区的字符串（你不能去修改他） 而 char []是在栈上分配的字符数组，你可以进行修改  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了[/quote]  是的，函数参数与返回值中的数组均会退化为指针，函数中你不可能通过sizeof得到数组大小，得到的其实是指针的大小 你把这个函数参数声明为数组与声明为指针其实是完全一样的[/quote]  还有一个问题： if((pdest > psrc)&&(pdest < (psrc + count))) //这一部分没想明白      {         for(size_t i=count-1;i>=0;--i)         {             pdest[i] = psrc[i];            }         pdest[count] = '\0';        } 内存拷给函数，，这一个条件不是太明白，为什么会有(pdest > psrc)&&(pdest < (psrc + count))的判断呢，，这样做的目的是什么???[/quote]  if((pdest > psrc)&&(pdest < (psrc + count))) 这个条件表示目的和源有重复的区域[/quote]  懂了，谢谢啊！！

引用 9 楼 daa20 的回复:退化成指针，，与直接用指针有什么区别呢  [quote=引用 6 楼 paschen 的回复:] [quote=引用 4 楼 daa20 的回复:] [quote=引用 1 楼 paschen 的回复:] char* 的话是让这个指针指向常量区的字符串（你不能去修改他） 而 char []是在栈上分配的字符数组，你可以进行修改  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了[/quote]  是的，函数参数与返回值中的数组均会退化为指针，函数中你不可能通过sizeof得到数组大小，得到的其实是指针的大小 你把这个函数参数声明为数组与声明为指针其实是完全一样的[/quote]  还有一个问题： if((pdest > psrc)&&(pdest < (psrc + count))) //这一部分没想明白      {         for(size_t i=count-1;i>=0;--i)         {             pdest[i] = psrc[i];            }         pdest[count] = '\0';        } 内存拷给函数，，这一个条件不是太明白，为什么会有(pdest > psrc)&&(pdest < (psrc + count))的判断呢，，这样做的目的是什么???[/quote]  if((pdest > psrc)&&(pdest < (psrc + count))) 这个条件表示目的和源有重复的区域

退化成指针，，与直接用指针有什么区别呢  引用 6 楼 paschen 的回复:[quote=引用 4 楼 daa20 的回复:] [quote=引用 1 楼 paschen 的回复:] char* 的话是让这个指针指向常量区的字符串（你不能去修改他） 而 char []是在栈上分配的字符数组，你可以进行修改  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了[/quote]  是的，函数参数与返回值中的数组均会退化为指针，函数中你不可能通过sizeof得到数组大小，得到的其实是指针的大小 你把这个函数参数声明为数组与声明为指针其实是完全一样的[/quote]  还有一个问题： if((pdest > psrc)&&(pdest < (psrc + count))) //这一部分没想明白      {         for(size_t i=count-1;i>=0;--i)         {             pdest[i] = psrc[i];            }         pdest[count] = '\0';        } 内存拷给函数，，这一个条件不是太明白，为什么会有(pdest > psrc)&&(pdest < (psrc + count))的判断呢，，这样做的目的是什么???

虽然在效果上数组名可以等同于指向数组的指针，但是在本质上它和实际的指针是有区别的。首先，数组名只是一个符号，系统不会为它分配任何空间。其次，数组名是一个常量，它不能作为左值进行运算（自增和自减也是不允许的）。而实际指针没有这方面的限制。

关于指针 http://blog.csdn.net/zhangxiangdavaid/article/details/37885275

引用 4 楼 daa20 的回复:[quote=引用 1 楼 paschen 的回复:] char* 的话是让这个指针指向常量区的字符串（你不能去修改他） 而 char []是在栈上分配的字符数组，你可以进行修改  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了[/quote]  是的，函数参数与返回值中的数组均会退化为指针，函数中你不可能通过sizeof得到数组大小，得到的其实是指针的大小 你把这个函数参数声明为数组与声明为指针其实是完全一样的

引用 2 楼 zhangxiangDavaid 的回复:常量不可修改，仅此而已。 注意区分： char str[] = "David"; 和 char *str = "David"; 的区别。  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了

引用 1 楼 paschen 的回复:char* 的话是让这个指针指向常量区的字符串（你不能去修改他） 而 char []是在栈上分配的字符数组，你可以进行修改  还有一个问题，，书上说，数组作为实参传递，会退化成指针。用数组作为实参传递就可以退化成指针了，这样与直接用指针做实参传递有什么区别呢？卡在这里了


Question: 满二叉树的定义

引用 3 楼 zhangxiangDavaid 的回复:二叉树 http://blog.csdn.net/zhangxiangdavaid/article/details/36189717你的是对的，感觉百度的定义有点错误。

一样的意思啊~

我不知道你上面那个是不是从维基百科上搜到的，那个应该是Completed  Binary Tree（完全二叉树）的定义，每个节点有0或者2个子节点 而满二叉树的每一次有2的k-1次方个节点，k为该层的层数。即百度百科，，，


Question: 打印100到200之间的素数，我是初学者，大神帮帮忙

引用 3 楼 ghx287524027 的回复:正确代码见楼上。 从代码中可知你已经知道怎么确定一个数是否为素数了。但是有一点，对于数a，必须当2~（a-1）中不存在a的约数时，才能确定数a为素数，也就是说只有当这（a-2）个数全部检测完之后才可以确定数a是不是素数。因此只有在外层循环中才可以对数进行输出。 我记得只需要测试2-a的平方根之间的数即可 也就是for(int i = 2 ; i < a * a ; i++)

谢谢各位大神的细心指导，问题解决了，令小弟恍然大悟，感动的热泪盈眶！

#include<stdio.h> int main() {     int temp;          for(temp=101;temp<200;temp++)     {         for(int i=2;i<temp;i++)         {             if(temp%i!=0) //逻辑错误，应改为temp%i ==0                 break;                 printf("%d ",temp);     //逻辑错误，一个数不被2整除不代表就是素数 参看1楼的写法        }         }     return  0; }

素数  #include<stdio.h> int main() { 	int n, i, t; 	int a[10000] = { 0 }; 	for (i = 2; i<10000; i++)//建立10000以内的素数表 		if (!a[i]) 			for (t = i + i; t<10000; t += i) 				if (!a[t]) 					a[t] = 1;  	for (i = 2; i<100; i++)//输出10000以内的素数   //素数从2开始 		if (a[i] == 0) 			printf("%d\n", i);  	return 0; }  //验证哥德巴赫猜想  char primes[10000]; int i, j, n; int main58(void)//58 { 	//先找出10000以内的所有素数 	memset(primes, '1', 10000); 	for (i = 2; i < 5000; i++) 		for (j = i*2; j < 10000; j+=i) 			primes[j] = '0'; 	while (1 == scanf("%d", &n)) 	{ 		j = n / 2; 		while ('0' == primes[j] || '0' == primes[n - j]) j--; 		printf("%d %d\n", j, n - j); 	}  	return 0; }

#include<stdio.h> int main() { 	int temp;  	for(temp=101;temp<200;temp++) 	{ 		bool bPrime = true; 		for(int i=2;i<temp;i++) 		{ 			if(temp%i==0) 			{ 				bPrime = false; 				break; 			} 		} 		if(bPrime) 			printf("%d ",temp);  	} 	return  0; }

#include <stdio.h> int main() {  	for (int i = 101; i < 201; ++i) 	{ 		 		for (int j = 2; j < i; ++j) 		{ 			if (i%j == 0) 				break; 		} 		if (j == i) 		{ 			printf("%d ", i);  		} 	}  	return 0; }


Question: C语言基础问题

1、算是吧 2、也算是吧，这个在scanf函数里实现 3、printf是直接把a的值复制到函数内，是按值传递的，并没有取地址

虽然在效果上数组名可以等同于指向数组的指针，但是在本质上它和实际的指针是有区别的。首先，数组名只是一个符号，系统不会为它分配任何空间。其次，数组名是一个常量，它不能作为左值进行运算（自增和自减也是不允许的）。而实际指针没有这方面的限制。

这就涉及到了scanf()和print()的工作原理和实现，scanf()的作用本质上就是给变量赋值，当你输入7时，这个7会被存放在一个叫键盘缓冲区的地方，按下回车之后scanf会读取这个缓冲区，并通过&获取要将7存放给的变量，实现赋值。输出时，print()并不知道参数个数，它只是逐个解析format字符串。对于特定类型%，使用va_arg去取相应参数的值，直到遍历字符串结束。

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  单步scanf和printf对应的汇编代码几步后，就会来到scanf和printf对应的C源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt

刨根问底不总是好事！ 特别是在前期。 要知道“未知是永远存在的”。


Question: C文件处理问题！

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

引用 15 楼 libinden71 的回复:[quote=引用 12 楼 paschen 的回复:] [quote=引用 11 楼 libinden71 的回复:] [quote=引用 9 楼 paschen 的回复:] 楼上说得对，max已经是指针了 max已经是指针了？我不是很懂这个意思[/quote]  int *max [/quote]   paixu(&max, cons);  ==> paixu(max, cons); 取地址去掉就可以了！我表示无法理解！传递给指针*p 不是应该传的是数组的地址吗？[/quote]  max本身已经是数组的首地址了，如果再&就变成max这个指针变量的地址了

引用 14 楼 paschen 的回复:[quote=引用 13 楼 libinden71 的回复:] [quote=引用 8 楼 user-3 的回复:] paixu(&max, cons);  ==> paixu(max, cons);  为什么传递地址反而错了？ max是数组，传递给指针*p 不应该传的是max的地址吗？ 还有个问题 为什么说max已经是指针了 表示不是很明白 ！[/quote]  你传递&max传递的就是max这个指针的地址，也就是int**类型了 max本身已经是一个指针了，只是他指向的内存作为了一个数组用[/quote]   懂了懂了 恍然大悟！万分感谢！

引用 12 楼 paschen 的回复:[quote=引用 11 楼 libinden71 的回复:] [quote=引用 9 楼 paschen 的回复:] 楼上说得对，max已经是指针了 max已经是指针了？我不是很懂这个意思[/quote]  int *max [/quote]   paixu(&max, cons);  ==> paixu(max, cons); 取地址去掉就可以了！我表示无法理解！传递给指针*p 不是应该传的是数组的地址吗？

引用 13 楼 libinden71 的回复:[quote=引用 8 楼 user-3 的回复:] paixu(&max, cons);  ==> paixu(max, cons);  为什么传递地址反而错了？ max是数组，传递给指针*p 不应该传的是max的地址吗？ 还有个问题 为什么说max已经是指针了 表示不是很明白 ！[/quote]  你传递&max传递的就是max这个指针的地址，也就是int**类型了 max本身已经是一个指针了，只是他指向的内存作为了一个数组用

引用 8 楼 user-3 的回复:paixu(&max, cons);  ==> paixu(max, cons);  为什么传递地址反而错了？ max是数组，传递给指针*p 不应该传的是max的地址吗？ 还有个问题 为什么说max已经是指针了 表示不是很明白 ！

引用 11 楼 libinden71 的回复:[quote=引用 9 楼 paschen 的回复:] 楼上说得对，max已经是指针了 max已经是指针了？我不是很懂这个意思[/quote]  int *max

引用 9 楼 paschen 的回复:楼上说得对，max已经是指针了 max已经是指针了？我不是很懂这个意思

楼上说得对，max已经是指针了

引用 5 楼 paschen 的回复:点重试，然后点中断，然后看断在哪，通过调用堆栈定位到你代码的位置，然后通过相关变量窗口观察分析原因 如果还是找不到，你发下断下是在哪，还有文件内容是什么，我帮你试下   初学者 还不会调试和断点 文件的内容就是一堆自己写的数字： 12 65 95 ... 把这些数字排序！   这个是断点的结果： Run-Time Check Failure #2 - Stack around the variable 'len' was corrupted.

引用 2 楼 libinden71 的回复:[quote=引用 1 楼 paschen 的回复:] int *max = (int*)calloc(cons, sizeof(int));  不行啊 还是错误！[/quote]  什么错误

引用 1 楼 paschen 的回复:int *max = (int*)calloc(cons, sizeof(int));  不行啊 还是错误！


Question: 求帮助QAQ 关于用控制台显示图片的问题 非常感谢

就是说你要调试那个dll你需要导入符号，而通常你不可能去调试那些

控制台能显示位图？ 发代码上来看看。


Question: C单链表问题 [讨论]

代码本身木有问题~

请检查scanf和malloc的返回值。

如果  由于某种原因   malloc申请失败，p会变成null  ，全是一个潜在的bug把。虽然基本上这种情况不会出现

单链表 http://blog.csdn.net/zhangxiangdavaid/article/details/25109205

引用 1 楼 user-4的回复:没发现有什么问题。 LZ觉得哪边不妥，有疑虑？ 我在做内存泄露查询，这段代码是我摘录出来的算法，我担心的是列表插入有问题了，刚刚查到问题的原因了，这段代码没问题，谢谢你的帮助。

没发现有什么问题。 LZ觉得哪边不妥，有疑虑？


Question: 关于内存变量输出问题

你这程序应该是64位程序，指针是8个字节，所以按指针输出的才是正确的，%x是32位的整数 如果32位的程序那就一样了

格式指示符与提供的数据类型不一致的时候，结果是未知的。

0x7fff5fbff86c  5fbff86c  其实是一样的啊

显然你的地址是64位, 整型是32位的

“内存地址”与“整数”位数不一定相同 不能想当然认为它们一样

%llx