Question: 关于字符数组初始化的问题

定义一个数组给它分配长度是个好习惯哟 而且   str[]={0}  其实是定义了数组长度为1，再往里面添加元素就是越界呢 定义二维数组的时候一维数组长度可省略，二维数组不可以哟

他们回答都是对的，必须分配内存~

这样定义的str初始化值只有一个“0” char str[10]//数组长度就确定了，分配10 个内存空间  char str[] = {0}//分配给str的空间就一个长度  char str[] = {0,1}//就是两个。 你试试语句改成: char str[] = {1,2,3,4,5,6,7}//运行结果看看效果

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() {     char str[] = {0};    /*定义的数组长度位1*/     printf("str's length is %u\n", sizeof(str));     scanf("%s", str);     printf("%s", str);     system("pause");     return 0; } 加一条这样的打印，看一下你定义的长度是多长。 printf("str's length is %u\n", sizeof(str));

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() {     char str[] = {0};    /*定义的数组长度位1*/     scanf("%s", str);     printf("%s", str);     system("pause");     return 0; } 数组越界了，因为这样定义的数组长度为1，那么字符串的空串也得是只有一个'\0'即0，所以只要输入一个字符就会导致越界；越界了就会出现这种情况 char str[] = {0};

char str[] = char *str

没有给str分配空间 怎么存


Question: 模板语法编译问题

没人 知道吗？

vs2015 的 ，应该支持吧

c++11语法？？ 找个支持c++11的编译器


Question: c语言运算符

如果是一个&，两边都要比较，如果是两个＆＆，左边是假就不比较右边了，这是死的规定，记住就好了，没难度

第一个是假的话不再计算第二个

可以看看这个运算符的讲解：https://cloud.tencent.com/developer/doc/1023

&和&&都可以用作逻辑与的运算符，表示逻辑与（and），当运算符两边的表达式的结果都为true时，整个运算结果才为true，否则，只要有一方为false，则结果为false。 &&还具有短路的功能，即如果第一个表达式为false，则不再计算第二个表达式。

m=a>b后m的值为0，这个对于&&运算来说已经为0，不必要再计算后面的值，即n=a>b不再计算，n仍然为1，这个是&&运算的短路原则

(m=a>b)&&(n=a>b)   a>b  = 0  故m=0 &&  左边表达式为假  故右边不执行   n为原值1

(m=a>b)&&(n=a>b) 这个本身的结果为false

表达式有短路

这是一个简单的关系运算短路问题： 运算符“&&”和运算符"||”都对操作数有“短路”计算。也就是说，对于“&&”来说，只有左边表达式的值为真时，才计算右边表达式的值；而对于“||”来说，只有左边表达式的值为假时，才计算右边的值。例如，表达式“（x=0)&&(y=2)&&(z=5)"，先执行“x=0”,x的赋值为0，整个表达式的值为0，此时后面的“y=2”和“z=5”并未执行。故整型变量m,n,a,b,c,d均为1时，执行(m=a>b)&&(n=a>b)后，m,n的值为0,1。 有帮助的话请采纳谢谢。

&对每一个都判断； &&只要前面是false就输出false，而不继续判断后面了

n没有被a>b的结果赋值，即n = a>b没有执行。因为m已经位0（为假）后面就不会执行，因为不论后面的为真还是为假都不会影响整个表达式为假的结果；

与运算当前面已经是0的时候，后面就不算了。

(m=a>b)   == 0       && 是 1 && x 才执行x表达式   所谓短路操作   ||   是 0 || x 执行表达式x

详情百度 & 和 &&的区别

表达式短路计算，顶

(m=a>b) && (n=a>b); 计算得出m为0后，不需要再接着计算后面的子表达式即可确定整个表达式结果为假 所以实际上 (n=a>b)未计算，所以n的值未改变，还是原来的初始值1 此所谓表达式短路计算

谁说n的值是1？


Question: 有大神能帮忙看一下怎么改吗

#include<stdio.h> #include<time.h> #include<stdlib.h>  int shuzhi(); int weizhi(); int shuzhi(int x[0],int x[1],int x[2],int x[3],int y[0],int y[1],int y[2],int y[3]);  int main() {   int x,y,z,q,m,i,h,sum,hello;     int w[999],a[4],b[4];     srand(time(0));     printf("1.开始游戏 2.查看上次成绩 3.输出帮助信息 4.退出游戏");      x = rand() % 5;     for(q=0;q>=0;q++)     {         scanf("%d",&m);         if(x==1)         {             for (i=0;i<=3;i++)             {                 a[i]=rand()%10;                 for (h=1;h<i+1;h++)                 {                     if (a[i]==a[h-1])                     {                         a[i]=rand()%10;                         h=0;                     }                 }             }              for(x=10;x>=1;x--)             {                 scanf("%d %d %d %d",&b[0],&b[1],&b[2],&b[3]);                 sum = shuzhi(a[0],a[1],a[2],a[3],b[0],b[1],b[2],b[3]);                 hello = weizhi(a[0],a[1],a[2],a[3],b[0],b[1],b[2],b[3]);                 z=sum-hello;                 if(z==4)                 {                     printf("you are the winner");                     break;                 }                 else                 {                     printf("有%d位置和数值正确,有%d数值正确但位置不对",hello,z);                     y=x*10;                     printf("%d",y);                 }             }         }          w[q]=y;     }     if(x==3)         printf("这是你的游戏，请输入4个数字，并用空格隔开，每次输入后，我们会给你提示，直到你猜对，当然机会有限，只有十次，每猜一次你就会减10分，猜到10次，就结束了");     if(x==2)     {         if(q==1)             printf("这是你的第一次游戏，着急什么");         else             printf("这是你上次的成绩%d，哈哈哈哈",w[q]);     }     if(x==4)         exit(0); }   int shuzhi(int x[0],int x[1],int x[2],int x[3],int y[0],int y[1],int y[2],int y[3]) {     //int x[4],y[4],z,t,sum=0;     int z,t,sum=0;     scanf("%d %d %d %d", &y[0], &y[1], &y[2], &y[3]);     for(t=0;t<4;t++)     {         for(z=0;z<4;z++)         {             if(x[t]==y[z])                 sum++;         }      }     return (sum); } int weizhi() {     int x[4],y[4],t,hello=0;     for(t=0;t<0;t++)     {         if(x[t]==y[t])             hello++;      }     return (hello);  }  代码逻辑很乱呢； 问题主要是： 1. 所有if判断表达式都写成赋值表达式，“全军覆没”；建议把C语言基础知识，尤其是语法相关的学好了。 2. 函数声明，定义不匹配；函数参数出现重名现象，这是基本语法； 上面的代码是修改了一些，但是有些无法继续修改，个人建议把你的需求贴出来，直接给你写个可以运行的。


Question: 菜鸟有个弱智问题

是这个int main(void);的原因 结果如下图：

很多时候，使用的工具越先进，人越笨；得到得越轻松，人越懒。

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

notepad++里的文件名是new 1.c 你命令里输入的是first.c吧

http://coliru.stacked-crooked.com  把你的代码拷贝到这里，然后点运行，分分钟解决~

notepad++只可以编辑，不可以编译，可以配合gcc（百度下，个人感觉麻烦） 考级的话熟悉VC++6.0（完了结果直接在软件中出来）但是界面不好 个人推荐C_Free，代码显示风格和notepad++差不多，可以直接按F5 编译  对于敲代码出现的小错误，只能说多练习练习就好了

我也是新手，我用的也是文本编辑器，首先你要先把代码写对吧。然后保存到比如C盘根目录下，然后再打开DOS界面，在这里面编译，好像还要配置环境吧，我同学告诉我一开始最好用DOS编译，你要不懂加我Q，376244279，一起交流，最后再说一遍，我也是菜鸟

notepad++应该不支持编译功能吧，notepad++作为一个编辑器还是比较好的。 另外，main函数和其他函数一样，定义时不能在后面加分号; 因为加了分号就相当于声明，声明的函数无函数体；

对对，打错了，后面确实没有分号。。 那个。。能不能请你说的更具体一点？就是具体怎么编译。。 我刚开始学，什么都不懂。。

再说，你怎么让它运行的？这是C程序，要编译，然后才能运行！

int main这一行最后不应该有分号


Question: debug模式下不识别汇编修改？

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

因为debug下，还会在栈中压入一些其他信息，mov dword ptr[ebp - 4], 20h;的位置并不是你变量i的位置，改成：mov dword ptr[i], 20h;即可


Question: C语言初学者问题

我看的书上也是这么写的，意义不大，但我觉得吧还是要写，然后吧for循环里面的第一个赋值表达式删掉好一点

引用 8 楼 cfjtaishan 的回复:如果第一个scanf的作用，可以作为初始化用；这个是硬性说的。 因为第一个scanf后，会将一个字符赋值给ch，但是这个ch马上被覆盖了，被'$'覆盖了。所以第一个scanf的意义不大； 如果想突出的作用，建议把for循环的第一个表达式去掉： 即 for(;ch!='g';scanf("%c",&ch)) 去掉第一个表达式，这样可以选择性的进入for循环，即若第一个scanf的ch接收的是'g'，则不进入循环；

for循环中ch的赋值会覆盖第一个scanf语句得到的值，可以认为第一个scanf语句没有实际意义。 教材(书)也不是百分之百准确，具体问题具体分析。

引用 3 楼 qq_33462307的回复:没用，多此一举 嗯嗯，这是书本上的一道练习，应该是答案错了

你想要实现什么功能  这才是重点

你就当它是初始化，谁知道为初始化的内存里装着什么数据，没准就是‘g’呢

没用，多此一举

引用 1 楼 user-7的回复:第一个scanf逻辑上有没有用 没懂呢，请问第一个scanf不是给ch一个初值吗，然后在for中ch='$'貌似等价于ch='初值'了呢

第一个scanf逻辑上有没有用


Question: hdu2005提交时显示Output Limit Exceeded，没找到问题

#include<stdio.h> int main() {     int year,month,day,sum=0,i;     int year1[]={31,29,31,30,31,30,31,31,30,31,30,31};     int year2[]={31,28,31,30,31,30,31,31,30,31,30,31};      while(scanf("%d/%d/%d", &year, &month, &day))     {         if(((year%4 == 0)&&(year%100!=0))||(year%400==0)) {             for(i = 0;i<month-1;i++)                 sum = sum + year1[i];         } else {             for(i = 0; i < month-1; i++)                 sum = sum+year2[i];         }         printf("%d\n",sum+day);         sum = 0;    /* reinit */     }     return 0; } 两个问题，一个是year1,year2数组是从0开始的，因此循环条件为month-1； 另一个问题是sum在计算上一个输入数据时，需要重新初始化位0；否则计算出来的天数是在上一次的基础上；

试试 scanf("%d/%d/%d",&year,&month,&day) 改成 scanf("%d%d%d",&year,&month,&day)


Question: 看不懂这段代码是怎么运行的，请指导

建议查一下SetWaitableTimer这个函数的定义，这个函数定义里会说明在何时调用timerun函数；  另外，对于回调函数，可以从网上详细了解一下；从定义到demo使用；

你应该去查一下SetWaitableTimer的用法，它就是指定多长时间后（这里是5秒）开始周期性或一次性（参数2000表示每2秒执行一次）的调用一个指定的函数（即timerun），而SleepEX表示每当回调函数被执行，线程就苏醒，于是循环会把dwParam进行加1操作，接着又等待下一次timerun的执行。 5次循环之后，CancelWaitableTimer被执行，定时器取消，回调函数也就不会再执行了。

建议仔细看下MSDN：  http://[url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms682492(v=vs.85).aspx][/url]  https://msdn.microsoft.com/en-us/library/windows/desktop/ms686289(v=vs.85).aspx

这里的回调函数是系统去调用，而不是你自己的程序调用

SetWaitableTimer 这个函数下面是我COPY的   启动一个可等待计时器。将它设为未发信号状态 返回值 Long，非零表示成功，零表示失败。会设置GetLastError 参数表 参数 类型及说明 hTimer Long，指定一个可等待计时器的句柄 lpDueTime FILETIME，指定一个包含了64位时间值的结构。如果为正，它代表计时器要触发的时间。如果为负，它代表自函数调用以来持续的时间。时间是以100ns为单位指定的 lPeriod Long，如果为零，这个计时器只会触发一次。否则，计时器会根据这里设置的持续时间自动重新启动(以毫秒为单位指定) pfnCompletionRoutine Long，指定零或者计时器触发时要调用的一个函数的地址。


Question: 大端格式和小端格式的问题

对于 short、int、long、long long 以及对应的无符号类型都区分，char 或 char 数组（字符串）不区分。

大端小端是以字节为基础的，如果是一个字节，其大端存储与小端存储结果都是一样的

从双字节开始，以字节为单位。

应该是一个字区分，

引用 1 楼 cfjtaishan 的回复:一个字节不区分大小写，因为内存是以字节为单位的。 不区分大小端，手误

一个字节不区分大小写，因为内存是以字节为单位的。


Question: 用链表作为堆栈实现10进制向8进制的转换，然而解决方案都没法生成，好多错误

自己定义TRUE FALSE也可以吧，vs2010是可以调用<stdbool.h>

#include<stdio.h> #include<malloc.h> #include <stdbool.h>    /*for bool type */  typedef struct Snode *PtrToSnode;//以链表做堆栈在头节点后面Push和Pop struct Snode {     int Data;     PtrToSnode Next; }; typedef PtrToSnode stack;  stack CreateStack(); bool IsEmpty(stack); bool push(stack,int ); int Pop(stack); void conversion();  int main() {     conversion();      return 0; } stack CreateStack()//生成栈的头节点 {     stack s;     s = (stack)malloc(sizeof(struct Snode));     s->Next =NULL;     return s; } bool IsEmpty(stack s) {     return (s->Next==NULL); } bool push(stack s,int x)//在头节点后面将元素压入堆栈 {     PtrToSnode Tmpcell;     Tmpcell=(PtrToSnode)malloc(sizeof(struct Snode));     Tmpcell->Data = x;     Tmpcell->Next=s->Next;     s->Next=Tmpcell;     return true; } int Pop(stack s)//在链表的头节点后面Pop {     PtrToSnode firstCell;//将要Pop出的元素     int TopElem;//firstCell的数据域     if(IsEmpty(s))     {         printf("堆栈空");         return 0;     }     else {         firstCell = s->Next;         TopElem = firstCell->Data;         s->Next=firstCell->Next;         free(firstCell);         return TopElem;     } } void conversion(void) {     int N;     stack s;     s = CreateStack();     scanf("%d",&N);     while(N)     {         push(s,N%8);         N=N/8;     }     while(!IsEmpty(s))     {         printf("%d",Pop(s));     }     putchar(10);     free(s);   /*最后释放头节点*/ } 参考一下吧； 在main函数里调用conversion函数；添加头文件<stdbool.h>


Question: PAT 平台中乙级 1050

对于没做过PAT平台作业的人怎么知道这个1050题是什么需求呢？所以先将需求贴出来，然后贴出代码；  你的问题可以参考一下以下的博主博客：  http://blog.csdn.net/zxyolo/article/details/52334495 http://blog.csdn.net/wanmeiwushang/article/details/51598869

到底想问啥呢


Question: 用单链表实现两个集合的交并

引用 8 楼 hzy_76 的回复:创建的过程中已经剔除了重复，所以这里的假定是输入链表本身是合法的，要求也并没有涉及链表纠错。  [quote=引用 7 楼 cfjtaishan 的回复:] [quote=引用 5 楼 hzy_76 的回复:] 没错，所以有这句：  if (!IsContain1(List1, node->data))  即先把List1复制一遍，然后对于List2的每个节点，判断是否存在于List1中，不存在才开始复制 我的意思是，本身List1中就有重复的，你把List1中的先拷贝到并集里，然后再拿List1和List2比较是否相同，所以还是没有解决，List1中或LIst2中有重复的时，如何去掉重复，因此先要将List1和List2去重。[/quote][/quote] 哈哈，严谨

创建的过程中已经剔除了重复，所以这里的假定是输入链表本身是合法的，要求也并没有涉及链表纠错。  引用 7 楼 cfjtaishan 的回复:[quote=引用 5 楼 hzy_76 的回复:] 没错，所以有这句：  if (!IsContain1(List1, node->data))  即先把List1复制一遍，然后对于List2的每个节点，判断是否存在于List1中，不存在才开始复制 我的意思是，本身List1中就有重复的，你把List1中的先拷贝到并集里，然后再拿List1和List2比较是否相同，所以还是没有解决，List1中或LIst2中有重复的时，如何去掉重复，因此先要将List1和List2去重。[/quote]

引用 5 楼 hzy_76 的回复:没错，所以有这句：  if (!IsContain1(List1, node->data))  即先把List1复制一遍，然后对于List2的每个节点，判断是否存在于List1中，不存在才开始复制 我的意思是，本身List1中就有重复的，你把List1中的先拷贝到并集里，然后再拿List1和List2比较是否相同，所以还是没有解决，List1中或LIst2中有重复的时，如何去掉重复，因此先要将List1和List2去重。

你搞得太复杂了，不需要一个无用的头结点，也不需要一个数据为$的尾节点，这是作为输入结束来用的。 CreateSeqList函数这么写就好了，创建出来的链表每个节点都有用。   SeqList* CreateSeqList(char n) { 	SeqList *Head = NULL, *Tail = NULL; 	SeqList* node = NULL; 	char ch;  	printf("输入集合%c的元素：\n", n); 	do 	{  		scanf("%c", &ch); 		if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))) 		{ 			if (!IsContain1(Head, ch)) 			{ 				node = (SeqList *) malloc(sizeof(SeqList)); 				if (node == NULL) 					return; 				node->data = ch; 				node->next = NULL; 				if (Tail != NULL) 				{ 					Tail->next = node; 					Tail = node; 				} 				else 				{ 					Head = Tail = node; 				} 			} 		} 	} 	while (ch != '$');  	return Head; }

//#include "targetver.h" //#include"HeadFile.h" #include <stdio.h> //#include <tchar.h> #include<stdlib.h>  /*******HeadFile.h***/ typedef struct Node {     char data;     Node* next; }SeqList;  bool IsContain(SeqList List, int x); bool IsContain1(SeqList* List, char x); SeqList* Intersection(SeqList* List1, SeqList* List2); SeqList* Union(SeqList* List1, SeqList* List2); SeqList* CreateSeqList(char n); void Print(SeqList* List);   //判断一个元素是否包含于一个集合 bool IsContain(SeqList* List, char x) {     SeqList* p = List->next;     while (p)     {         if (p->data == x)             return true;         p = p->next;     }     return false; } //用于判断一个元素是否包含于一个不用头结点表示的集合 bool IsContain1(SeqList* List, char x) {     SeqList* p = List;     while (p != NULL)     {         if (p->data == x)             return true;         p = p->next;     }     return false; } //求交集 SeqList* Intersection(SeqList* List1, SeqList* List2) {     SeqList* Seq,*Node,*r;     SeqList* p = List1->next;     Seq = (SeqList*)malloc(sizeof(SeqList));     r = Seq;     while (p != NULL)     {         if (IsContain(List2, p->data))         {             Node = (SeqList*)malloc(sizeof(SeqList));             Node->data = p->data;             r->next = Node;             r = r->next;         }         p = p->next;   /*向后遍历*/     }     return Seq; } //求并集 SeqList* Union(SeqList* List1, SeqList* List2) {     SeqList* Seq = (SeqList*)malloc(sizeof(SeqList));     SeqList* p = List1->next;     SeqList* q = List2->next;     SeqList* r = Seq;     while (p != NULL)     {         SeqList* node = (SeqList*)malloc(sizeof(SeqList));         node->data = p->data;         r->next = node;         r = r->next;         p = p->next;     }     while (q != NULL)     {         if (!IsContain(List1, q->data))         {             SeqList* node = (SeqList*)malloc(sizeof(SeqList));             node->data = q->data;             r->next = node;             r = r->next;         }         q = q->next;     }     return Seq; } //创建一个集合 SeqList* CreateSeqList(char n) {     SeqList* Seq = (SeqList*)malloc(sizeof(SeqList));     SeqList* Head = (SeqList*)malloc(sizeof(SeqList));     Seq->data = '$';     Seq->next = NULL;     // SeqList* p,*q;     //p = Seq;     //q = Seq;     printf("输入集合%c的元素：\n", n);     char ch;     do     {         scanf("%c", &ch);     } while (!((ch >= 'a'&& ch <= 'z') || (ch >= '0'&&ch <= '9')) && ch != '$');     while(ch!='$')     {         // q = Seq;         if (IsContain1(Seq, ch))         {             do{                 scanf("%c", &ch);             } while (!((ch >= 'a'&&ch <= 'z') || (ch >= '0'&&ch <= '9')));         }         else         {             SeqList* node = (SeqList*)malloc(sizeof(SeqList));             node->data = ch;             node->next = Seq;             Seq = node;             do{                 scanf("%c", &ch);             } while (!((ch >= 'a'&&ch <= 'z') || (ch >= '0'&&ch <= '9')) && ch != '$');         }     }     Head->next = Seq;     return Head; } //输出集合 void Print(SeqList* List) {     SeqList* p = List->next;     printf("(");     while (p->next!= NULL)     {         printf("%c,", p->data);         p = p->next;     }     printf("%c", p->data);     printf(")");     printf("\n"); }  /******Main.cpp***/  int main() {     SeqList* sq1, *sq2;     char cname1, cname2;     printf("输入第一个集合的名字:\n");     scanf("%c", &cname1);     getchar();     sq1 = CreateSeqList(cname1);     getchar();     printf("输入第二个集合的名字:\n");     scanf("%c", &cname2);     getchar();     sq2 = CreateSeqList(cname2);     printf("集合%c：\n", cname1);     Print(sq1);     printf("集合%c：\n", cname2);     Print(sq2);      printf("交集\n");     Print(Intersection(sq1, sq2));     printf("并集\n");     Print(Union(sq1, sq2));     return 0; } 求交集时，由于IsContain函数里没有对p执行p = p->next;很容易导致系统死机。建议注意下； 上面的代码是修改后的，参考一下吧；

还是创建集合函数的问题，输入的判断太繁琐了，而且在主函数调用时，在输完第一个集合元素时，就跳过了第二个元素名的输入，其实是在输完第一个集合的元素时按下的回车被存储在缓冲区，当执行到输入第二个集合名的getchar()时被当做集合名了。

引用 3 楼 hzy_76 的回复:重新帮你改写了创建、交集、并集函数如下，请参考：   SeqList* CreateSeqList(char n) { 	SeqList *Head = NULL, *Tail = NULL; 	SeqList* node = NULL; 	char ch;  	printf("输入集合%c的元素：\n", n); 	do 	{  		scanf("%c", &ch); 		if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))) 		{ 			if (!IsContain1(Head, ch)) 			{ 				node = (SeqList *) malloc(sizeof(SeqList)); 				if (node == NULL) 					return Head; 				node->data = ch; 				node->next = NULL; 				if (Tail != NULL) 				{ 					Tail->next = node; 					Tail = node; 				} 				else 				{ 					Head = Tail = node; 				} 			} 		} 	} 	while (ch != '$');  	return Head; }  //求交集 SeqList *Intersection(SeqList *List1, SeqList *List2) { 	SeqList *node1 = NULL, *node2 = NULL, *node = NULL; 	SeqList *Head = NULL, *Tail = NULL;  	node1 = List1; 	while (node1) 	{ 		if (IsContain1(List2, node1->data)) 		{ 			node = (SeqList *) malloc(sizeof(SeqList)); 			if (node == NULL) 				return Head; 			node->data = node1->data; 			node->next = NULL; 			if (Tail != NULL) 			{ 				Tail->next = node; 				Tail = node; 			} 			else 			{ 				Head = Tail = node; 			} 		} 		node1 = node1->next; 	}  	return Head; }  //求并集 SeqList *Union(SeqList *List1, SeqList *List2) { 	SeqList *Head = NULL, *Tail = NULL, *node = NULL, *tmp_node = NULL;  	node = List1; 	while (node) 	{ 		tmp_node = (SeqList *) malloc(sizeof(SeqList)); 		if (tmp_node == NULL) 			return Head; 		tmp_node->data = node->data; 		tmp_node->next = NULL; 		if (Tail != NULL) 		{ 			Tail->next = tmp_node; 			Tail = tmp_node; 		} 		else 		{ 			Head = Tail = tmp_node; 		}  		node = node->next; 	}  	node = List2; 	while (node) 	{ 		if (!IsContain1(List1, node->data)) 		{ 			tmp_node = (SeqList *) malloc(sizeof(SeqList)); 			if (tmp_node == NULL) 				return Head; 			tmp_node->data = node->data; 			tmp_node->next = NULL; 			if (Tail != NULL) 			{ 				Tail->next = tmp_node; 				Tail = tmp_node; 			} 			else 			{ 				Head = Tail = tmp_node; 			} 		}  		node = node->next; 	} 	 	return Head; }  求并集时，若链表1或链表2中有重复的，那么求出并集就会有重复的；所以，是不是需要考虑重复的问题；


Question: 在Linux下写了一段读写操作的程序，运行卡住，gdb调试也无反应

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

引用 5楼自信男孩 的回复:#include <stdio.h> #include <stdlib.h> //#include <unistd.h> #include <string.h> #include <errno.h> //#include <sys/types.h> //#include <sys/stat.h> //#include <fcntl.h>  struct Max_Minni_Aver {     int m_max;     int m_mini;     int m_average; };  struct Max_Minni_Aver calc( const char (*str)[32], int len) {     int *num = (int *)malloc(sizeof(int) * len);     for (int i = 0 ; i < len ;++i)     {         num[i] = atoi(str[i]);    //把str数组里的元素全部转换为int并存入num数组中         //printf("num[%d] = %d\n", i, num[i]);    /* debug*/     }      int max_value = num[0];     int mini_value = num[0];     //得到最大最小值     for(int i = 0; i < len;++i)     {         if (num[i]> max_value)         {             max_value = num[i];         }         else if (num[i] < mini_value)         {             mini_value = num[i];         }     }      int sum = 0;     //得出总值     for(int i = 0; i < len;++i)     {         sum +=num[i];     }     //得出平均值     int average = sum / len;      struct Max_Minni_Aver mma;     mma.m_max = max_value;     mma.m_mini = mini_value;     mma.m_average=average;     return mma; }  int main(int argc, char *argv[]) {     char str[1024];     char num[10][32];     char *line = NULL;     int i = 0, j = 0;     FILE *p = fopen("c.txt","r");     if (p == NULL)     {         printf("打开文件失败! %s\n",strerror(errno));         return 0;     }     else     {         while ( fgets(str, sizeof(str),p) != NULL)    //循环每一行         {             line = str;             while (*line++ != '=')  /* get number */                 ;             while(*line != '\0')             {                 if (*line >= '0' && *line <='9')                 {                     num[i][j] = *line;    //找到数字存放到num数组里                     j++;                 }                 line++;    //指向字符串下一个元素             }             num[i][j] = 0;             //printf("numlist = %s\n", num[i]);    /* debug */             i++;             j = 0;         }         struct Max_Minni_Aver value = calc(num, i);    //得到最大值，平均值，最小值         printf("最大值:%d,最小值:%d,平均值:%d\n",value.m_max,value.m_mini,value.m_average);     }     fclose(p);     return 0; } 问题挺多，建议对比以下上面的代码然后总结一下；  比如：若文件打开失败，那么没必要fclose，所以若打开失败，直接return退出； 再比如每行得到的数字都放在一个num里，那么就是只得到文件最后一行的num；前面的要么被覆盖，要么被破坏；感谢热心回答！

引用 3楼heronism 的回复:               /*  卡住是因为这里，line++应放到判断外 */              if (*line >= '0' && *line <='9')                 {                     num[i] = *line;    //找到数字存放到num数组里                     i++;                     line++;    //指向字符串下一个元素                 }      /* 这一步确定没问题吗，还是你就是要算这个，例如str为"123"， 你要计算123 + 23 + 3*/  num[i] = atoi(&(str[i]));

来晚了，你自己已经解决了，我就再说说吧。    FILE *p = fopen("c.txt","r");//这里最好是rb，问题也不在这里   问题在这里：              while(*line != '\0')             {                 if (*line >= '0' && *line <='9')                 {                     num[i] = *line;    //找到数字存放到num数组里                     i++;                     //这一句放到循环体外面//line++;    //指向字符串下一个元素                 }                     line++;    //指向字符串下一个元素             }

自己能发现问题，赞！

额，已经发现问题了。


Question: C语言进阶求帮助

链到下一个节点，不是把下一个节点的地址复制给当前节点的指针域嘛 链表的创建过程会这样做。

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

推荐这篇博客，写得很不错。 https://livesun.github.io/2017/10/27/single_linked/

新建节点的时候就把它链好。


Question: 不知道哪里错了

#include <stdio.h> #include <malloc.h> //#include "stdio.h" //#include "malloc.h"  #define H sizeof(Node) typedef int ElemType;  typedef struct Node {     ElemType data;     struct Node* next; }Node;  typedef struct Node* linklist;  int n=0;  linklist creat(linklist head) {     int i;     linklist p1,p2;     head=(linklist)malloc(H);     //head = NULL;    /* remove this statement*/     p2 = head;     scanf("%d",&i);     while(i!=0)     {         p1=(linklist)malloc(H);         p1->data=i;         p2->next=p1;         p2=p1;         n++;         scanf("%d",&i);      }     p2->next=NULL;      return head;    /*return header node */ }  void print(linklist head) {     linklist p;      if (!head) {         printf("The link is empty!\n");         return;     }      p = head->next;     while (p) {         printf("%d ",p->data);         p = p->next;     }     putchar(10);     /*        if(head!=NULL)        {        p=head->next;        for(;p!=NULL;p=p->next)        printf("%d ",p->data);        }        else        printf("NULL");        */ }  int search(linklist head) {     int i,j=1;     linklist p;     printf("Please input the data to be searched: ");     scanf("%d",&i);     if(i<1||i>n) {         printf("查找范围不合理");         return -1;     } else {         p = head->next;         while(p && j < i) {             p = p->next;             j++;         }         if (p)             printf("Your searched data is: %d\n", p->data);     }      return 0; }  linklist charu(linklist head) {     int i,j;     linklist p1,p2;     printf("Please input the data to be inserted: ");     scanf("%d",&i);     if(i<1||i > n)         printf("插入位置错误");     else     {         if(head==NULL)         {             p1=(linklist)malloc(H);             scanf("%d", &p1->data);    /* should add & */             head->next=p1;             p1->next=NULL;   /* = not == */         }         else         {             if(i==1)             {                 p2=head->next;                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 head->next=p1;                 p1->next=p2;              }             if(i<n)             {                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 p2=head;                 for(j=1;j<i;j++)                 {                     p2=p2->next;                 }                 p1->next=p2->next;                 p2->next=p1;             }             if(i==n)             {                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 p2=head;                 for(j=1;j<=i;j++)                 {                     p2=p2->next;                 }                 p2->next=p1;                 p1->next=NULL;             }         }         n++;     }      return head;  /* return header node */ }  linklist del(linklist head) {     int i,j;     linklist p1,p2;     if(!head) {         printf("NO STATISTIC DELATE\n");         return NULL;     }      printf("Please input the data to be deleted: ");     scanf("%d",&i);     if(i==1)     {         p2=head;         p1=head->next;         p2->next=p1->next;     }     if(i==n)     {         p2=head;         for(j=1;j<n;j++)         {             p2=p2->next;             p2->next=NULL;   /* = not == */         }     }     else     {         p2=head;         p1=head;         for(j=1;j<n;j++)         {             p2=p2->next;          }         for(j=1;j<=n+1;j++)         {             p1=p1->next;         }         p2->next=p1;     }     n--;      return head; }  int main(void) {     linklist head = NULL;     head=creat(head);     print(head);     search(head);     head=charu(head);     print(head);     head=del(head);     print(head);      return 0; }  删除操作没有将删除之后的节点free掉会导致内存泄露，因此还需要优化一下；

#include <stdio.h> #include <malloc.h> //#include "stdio.h" //#include "malloc.h"  #define H sizeof(Node) typedef int ElemType;  typedef struct Node {     ElemType data;     struct Node* next; }Node;  typedef struct Node* linklist;  int n=0;  linklist creat(linklist head) {     int i;     linklist p1,p2;     head=(linklist)malloc(H);     //head = NULL;    /* remove this statement*/     p2 = head;     scanf("%d",&i);     while(i!=0)     {         p1=(linklist)malloc(H);         p1->data=i;         p2->next=p1;         p2=p1;         n++;         scanf("%d",&i);      }     p2->next=NULL;      return head;    /*return header node */ }  void print(linklist head) {     linklist p;      if (!head) {         printf("The link is empty!\n");         return;     }      p = head->next;     while (p) {         printf("%d ",p->data);         p = p->next;     }     putchar(10);     /*     if(head!=NULL)     {         p=head->next;         for(;p!=NULL;p=p->next)             printf("%d ",p->data);     }     else         printf("NULL");         */ }  int search(linklist head) {     int i,j=1;     linklist p;     printf("Please input your searching data: ");     scanf("%d",&i);     if(i<1||i>n)         printf("查找范围不合理");     else     {         p=head->next;         while(p!=NULL&&j<i)         {             p=p->next;             j++;         }         printf("%d",p->data);      }      return 0; }  linklist charu(linklist head) {     int i,j;     linklist p1,p2;     printf("Please input your inserting data: ");     scanf("%d",&i);     if(i<1||i>n)         printf("插入位置错误");     else     {         if(head==NULL)         {             p1=(linklist)malloc(H);             scanf("%d", &p1->data);    /* should add & */             head->next=p1;             p1->next=NULL;   /* = not == */         }         else         {             if(i==1)             {                 p2=head->next;                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 head->next=p1;                 p1->next=p2;              }             if(i<n)             {                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 p2=head;                 for(j=1;j<i;j++)                 {                     p2=p2->next;                 }                 p1->next=p2->next;                 p2->next=p1;             }             if(i==n)             {                 p1=(linklist)malloc(H);                 scanf("%d", &p1->data);    /* should add & */                 p2=head;                 for(j=1;j<=i;j++)                 {                     p2=p2->next;                 }                 p2->next=p1;                 p1->next=NULL;             }         }         n++;     }      return head;  /* return header node */ }  linklist del(linklist head) {     int i,j;     linklist p1,p2;     printf("Please input your deleting data: ");     scanf("%d",&i);     if(head==NULL)         printf("NO STATISTIC DELATE");     else     {         if(i==1)         {             p2=head;             p1=head->next;             p2->next=p1->next;         }         if(i==n)         {             p2=head;             for(j=1;j<n;j++)             {                 p2=p2->next;                 p2->next=NULL;   /* = not == */             }         }         else         {             p2=head;p1=head;             for(j=1;j<n;j++)             {                 p2=p2->next;              }             for(j=1;j<=n+1;j++)             {                 p1=p1->next;             }             p2->next=p1;         }         n--;     }      return head; }  int main(void) {     linklist head = NULL;     head=creat(head);     print(head);     search(head);     head=charu(head);     print(head);     head=del(head);     print(head);      return 0; }  有多处错误，有些编译器应该已经提示警告了。所以对于警告信息不要放过； 主要是语法错误；scanf输入第二个参数应该是地址，因此应该加& 函数需要返回链表头，但是却没有返回；


Question: 文件包含问题

我把p2();p3();改过来了，还是没有用，怎么办。

ppt上是p1() p2() 你输入的是p2() p3()

如果是一个个敲出来，那么后缀名不应该敲错吧； 建议将错误信息再发出来。  include一般是用于引入头文件，不建议引入源文件；

错误是什么额？你看的ppt应该是老古董了吧，需要老古董的编译器才支持，c语言main有返回类型的 void main() {},还有一般应该包含.h文件，而不是.c


Question: TCP传输图片的问题

2 3 4 5 6 typedef struct { unsigned int packet_num;//一次传送分包数量 unsigned int packet_index;//当前传送包的序号 unsigned char data[1024];//每个包的大小 }tcp_packet;

我拿了你的代码学习了一下.顺便学习了VS2017,整了一天,调试发现,    根据图片显示的效果以及文件头正确 文件尾显示不正确,说明只接受到了数据包的前部分,后部分没有收到, 发现是你的发送和接收的缓存设置过大.   1M太大了,建议换成1024b,把数据包拆分发送,不存在丢失现象了,图片解析正确.

引用 21 楼 HANKER131523 的回复:[quote=引用 18 楼 ananluowei 的回复:] tcp发送和接收不是同步的 不能依赖发送一次就接收一次。 tcp没有保证一次能把你要发送的发送完整，同样接收也是这样。 要根据send或者recv返回的值，判断是否发送或者接收完整。不完整就继续发送或者接收。 发送和接收的过程不是一次，需要在循环中进行，完整了才退出循环。 你说的对，可是send和recv函数里面有一个包的字节数的参数，这个一般要选多大了，我试了好多次，发现几M貌似都可以的，而且单次发单次收都没什么问题[/quote] 一个包的大小是无所谓的，只要发送过去的格式，接收方能解析，能知道这个包多大就可以。发送和接收的过程不是一次send或者recv的，给你看一个简单的发送接收的函数代码//增加一个send、recv共用的函数，减少重复代码  int sendrecv(SOCKET sock, char* buff, unsigned int len, bool sendflag) { 	int ret = 0; 	do 	{ 		int i; 		if (sendflag) //发送标志，接收为false 			i = send(sock, buff + ret, len - ret, 0); 		else 			i = recv(sock, buff + ret, len - ret, 0); 		if (i == 0) 		{ 			//cout << "connect closed\n"; 			ret = i; 			break; 		} 		else if (i < 0) 		{ 			//cout << "recv failed with error: " << WSAGetLastError() << endl; 			ret = i; 			break; 		} 		else 		{	 			ret += i; 		} 	} while (ret >0 && ret < len); 	return ret; }   inline int recvtobuff(SOCKET sock, char* buff, unsigned int len) { 	return sendrecv(sock, buff, len, false); }  inline int sendfrombuff(SOCKET sock, char* buff, unsigned int len) { 	return sendrecv(sock, buff, len, true); }

引用 20 楼 HANKER131523 的回复:[quote=引用 19 楼 chenandczh 的回复:] 包协议里面 应该添加 一些信息细节 。例如 ，图片总的BYTE大小，总包数，当前包序号，这样就能保证接收后数据整合处理。 兄弟，你看程序了吗，里面有的[/quote] 有跟逻辑正确是两码事，既然有这个思路，为什么不去调一下，完成接收后对比总包数以及计算一下文件MD5和采集收集的全部字节的MD5是否在一致。等你确认收集过程没有问题再看看是不是图片解码问题。

引用 18 楼 ananluowei 的回复:tcp发送和接收不是同步的 不能依赖发送一次就接收一次。 tcp没有保证一次能把你要发送的发送完整，同样接收也是这样。 要根据send或者recv返回的值，判断是否发送或者接收完整。不完整就继续发送或者接收。 发送和接收的过程不是一次，需要在循环中进行，完整了才退出循环。 你说的对，可是send和recv函数里面有一个包的字节数的参数，这个一般要选多大了，我试了好多次，发现几M貌似都可以的，而且单次发单次收都没什么问题

引用 19 楼 chenandczh 的回复:包协议里面 应该添加 一些信息细节 。例如 ，图片总的BYTE大小，总包数，当前包序号，这样就能保证接收后数据整合处理。 兄弟，你看程序了吗，里面有的

这么复杂的程序，佩服，一个菜鸟的我表示看不懂，写这个程序语言多久？要向你学习

发送时，检查下send返回值，看下是否全部成功了，建议分多次发送，每次发送一小块。 tcp是流式的，不一定就是服务器发了一个数据包，客户端就收到一个数据包

TCP不仅是可靠不丢包，而且保证了顺序，除非连接被重置，否则根本不需要关心这些问题。

引用 9 楼 hzy_76 的回复:那就更是跟发送顺序无关了，要知道TCP的基本特点正是“可靠连接”，数据顺序都要自己处理了，干嘛不用UDP？  [quote=引用 8 楼 HANKER131523 的回复:] [quote=引用 7 楼 hzy_76 的回复:] TCP协议应该已经保证了数据的顺序，除非你重新创建了socket连接。所以应该不是这方面的问题。 你可以标记一下数据，调试看看发送的每个数据包和对端收到的都是什么。 我现在只是用了一次发送和一次接收来测试[/quote][/quote] TCP不是说可靠不丢包吗，这个也不是我一个人决定的，也本着学东西的态度试试

引用 10 楼 cfjtaishan 的回复:[quote=引用 5 楼 HANKER131523 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] 有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常； 解决网络动荡的方法是客户端使用环形缓冲区，也可以理解为缓冲队列；每个收到的包先存到缓冲队列里，然后再从缓冲队列里取数据解析，即使每个从服务到的数据都加了包头和包尾，我们从缓冲队列里取数据然后分别解析，如果收到的包头（包头里有数据长度吧）都包含数据长度，那么根据这个长度和缓存队列里的数据长度比较，若包头里记录的长度大于当前缓存队列里数据长度，那么则不读取，反之则读取解析（去掉包头和包尾）  有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常；，这句话不太理解，感觉没什么关系啊[/quote] 网络动荡是指网络有可能好有可能不好；如果网络好，服务器发送一个，客户端马上收到了，这个我们想要的，但是有时候网络不像我们那样想的顺畅；不然我们下载东西，怎么会有时候快，有时候慢呢。[/quote] 我用的是本机的127.0.0.1，应该不存在动荡的问题吧

引用 11 楼 HANKER131523 的回复:[quote=引用 10 楼 cfjtaishan 的回复:] [quote=引用 5 楼 HANKER131523 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] 有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常； 解决网络动荡的方法是客户端使用环形缓冲区，也可以理解为缓冲队列；每个收到的包先存到缓冲队列里，然后再从缓冲队列里取数据解析，即使每个从服务到的数据都加了包头和包尾，我们从缓冲队列里取数据然后分别解析，如果收到的包头（包头里有数据长度吧）都包含数据长度，那么根据这个长度和缓存队列里的数据长度比较，若包头里记录的长度大于当前缓存队列里数据长度，那么则不读取，反之则读取解析（去掉包头和包尾）  有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常；，这句话不太理解，感觉没什么关系啊[/quote] 网络动荡是指网络有可能好有可能不好；如果网络好，服务器发送一个，客户端马上收到了，这个我们想要的，但是有时候网络不像我们那样想的顺畅；不然我们下载东西，怎么会有时候快，有时候慢呢。[/quote] 我用的是本机的127.0.0.1，应该不存在动荡的问题吧[/quote] 如果是本地的服务器和客户端，那么不存在网络动荡问题，但是需要考虑CPU调用机制，因为在同一台电脑上，服务器和客户端是属于不同的两个进程，因此他们的通信可以简单的理解为进程间通信（异步的），这样也可能出现类似网络动荡的问题，比如给服务器的时间片多一些，给客户端的时间片少一些。

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

引用 5 楼 HANKER131523 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常； 解决网络动荡的方法是客户端使用环形缓冲区，也可以理解为缓冲队列；每个收到的包先存到缓冲队列里，然后再从缓冲队列里取数据解析，即使每个从服务到的数据都加了包头和包尾，我们从缓冲队列里取数据然后分别解析，如果收到的包头（包头里有数据长度吧）都包含数据长度，那么根据这个长度和缓存队列里的数据长度比较，若包头里记录的长度大于当前缓存队列里数据长度，那么则不读取，反之则读取解析（去掉包头和包尾）  有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常；，这句话不太理解，感觉没什么关系啊[/quote] 网络动荡是指网络有可能好有可能不好；如果网络好，服务器发送一个，客户端马上收到了，这个我们想要的，但是有时候网络不像我们那样想的顺畅；不然我们下载东西，怎么会有时候快，有时候慢呢。

那就更是跟发送顺序无关了，要知道TCP的基本特点正是“可靠连接”，数据顺序都要自己处理了，干嘛不用UDP？  引用 8 楼 HANKER131523 的回复:[quote=引用 7 楼 hzy_76 的回复:] TCP协议应该已经保证了数据的顺序，除非你重新创建了socket连接。所以应该不是这方面的问题。 你可以标记一下数据，调试看看发送的每个数据包和对端收到的都是什么。 我现在只是用了一次发送和一次接收来测试[/quote]

引用 7 楼 hzy_76 的回复:TCP协议应该已经保证了数据的顺序，除非你重新创建了socket连接。所以应该不是这方面的问题。 你可以标记一下数据，调试看看发送的每个数据包和对端收到的都是什么。 我现在只是用了一次发送和一次接收来测试

引用 4 楼 cfjtaishan 的回复:[quote=引用 3 楼 HANKER131523 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] 有可能是网络动荡，即服务器是顺序发送的，但是到客户端收到的数据可能不是按照一个个接收，有可能一下子接收到2个包（即服务器发2次，客户端一次接收）这就是为什么如果中间不加包头包尾图片就正常； 解决网络动荡的方法是客户端使用环形缓冲区，也可以理解为缓冲队列；每个收到的包先存到缓冲队列里，然后再从缓冲队列里取数据解析，即使每个从服务到的数据都加了包头和包尾，我们从缓冲队列里取数据然后分别解析，如果收到的包头（包头里有数据长度吧）都包含数据长度，那么根据这个长度和缓存队列里的数据长度比较，若包头里记录的长度大于当前缓存队列里数据长度，那么则不读取，反之则读取解析（去掉包头和包尾） 你意思是我每次接收的数据都设置为很小，然后多次接收，那这个大小一般应该设置为多大呢[/quote] 我说的环形缓冲区，建议从网上找一个这个技术点；这个需要多线程操作了，即在客户端用一个线程去接收写到环形缓冲区里，一个线程去读环形缓冲区，然后解析数据报文；[/quote] 我这个程序里含有用数组实现的缓冲区程序的，只是，我前面发现1M左右的图片直接发过来好像就能接受成功，就不用了


Question: 请求帮助

有人吗，请各位大神帮忙


Question: 关于结构体强制转换的问题

// dm->data一定是个指针（指向DM_Swarm型变量）或字符数组（原样存储了 DM_Swarm结构），这样才具备转换的条件  DM_Swarm *swarm = (DM_Swarm*)dm->data;

将dm->data转换为指向DM_Swarm结构体的指针类型，通常来说dm->data也是一个指针类型，这里是在做指针类型的转换，转换为DM_Swarm*类型，而不是转换为结构体类型

这个是强制类型转换，即将dm结构体下的data强制转换位DM_Swarm *类型； 如果data是char *类型的，那么就会将字符数组转换位DM_Swarm类型的格式；


Question: 我好像发明了一种新的排序算法,不知道前人有没有这样写过

仅供参考：#include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2

好#。。。。。。

交换两整数，其实可读性不好，可读性>技巧。

还是冒泡排序，但是赋值方法很不错。

你是把两个数交换用异或写了，数组传进来还需要返回吗？

。。你这是复杂版的选择排序，多了很多交换操作

排序方法没有创新吧，这就是冒泡排序。只是交换数据的方式变了； 建议试一下能够通用，比如交换两个结构体变量；我估计对于两个结构体变量的交换不好使呢。

这不就是冒泡排序吗？

前人这样写过

只是交换数据上的区别，但这种也有局限，比如对于浮点数排序就不适用


Question: 指针变量所占内存大小

64位的系统支持64位和32位的编译器；所以个人觉得跟系统和编译器都有关系。 以下是Windows10 64位+VS2015的调试效果

64位系统可以安装指针为32位编译器（向前兼容），也可以安装指针为64位的编译器； 因此指针占的字节数，跟编译器有直接关系，跟系统也是有关系的。

我觉得该说得更清楚一些。  首先是平台，32位平台只能执行32位程序，64位平台一般能兼容32位和64位程序（Intel曾经有平台激进的只允许64位，但死了）。说跟编译器有关的朋友，忽略了一个事实：如果编译了64位程序，是不能在32位平台上运行的。  接着来说编译器，如果是32位编译器，即编译成32位程序，则指针都是32位，即4字节；如果编译成64位程序，则指针就是64位，即8字节。

编译器一般是32位的  指针占4个字节

引用 6 楼 ananluowei 的回复:编译成32位程序，指针4字节，地址32位 编译成64位程序，指针8字节，地址64位 是看编译器吗？

引用 1 楼 hzy_76 的回复:系统决定的，我们原来都是32位系统，现在基本都是64位了。 意思是64位系统下，变量的地址是64位，指针变量64/8 = 8个字节吗？

系统决定的，我们原来都是32位系统，现在基本都是64位了。

引用 4 楼 adusuccessfully 的回复:[quote=引用 2 楼 darker0019527 的回复:] [quote=引用 1 楼 hzy_76 的回复:] 系统决定的，我们原来都是32位系统，现在基本都是64位了。 意思是64位系统下，变量的地址是64位，指针变量64/8 = 8个字节吗？[/quote]  不是，64位系统下，指针变量还占得是4字节。[/quote] 为什么64位系统下还是4B？

引用 2 楼 darker0019527 的回复:[quote=引用 1 楼 hzy_76 的回复:] 系统决定的，我们原来都是32位系统，现在基本都是64位了。 意思是64位系统下，变量的地址是64位，指针变量64/8 = 8个字节吗？[/quote]  不是，64位系统下，指针变量还占得是4字节。

当然是编译器决定的。64位系统就不能编译32位程序了吗？


Question: 跪求大神看看

引用 4 楼 weixin_41174083 的回复:[quote=引用 3 楼 das白的回复:]单词拼写错误  switch   swtich 写写，看到了，刚开始没注意  编译器应该有提示吧 你这样写应该编译都过不了吧

#include<stdio.h> int main() {     int x;     printf("Please enter a integer between 1 and 7 ");     scanf("%d",&x);     switch(x)     {         case 1:             printf("Today is Monday!\n");             break;         case 2:             printf("Today is Tuesday!\n");             break;         case 3:             printf("Today is Wendy!\n");             break;         case 4:             printf("Today is Tuesday!\n");             break;         case 5:             printf("Today is Friday!\n");             break;         case 6:             printf("Today is weekend!\n");             break;         default:             printf("Today is weekend!\n");     }     return 0; }  switch单词拼写错误；另外，每个case后面缺少break;

类似错误人工走查不太容易看出来， 但编译器有错误提示，应该能够提供一些线索。

单词拼写错误  switch   swtich

这个哪里错了，运行不了，求解。

#include<stdio.h> int main() {     int x;     printf("Please enter a integer between 1 and 7 ");    scanf("%d",&x);    switch(x)         {         case 1:                 printf("Today is Monday!\n");break;         case 2:                 printf("Today is Tuesday!\n");break;         case 3:                 printf("Today is Wendy!\n");break;         case 4:                 printf("Today is Tuesday!\n");break;         case 5:                 printf("Today is Friday!\n");break;         case 6:                 printf("Today is weekend!\n");break;         default:                 printf("Today is weekend!\n");break;         }     return 0; }

引用 3 楼 das白的回复:单词拼写错误  switch   swtich 写写，看到了，刚开始没注意


Question: C语言 U64与U8计算求助

引用 3 楼 das白的回复:试试这个 图片上不去... 输出格式都为 0x%x

试试这个

你给一个 UINT8 左移 24 位还想得到正确结果……

printf("sum:b+a<<24 = 0x%016I64x\n", b+(a<<24)); 改为 printf("sum:b+a<<24 = 0x%016I64x\n", b+(((unsigned int)a)<<24)); 可以吗

主要原因是a 是unsigned char类型，在执行b + (a <<24)时，现将unsigned char 类型转int类型，然后int类型再转u64;这个过程是类型隐式提升 所以在转int类型时，已经是有符号数，再转u64时，就是最高位位符号位，所以是除低24位位0，其他64 - 24位位1； 解决办法可以考虑：  printf("sum:b+a<<24 = 0x%llx\n", b+((unsigned int)a<<24)); 这个办法是去掉u8 转int这个过程，直接跳到u32; 也可以这么解决：  printf("b = %#llx\n", (b << 8)+ a);

(a<<24)的结果是一个int，与b相加的时候被扩展到64位（符号扩展）。 像#1那样把a或者a<<24作为无符号数处理就可以了。


Question: 二叉树， C语言编译

引用 16 楼 zhao4zhong1 的回复:完美纯C版：#include <locale.h> #include <stdio.h> #include <stdlib.h> #include <malloc.h> typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int nn=0; int CreateBiTree(BiTree *T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         *T = NULL;     } else {         *T = (BiTree)malloc(sizeof(BiTNode)); nn++;         (*T)->data = data;         //生成根结点         CreateBiTree(&(*T)->lchild);//构造左子树         CreateBiTree(&(*T)->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     BiTree *stack=(BiTree *)malloc(nn*sizeof(BiTree));     int sp=0;     BiTree p = T;//p是遍历指针     while (p || sp) {   //栈不空或者p不空时循环         if (p != NULL) {             stack[sp]=p;sp++;       //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             sp--;p=stack[sp];       //退栈             p = p->rchild;          //访问右子树         }     }     free(stack); } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     BiTree *stack=(BiTree *)malloc(nn*sizeof(BiTree));     int sp=0;     BiTree p = T;//p是遍历指针     while (p || sp) {   //栈不空或者p不空时循环         if (p != NULL) {             stack[sp]=p;sp++;       //存入栈中             p = p->lchild;          //遍历左子树         } else {             sp--;p=stack[sp];       //退栈             printf("%c ",p->data);             p = p->rchild;          //访问右子树         }     }     free(stack); }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     BiTreePost *stack=(BiTreePost *)malloc(nn*sizeof(BiTreePost));     int sp=0;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || sp) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack[sp]=BT;sp++;       //存入栈中             p = p->lchild;         }         while (sp && (stack[sp-1])->tag == 'R') {//左右子树访问完毕访问根节点             sp--;BT=stack[sp];        //退栈             printf("%c ",BT->biTree->data);             free(BT);         }         if (sp) {//遍历右子树             BT=stack[sp-1];             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     }     free(stack); } void LevelOrder(BiTree T) {//层次遍历     BiTree p;     BiTree *queue;     int h=0,t=0,n=0;      if (T == NULL) return;     p=T;     queue=(BiTree *)malloc(nn*sizeof(BiTree));     queue[t]=p;t=(t+1)%10;n++;//根节点入队     while (n) {    //队列不空循环         p=queue[h];             //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         h=(h+1)%10;n--;         //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue[t]=p->lchild;t=(t+1)%10;n++;         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue[t]=p->rchild;t=(t+1)%10;n++;         }     }     free(queue); } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(&T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G  谢谢

[/code][/quote] 谢谢谢谢

纯C版： #include <locale.h> #include <stdio.h> #include <stdlib.h> #include <malloc.h> typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree *T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         *T = NULL;     } else {         *T = (BiTree)malloc(sizeof(BiTNode));         (*T)->data = data;         //生成根结点         CreateBiTree(&(*T)->lchild);//构造左子树         CreateBiTree(&(*T)->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     BiTree stack[10];     int sp=0;     BiTree p = T;//p是遍历指针     while (p || sp) {   //栈不空或者p不空时循环         if (p != NULL) {             stack[sp]=p;sp++;       //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             sp--;p=stack[sp];       //退栈             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     BiTree stack[10];     int sp=0;     BiTree p = T;//p是遍历指针     while (p || sp) {   //栈不空或者p不空时循环         if (p != NULL) {             stack[sp]=p;sp++;       //存入栈中             p = p->lchild;          //遍历左子树         } else {             sp--;p=stack[sp];       //退栈             printf("%c ",p->data);             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     BiTreePost stack[10];     int sp=0;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || sp) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack[sp]=BT;sp++;       //存入栈中             p = p->lchild;         }         while (sp && (stack[sp-1])->tag == 'R') {//左右子树访问完毕访问根节点             sp--;BT=stack[sp];        //退栈             printf("%c ",BT->biTree->data);         }         if (sp) {//遍历右子树             BT=stack[sp-1];             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     BiTree queue[10];//队列     int h=0,t=0,n=0;     queue[t]=p;t=(t+1)%10;n++;//根节点入队     while (n) {    //队列不空循环         p=queue[h];             //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         h=(h+1)%10;n--;         //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue[t]=p->lchild;t=(t+1)%10;n++;         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue[t]=p->rchild;t=(t+1)%10;n++;         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(&T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G

iostream头文件是输出流，语法没有区别，在于输出输入改为了cout和cin

引用 10 楼 zhao4zhong1 的回复:仅供参考：#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G  谢谢，我还想问一下，这个代码我在C编译器里编译不出来，C++里可以正常编译。但是我看不懂C++的，这个代码的头文件我也是没见过

引用 9 楼 destory27 的回复:[quote=引用 8 楼 qq_40933663 的回复:] 不好意思，我还想问一下，这是C++吗？我只会一点点C语言，所以好像看不懂，也编译不出来  回复是引用一下，不然别人看不见你的回答，    他那个是C语言   输出输出用c++的头文件 你用 C语言的头文件就可以了。  定义结构体保存结点的数据和左子树，右子树结点，，递归创建子树  #结束[/quote]  引用 9 楼 destory27 的回复:[quote=引用 8 楼 qq_40933663 的回复:] 不好意思，我还想问一下，这是C++吗？我只会一点点C语言，所以好像看不懂，也编译不出来  回复是引用一下，不然别人看不见你的回答，    他那个是C语言   输出输出用c++的头文件 你用 C语言的头文件就可以了。  定义结构体保存结点的数据和左子树，右子树结点，，递归创建子树  #结束[/quote]  好的，谢谢

引用 8 楼 qq_40933663 的回复:不好意思，我还想问一下，这是C++吗？我只会一点点C语言，所以好像看不懂，也编译不出来  回复是引用一下，不然别人看不见你的回答，    他那个是C语言   输出输出用c++的头文件 你用 C语言的头文件就可以了。  定义结构体保存结点的数据和左子树，右子树结点，，递归创建子树  #结束

谢谢

引用 4 楼 qq_40933663 的回复:但是我编译不出来，不好意思，我还有点看不懂 这个是多个文件的，包括头文件和源文件；注意不能放在一个文件里编译

#include<iostream> #include<malloc.h> using namespace std;   typedef struct node {     char data;     struct node *lchild;     struct node *rchild; }BTnode;   BTnode* CreateBiTree(BTnode *&T) {     char ch;     cin >>ch;     if (ch == '#')    /*空格改成#*/         return  NULL;     else     {         T = (BTnode*)malloc(sizeof(BTnode));         T->data = ch;         T->lchild=CreateBiTree(T->lchild);         T->rchild=CreateBiTree(T->rchild);         return T;     } }   void PreOrder(BTnode *b) {     if (b != NULL)     {         cout << b->data;         PreOrder(b->lchild);         PreOrder(b->rchild);     } } int main() {     BTnode *B = (BTnode*)malloc(sizeof(BTnode));     B=CreateBiTree(B);     PreOrder(B);     return 0; } 楼主的二叉树创建是有问题的。

但是我编译不出来，不好意思，我还有点看不懂

引用 2 楼 qq_40933663 的回复:这是C语言吗？    是啊

这是C语言吗？

create_tree.c  #include "head.h" typedef  int DataType;  typedef struct tree{ 	DataType num; 	struct tree *left_child; 	struct tree *right_child; }node;  node * init_tree(void) { 	node *root = (node *)malloc(sizeof(node)); 	(node *)memset(root, 0x00, sizeof(node)); 	 	root->left_child = NULL; 	root->right_child = NULL; 	 	return root; }  void insert_tree(node **root) { 	static node *last_node = NULL; 	 	if(*root != NULL){ 		fprintf(stderr, "%s\012", "Here is not empty !"); 		return; 	} 	node *rt = (node *)calloc(1, sizeof(node)); 	*root = rt; 	if(!last_node){ 		system("color 0C"); 		fprintf(stderr, "%s\012", "\"The data inserted into the root node .\""); 		Sleep(2000); 		system("color 0A"); 	} 	printf("Enter to insert data :"); 	while(scanf("%d", &rt->num) == 0){ 		fflush(stdin); 		fprintf(stderr, "%s", "Illegal input and input again :"); 	} 	rt->left_child = NULL; 	rt->right_child = NULL; 	 	system("color 0C"); 	fprintf(stderr, "%s", "\n\t-----------------------------------------\n"); 	fprintf(stderr, "%s\n", "\t1.insert left_child  2.insert right_child\n\ 	3.insert brother     0.end_insert"); 	fprintf(stderr, "%s", "\t-----------------------------------------\n\n"); 	Sleep(3000); 	system("color 0A"); 	int choose; 	lb: fprintf(stderr, "%s", "Please select a :"); 	while(scanf("%d", &choose) == 0){ 		fflush(stdin); 		fprintf(stderr, "%s", "Illegal input and input again :"); 	} 	if(choose > 3 || choose < 0){ 		fprintf(stderr, "%s", "There is no this option.\012"); 		goto lb; 	}	 	 	switch(choose){ 		case 1:{ 			last_node = rt; 			insert_tree(&rt->left_child); 		}break; 		 		case 2:{ 			last_node = rt; 			insert_tree(&rt->right_child); 		}break; 		 		case 3:{ 			if(last_node != NULL){ 				if(last_node->left_child != NULL && last_node->right_child != NULL) 					fprintf(stderr, "%s", "Have no place to insert .\012"); 				 				else if(last_node->left_child == NULL) 					insert_tree(&last_node->left_child); 				 				else 					insert_tree(&last_node->right_child); 			} 	 		}break; 		case 4:{ 			 		}break; 		 		case 0: 			return; 	} 	 }  void preorder(node **p) { 	if(*p == NULL) 		return; 	fprintf(stderr, "%d ",(*p)->num); 	preorder(&(*p)->left_child); 	preorder(&(*p)->right_child); 	 }  void inorder(node **p) { 	if(*p == NULL) 		return; 	inorder(&(*p)->left_child); 	fprintf(stderr, "%d ",(*p)->num); 	inorder(&(*p)->right_child); 	 }  void postorder(node **p) { 	if(*p == NULL) 		return; 	inorder(&(*p)->left_child); 	inorder(&(*p)->right_child); 	fprintf(stderr, "%d ",(*p)->num); 	 }  void show(node **root) { 	node *p = *root; 	char order; 	fflush(stdin); 	lb2:system("color 0C"); 	fprintf(stderr, "%s", "\n\t--------------------------------------\n"); 	fprintf(stderr, "%s", "\tb:PreOrder i:Inorder a:PostOrder e:end\012"); 	fprintf(stderr, "%s", "\t--------------------------------------\n\n"); 	Sleep(3000); 	system("color 0A"); 	fprintf(stderr, "%s", "Choose the way to traverse :"); 	while(scanf("%c", &order) != '\n'){ 		fflush(stdin); 		switch(order){ 			case 'b': 				fprintf(stderr, "%s", "For the former sequence traversal results:"); 				preorder(&p); 				fprintf(stderr, "%c", '\012'); 				goto lb2; 				break; 		 			case 'i': 				fprintf(stderr, "%s", "In order to traverse the results :"); 				inorder(&p); 				fprintf(stderr, "%c", '\012'); 				goto lb2; 				break; 		 			case 'a': 				fprintf(stderr, "%s", "After the sequence traversal results for: \ "); 				postorder(&p); 				fprintf(stderr, "%c", '\012'); 				goto lb2; 				break; 				 			case 'e': 				return; 				 			default:{ 				fprintf(stderr, "%s", "There is no this option.\012"); 				goto lb2; 			} 		} 		 	}  }  node * creat_tree(void) { 	node *root = init_tree(); 	insert_tree(&root->left_child); 	show(&root->left_child); 	 	return root; }    main.c  #include "head.h"  int main(int argc, char *argv[]) { 	system("title Binary tree basic implementation and operation "); 	system("mode con  lines=20 cols=60"); 	 	node *root = creat_tree(); 	 	return 0; }   head.h  #ifndef _HEAD_H #define _HEAD_H #include <stdio.h> #include <malloc.h> #include <string.h> #include <windows.h>  typedef struct tree node; node * creat_tree(void); #endif   以前写的例子，你可以看下


Question: emwin小工具有数量上限 吗？为什么我只要多加一个小工具，程序就跑死了

兄弟感觉你发错地方了，这边人应该不玩这种板子的吧，我记得原子论坛和秉辉火论坛玩这个的。你到那问问比较好吧。


Question: c语中百亿之上的数求a+b

银行系统对大金额的计算用的都是unsigned char数组储存每一位数。

大数据加法；下面是大数乘法的例子，可以在这个基础上修改：  #include <stdio.h> #include <stdlib.h> #include <string.h>  #define MAX_NUM_LEN 2048  int cal_factorial(unsigned char *num_list, int num_size, int n);  int cal_val(unsigned char *num_list, int num_size, int base, int num) {     int i = 0, j;     int len = 1, tmp, carry_bit;      num_list[1] = 1;      while (i < num) {         carry_bit = 0;         for (j = 1; j <= len; j++) {             tmp = num_list[j] * base + carry_bit;             num_list[j] = tmp % 10;             carry_bit = tmp / 10;             if (j >= len && carry_bit != 0)                 len++;             if (num_size-1 < len) {/* overflow */                 printf("Overflow!\n");                 return num_size-1;             }         }         i++;     }      return len; }   int main(void) {     unsigned char num_list[MAX_NUM_LEN];     int num_len, i;     int base, power;      memset(num_list, 0, sizeof(num_list));     printf("Please input two numbers: ");     scanf("%d%d", &base, &power);      if (base < 0 && power % 2)         num_list[0] = 1; /* negative number */     else         num_list[0] = 0;     base = abs(base);      num_len = cal_val(num_list, MAX_NUM_LEN, base, power);     printf("len = %d\n", num_len);     if (num_list[0])         putchar('-');     for (i = num_len; i >= 1; i--)         printf("%d", num_list[i]);     printf("\n");     return 0; }   int cal_factorial(unsigned char *num_list, int num_size, int n) {     int carry_bit, i, j, len = 1;     int tmp;      num_list[1] = 1;     for (i = 2; i <= n; i++)     {         carry_bit = 0;         for (j = 1; j <= len; j++) {             tmp = num_list[j] * i + carry_bit;             num_list[j] = tmp % 10;             carry_bit = tmp / 10;             if (j >= len && carry_bit != 0)                 len++;             if (num_size -1 < len) { /* overflow */                 printf("Overflow!\n");                 return num_size-1;             }         }      }      /*     for (i = len; i >= 1; i--)//逆序输出数组就是结果         printf("%d", a[i]);     printf("\n");     */     return len; }

百度 c语言 大数四则运算

输入的位数很大，肯定是字符串形式输入的12345格式。 最朴素的实现方法：模拟人工计算加法，从个位开始做个位数的加法，同时用一个变量记录进位。循环到最高位即可（字符串短的前面补字符0）。 不是很难的。 关键点在于字符相加 比如 ‘1‘+’2‘，操作是 ’1‘-’0‘+’2‘-’0‘，得出的是数值，判断是否大于10，大于计算进位，减去10，最后+’0‘把数值转换为数字。

不需要自己造轮子 看这篇，从开源代码中取出来的 http://www.cnblogs.com/youyou/archive/2012/05/13/2498317.html


Question: 大一初学者一个题写错了。。

这个问题得要求输入集合的个数和集合本身吧？ 没有看到相关的代码啊。

楼上思路没错，可以再加些判断优化一下： 1. 判断A[i] != A[j] 2.最大和不超过X，例如10

我的思路是先用快排排一下，然后嵌套循环两两相加每当和大于最大数就退出循环，比较过程中可以从上次找到的点往后找，应该能快一点

int sum=0; int count=0;//记录好数对的个数 int A[10]={1,2,3,4,5,6,7,8,9,10};//给定的集合 for(int i=0;i++;i<10) { for(int j=i+1;j++;j<10) { sum=A[i]+A[j] for(int n=j+1;n++;n<10) { if(sum==A[n]) count++; } } } cout<<"好数对的个数为："<<count<<endl   应该是这样的，我没有运行，思路是这样的，有错你可以改一下。


Question: c语言中有单例模式么？单例的演化模式 是否为，单线程--多线程--分布式

引用 16 楼 wangyaninglm 的回复: typedef int *SINGLETON;   /* 定义自己的类型 */ SINGLETON *singleton = NULL; pthread_mutex_t singleton_lock=PTHREAD_MUTEX_INITIALIZER; SINGLETON *init_singleton(void) {     pthread_mutex_lock(&singleton_lock);     if (NULL == singleton)     {         singleton = calloc(1, sizeof(SINGLETON));         if (NULL == singleton)         {             pthread_mutex_unlock(&singleton_lock);             return NULL;         }         /*  SINGLETON 初始化 */     }     pthread_mutex_unlock(&singleton_lock);     return  singleton; }   单例适用场景：    在模块化设计时，应该遵循耦合度越低越好，但是总是存在一些公共的调用函数库或者模块，这些公共的调用函数库或者模块有以下几个特点： 1、需要被其他的模块使用 2、其他模块之间并不知道对方使用会去调用或者初始化 3、公共的调用函数库或者模块却希望在整个系统中初始化一次。 这种模块其实也很常见，     比如：线程池(整个系统希望只有那么线程，其他模块不能线程)。 再比如：内存池，整个系统中只能存在这么一个内存池。

引用 14 楼 zjq9931 的回复:[quote=引用 13 楼 zjq9931 的回复:] [quote=引用 12 楼 wangyaninglm 的回复:] 全局唯一id和单例模式的区别联系是啥？ 全局唯一Id和单例模式的相同点：全局只操作一个实例。 全局唯一Id是全局可见的，任意一个地方都可以修改。单利模式不是全局可见，要想操作必须先通过获取语句来获取。 多线程的时候同步封装，单例模式相对的比较容易实现封装。 全局唯一Id只能通过制度来规定唯一性，不能通过编译器来限定唯一性。单例模式是通过编译器来限定唯一性的。 构造函数私有，构造对象为static类型，只能有一个。  [/quote] 说的不全或者有问题的地方，请指正。[/quote]  http://blog.csdn.net/wangyaninglm/article/details/78658318  找到一些资料，未完待续

引用 13 楼 zjq9931 的回复:[quote=引用 12 楼 wangyaninglm 的回复:] 全局唯一id和单例模式的区别联系是啥？ 全局唯一Id和单例模式的相同点：全局只操作一个实例。 全局唯一Id是全局可见的，任意一个地方都可以修改。单利模式不是全局可见，要想操作必须先通过获取语句来获取。 多线程的时候同步封装，单例模式相对的比较容易实现封装。 全局唯一Id只能通过制度来规定唯一性，不能通过编译器来限定唯一性。单例模式是通过编译器来限定唯一性的。 构造函数私有，构造对象为static类型，只能有一个。  [/quote] 说的不全或者有问题的地方，请指正。

引用 12 楼 wangyaninglm 的回复:全局唯一id和单例模式的区别联系是啥？ 全局唯一Id和单例模式的相同点：全局只操作一个实例。 全局唯一Id是全局可见的，任意一个地方都可以修改。单利模式不是全局可见，要想操作必须先通过获取语句来获取。 多线程的时候同步封装，单例模式相对的比较容易实现封装。 全局唯一Id只能通过制度来规定唯一性，不能通过编译器来限定唯一性。单例模式是通过编译器来限定唯一性的。 构造函数私有，构造对象为static类型，只能有一个。

离开操作系统，不要谈单例模式。 《Windows核心编程》

引用 8 楼 zjq9931 的回复:引用 4 楼 wangyaninglm 的回复:c里面搞出个单例，干什么用呢？ 单例模式，我个人认为就是全局变量的一种优雅的实现方式。 可以通过一个函数获取到一个实例的指针，或者引用。[/quote] 当然我说的很片面，单例模式有很多全局变量所没有的优点，比如封装同步等等很多优点。 https://www.cnblogs.com/xiangshancuizhu/archive/2012/11/03/2752156.html http://blog.csdn.net/ozdazm/article/details/8538014

引用 4 楼 wangyaninglm 的回复:c里面搞出个单例，干什么用呢？ [/quote] 单例模式，我个人认为就是全局变量的一种优雅的实现方式。 可以通过一个函数获取到一个实例的指针，或者引用。

全局唯一id和单例模式的区别联系是啥？     引用 10 楼 cfjtaishan 的回复:没怎么研究过单例模式，可以参考一下别人的：  http://cantellow.iteye.com/blog/838473 https://baike.baidu.com/item/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/5946627?fr=aladdin http://blog.chinaunix.net/uid-22291256-id-3486413.html 引用 8 楼 zjq9931 的回复:引用 4 楼 wangyaninglm 的回复:c里面搞出个单例，干什么用呢？ 单例模式，我个人认为就是全局变量的一种优雅的实现方式。 可以通过一个函数获取到一个实例的指针，或者引用。[/quote]

看你的问题，让我想起了马大师关于臭虫药的相声

引用 6 楼 hdt 的回复:看你的问题，让我想起了马大师关于臭虫药的相声why

引用 1 楼 user-6 的回复:单例模式是设计模式里的概念，是独立于语言的，很多语言都可以实现单例模式，C语言也可以，只是优雅程度不高 单例模式是限制只生成一个实例，单线程--多线程--分布式是另外的概念  单线程--多线程--分布式 应该有自己对应的单例实现

引用 2 楼 hdt 的回复:c里面搞出个单例，干什么用呢？

看过一个单例模式的写法 核心是使用锁实现多线程同步， 使用barrier()或者volatile，防止编译时内存乱序访问

c里面搞出个单例，干什么用呢？


Question: 求大神看看哪里不对

#include<stdio.h> #include<string.h>  void exchange(char*p1,char*p2,char*p3); int main() {     char a[32],b[32],c[32],*p1,*p2,*p3;     p1=a;p2=b;p3=c;     printf("原字符串:\n");     scanf("%s%s%s", a, b, c);     exchange(p1,p2,p3);     printf("排序后字符串:%s %s %s\n",a,b,c);     return 0; } char swap(char*p1,char*p2);  void exchange(char*p1,char*p2,char*p3) {     if(strcmp(p1, p2)>0) swap(p1,p2);     if(strcmp(p1,p3)>0) swap(p1,p3);     if(strcmp(p2,p3)>0) swap(p2,p3); } char swap(char *p1, char *p2) {     char t[32];     strcpy(t, p1);     strcpy(p1, p2);     strcpy(p2, t); }  字符串的含义还需要学习一下，基础知识还需要加强呢

感觉楼主指针没有搞清楚，《深入理解C指针》这本书可以参考一下。


Question: 关于c语言变量的内存分配问题

引用 1 楼 athbss 的回复://getstring1(),   getstring2()  一样的意思  //这里我要说的是：p1指针指向的是文字常量区，并不是全局区，并且你返回的是一个函数的局部变量 //p1本身的地址是被弹栈了，但是它所指向的a的地址，还是存在的， //所以返回的是一个存在文字常量区的内容，至于为什么地址相同，是因为指针指向的都是文字常量区的a的地址。  char * func_1() {     char buff[3] = "ac";     return buff; } //func_1()这里使用的是一个数组，是在栈中开辟空间来存放ac和‘\0’的，函数一旦调用结束， //就会释放这个函数的栈区空间，你再返回他的地址，所对应的内容，就会出错。结果是一个未知，可能是正确，也可能是错误的。 十分感谢！明白了


Question: 运行崩溃的问题

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

if((fp=fopen("pic.h","r")==NULL)),逻辑运算大于赋值晕算，所以你这句话的意思是把bool量给了fp，改成if((fp=fopen("pic.h","r"))==NULL),就好了。  #include <iostream>  unsigned char buffer[153600]; int main(void) { 	unsigned long int i,j; 	unsigned char k; 	FILE *fp,*fp1; 	fp=fopen("pic.h","r"); 	if((fp=fopen("pic.h","r"))==NULL) 	{ 		printf("cannot open file!"); 		exit(0); 	} 	if((fp1=fopen("picture.bin","wb"))==NULL) 	{ 		printf("cannot open file!"); 		exit(0); 	} 	fscanf(fp,"%d,",&k);                                        //运行到这就死了 	printf("ok"); 	fscanf(fp,"%c,",&buffer[0]); 	printf("\nok1"); 	for(i=0;i<5400;i++) 	{ 		for(j=0;j<15;j++) 		{ 			fscanf(fp,"%c,",&buffer[i*16+j]); 			printf("%c",buffer[i*16+j]); 		} 		fscanf(fp,"%c,\n",&buffer[i*16+15]); 		printf("%c\n",buffer[i*16+15]); 	}  	fclose(fp);  	fwrite(&buffer,86400,1,fp1); 	fclose(fp1); }

if((fp=fopen("pic.h","r")==NULL)) 改成 if((fp=fopen("pic.h","r"))==NULL) 后面一个也是

%c也不对，照样崩溃

k 对应的应该是 %c


Question: 新手初学，if else问题求教...

if else if 后面的的if只有当前面的if不满足才执行

Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt

你怎么知道没有执行呢？最后不是有 Height=Height; 吗？估计这一句执行了，但是没什么变化啊。你输入的时候不用空格隔开输入项试试

就是只执行判断sex的那组if-else 后面的if-else if-else if-else不执行，不知道为啥。。。

是f9和f5吗？我的是阉割版，设断点就停止运行...emmm不想重新下载了，不过还是谢谢。

自己设置几个断点调试一下


Question: 求解一个关于鞍点的题，非常感谢

#include <stdio.h> #include <stdlib.h> #include <time.h>  #define ROW 4 #define COL 5   void init_array(int (*array)[COL], int row, int col) {     int i, j;      srand(time(NULL));     for (i = 0; i < row; i++)         for (j = 0; j < col; j++)             array[i][j] = rand() % 100; }   void show_array(int (*array)[COL], int row, int col) {     int i, j;      for (i = 0; i < row; i++) {         for (j = 0; j < col; j++)             printf("%2d ", array[i][j]);         putchar(10);     } }  void check_saddle_point(int (*point)[2], int (*array)[COL], int row, int col) {     int i, j, k, cnt = 0;     int row_idx, col_idx;     int max_row, min_col;      for (i = 0; i < row; i++) {         max_row = array[i][0];         col_idx = 0;         /* find max value in row */         for (j = 1; j < COL; j++)             if (max_row < array[i][j]) {                 max_row = array[i][j];                 col_idx = j;             }          /* Find min value in col */         min_col = array[i][col_idx];         row_idx = i;         for (k = 0; k < row; k++)             if (min_col > array[k][col_idx]) {                 min_col = array[k][col_idx];                 row_idx = k;             }         /* Check the condition*/         if (row_idx == i && min_col == max_row) {             point[cnt][0] = row_idx;             point[cnt][1] = col_idx;             cnt++;         }      } }  void init_point_array(int (*point)[2], int row) {     int i, j;      for (i = 0; i < row; i++)         for (j = 0; j < 2; j++)             point[i][j] = -1; }  void show_saddle_point(int (*point)[2], int (*array)[COL], int row) {     int i, row_idx, col_idx;      for (i = 0; i < row; i++) {         row_idx = point[i][0];         col_idx = point[i][1];         if (row_idx >= 0 && col_idx >= 0)             printf("鞍点为array[%d][%d] = %d\n", row_idx, col_idx, array[row_idx][col_idx]);     } }  int main(void) {     int array[ROW][COL];     int point[ROW][2];      init_array(array, ROW, COL);     init_point_array(point, ROW);     show_array(array, ROW, COL);     check_saddle_point(point, array, ROW, COL);     show_saddle_point(point, array, ROW);      return 0; } 求鞍点，参考一下吧； 可以在这个基础改一下，鞍点的检查已经有了。

这样总是会多出一行输出结果，不知道是什么原因，求指教，谢谢

改了N次还是会多输出一个No

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


Question: 谁能解释一下下面的代码？

引用 6 楼 郁闷星期三的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 首先需要了解的是a和&a的区别； a是数组名，也是数组的首地址，类型是int *； &a是数组的地址，这个地址值和a的地址值是一样的，因为都指向同一个地址；但&a的类型是int (*)[5];即&a是5个元素为单位的地址； 所以a+1是向后偏移一个int类型长度的地址，即元素2的地址； &a+1是向后偏移5 * sizeof(int)长度。 了解这些就基本上能理解输出的结果了。  p-1是向后偏移一个sizeof(int)个字节，因为p的类型是int *  你看我打印(int *)(&a +1) 的地址是 0x0018ff35 这个这个地址明显不是5*sizeof(int)的[/quote] 在我这不会，它的值应该是要和p是一样的

输出是2和5，数组名a退化为指针后是int*类型，+1移动1个int距离，&a是int(*)[5]类型，+1移动的是一个数组的大小

引用 2 楼 cfjtaishan 的回复:首先需要了解的是a和&a的区别； a是数组名，也是数组的首地址，类型是int *； &a是数组的地址，这个地址值和a的地址值是一样的，因为都指向同一个地址；但&a的类型是int (*)[5];即&a是5个元素为单位的地址； 所以a+1是向后偏移一个int类型长度的地址，即元素2的地址； &a+1是向后偏移5 * sizeof(int)长度。 了解这些就基本上能理解输出的结果了。  p-1是向后偏移一个sizeof(int)个字节，因为p的类型是int *  你看我打印(int *)(&a +1) 的地址是 0x0018ff35 这个这个地址明显不是5*sizeof(int)的

*(a+1)=a[0+1]; *(p-1)=*((int *)(&a +1)-1)=(a数组的地址后加一个int地址再减掉一个int地址最后指向a[4]) =a[4];

引用 2 楼 cfjtaishan 的回复:首先需要了解的是a和&a的区别； a是数组名，也是数组的首地址，类型是int *； &a是数组的地址，这个地址值和a的地址值是一样的，因为都指向同一个地址；但&a的类型是int (*)[5];即&a是5个元素为单位的地址； 所以a+1是向后偏移一个int类型长度的地址，即元素2的地址； &a+1是向后偏移5 * sizeof(int)长度。 了解这些就基本上能理解输出的结果了。  p-1是向后偏移一个sizeof(int)个字节，因为p的类型是int * 谢谢谢谢！

这种题目锻炼C语言的细节理解，虽然实际项目中不推荐这么写。


Question: 各位大神看看啦，这是我自己写的一个关于加减乘除的小程序，出了点小问题。

引用 3 楼 paschen 的回复:a + b == c 改成 a + b - c < 0.0001   同理其他，否则可能因存储精度问题导致判断为不相等 需要加上绝对值即fabs(a+b-c) < 1e-6;

比较两个浮点数是否相等，可以用两个数差值的绝对值小于等于某个精度值，比如 abs(x-y)<=1e-6 类似这样。

去掉一个=就有error了。。。。。

float精度有限 建议不要用==判断两个数是否相等 而是两数相减小于0.001或者其它 就判断其相等


Question: C语言 求问每一项指针指向哪？//后为输出的值

把 iArray数组想象成5个连续的方块，指针p就像方块的标签，原来p指向第0个方块，++p，指向的就是第一个方块，（p+2）就指向的第3个方块。 注意方块是从0开始数。

建议自己测试一下，想了解指针的指向情况，建议%p打印出地址出来；分析需要一些时间，但是如果通过自己的动手分析到原因，这样的结果自己能学到更多。

闲的没事干，给你说一下吧。 int main() { 	int iArray[] = { 1,2,3,4,5 }; 	int *p = NULL;  	p = iArray; 	printf("%d", p[0]);//1       指向第一个元素，没问题吧 	printf("%d", *(++p));//2     P指向第二个 	printf("%d", *(p + 2));//4   指针P依然指向第二个，没有变化 	printf("%d", *(p--));//2     P在这一句之后指向第一个元素，也就是1 	printf("%d", *p++);//1       p指向没有变化，第一个元素在此句后加一 	printf("%d", *p);//2         P指向第一个，现在iArray[0]=2 	printf("%d", ++(*p));//3     指向第二个 	printf("%d", *p);//3         指向第二个 	system("pause"); 	return 0; }  自己还是多想想，推荐看《C和指针》

计算机组成原理→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 http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

就是不是很清楚

只有自加自减会改变p的值 分清前++ 和 后++的区别即可


Question: 求大佬解疑，怎么解决这个问题呢

你可以新建一个项目，把代码放到项目里的源文件，然后就可以编译了。不过好像再编译一次又会这样。或者你也可以关掉dev再开。

在D盘建一个目录来保存源代码项目。

换个路径?     以管理员身份运行试试 关闭杀毒软件 重启电脑 重装软件 换个编译器


Question: 算法的时间复杂度与CPU速度

引用 3 楼 m0_37605715 的回复:引用 1 楼 iloveyou418 的回复:因为原来要1000秒的程序现在只需要10s就是后者的100倍原来要1000秒误会写成1000000秒的程序-cpu提升100倍就是10*10=100s原来需要1000秒现在需要100s不就是10倍喽接着还有还有一段话“也就是说，一台老式CPU计算机运行O（n）的程序，和一台速度提高一百倍新式CPU运行O（n^2）的程序，最终胜利方却是老式CPU的计算机。”照你的推论，这段话肯定不成立！！！查阅渐近分析法的大O符号表示，可知：当n趋近于无穷大时     n^2>(n^2)/100>n>n/100 ，n是(n^2)/100的10倍，当且仅当n=10时才成立。这样才解释得通，最后还是谢谢你的回答！  不好意思，之前回答的比较随意，它说的意思实际是：在o(n)下速度提高100倍速对应于o(n*n)下只提高了10倍，而正如你所说，当n越大，o(n)与o(n*n)相差的倍数也就越多，故老式机器运行o(n)肯定获胜

引用 2 楼 paschen 的回复:楼上已经说了，就一个简单的计算 兄弟，谢谢你的回答，不过你可以看看我下面的解释，那个应该才是正确的。

引用 1 楼 iloveyou418 的回复:因为原来要1000秒的程序现在只需要10s就是后者的100倍  原来要1000秒误会写成1000000秒的程序-cpu提升100倍就是10*10=100s 原来需要1000秒现在需要100s不就是10倍喽  接着还有还有一段话“也就是说，一台老式CPU计算机运行O（n）的程序，和一台速度提高一百倍新式CPU运行O（n^2）的程序，最终胜利方却是老式CPU的计算机。” 照你的推论，这段话肯定不成立！！！查阅渐近分析法的大O符号表示，可知：当n趋近于无穷大时     n^2>(n^2)/100>n>n/100 ，n是(n^2)/100的10倍，当且仅当n=10时才成立。这样才解释得通，最后还是谢谢你的回答！

楼上已经说了，就一个简单的计算


Question: 编写一个程序，从键盘输入一个长整数m，计算m各位数的和

万一m是一个10000000000000000000000000位的长——整数呢？

while(a=0)   //

#include <stdio.h> int main() {     unsigned long a;     int k = 0;      printf("Please input a:");     scanf("%lu", &a);      while (a) {         k = a % 10 + k;         a = a/10;     }      printf("%d\n", k);     return 0; } 参考一下吧

这个论坛大牛真多

k未赋予初始值０；

引用 11 楼 binaryhead 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] 在现实世界中，除时间和空间可能是无限的以外，其它任何事物都是有限的。 没那么绝对吧，圆周率pi就是无限不循环数字[/quote] π是现实世界中的东东吗？现实世界存在无瑕疵的圆或球吗？

引用 10 楼 zhao4zhong1 的回复:在现实世界中，除时间和空间可能是无限的以外，其它任何事物都是有限的。 没那么绝对吧，圆周率pi就是无限不循环数字

在现实世界中，除时间和空间可能是无限的以外，其它任何事物都是有限的。

#include <stdio.h>  int main() {   int s = 0; char c;   printf("Please input a number: ");   while (scanf("%c", &c))     if (c > 47 && c < 58) s += c - 48; else       if (c == 10) {printf("%d\n", s); break;} else         {printf("bad input\n"); break;}    return 0; }

k=0,如果数字太大的话也要考虑可行性，比如看成字符串会好点

[size=16px] 1.因为是要求一个串数字的累和，你必须先将k初始化为0; 2.二楼说的没错，循环条件应该是a!=0;但你这程序有Bug,只能对十位数以内的长整数有效；超过十一位就会出错（我举输入十一个1为例）；运行结果如下;   3.下面是我自己的做法，你可以根据自己定义想要的数组长度来满足自己需求: #include<stdio.h> #include<string.h> char a[1001]; //假定这个数字有1000位 int i,m,sum=0; int main() { scanf("%s",&a); //输入字符串a m=strlen(a); //计算a的长度，并将其赋值给m for(i=0;i<m;i++) sum+=a[i]-48; //对数的每一位进行累加 printf("sum=%d\n",sum); //输出最后累加结果 sum return 0; } 运行结果如下; 你可以自己运行看看，有问题可以一起交流哈！

楼上正解  循环条件 a!=0

k没有赋初始值


Question: 求解关于字符串数组的问题

你要在结尾加一个‘\0'

char a[100],b[100]="0"; b的初始化需要注意，这样初始化只是说明b[0] = ‘0’， b[1] = ‘\0'；

#include <stdio.h> #include <stdlib.h> #include <string.h>  int main() {     int i=0,n;     char a[100],b[100]="0";     printf("请输入一串字符：\n");     gets(a);     printf("字符长度为：%d\n",strlen(a));     for(;i<100;i++)         if(a[i]=='\0')         {             n=i;             break;         }     for(i=0;i<n;i++)     {         b[i]=a[n-i-1];     }     // b[n]=a[n];     printf("反向输出的结果是:\n");     //for(i=0;i<100;i++)     for(i=0;i<n;i++)         printf("%c",b[i]);     return 0; } 字符数组输出超过'\0'了，后面的数都是随机值；    //for(i=0;i<100;i++)     for(i=0;i<n;i++) 直接输出有效字符即可；


Question: 绿化软件，如何对租号玩这个软件今夕绿化

感谢楼上的大佬，我做出来了

4. 先执行导入注册表操作，然后开启软件，（大部分的软件，注册表导入后就能使用了）

3. 这个命令可以直接导入注册表，ShellExecute(NULL, _T("open"), _T("Regedit.exe"), _T("/s C://Test.reg"), NULL, NULL);

引用 4 楼 lxuyang210 的回复:2. 软件安装后，找到软件路径，复制一下里面的内容，找个新的文件夹下先存着这一步我早就做了

引用 3 楼 lxuyang210 的回复:1. 一般软件绿化，只要在regedit里面找到对应软件的注册表项，然后右键导出嗯嗯，大佬，然后呢

2. 软件安装后，找到软件路径，复制一下里面的内容，找个新的文件夹下先存着

ISTool 是帮助你创建由 Jordan Russell 制作的 Inno Setup 编译器脚 本的工具。Inno Setup 是一个出色的编译器，即使对于某些专业的安装 制作程序，它唯一的缺点就是它的脚本必须手动编写。  这就是为什么要有 ISTool 的理由。使用该程序，你可以在一个可视化的 环境中编辑 Inno Setup 的脚本，并且创建 Inno Setup 的安装程序脚本 也由此而变得十分简单。  ISTool 支持以下功能: ⑴.支持 Inno Setup 的全部指示 ⑵.拖曳操作。你可以从 Windows 资源管理器中拖曳文件到 ISTool 的文    件区段中 ⑶.使用语法高亮显示脚本 ⑷.大多数区段已完全支持剪贴板的操作 ⑸.保存脚本注释 ⑹.可以导入 Visual Basic .lst 文件与 InstallShield .iwz 文件 ⑺.已经被翻译为多重语言 ============================== 需要2个软件 ISTool调试工具汉化版.exe 安装包制作Innosetup.exe

希望最后的效果是，周末前给需求一个压缩包，解压缩之后就可以使用，或者一个文件夹，复制一下就能用，可以有批处理（解决注册表的问题）


Question: 求大神带队呦

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

VS2015+Windwos10 64位，没看出来有啥子区别

测试过！完全没问题啊·~大佬你说的问题是什么啊？

引用 楼主 qq_41025372 的回复:为什么d=c>0?c:c*(-1);不对，改成d=c>=0?c:c*(-1);就对了？是什么问题，虽然输出的分别是0和-0，但是在计算机中正0与-0没区别啊。。。我在DEV-C++ 5.10中没有出现编译错误，但是在一个网站的提交代码时，却出现错误，当我将>改成>=时，就行了,求解释清楚！！！ 变量c是什么类型，是浮点型吗 原题是什么？发出了看看

d=c>0?c:c*(-1); d=c>=0?c:c*(-1);  这两个表达式的区别不是有没有=号那么简单的， 第一个没有等号，那说明若c为0，则c * (-1) 第二个有等号，那说明c为0时，则是c；  最终d要么是0，要么是-0;没什么区别； 还是看你的代码背景吧

对与不对的依据是什么？

语法上都没有问题，你说的对和不对，指的是什么？

没听说有正0 和负0，看你 C   实际是多少吧

网站的锅


Question: 数据结构和算法的学习时间建议

csdn的一条标语~最没用的是源代码，最有用的是数据结构和算法！

《数据结构（C语言描述）》 《算法精解（C语言描述）》

建议还是继续学C语言，因为基础不牢固直接去学数据结构和算法，那会让你更难受，学不懂； 要想盖高楼，首先需要把地基打牢了。与其求多，不如求精。一步步来，不要着急。学好，用好C语言，没有3~5年学习和运用谈不上精通C语言。

学数据结构吧，这里面其实涉及了算法，常见常用的算法。这个学会了，基本的题你就都能做了。

C语言 --》数据结构 --》算法（《算法导论》）             --》自己做程序训练，解决实际问题而不是刷那种简单的考查语法的题                                      - -》练习数据结构（模式匹配，链表，图， 树，二叉树，排序算法）                                                           --研究更高级算法（分治法、贪心法等） ps：本来不是大神，但学习路径基本这样，修行深浅全在个人

大神出来解答吧


Question: hdoj 巨大数相加 （不知道哪里错了，被wa，求大牛指导）

#include <stdio.h> #include <stdlib.h> #include <string.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */  int main(int argc, char *argv[]) {     char a[1010];     char b[1010];     int  num1[1000];     int  num2[1000];     int  sum[1001];     int  num1_len;     int  num2_len;     int t;     int t1;     int i;     int x;     int y;          scanf("%d",&t);     for(t1=1;t1<=t;t1++)     {         memset(num1,0,sizeof(int)*1001);         memset(num2,0,sizeof(int)*1001);         memset(sum,0,sizeof(int)*1001);         for(i=0;i<1010;i++)         {             a[i]='\0';             b[i]='\0';                                       }                                         //清0          x=0;         scanf("%s %s",a,b);                  num1_len=strlen(a);         num2_len=strlen(b);         for(i=num1_len-1;i>=0;i--)                 {             num1[i]=(int)a[x]-(int)'0';             x++;         }         x=0;         for(i=num2_len-1;i>=0;i--)                    //反序存储          {             num2[i]=(int)b[x]-(int)'0';             x++;         }                  if(num1_len>=num2_len)         {                          for(i=0;i<num1_len;i++)             {                 if(num1[i]+num2[i]+sum[i]>9)                 {                     sum[i]+=num1[i]+num2[i]-10;                     sum[i+1]++;                 }                 else                 {                     sum[i]+=num1[i]+num2[i];                 }             }         }         else         {             for(i=0;i<num2_len;i++)             {                 if(num1[i]+num2[i]+sum[i]>9)                 {                     sum[i]+=num1[i]+num2[i]-10;                     sum[i+1]++;                 }                 else                 {                     sum[i]+=num1[i]+num2[i];                 }             }         }                  printf("Case %d:\n",t1);         printf("%s + %s = ",a,b);         for(i=1000;i>=1;i--)         {             if(sum[1000]==1)             {                 y=1000;                 break;             }                                               if(sum[i]==0 && sum[i-1]!=0)             {                 y=i-1;                 break;             }             if(i-1==0 && sum[i-1]==0 )             {                 printf("%d",0);                 y=-1;                              }                          }                  for(i=y;i>=0;i--)         {             printf("%d",sum[i]);         }         printf("\n");         if(t1!=t)             printf("\n");             }               return 0; }


Question: gcc编译c程序出错，一个简单的结构体指针定义，各位大神看下是哪里有问题啊

在结构体内的指针定义前面把struct加上：struct unsigned char *data;

最终也没搞清楚是哪里的问题，把指针的定义移到结构体外面就没报错了

代码没问题，错误内容是什么

typedef struct { int version;         int width;          unsigned char *data;  } QRcode; 这儿是不是应该定义下名字呢，直接定义别名，那么别名也应该是谁的名字。  试一下这样是否可行： typedef struct recode { int version;         int width;          unsigned char *data;  } QRcode;


Question: 一道c语言题目，请问一下各位大神，以下四道程序各自允许结果是什么？为什么？谢谢le

引用 7 楼 glenshappy 的回复:[quote=引用 1 楼 paschen 的回复:] 依次是4 4 1 0  ~b的值为-4，b&(~b)的值为0  但要注意的是，+的优先级高于&，所以sizeof(t)+b&(~b)是先做+运算，再去做&运算 没大懂啊。。版主，先做+运算，结果为4，然后和-4做与运算，结果为0？不是说输出是4吗？[/quote] 想了一想，突然又懂了

引用 1 楼 paschen 的回复:依次是4 4 1 0  ~b的值为-4，b&(~b)的值为0  但要注意的是，+的优先级高于&，所以sizeof(t)+b&(~b)是先做+运算，再去做&运算 没大懂啊。。版主，先做+运算，结果为4，然后和-4做与运算，结果为0？不是说输出是4吗？

引用 3 楼 cfjtaishan 的回复:[quote=引用 1 楼 paschen 的回复:] 依次是4 4 1 0  ~b的值为-4，b&(~b)的值为0  但要注意的是，+的优先级高于&，所以sizeof(t)+b&(~b)是先做+运算，再去做&运算 b是u32的，~b按位取反后，不会是-4，-4是有符号数； ~b按位取反后，是除第一和第二位位0，其他位（2~31位，从0开始）全位1；[/quote] 我试了一下，确实是的，~b的结果是0Xffff fffb十六进制对应的正整数。。

引用 3 楼 cfjtaishan 的回复:[quote=引用 1 楼 paschen 的回复:] 依次是4 4 1 0  ~b的值为-4，b&(~b)的值为0  但要注意的是，+的优先级高于&，所以sizeof(t)+b&(~b)是先做+运算，再去做&运算 b是u32的，~b按位取反后，不会是-4，-4是有符号数； ~b按位取反后，是除第一和第二位位0，其他位（2~31位，从0开始）全位1；[/quote]  数据在内存中实际是一样的，不必纠结于此，用有符号理解更容易

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

引用 1 楼 paschen 的回复:依次是4 4 1 0  ~b的值为-4，b&(~b)的值为0  但要注意的是，+的优先级高于&，所以sizeof(t)+b&(~b)是先做+运算，再去做&运算 b是u32的，~b按位取反后，不会是-4，-4是有符号数； ~b按位取反后，是除第一和第二位位0，其他位（2~31位，从0开始）全位1；

建议每个程序都运行一遍，然后根据结果挨个分析。注意运算符的优先级；


Question: VS2013用C写串口收发数据，发送数据没问题，然后自己接收奇怪的错误

为啥我运行后啥数据也没有

引用 10 楼 zhao4zhong1 的回复:#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <windows.h> #include <string.h> #include <conio.h> #include "tchar.h"  int main() {     HANDLE hCom1;     hCom1 = CreateFile(_T("COM1"),//COM1口                        GENERIC_READ | GENERIC_WRITE,//允许读和写                        0,//独占方式                        NULL,                        OPEN_EXISTING,//打开而不是创建                        0,//同步方式                        NULL);     if (hCom1 == (HANDLE)-1) {         printf("打开COM失败!\n");         return FALSE;     } else {         printf("COM打开成功！\n");     }     SetupComm(hCom1, 20480, 20480);//输入缓冲区和输出缓冲区的大小都是1024     COMMTIMEOUTS TimeOuts;     //设定读超时     TimeOuts.ReadIntervalTimeout = 1000;     TimeOuts.ReadTotalTimeoutMultiplier = 500;     TimeOuts.ReadTotalTimeoutConstant = 5000;     //设定写超时     TimeOuts.WriteTotalTimeoutMultiplier = 500;     TimeOuts.WriteTotalTimeoutConstant = 2000;     SetCommTimeouts(hCom1, &TimeOuts);//设置超时     DCB dcb1;     GetCommState(hCom1, &dcb1);     dcb1.BaudRate = 115200;//波特率为9600     dcb1.ByteSize = 8;//每个字节有8位     dcb1.Parity = NOPARITY;//无奇偶校验位     dcb1.StopBits = TWOSTOPBITS;//两个停止位     dcb1.fParity = FALSE;     dcb1.fNull = FALSE;     SetCommState(hCom1, &dcb1);     DWORD wCount,n;//读取的字节数     FILE *fp1;     fp1 = fopen("串口发送的数据11.txt", "a+");     unsigned char str[8]; //  PurgeComm(hCom1, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓冲区     n=0;     while (1) {         wCount=8;         if (!ReadFile(hCom1, str, wCount, &wCount, NULL)) {             printf("读串口失败!");             break;         }         for (i = 0; i < wCount; i++) {             fprintf(fp1, "%02X ", str[i]);             printf("%02X ",str[i]);             if (n%16==0) printf("\n %08X - ",n);             if (n%320==0) system("cls");             n++;             printf("%02X ",str[i]);         }         fflush(fp1);     }     fclose(fp1);     CloseHandle(hCom1); } 非常感谢，把wCount改成8就可以了，老师真的非常感谢。祝您工作顺利，天天开心哦！

引用 7 楼 zhao4zhong1 的回复:如果pormon中显示的数据没错而你的程序有错，那就是你接收数据或显示数据出错； 如果pormon中显示的数据也出错，那就是串口参数设置或硬件传输出错。  老师您好，我用串口助手接收到的数据和发送的数据一致没有问题。但是串口助手不能保存全部的数据，所以我还是接收程序的问题，还是上述的问题，把wCount变大一点，还是固定的那四个字节出错，其他没有错误。但是那个wCount只能到24*10，再大就会读串口失败。您能接着帮我指导一下程序中的错误吗？非常感谢！

推荐使用portmon软件辅助调试串口通信程序。

数据线太长？

portmon

引用 5 楼 zhao4zhong1 的回复:portmon更底层，实现了串口抓包。 引用 5 楼 zhao4zhong1 的回复:portmon更底层，实现了串口抓包。那我接收程序可能是哪里出错了呢，固定的错误是怎么回事呢，感谢您的回复

portmon更底层，实现了串口抓包。

引用 2 楼 zhao4zhong1 的回复:推荐使用portmon软件辅助调试串口通信程序。这个串口助手有什么优势吗，我就用的普通的串口助手

引用 1 楼 zhao4zhong1 的回复:数据线太长？跟数据线长度没关吧，我用虚拟串口调试也是一样的错误。我想把读取的数据组弄大点，但是那样就读取失败了，最多能读取多少个字节呢


Question: C语言链表操作集.exe 中的 0x00351699 处有未经处理的异常: 0xC0000005: 读取位置 0xcdcdcdcd 时发生访问冲突

感谢感谢感谢

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

#include <stdio.h> #include <stdlib.h>  typedef struct Snode * PtrToNode;  struct Snode   /*去掉typedef，这儿加了没有意义*/ {     PtrToNode next;     int data; };  typedef PtrToNode List;  List CreateList(List L,int n); void printList(List L);  int main() {     List l,L;     int N;     //l=initial();     printf("请输入链表长度");     scanf("%d",&N);     L=CreateList(l,N);     printf("输出链表");     printList(L); }  List CreateList(List L,int n) {     int i;     List p,temp;      //L = (List)malloc(sizeof(PtrToNode));     L = (List)malloc(sizeof(struct Snode));     L->next = NULL;     temp = L;     for(i=0;i<n;i++)     {         p = (List)malloc(sizeof(struct Snode));         scanf("%d",&(p->data));         temp->next=p;         temp=p;     }     return L; } void printList(List L) {     List r;     r=L->next;     while(r)     {         printf("%d ",r->data);         r=r->next;     } } 参考一下吧； 申请空间时，申请的sizeof大小不对； PtrToNode是struct Snode *类型，即是一个指针，应该申请struct Snode才对； 其他问题，详见代码；

哦，想起来了，本来是写了一个初始链表的函数，后来感觉没什么用就删掉了，没删全，那个初始化的函数可以忽略掉

// 你确定链表创建是这样 L=(List)malloc(sizeof(PtrToNode)); // 而不是 L=(List)malloc(sizeof( struct Snode ));  其他地方再检查细化吧

有一句l=initial()是什么意思？也没见你申明inital函数呀！


Question: 一个小问题求指教

循环退不出来时，中断下来，单步跟踪程序运行，观察程序流程及变量怎么变化，分析原因

代码逻辑不好理解，i, j, k一般都是用于循环变量，这基本上是大家的共识了。如果用于普通变量或者结构体成员，就不很好理解了，代码的可读性就会降低；

引用 5 楼 hdt 的回复:问题多多，那个循环先不说 main函数里调用  CreateSMatrix_OL(&M); 进入到 Status CreateSMatrix_OL(CrossList *M)   /* Create the CrossList M */ {    int m,n,t,i,j,e,k;    OLNode *p,*q;     if(M) free(M);//这里，你把一个指向栈上的指针free掉了 free是对应malloc/realloc/calloc的，除这三个申请的堆上空间，其他方式申请的，不能调用free； 还有问题：  //M->rhead=(OLink*)malloc(sizeof(OLNode)*(m+1));     M->rhead=(OLink*)malloc(sizeof(OLink)*(m+1));     if(!M->rhead)         exit(OVERFLOW);      //M->chead=(OLink*)malloc(sizeof(OLNode)*(n+1));     M->chead=(OLink*)malloc(sizeof(OLink)*(n+1));     if(!M->chead)         exit(OVERFLOW); 申请的空间不对  循环出不去，很可能死循环了，死循环不是在外边的for循环，而应该是内部的循环，内部还有两个循环，建议通过调试打印看一下内部的连个循环那个是死循环；

for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }  输入0,0,0退出循环

然后那个循环呢？

用过单步跟踪。就是未发现

表示觉得没什么问题

积分不够很尴尬


Question: 产生0-9之间的不同的随机数，为什么这种循环两次会出现相同的数字呢？？？求解

引用 19 楼 destory27 的回复:计算机随机数并不是所谓正真的随机数，是根据随机数种子产生的看似随机的东西，如果没有修改随机数种子，那产生的数就一样   和上边回答重了

（伪）随机数的一种实现，mysrand和myrand代码参考VS源代码做了简化：  #include <stdio.h>  unsigned long rand_seed=1;  void mysrand(unsigned int seed) { 	rand_seed=(unsigned long)seed; }  int myrand(void) {  /* rand_seed每次迭代为新的值 */ 	return( ((rand_seed = rand_seed * 214013L             + 2531011L) >> 16) & 0x7fff ); }  int main() { 	int i; //	mysrand((unsigned)time(NULL)); 	for(i=0;i<10;i++) 		printf("%d\t",myrand()%100); 	return 0;	     }

#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main(void) {         srand(time(NULL));     for (int h=0;h<3;h++)     {         int a[5], aa[5] = {0}, i;         for (i = 0;i < 5;)             if (aa[i] == 0)             {                 a[i] = rand() % 10;                 //cout<<"a[i] = "<< a[i]<<endl;                 aa[i]++;                 i++;    //保证每个都能获取一个随机值             }           for (i = 0;i < 5;i++)             cout << a[i] << "," << "\t";         cout<<endl;     }     cout << endl;      return 0; }  若想保证每个数组元素都获得一个随机值，建议将i++放在if判断体内；

随机必然有重复，所谓“不重复的随机”实际上是洗牌。洗牌算法参考下面： #include <stdio.h> #include <stdlib.h> #include <time.h> int d[6]; int i,n,a,b,t; int c,j; void main() {     srand(time(NULL));     printf("shuffle 0..n-1 demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=0;i<n;i++) d[i]=i;/* 填写0～n-1 */             for (i=n;i>0;i--) {/* 打乱0～n-1 */                 a=i-1;b=rand()%i;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=0;i<n;i++) printf("%d",d[i]);             printf("\n");         }     }     printf("shuffle 1..n demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=1;i<=n;i++) d[i]=i;/* 填写1～n */             for (i=n;i>1;i--) {/* 打乱1～n */                 a=i;b=rand()%i+1;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=1;i<=n;i++) printf("%d",d[i]);             printf("\n");         }     } }

/* 保证5次结果的每组3个均不同，并且这5次的结果也应该不同*/  #include <iostream> using namespace std;  void DE(int i) { 	int  aa[100],h = 100,m,x,y,j,k,xr[3];  	for (k=0;k<5;k++)   // 保证5次结果的3组数字都应该不同 	{    	for (m = 0;m<100;m++) 		aa[m] = m;  	for (y = i;y< h - 1;y++)   // 删除第i个元素,这样数组中就没有i元素，可以保证与xr[0]、xr[1]、xr[2]不重复 		aa[y] = aa[y + 1];  		h--;     	for (x = 0;x <3;x++)     //每组3个数组都不应该相同 	{ 		int g = rand() % h; 		xr[x] = aa[g];  		for (y =aa[g] ;y < h - 1;y++)     //删除当前xr[x]元素，保证xr[0]、xr[1]。、xr[2]不相同 			aa[y] = aa[y + 1]; 			h--; 		 	} 	  	for (x = 0;x < 3;x++) 		cout << xr[x] << "," << "\t"; 		cout << endl;  	} } int main(void) { 	for (int h = 0;h < 1;h++)  // 运行3次 		DE(2);      //  调用函数，保证2与产生的每组随机数不一样 	return 0; }  这样还是不行

引用 13楼赵4老师 的回复:[quote=引用 12 楼 iloveyou418 的回复:] 因为计算机不存在真正的随机数，要保证两次出现的不一样需要做srand处理 概念错误！真正的随机是两次出现也有一样的。比如扔硬币这种真正的随机。[/quote]好吧好吧-

其实楼主有空可以找到VS安装目录，查看一下rand和srand的源代码，比较明了。

如果不使用srand()这个函数，直接通过数组标记。每次运行5次，每次的运行结果都不一样，保证5次中的每组三个数字都应该不同，我想想这样编写还是不对。，请大家看看。 #include <iostream> using namespace std;  void DE(int i) { 	int  aa[100],h = 100,m,x,y,j,k,xr[3];  	for (k=0;k<5;k++)   // 保证5次结果的3组数字都应该不同 	{  	for (m = 0;m<100;m++) 		aa[m] = m;  	for (y = i;y< h - 1;y++) 		aa[y] = aa[y + 1];  		h--; 	for (x = 0;x <3;x++)     //每组3个数组都不应该相同 	{ 		int g = rand() % h; 		xr[x] = aa[g];  		for (y = i;y < h - 1;y++)     //剔除 i元素   			aa[y] = aa[y + 1]; 			h--;	 	}   	for (x = 0;x < 3;x++) 		cout << xr[x] << "," << "\t"; 		cout << endl;  	} } int main(void) { 	for (int h = 0;h < 3;h++)  // 运行3次 		DE(2);      //  调用函数，保证2与产生的每组随机数不一样 	return 0; }    计算结果截图  ：

引用 12 楼 iloveyou418 的回复:因为计算机不存在真正的随机数，要保证两次出现的不一样需要做srand处理 概念错误！真正的随机是两次出现也有一样的。比如扔硬币这种真正的随机。

因为计算机不存在真正的随机数，要保证两次出现的不一样需要做srand处理

用例

引用 8 楼 u010165006 的回复:@zhao4zhong1 老赵洗个牌为什么这么复杂？ 自带测试用列而已。

@program_Three3 如果不用srand((unsigned)time(NULL)); 这条语句该怎么操作 —————— 用GetTickCount来初始化随机数种子应该也可以。

@zhao4zhong1 老赵洗个牌为什么这么复杂？

使用rand前需要先调用srand对初始化

如果不用srand((unsigned)time(NULL)); 这条语句该怎么操作，

srand((unsigned)time(NULL)); //用当前时间初始化随机数种子 参考： C++/C语言rand()和srand()函数产生伪随机数 http://blog.163.com/tab_98/blog/static/11924097201772931815266/

先调用srand函数


Question: 关于猜数游戏的小程序。分不多，希望大神能指导指导，应该怎样修改。

#include <stdio.h> #include <stdlib.h> #include <time.h>  int main() {     int a,b;     srand(time(NULL));     a = rand() % 100 + 1;     printf ("请随便输入一个数字，与系统产生的数字进行比较！ :");     scanf ("%d", &b);      while (1) {         if (b > a) {             printf ("您的数字太大啦，请重新输入一个数字！ :");         } else if (b < a) {             printf ("您的数字太小啦，请重新输入一个数字！ :");         } else {             printf ("非常棒，猜对了！ :");             break;         }         scanf ("%d", &b);     }      return 0; }   这个更严谨一些

#include <stdio.h> #include <stdlib.h> #include <time.h> main() {     int a,b;     srand(time(NULL));     a = rand() % 100 + 1;     printf ("请随便输入一个数字，与系统产生的数字进行比较！ :");     scanf ("%d", &b);      while (1) {         if (b > a)             printf ("您的数字太大啦，请重新输入一个数字！ :");         else             printf ("您的数字太小啦，请重新输入一个数字！ :");         scanf ("%d", &b);         if (b == a) {             printf ("非常棒，猜对了！ :");             break;         }     } /*      for (;b > a;)     {         printf ("您的数字太大啦，请重新输入一个数字！ :");         scanf ("%d", &b);         if (b <= a)             break ;     }     for (;b<a;)     {         printf ("您的数字太小啦，请重新输入一个数字！ :");         scanf ("%d", &b);         if (b==a)             printf ("非常棒，猜对了！ :");         break;     }     */     return 0; }   参考一下吧 基本的语法错误就有多个，建议基础只是还要多练习一下

注意for的使用格式，两个分号不能省略

原本好像可以运行的诶，为什么还要把那段加进去呢？

printf ("请随便输入一个数字，与系统产生的数字进行比较！ :"); scanf ("%d", &b); 这些代码放在一个while(1)循环里面，如果相等了break退出循环。

#include <stdio.h> #include <stdlib.h> #include <time.h> main() {     int a,b;     srand(time(NULL));     a = rand() % 100 + 1;     printf ("请随便输入一个数字，与系统产生的数字进行比较！ :");     scanf ("%d", &b);      while (b != a)     {         if (b > a)         {             printf ("您的数字太大啦，请重新输入一个数字！ :");             scanf ("%d", &b);         }         else         {             printf ("您的数字太小啦，请重新输入一个数字！ :");             scanf ("%d", &b);         }     }     printf ("非常棒，猜对了！ :");     return 0; } #include <stdio.h> #include <stdlib.h> #include <time.h> main() {     int a,b;     srand(time(NULL));     a = rand() % 100 + 1;     printf ("请随便输入一个数字，与系统产生的数字进行比较！ :");     scanf ("%d", &b);      while (b != a)     {         if (b > a)         {             printf ("您的数字太大啦，请重新输入一个数字！ :");             scanf ("%d", &b);         }         else         {             printf ("您的数字太小啦，请重新输入一个数字！ :");             scanf ("%d", &b);         }     }     printf ("非常棒，猜对了！ :");     return 0; }

有大神教教小白么。。。