Question: 单向链表排序函数有问题，请大神帮忙看一下！谢谢

供楼主参考  /**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) { val = x; }  * }  */ public class Solution {     public ListNode sortList(ListNode head) {         if ((null == head) || (null == head.next)) {             return head;         }          ListNode[] list = divideList(head);         list[0] = sortList(list[0]);         list[1] = sortList(list[1]);         return mergeList(list[0], list[1]);     }      private ListNode[] divideList(ListNode head) {         ListNode slow = head;         ListNode fast = head;         while ((null != fast.next) && (null != fast.next.next)) {             slow = slow.next;             fast = fast.next.next;         }          ListNode[] list = new ListNode[2];         list[0] = head;         list[1] = slow.next;         slow.next = null;         return list;     }      private ListNode mergeList(ListNode headA, ListNode headB) {         if (null == headA) {             return headB;         } else if (null == headB) {             return headA;         }          ListNode head = null;         ListNode tail = null;         while ((null != headA) && (null != headB)) {             ListNode node = null;             if (headA.val < headB.val) {                 node = headA;                 headA = node.next;             } else {                 node = headB;                 headB = node.next;             }              node.next = null;             if (null == head) {                 head = node;                 tail = node;             } else {                 tail.next = node;                 tail = node;             }         }          if (null != headA) {             tail.next = headA;         } else if (null != headB) {             tail.next = headB;         }          return head;     } }

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

再供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=5;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=5;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         ta=(struct NODE **)malloc(n*sizeof(struct NODE *));         if (NULL==ta) exit(1);         s=head;         for (i=0;i<n;i++) {             ta[i]=s;             s=s->next;         }         head=ta[n-1];         for (i=n-1;i>0;i--) {             ta[i]->next=ta[i-1];         }         ta[0]->next=NULL;         free(ta);     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

为何排序时不用while，或for。而且do while，当 q = p->pNext;= null时，q->data就会崩溃  p->pNext =q->pNext;                 q->pNext = q->pNext->pNext;                 p->pNext->pNext = q;  这是什么意思，楼主你画图看看，是否能达到你要的结果，


Question: 从字符串中提取信息的问题

比如：//有字符串 //1_22_333,,4444__55555,_666666 //需要解析为 //1 //22 //333 //_ //4444 //55555 //666666 #include <stdio.h> char s[]="1_22_333,,4444__55555,_666666"; char c,*p,*p1; int st; void main() {     st=0;     p=s;     while (1) {         c=*p;         if (0==c) {             switch (st) {             case 1:printf("_\n");    break;             case 2:printf("%s\n",p1);break;             }             break;//         }         switch (st) {         case 0:                  if ('_'==c) {                            st=0;}             else if (','==c) {                            st=1;}             else             {p1=p;                       st=2;}         break;         case 1:                  if ('_'==c) {                            st=1;}             else if (','==c) {printf("_\n");              st=1;}             else             {p1=p;                       st=2;}         break;         case 2:                  if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}             else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}             else             {                            st=2;}         break;         }         p++;     } } //1 //22 //333 //_ //4444 //55555 //666666

引用 20 楼 fefe82 的回复:[quote=引用 18 楼 zhao4zhong1 的回复:] 有限状态自动机中可以使用if，可以使用for，可以调用外部函数。  看来我们对有限状态机的理解不太一样。 我说的是数学上的有限状态机，它只包括一个有限的输入符号集，一个有限的状态集，一个起始状态，一个状态转移函数，和一个接受状态集。  它的状态转移函数只能根据输入符号转移到另一个装态。没有循环、没有栈，没有存储。  如果状态转移的时候可以操作一个栈，那个它就变成了下推自动机，对应上下文无关文法。  如果在状态转移的时候还可以做更多的操作，那通常要用一个叫做图灵机的数学模型来描述。图灵机的能力是与现在的计算机的处理能力等价的（忽略量子计算机）。[/quote] 完全同意阁下的观点。 我的意思本来就是很多字符串过滤提取问题用正则表达式很难或根本无法实现，但用《编译原理》中的词法分析和有限状态自动机的思想写一段小程序，就能相对容易地实现。

引用 18 楼 zhao4zhong1 的回复:有限状态自动机中可以使用if，可以使用for，可以调用外部函数。  看来我们对有限状态机的理解不太一样。 我说的是数学上的有限状态机，它只包括一个有限的输入符号集，一个有限的状态集，一个起始状态，一个状态转移函数，和一个接受状态集。  它的状态转移函数只能根据输入符号转移到另一个装态。没有循环、没有栈，没有存储。  如果状态转移的时候可以操作一个栈，那个它就变成了下推自动机，对应上下文无关文法。  如果在状态转移的时候还可以做更多的操作，那通常要用一个叫做图灵机的数学模型来描述。图灵机的能力是与现在的计算机的处理能力等价的（忽略量子计算机）。

可以使用数组。

有限状态自动机中可以使用if，可以使用for，可以调用外部函数。

引用 15 楼 zhao4zhong1 的回复:来个最简单的练练手，请用正则表达式提取出以类似下列格式表示的一组正整数中的最大值： 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001  正则表达式，有限状态自动机，上下文无关文法，下推自动机，他们所能完成的工作很简单，就是判断某一个串是否属于某一种语言。 正则表达式，有限状态自动机 描述的正则语言；上下文无关文法，下推自动机 描述的上下文无关语言。  另外想请问一下，您觉得您用有限状态自动机应该怎么解决这个问题呢？

引用 14 楼 fefe82 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 那你可以试试参照CSV格式的RFC文档，写一个正则表达式用来提取任意符合CSV标准的数据文件中的指定字段的值。  看了一下，RFC4180 是吧，这个正则表达式貌似真的可以描述。  至于取值，使用各种正则扩展出来的取子串的操作应该也是可以做的。[/quote] 2.  Definition of the CSV Format     While there are various specifications and implementations for the    CSV format (for ex. [4], [5], [6] and [7]), there is no formal    specification in existence, which allows for a wide variety of    interpretations of CSV files.  This section documents the format that    seems to be followed by most implementations:     1.  Each record is located on a separate line, delimited by a line        break (CRLF).  For example:         aaa,bbb,ccc CRLF        zzz,yyy,xxx CRLF     2.  The last record in the file may or may not have an ending line        break.  For example:         aaa,bbb,ccc CRLF        zzz,yyy,xxx     3.  There maybe an optional header line appearing as the first line        of the file with the same format as normal record lines.  This        header will contain names corresponding to the fields in the file        and should contain the same number of fields as the records in        the rest of the file (the presence or absence of the header line        should be indicated via the optional "header" parameter of this        MIME type).  For example:         field_name,field_name,field_name CRLF        aaa,bbb,ccc CRLF        zzz,yyy,xxx CRLF  4.  Within the header and each record, there may be one or more     fields, separated by commas.  Each line should contain the same     number of fields throughout the file.  Spaces are considered part     of a field and should not be ignored.  The last field in the     record must not be followed by a comma.  For example:      aaa,bbb,ccc  5.  Each field may or may not be enclosed in double quotes (however     some programs, such as Microsoft Excel, do not use double quotes     at all).  If fields are not enclosed with double quotes, then     double quotes may not appear inside the fields.  For example:      "aaa","bbb","ccc" CRLF     zzz,yyy,xxx  6.  Fields containing line breaks (CRLF), double quotes, and commas     should be enclosed in double-quotes.  For example:      "aaa","b CRLF     bb","ccc" CRLF     zzz,yyy,xxx  7.  If double-quotes are used to enclose fields, then a double-quote     appearing inside a field must be escaped by preceding it with     another double quote.  For example:      "aaa","b""bb","ccc"  The ABNF grammar [2] appears as follows:  file = [header CRLF] record *(CRLF record) [CRLF]  header = name *(COMMA name)  record = field *(COMMA field)  name = field  field = (escaped / non-escaped)  escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE  non-escaped = *TEXTDATA  COMMA = %x2C  CR = %x0D  DQUOTE =  %x22  LF = %x0A  CRLF = CR LF   TEXTDATA =  %x20-21 / %x23-2B / %x2D-7E

引用 11 楼 zhao4zhong1 的回复:那你可以试试参照CSV格式的RFC文档，写一个正则表达式用来提取任意符合CSV标准的数据文件中的指定字段的值。  看了一下，RFC4180 是吧，这个正则表达式貌似真的可以描述。  至于取值，使用各种正则扩展出来的取子串的操作应该也是可以做的。

引用 12 楼 zhao4zhong1 的回复:你还可以试试用正则表达式写一个C语言编译器。  C 语言已经远远超过个有限状态机的表示范围。它的基本语法需要使用上下文无关文法来表示。上下文无关文法需要使用下推自动机(pushdown automata)，有限状态自动机已经无能为力了。

你还可以试试用正则表达式写一个C语言编译器。

引用 9 楼 zhao4zhong1 的回复:谁告诉你“正则表达式和有限状态机是等价的”，把他宰了！  From Wikipedia: https://en.wikipedia.org/wiki/Regular_language  Equivalent formalisms  A regular language satisfies the following equivalent properties:      it is the language of a regular expression (by the above definition)     it is the language accepted by a nondeterministic finite automaton (NFA)[note 1][note 2]     it is the language accepted by a deterministic finite automaton (DFA)[note 3][note 4]     it can be generated by a regular grammar[note 5][note 6]     it is the language accepted by an alternating finite automaton     it can be generated by a prefix grammar     it can be accepted by a read-only Turing machine     it can be defined in monadic second-order logic (Büchi-Elgot-Trakhtenbrot theorem[5])     it is recognized by some finite monoid, meaning it is the preimage of a subset of a finite monoid under a homomorphism from the free monoid on its alphabet[note 7]  Some authors use one of the above properties different from "1." as alternative definition of regular languages.  Notes 1. ⇒ 2. by Thompson's construction algorithm 2. ⇒ 1. by Kleene's algorithm 2. ⇒ 3. by the powerset construction 3. ⇒ 2. since the former definition is stronger than the latter 2. ⇒ 4. see Hopcroft, Ullman (1979), Theorem 9.2, p.219 4. ⇒ 2. see Hopcroft, Ullman (1979), Theorem 9.1, p.218 3. ⇔ 9. by the Myhill–Nerode theorem  当年学自动机的时候前4个的等价性是证过的。

谁告诉你“正则表达式和有限状态机是等价的”，把他宰了！

引用 7 楼 zhao4zhong1 的回复:[quote=引用 6 楼 genghaomail 的回复:] 终极解决方案，boost库的正则表达式 提醒：正则表达式不是万能的；而有限状态自动机是万能的。[/quote]  正则表达式和有限状态机不是等价的嘛 ... 所有可以用有限状态机的表达的语言，都可以找到一个等价的正则表达式。反之亦然。  正则表达式好多是用有限状态机实现的吧。

引用 6 楼 genghaomail 的回复:终极解决方案，boost库的正则表达式 提醒：正则表达式不是万能的；而有限状态自动机是万能的。

终极解决方案，boost库的正则表达式

sscanf(message, "name: %19[^,],age%d", name, &age);

1.2真心快  楼主去了解下sscanf吧 顺便再了解下sprintf

我想说12楼好快。。。


Question: 窗口中标签页和能点击的文字的标识是什么，不是button

这个标签页的元素获取不到阿，还有就是如果我这边程序用了多线程，我在判断环节可以用多进程么？？？

引用 2 楼 lm_whales 的回复:自己的程序中，你可以在消息循环中处理，也可以在窗口的PreTranslateMessage中处理 你是用钩子嘛？钩子的话，钩住消息或者钩住鼠标就可以了 不是钩子，我是想找到所有能点击的元素，然后发一个点击的消息，但是只能获取按钮的，标签页不能获取。

引用 1 楼 hnwyllmm 的回复:楼主你用的啥写的界面？MFC吗？找个MFC的版块问下吧 所有能点击的控件，就是能够接受点击事件或者重载了点击事件的控件了 好吧我去看看


Question: UVA455 水题,然而我总是WA,实在是检查不出来了,各位帮忙看看吧

我的也不行，

#include <iostream> #include <cstring> using namespace std;  int strcmpx(char *str1,int k){ 	int len1=strlen(str1); 	int i; 	for(i=0;i<len1-k;i++){ 			if(str1[i]!=str1[i+k]) 			    return 0;  		} 	return 1; }  int main(int argc, char** argv) { 	int i,n,k=1; 	int len; 	cin>>n; 	char a[n][200]={0}; //	for(i=0;i<n;i++){ //		cin>>a[i]; //	} 	for(i=0;i<n;i++){ 		cin>>a[i]; 		len=strlen(a[i]); 		for(k=1;k<len/2;k++){ 			if(a[i][0] == a[i][k] && (len % k) == 0) 				if (strcmpx(a[i], k) ==1) 	break;	 		} 		if(strcmpx(a[i], k)) 			printf("%d\n",k); 		else 		    printf("%d\n",len); 		if(i!=n-1) 		    cout<<endl; 	} 	return 0; }

谢谢！！！ LZ本来以为还是格式问题，找了好久 谢谢谢谢

LZ程序 对于如下输入不能输出正确结果: aba abca abcda abcdea


Question: 高人请进：1.msgsnd返回小于0会发送成功吗 2.core文件如何确定内存重复释放

不会发送成功，但是msgsnd返回<0的。 内存重复释放一般会打印说double free


Question: 数组和指针之间有什么关系？

指针： 一个地址 数组： 连续存储的 n 个相同类型的元素  在绝大多数情况下，当一个数组类型的变量被使用的时候，会被自动的转换为一个指向数组第一元素的指针。 少数数组变量不会转换的情况包括数组变量出现在 sizeof 运算符后时，等。  数组不能作为函数的参数传递。函数参数位置的数组形式的参数声明，实际上是声明了一个指针。在函数参数位置上，数组形式的声明与指针声明是等价的。

指针可以说是C语言中最核心的东西了，弄懂指针（以及数组）一定能困扰很多人吧。作为过来人，我已经忘记当初是怎么学会指针的，因为那时候先学的C++，之后自己有兴趣再看的C，期间看了汇编，操作系统，以及少量编译知识，综合起来理解指针和数组还是不难的。这个话题要讲清楚，我想至少可以写一本小书了。网上找点资料吧，有一本书叫《The C Puzzle Book》，里面列出了很多编程中容易出错的地方，包括语法，操作符，数组，指针。书很小巧，电子书大约2天就能看完，前半部分全是题目，后半部分全是答案，里面的题目全部做对可以称得上是C语言运用高手了。另外其他的书像《C和指针》和《C专家编程》，我自己没看过，不过豆瓣评价都很高。希望对你有所帮助。


Question: ctrl+c 会导致孤儿进程死了？

不对啊，    centos7里，   ./test.sh   执行后，   ps  -ef | grep test  搜索不到任何东西，说明 ./test.sh已经 结束了。  我对脚本已经彻底无语了。  顺便指出 centos7里，  ps -fe|grep hello.sh也是搜索不到的。 能搜索到的只有./hello

引用 8楼www_adintr_com 的回复:你确定你没看错？  hello.sh    : ./hello  这个脚本是会等待 ./hello 退出后它才退出的，父进程怎么可能会是 test.sh++ 会等到hello退出，这种前台调用方式是堵塞的

问题2：   test.sh    #!/bin/bash  ./hello.sh  while ((1))  do      echo "xxx"  done    exit 0     hello.sh    :  ./hello    hello.c:  int main()  {      while(1)        sleep(3);      return 0;  }    你们实验一下， 惊奇地发现，  hello这个进程 父进程变成了test.sh， 其父进程似乎被修改过了。   /////////////////////////////////////// 请问这个问题如何解答？  父进程似乎不存在过继的概念啊？

nohup 是忽略 SIGHUP 信号, Ctrl + C 发送的是 SIGINT 信号吧

引用 4 楼 adlay 的回复:[quote=引用 3 楼 caddor9100 的回复:] [quote=引用 2 楼 adlay 的回复:] 他们还是属于同一个进程组的吧  1.  除了代码外，用什么法子可以看出 是否属于同一个进程组，  2. 属于谁和谁属于同一个进程组，还有属于同一个进程组怎么了？  感谢你的参与[/quote]  1. 用 ps -o pgid,pid  命令，输出的 PGID 列就是进程组 ID 2. Ctrl + C 会发送给 shell 的前台进程组. [/quote]  你好，  你注意看主楼里的 nohup 进程 &

引用 3 楼 caddor9100 的回复:[quote=引用 2 楼 adlay 的回复:] 他们还是属于同一个进程组的吧  1.  除了代码外，用什么法子可以看出 是否属于同一个进程组，  2. 属于谁和谁属于同一个进程组，还有属于同一个进程组怎么了？  感谢你的参与[/quote]  1. 用 ps -o pgid,pid  命令，输出的 PGID 列就是进程组 ID 2. Ctrl + C 会发送给 shell 的前台进程组.

引用 2 楼 adlay 的回复:他们还是属于同一个进程组的吧  1.  除了代码外，用什么法子可以看出 是否属于同一个进程组，  2. 属于谁和谁属于同一个进程组，还有属于同一个进程组怎么了？  感谢你的参与

他们还是属于同一个进程组的吧


Question: c语言语法问题，求教啊~ 谁能教我一下？谢谢

引用 3 楼 u013790834 的回复:代码意思是开辟一个结构体指针，指向数组，但是却没有开辟空间，这么用是错误的，需要在使用数组之前把数组的大小确定，再使用，使用完毕还要进行内存释放。  我感觉是2楼，3楼的对 ，    这么用指针， 指针肯定指向的一个数组的首地址啊，  不然指向一个变量，这么 操作肯定有问题

A[B] *(A+B) *(B+A) B[A] //以上四行等价  "abc"[1] *("abc"+1) *(1+"abc") 1["abc"] //以上四行等价

引用 3 楼 u013790834 的回复:代码意思是开辟一个结构体指针，指向数组，但是却没有开辟空间，这么用是错误的，需要在使用数组之前把数组的大小确定，再使用，使用完毕还要进行内存释放。你说的不对

3楼净乱说

引用 5 楼 realmardrid 的回复:引用 2 楼 fefe82 的回复:for 之前应该有一句 streams_pool = malloc(sizeof(struct tcp_stream) * max_stream); 才对。为什么要这样用呢？  你的指针要指向一块已分配的空间之后你才可以用啊 ...

求教......


Question: float存在的意义是什么

比如MFC下CString类的Format也是这么做。。

因为printf自动把float提升为double，所以float无意义。 这是什么逻辑？

C语言支持不定参数, 经过这条函数, float会提升到double. 然后就认为float没意义? 有了double, float没意义? 那是不是有了long long, 那long, int, short,... 都没意义了. 民用级别显卡double处理速度远低于float处理速度, 就一个语言特性而已, 记住就行, 不要扯意义什么的.

引用 7 楼 dgwreghwr 的回复:[quote=引用 4 楼 lm_whales 的回复:] ｆloat 小，计算也快 以前的做法是　除了存储外 所有参数传递，乃至数学运算，都是按照提升后的数据类型进行的。 如今，标准里，可以不提升了。 但是printf 这一类　变长参数函数，还是提升后再传入函数的 多谢，那为什么printf这一类函数要这么做？除了printf还有哪些函数也是这么做的？[/quote]  可变参数的 ... 部分都会这么做。

现在double是用%lf了 float占用内存比double少一半啊，试想一个很大的数组或矩阵，不需要很高的精度，用double存就会比float浪费出很多空间 这也好比int与short的关系

printf 是后来人为了输出写的一个函数，只是被做到标准里面去了， 如果它为了方便讲double 都变成float输出的话 ，你觉得double还有意义么？

引用 4 楼 lm_whales 的回复:ｆloat 小，计算也快 以前的做法是　除了存储外 所有参数传递，乃至数学运算，都是按照提升后的数据类型进行的。 如今，标准里，可以不提升了。 但是printf 这一类　变长参数函数，还是提升后再传入函数的 多谢，那为什么printf这一类函数要这么做？除了printf还有哪些函数也是这么做的？

注意open GL 许多数据类型内部，都是用的　float ,不是　double

意义就是它小了, 一般也用不了小数点后几位, 没必要double, 寸有所长吧

比如 float 的大小只有 double 的一半


Question: Linux 信号题 新手求解

void PushBackTable（int sig）是这个,上面写错了

void PushBackTabke() {        ...    //这里插入表的函数        alarm(30*60*60); }   int main() {   signal(SIGALARM, PushBackTable);    alarm(0);    while(1); }  当然你可可以使用settimer来做，那个我就不多写了

引用 3 楼 bsnry的回复:明显定时器啊 给个代码可以嘛。不是很了解定时器

引用 2 楼 羽飞的回复:为毛要用信号，定时器不行吗？ 能给个简单的代码嘛。定时器不是很了解

明显定时器啊

为毛要用信号，定时器不行吗？


Question: c 操作SQL(orcale数据库)

选择A表所有的列 插入B表 这个主要是ＳＱＬ语言，本质上和Ｃ没有关系 如果有需要合并的项，可能需要一些计算 那就先生成一个视图 把需要合并的找出来 合并的按照需要合并 其他直接插入


Question: 为什么使用strcat之后出现堆已损坏错误

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

楼主，你有没有考虑'\0'  pContent = (char *)realloc(pContent, strlen(pContent) + strlen(pStr) + 1);


Question: 红黑树的一个小问题

引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote]  引用 8 楼 fly_dragon_fly 的回复:[quote=引用 6 楼 New_Vest 的回复:] [quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚[/quote] 嗯，确实，把黑点理解成子树的根节点是black就解释通了。。。 正如   引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  引用 7 楼 mxway 的回复:就这张图来说，如果这是一棵红黑树，那么P的左右子树(分别以1和2为根)一定不会为空，并且1,2节点还必须是黑色，这样才能保证以P为根结点子树到叶节点黑色节点等于以U为根节点到叶节点黑色节点数。如果1,2为空，就已经违反了红黑树性质，后面再做插入也就没有意义了。  说的那样。。。多谢，两位，已经差不多理解了！

引用 4 楼 fly_dragon_fly 的回复:你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？

引用 2 楼 hnwyllmm 的回复:楼主说的这个是红黑树旋转前的状态吧，这明显不符合这一条规则： 如果一个结点是红的，则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。  叶子节点不一定是黑色的： 每个叶子结点都带有两个空的黑色结点（被称为黑哨兵），如果一个结点n的只有一个左孩子，那么n的右孩子是一个黑哨兵；如果结点n只有一个右孩子，那么n的左孩子是一个黑哨兵。  只是要求根节点一定是黑色的   引用 3 楼 mxway 的回复:红黑树所有的叶节点都是黑色节点。上图展示的是红黑树出现“不平衡”时的调整过程，没有画完。后面还需要一步以N为根节点的右旋操作，操作后就会出现平衡。    1.A node is either red or black. 2.The root is black. This rule is sometimes omitted. Since the root can always be changed from red to black, but not necessarily vice versa, this rule has little effect on analysis. 3.All leaves (NIL) are black. 4.If a node is red, then both its children are black. 5.Every path from a given node to any of its descendant NIL nodes contains the same number of black nodes. The uniform number of black nodes in the paths from root to leaves is called the black-height of the red–black tree.[14] 以上是维基百科上的给出的红黑树的五性质，第三条不是说叶子节点应该是黑色么， 上图中N节点是新插入节点，抛开这个节点，那么P节点的右孩子也是个叶子节点，是不是应该也是黑色呢？ 如下图， 但是不是说所有叶子节点是黑色么？那么4和5叶子节点为什么不是黑色，如果是黑色，肯定又违背性质5了啊？

要沉了吗、、、、、、

引用 6 楼 New_Vest 的回复:[quote=引用 4 楼 fly_dragon_fly 的回复:] 你这图少了, 两个红结点在一起,显然是演示insert后的fixup, 1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少  这张图就是一张待调整的图，但是我不太明白你说的：“1,2,3,4,5都应该代表子树, 黑色代表子树的根是黑色,也就是无法知道黑高是多少”，能说一下123和45之间的区别么？为什么123是黑色，而45没有画黑色呢？[/quote] 看你引用英语应该来自算法导论, 图肯定不是,上面说的很清楚, 叶子节点(NIL) 就是黑色, 所以反过来,4,5不是叶子,把这些看成子树不就简单了, 图看得确实很奇怪, 直接看算法导论好了,那上面画得很清楚


Question: 父进程向0号进程随便发送一个信号，比如SIGUSR1，怎么该进程的子进程也收到了？？？

好的!谢谢！

If process number 0 is specified, all processes in the current process group shall be signaled. 0是一个特殊的参数，楼主看下手册


Question: c语言编译器第三方库问题

将错误信息中出现的标识符放在百度里面搜一下，看其在哪个.lib中，然后在本地硬盘上搜索该.lib,如果没有，在网上搜索相关库或模块下载安装，然后将其所在目录填写到“附加依赖库所在目录”中，将其名字添加到“附加依赖库”中，重新连接。 VC6： 工程、设置、C/C++、分类：Preprocessor、附加包含路径：填写附加头文件所在目录 逗号间隔多项 工程、设置、Link、分类：Input、附加库路径：填写附加依赖库所在目录 分号间隔多项 工程、设置、Link、分类：Input、对象/库模块：填写附加依赖库的名字.lib 空格间隔多项 VS20xx： 项目、属性、C/C++、附加包含目录：填写附加头文件所在目录 分号间隔多项 项目、属性、链接器、常规、附加库目录：填写附加依赖库所在目录 分号间隔多项 项目、属性、链接器、输入、附加依赖项：填写附加依赖库的名字.lib 空格或分号间隔多项

引用 2 楼 user-3 的回复:我初步解决了上述问题。在我说的那些步骤之后，再在cfree的工程-设置中，找到连接，将几个lib库的名字填写进去，就可以链接通过了。注意两点，1，在构建-构建选项里，有一个一模一样的菜单界面，也有连接，但是在那里设置就不行。2，填写库的名字，不可以带路径，也不可以有后缀，直接填名字才行。  经过上述几步，我链接虽然通过了，可是运行时有问题（不是源代码的问题）。程序会直接结束，直接输出“按任意键继续”，什么也不显示，也不报错。 产生这种情况的必要条件是源代码中有引用xml的库函数。没有引用xml库函数则不会有上述错误。一旦有引用，即便引用的函数根本就没有被main函数调用，也会出现上述问题。  这又是哪里出了问题？怎么会有根本就没被调用的函数也会导致程序运行出错的问题，而且是连main函数第一句都不会执行。 全局变量在main函数之前就初始化，看看哪个全局变数执行初始化时会出错


Question: 关于socket的基本接收问题，求教，哪里不对

建议查MSDN,对照着规范代码学习 先要WSAStartup才能进行其它相关处理

socket服务都没有开启，怎么怎么能进行socket服务呢

1楼说的对，因为http://blog.csdn.net/stpeace/article/details/13279349

sre = socket(AF_INET, SOCK_DGRAM, 0);  这句需要放到   WSAStartup(ver, &WSAData);  之后才行


Question: C语言不知道那里错了，求解

引用 3 楼 NiuloveZhu 的回复:引用一下别人的说法: 加\n是过滤空格、制表符、回车等输入，也就是说 scanf("%d\n", &i); printf("%d\n", i); 你输入一个数后，它是不会立即显示的，要等再接收到一个非（空格、制表符、回车）的输入scanf语句才结束。 然后下一个scanf继续读到这个非空字符，然后把此字符放回队列，不作任何事情，执行下一句

顶起顶起，混人气，

引用 1 楼 NiuloveZhu 的回复:把两个scanf里面的"\n"，去掉就可以了  我在VS上试了下，去掉两个scanf里面的"\n"就可以。 请教下，为啥加上“\n"就不行？？

把两个scanf里面的"\n"，去掉就可以了


Question: lcd12232 实现汉字滚屏 怎么汉字中出现其他汉字啊

结帖怎么结？

把分散一下吧

帮结帖＋蹭分


Question: 求这题的输出结果，笔试题

如果是笔试, 我想出题人要么是不懂,要么是找了个编译器发现在i=0 可能在acNew之后,总之就是无聊

楼上解答的很好 楼主也可以参考下面这两个帖子的问题 http://bbs.csdn.net/topics/390911090 http://bbs.csdn.net/topics/390934607

输出的值是一个随机的数字，这个数字取决于何时遇到'\0'。因为acNew没有初始化，里头是脏数据；而acNew[i]='0';并不是acNew[i]='\0';strlen是遇到'\0'结束 strlen所作的仅仅是一个计数器的工作，它从内存的某个位置（可以是字符串开头，中间某个位置，甚至是某个不确定的内存区域）开始扫描，直到碰到第一个字符串结束符'\0'为止，然后返回计数器值(长度不包含“\0”)。


Question: gcc -l选项必须放在文件名后面吗？关于apue中libapue的问题

引用 3 楼 mymtom 的回复:对于静态库的链接，有顺序要求的，被调用的函数所在的库必须在调用函数所在的模块或库的后面  http://blog.csdn.net/mymtom/article/details/1674184 看来的确是这样的，不知道有没有官方说明。 PS，看兄台的头像也是war3爱好者啊，有空切磋切磋。 +q 20789379

引用 5 楼 zxqatqd 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 我以前遇到过很多次当文件名以数字开头时，被命令行程序解析为option而非filename的意外情况。 试试将文件名用半角双引号括住或将文件名作为第一个参数。 我是了一下，吧文件名加上引号也不起作用，只能是把文件名作为第一个参数[/quote] 两个错别字，"是“ 应为 "试‘, "吧” 应为 "把“

引用 2 楼 zhao4zhong1 的回复:我以前遇到过很多次当文件名以数字开头时，被命令行程序解析为option而非filename的意外情况。 试试将文件名用半角双引号括住或将文件名作为第一个参数。 我是了一下，吧文件名加上引号也不起作用，只能是把文件名作为第一个参数

-L 目录 -I  目录  L = lib I = include

源文件在最前面就行了，其他顺序无所谓


Question: 关于strtok的问题

明白了，谢谢

char *string 与char string[] 的区别 当对这两者字符串处理时，前者字符串本身并不会变，变的只是指针，只有后者才可以改变字符串内容 而strtok()函数会改变原字符串， 所以用前者错误，后者正确

指针也可以的，但是你要给它动态分配内存。


Question: C语言二叉树非递归遍历问题

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

但是这个真的没办法调试。。。。

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

#include"stdio.h" #include"stdlib.h" #include"string.h"  #define OK 1 #define ERROR 0 #define OVERFLOW -1 typedef char TElemType;  typedef struct BiTNode{     TElemType data; 	struct BiTNode *lchild,*rchild; }BiTNode,*BiTree;  typedef int Status; typedef struct LNode{ 	BiTree data; 	struct LNode *next; }LNode; typedef struct{ 	LNode *top; }LStack;  int main(){ 	Status CreateBiTree(BiTree &T); 	Status Pop(LStack &S); 	Status Init_Stack(LStack &S);     Status Push(LStack &S,BiTree T); 	Status StackEmpty(LStack S);     Status PreOrderTraverse(BiTree T);     void visit(TElemType data);      BiTree T; 	printf("创建树中...");     if(CreateBiTree(T)) 		printf("创建成功\n");     PreOrderTraverse(T); 	return 0; }  Status CreateBiTree(BiTree &T){ 	TElemType ch;     if((ch=getchar())=='\n') 		T=NULL; 	else{ 		T=(BiTNode *)malloc(sizeof(BiTNode)); 		if(!T) 			exit(OVERFLOW); 		T->data = ch; 		CreateBiTree(T->lchild); 		CreateBiTree(T->rchild); 	} 	return OK; }  Status Init_Stack(LStack &S){ 	LNode *p; 	p=(LNode *)malloc(sizeof(LNode)); 	if(!p) 		exit(OVERFLOW); 	p->next=NULL; 	S.top=p; 	return OK; }  Status Push(LStack &S,BiTree T){ 	LNode *p; 	p=(LNode *)malloc(sizeof(LNode)); 	if(!p) 		exit(OVERFLOW); 	S.top->data = T; 	p->next = NULL;     S.top = p; 	return OK; }  Status StackEmpty(LStack S){ 	if(S.top->next==NULL) 		return 1; 	else 		return 0; }  void visit(TElemType data){ 	printf("%c\n",data); }  BiTree Pop(LStack &S){ 	BiTree tran; 	LNode *t; 	tran=S.top->data; 	t=S.top; 	S.top=S.top->next; 	free(t); 	return tran; }  Status PreOrderTraverse(BiTree T){     LStack S;     Init_Stack(S);     BiTree p; 	p=T; 	while(p||!(StackEmpty(S))){ 		if(p){ 			Push(S,p); 			visit(p->data); 			p=p->lchild; 		} 		else{ 			p=Pop(S); 			p=p->rchild; 		} 	} 	return OK; }   \ 这是运行结果 ，每次都只能输出ABC.......求教


Question: 求大神指教卡尔曼滤波算法C 程序中的"rinv.c"函数在哪里

这是一本书的实例代码修改而来的程序，rinv.c文件其实是同一本书矩阵求逆函数rinv(double*, int)的代码文件……

兄弟搞定没 能不能教教我


Question: 实参为uint，形参为指针。调用函数问题~~~

谢谢，我明白了。

引用 2 楼 afdlig 的回复:这是发送一组数据进行交互信息，第一个字符数据为\0后面的数据就不会读取了吗？  字符串以\0结尾

那你定义一个uchar*变量把字符串填进去呢？

引用 6 楼 niino 的回复:[quote=引用 4 楼 q3733353520 的回复:] [quote=引用 2 楼 afdlig 的回复:] 这是发送一组数据进行交互信息，第一个字符数据为\0后面的数据就不会读取了吗？  字符串以\0结尾[/quote] 你理解错了，这里并不是对字符串的处理，这是数据[/quote] 数据？编译器不认识，它只知道这是个常量字符串

引用 4 楼 q3733353520 的回复:[quote=引用 2 楼 afdlig 的回复:] 这是发送一组数据进行交互信息，第一个字符数据为\0后面的数据就不会读取了吗？  字符串以\0结尾[/quote] 你理解错了，这里并不是对字符串的处理，这是数据

这个是编译的时候报的错？不是吧，感觉你是想查找某个symbol呢？代码没有什么问题

你那个字符串的开头第一个字符就是\0

引用 1 楼 q3733353520 的回复:你那个字符串的开头第一个字符就是\0 这是发送一组数据进行交互信息，第一个字符数据为\0后面的数据就不会读取了吗？

这是发送一组数据进行交互信息，第一个字符数据为\0后面的数据就不会读取了吗？


Question: 单链表的题目，部分不会，求大神解答，急急急

再供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=5;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=5;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         ta=(struct NODE **)malloc(n*sizeof(struct NODE *));         if (NULL==ta) exit(1);         s=head;         for (i=0;i<n;i++) {             ta[i]=s;             s=s->next;         }         head=ta[n-1];         for (i=n-1;i>0;i--) {             ta[i]->next=ta[i-1];         }         ta[0]->next=NULL;         free(ta);     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

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

不会弄，有例子吗？ 良辰必有重谢

链表创建的时候就可以统计同一作者的书以及高于50的数量了


Question: 一个无意间发现的关于指针的问题？

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

%d用于整型，实型用%f或%e

%d代表的是int类型，而你的参数是一个double类型，数据在内存里面都是0101的二进制，数据类型决定你取数的长度和方式

打印double类型，用%e而不是%d。

printf里面都%d了，能正常吗


Question: C语言参数传递

abc函数改成 void abc(int &e) {e=123;} 主函数中应该是int e=456;

C++还是C  C    引用 5 楼 zhao4zhong1 的回复:#include <stdio.h> #include <stdlib.h>  void abc(int *e) {   *e = 123; }  main() {    auto e=456;    abc(&e);    printf("%d",e); }  ++ 赵老师这个就是 C++ #include <stdio.h> #include <stdlib.h>  void abc(int &e)//改成引用传递 {     e = 123; }  main() {    auto e=456;    abc(e); //引用传递的调用方式和值传递相同    printf("%d",e); }

引用 2 楼 lm_whales 的回复:int abc(int &e);  可以帮忙写一下 具体的程序么？谢谢！

int abc(int &e);

#include <stdio.h> int abc(int e); int main(void) {     int e = 456;          e = abc(e);     printf("%d", e); } int abc(int e) {     int e = 123;     return e; }

要想改变实参的值，必须把实参的指针地址作为函数参数传过去，而不是单单将值传过去。否则实参不会改变。

指针   或者把e设为全局变量

对源代码后缀为.cpp的文件，才默认用C++语法编译。

引用 6 楼 lm_whales 的回复:C++还是C  C    [quote=引用 5 楼 zhao4zhong1 的回复:] #include <stdio.h> #include <stdlib.h>  void abc(int *e) {   *e = 123; }  main() {    auto e=456;    abc(&e);    printf("%d",e); }  ++ 赵老师这个就是 C++ #include <stdio.h> #include <stdlib.h>  void abc(int &e)//改成引用传递 {     e = 123; }  main() {    auto e=456;    abc(e); //引用传递的调用方式和值传递相同    printf("%d",e); }  [/quote]  你的程序有错，不能运行


Question: 大牛们进来看看，A Not allowed system call: runid:64054 :使用了系统禁止的操作系统调用，看看是否越权访问了文件或进程等资源

出现这个报错大部分是访问越界，或者指针的指向有问题。

在WinXP下运行。

北邮的吧，我也出现这个问题

栈这么小, push的时候不会不够吗


Question: 带行指针向量的单链表存储稀疏矩阵

#include <stdio.h> #include <malloc.h> typedef int DataType;  struct LNode//数据结构 {     int col;//列     DataType value;//元素值     struct LNode *next;//指向同行下一个非零结点指针 };  void InArray(struct LNode *row[],int r,int col,int value); void PrintArray(struct LNode *row[]);  int main() {     struct LNode *row[5]= {NULL};      InArray(row,0,0,11);     InArray(row,0,3,14);     InArray(row,0,4,15);     InArray(row,1,1,22);     InArray(row,2,4,35);     InArray(row,4,0,51);     InArray(row,4,2,53);      PrintArray(row);     return 0;//程序退出时，malloc的内存会被操作系统自动回收，所以不用free }  void InArray(struct LNode *row[],int r,int col,int value) {     struct LNode *q,*s;      s=(struct LNode *)malloc(sizeof(struct LNode));     s->col=col;     s->value=value;     s->next=NULL;      if (row[r]==NULL) {         row[r]=s;         return;     } else {         q=row[r];         while (q->next!=NULL) q=q->next;         q->next=s;     } }  void PrintArray(struct LNode *row[]) {     int i,j,value;     struct LNode *q;     for(i=0;i<5;i++) {         for(j=0;j<5;j++) {             q=row[i];             value=0;             while (1) {                 if (q==NULL) break;                 if (q->col==j) {                     value=q->value;                     break;                 } else {                     q=q->next;                 }             }             printf("%4d",value);         }         printf("\n");     } } //  11   0   0  14  15 //   0  22   0   0   0 //   0   0   0   0  35 //   0   0   0   0   0 //  51   0  53   0   0 //

在线等，急用

要实现的打印结果


参数处理时，应该是按照字符串来处理的，虽然你输入了个 ‘h’。 你就按照char*字符串来处理，然后取第一个字符好了。

而参数传递，利用的是提升规则，本质上是语法糖的效果

某些编译器，不能处理，char，short float 则 无论那个编译器都处理不了 因为 val_list,v_start,va_arg,va_end 采用的是宏定义 ，而不是语法糖 的方式实现


Question: 请问数组值传递是否更改原始数组

数组，指针，是不同的。唯一能画等号的，就是数组当参数。看c专家编程，里面有写

没有数组作为参数这种说法 这段代码说的是 数组名是一个地址值，复制到了形参变量（指针类型）中，仍然是值参数 被调函数可以通过这个地址值访问原数组位置的内容 于是原数组中的数据就可以由被调函数修改了 形参尽管写成数组的形式，不能掩盖它是自动的、局部的指针变量的事实 所有形参都是自动局部变量，不可能是什么“栈中的数组” 那本书不仅说错了，而且还装作讲道理的，太误导人了

这里的数组退化成指针了。

byval_func(x);这样实际是将x的地址复制一份（值传递）传递给 byval_func函数，并没有将x的元素值复制。 所以在 byval_func函数中，1. 如果是以x = other_int_array;这样的方式修改，是不会改变函数外x的值的。2. 如果以x[0] = new_int_val;这样的方式修改，会将函数外的x的第一个元素值修改为new_int_val。示意图如下： 原本的x是一个指向int数组的指针: x --> {1, 2, 3, 4, 5}; 调用byval_func(x)函数后，实际是将x作为指针复制一份，假设在byval_func函数内用infunc_x表示，此时两者指向同一块内存，如下： x --> {1, 2, 3, 4, 5};          ^          | infunc_x 如果用第1种方法修改，修改后如下： x --> {1, 2, 3, 4, 5};  infunc_x --> other_int_array 可以看到，实际是将infunc_x指向其他地方，但是原来的x的指向没有变，还是原来的内存。 如果用第2种方法修改，是将infunc_x指向的数组的第一个元素改为其他值，此时如下： x --> {new_int_val, 2, 3, 4, 5};          ^          | infunc_x 可见，此时虽然是通过infunc_x修改的元素值，但是由于infunc_x和x指向的是同一块内存，x数组的值也同时被修改了。

标准数组不可能值传递，除非你用STL中的vector做数组，值传递效率很低

你这个传递不能定义为值传递。

Ｃ,C++ 没有标准数组的值传递方式，数组从来不会整体传递。 Ｃ,C++ 数组参数传递的方式，通常是传递一个指针，这是Ｃ,C++ 通用的 Ｃ++还可以传递数组引用。  顺便说一下，其它语言通常也没有， 通常也是地址传递，或者叫引用传递。 例如　fortran,pascal 等是引用传递　pascal var 参数就是引用传递的，即便非　var,参数，实现上数组也是引用传递的

引用 5 楼 u013356755 的回复:在值传递方式中，数组x将被复制一份，复制所得的数组将被存放在栈中，然后由byval_func()函数接收并打印出来。由于传递给byal_func()函数的是初始数组的一份拷贝，因此在byval_func()函数内部修改传递过来的数组对初始数组没有任何影响。  -----这是书上说的额，  在 C 或 C++ 里，数组都不能作为参数传递。 写成数组形式的参数，实际都是指针。

你的那个参数建议不要写成int i[]这样！ 你不觉得让编译器帮你多做一步对[]的转换好么？ 从i[]转换成*(i) 直接写成int *i 而你问的问题不就知道了！ 形参实参是不同的变量！他不在同一内存中 只是做了简单的复制操作！ 但参数为指针的话！形参与实参所在的地址不同 也就是内存块不同（指针的地址不同）但是指针的值是相同的！ 换句话说编译器重新在栈区申请了一个指针指向同一块内存地址！ 所以不同的是指针自己的地址(&p)不影响指针的值（*p）  看的出来函数参数在这里传送的是地址巧妙的解决的传送数组的低效率方法

其实传入到函数里就只是一个指向数组头的指针了，这样做是为了提高效率，也也是在函数中使用sizeof求数组大小时其实得到的是指针的大小，另在函数内修改数组元素是对外部有影响的，楼主可以自己试一下

我的意思就是以实际运行结果为准。

引用 2 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！的确，书上说的不能更改原始数组，但是在调用函数中修改了数组真的影响到了原始数组，在问是不是这个样子？

printf


Question: C 语言能干啥？来瞅瞅这！

DOS年代的一些C语言高级编程的书里，经常就有简单的BASIC解释器的实现。

学到家了，做系统，做编译器不难啊~

引用 1 楼 zhao4zhong1 的回复:《编译原理》 LEX+YACC Flex+Bison  多谢. 我慢慢消化。。

《编译原理》 LEX+YACC Flex+Bison


Question: c/c++单链表非递减有序表插入x保持单链表有序性 求看程序问题

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  仅供参考://带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //


Question: c/c++合并非递减线性表求看程序哪里出问题

while(LA.data[i]!=NULL)这里有问题, 这个又不是指针,跟NULL比没意义, 就算是当0, Seqlist也没有初始化为0


Question: 关于i++和++i

在C中i++和++i都是右值，不过++的位置会决定一个执行的先后顺序。比如 i=1； n=i++；//n=1 n=++i;//n=2

个人意见不要再研究这些东西了，没什么大用的。

你这样搞纯粹是为了笔试吗，不是的话，没有必要这样搞。

从来不写这样的代码。 尽量把代码写的容易读一点。

为什么这么多人探讨 ++i 或 i++的区别？ 你们在实际工作中的代码有见过几次这种混淆的代码？？ 研究这个有什么具体意义？？？ 有这时间还不如研究下内存，或学习下具体的业务

去看本论坛第一个置顶帖,也就是"http://bbs.csdn.net/topics/370153775"

引用 14 楼 lin5161678 的回复:C++ 才是这样  C语言中 全部都不是左值 你的文件后缀名是什么 .c文件

() [] -> . ++(后缀自增) --(后缀自减) left to right ! ~ ++(前缀自增) --(前缀自减) + - * sizeof(type) right to left 后缀自增的优先级要高

++i 是左值，没有问题 i++ 是右值，也没问题 ++++i; 虽然可以，但是并不好，因为 两次修改 i值。 ++i++ = ++(i++)当然不可以，

++i=5 的问题是两次修改i

C++ 才是这样  C语言中 全部都不是左值 你的文件后缀名是什么

引用 7 楼 CZ_0100001101011010 的回复:C++ primier 第五版，P121 然而以常量为代表的某些左值实际上不能作为赋值语句的左侧运算对象。  (++i)++这样就行了吧 不知道是不是翻译错误，常量是明明白白的右值 用const定义的symbolic constant才是左值

i++是左值绝对没问题 如果++i是右值，那么++i=5也没有逻辑上的错误，也许正向上面说的编译器不允许两次赋值 因为后缀自增比前缀自增优先级高，所以 ++i++要解释为：++(i++)，根据LZ的论据1，显然是行不通的。 lm_whales已经说得很明白了

引用 1 楼 baidu_31809147 的回复:左值一定是变量么？ 不是，左值涉及一个内存位置，左值除开变量还有其他； 但是用const定义的符号常量一定是左值； 变量一定是可修改左值。

C和C++有所不同 C都是右值 C++  前缀左值，后缀右值

引用 22 楼 mujiok2003 的回复:[quote=引用 8 楼 lm_whales 的回复:] ++i=5 的问题是两次修改i  that's not why the c compiler complains. [/quote]明白了

引用 8 楼 lm_whales 的回复:++i=5 的问题是两次修改i  that's not why the c compiler complains.

引用 20 楼 fefe82 的回复:C 与 C++ 是不同的。  14楼/16楼 已经给出了解答。  C / C++ 在细节的地方有很多不同。各位可以想一下自己贴的答案是在说 C 还是 C++（C++ Primer 说的定然的 C++ 而不是 C）  P.S. 这好像是 C语言 区 ...  ++. that's the point.

这个问题的根本原因是编译器对语法树的解析方式，若根据编译理论，将语法树绘制出来以后便可以清晰的知道无法正确编译的原因


Question: 函数参数传递的问题

引用 2 楼 swimmingfish2004 的回复:@user-7 只是单纯探讨为什么？而不讨论是否”有意义“。  那就是对编译器做逆向工程了。

printf 参数里面不要用++   --，参数是可变宏的都不要这样用。写在外部。

这些结果，都是对的，不用解释， 唯一的解释就是你用了语言中，不可控的特性（未定义）， 你不能控制你的程序，在不同（编译器，版本，等等）环境下的行为。

有些东西不同编译器解释方式不同的，还有些东西根据运行时状态结果也不同的

能把无意义的东西，讲出个为什么来的，什么结论推不出来？推出来的结论能让人相信吗？

引用 2 楼 swimmingfish2004 的回复:@user-7 只是单纯探讨为什么？而不讨论是否”有意义“。 唯一的意义就是面试的时候考官可以考你

@user-7 只是单纯探讨为什么？而不讨论是否”有意义“。

看来目前在CSDN算是周经帖. 查看置顶帖"[置顶] [C/C++板块推荐阅读] 关于C,C++表达式求值顺序. [推荐] [ C++ 语言]"


Question: 急！急！C语言菜鸟紧急求助！

week = (year + year / 4 + year / 400 - year / 100 - 1) % 7;//输入year的一月一号是星期几 week = (week + total) % 7;//四月份最后一个星期的天数 day = 7 - week + 8;//五月过完四月份最后一个星期剩余的天数+8（第二个星期日）西方：星期日为一个星期的第一天

week = (year + year / 4 + year / 400 - year / 100 - 1) % 7 算出这一年的一月一日是星期几。计算原理是这样的：公元元年的一月一日是周六，假设不是闰年的话（闰年是年份除4或除400余数为0，除100余数为0不是闰年，比如2000），那么下一年的的一月一日应该是周日，因为一年365天除以7余1，也就是说，如果没有闰年，每年的一月一日是上一年一月一日的星期天数加1，闰年的话要多加一天，year / 4 + year / 400 - year / 100 就是算出元年至今有多少个闰年， 最后得出year这一年的一月一日是周几。 week = (week + total) % 7 就是算出这一年四月最后一个星期的天数。 day = 7 - week + 8 算出五月第二个周日是第几天。


Question: call stack 窗口突然弹出，是什么问题啊

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

引用 1 楼 csdn_mr_l的回复:上面的图片不太清晰。 这两张照片稍微清楚一点 这是上面的图。。。。。。

上面的图片不太清晰。 这两张照片稍微清楚一点


Question: 新人求教！关于不匹配类型转换的问题！

你这不叫类型转换，这叫错误，从数据类型在内存中的存储，这问题有解

闲来无事，你还可以参考printf的源代码比如： C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c

确定参数传递，和不定参数的传递有所不同。 因为C,C++标准修改了确定参数的传递方式。 而不定参数的传递方式没有改变。

printf 仅仅按照 format 串中的格式，匹配其他参数 不匹配就会出错 至于出错成为什么样子，其实和数据长度有关。 注意，不是数据本身的长度，而是压栈的长度。 char,short,int 在传递的时候，都是int float ,double 都是 double

标识%f时printf会按double来读取参数，而参数是个int，是未定义行为

浮点数与整数的内存模型是不同的


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

# include <stdio.h>  void huhuan_1(int , int); void huhuan_2(int *, int *); void huhuan_3(int *, int *);  int main(void) { 	int a = 3; 	int b = 5; 	 	huhuan_3(&a, &b); //huhuan_2(*p, *q); 是错误的, huhuan_2(a, b);也是错误的 	printf("a = %d, b = %d\n", a, b);  	return 0; }  //不能完成互换功能 void huhuan_1(int a, int b) { 	int t;  	t = a; 	a = b; 	b = t;  	return; }  //不能完成互换功能 void huhuan_2(int * p, int * q) { 	int * t;//如果要互换p和q的值，则t必须是int *,不能是int,否则会出错  	t = p; 	p = q; 	q = t; }  //可以完成互换功能 void huhuan_3(int * p, int * q) { 	int t; //如果要互换*p和*q的值, 则t必须定义成int,不能定义成int *, 否则语法出错  	t = *p;  //p是int *,  *p是int 	*p = *q; 	*q = t; }

谢谢大家，我明白了

传值和传地址的问题！

两个输入数字用空格隔开试试。

先不说是否交换了两个数，你输入的根本没有存进去。 问题出在 scanf("%d  %d",&x,&y); 中。 键盘输入的东西由scanf函数转换成十进制整数（注意，整数，int），存入从&x和&y开始的内存中（注意，存入的时候占据int大小的空间），而你实际给准备的内存大小是多少呢？uint8_t x,y; char那么大，于是写入数据时越界了。 结论：scanf中的格式说明一定要与输入项的大小匹配。如果确实要那样输入，可以 uint8_t x,y; int        xx, yy; scanf("%d  %d",&xx,&yy);  x = xx, y = yy;

我用的是啊哈C的软件，谢谢了，我换一个环境试试

void swapdata(uint8_t dat_x,uint8_t dat_y) 参数用引用吧；或者地址，需要改函数体和调用方式。

void swapdata(uint8_t dat_x,uint8_t dat_y) 参数用引用吧，或者地址，需要改函数体。

你这都能改变，那就怪了！ 你只改变了形参的值！ 去看看参数的传递吧！

你在什么环境下运行的，我在vs2010下运行正常。


Question: 一道C语言算法题

懂了，不过二楼还是说错了一点，Q.front->next = p->next ,我调试的时候改了

从程序来看，该queue的头结点应该是个空结点，专门表示头结点，所以实际删除的是第二个。但程序似乎有问题，Q.front=p.next 应该是Q.front=p->next 吧。


Question: C语言使用指针去除字符串中的空格

这个程序效率太低了，遍历一次字符串去掉一个空格，总共要遍历sizeof（字符串）次

谢谢各位， 我也是用的三楼同学的思路，不过是字符串先倒序，再各个单词倒序。  四楼中要另外开辟内存，如果数据量大的话就不太好吧。

#include <ctype.h>  int isspace(int ch);

你那种方法挺麻烦，给个新的思路：  新建另一个字符数组，遍历你之前的字符数组，如果不是空格，就复制到新的数组中

先将每个单词倒过来，即将“I am from shanghai”转换成“I ma morf iahgnahs”，再将整个字符串倒过来变成“shanghai from am I”

char *fun1(char *ptr) {     char *p,*q;     for(p=ptr;*p!='\0';)     {         q=p;         if(*q==' ')         {             while(*q!='\0')             {                 *q=*(q+1);                 q++;             }         }         else               p++;      }     return ptr; }  谢谢，改了一下，这样就可以了。  另外， 将“I am from shanghai”倒置为“shanghai from am I”  我看了一下别人的代码，不太明白它的算法思想，能帮忙解释一下吗？  char *fun2(char *src) {     char temp;     char *start = src, *end = src, *ptr = src;      while(*ptr++ != '\0')     {         if(*ptr == ' ' || *ptr == '\0')         {             end = ptr - 1;             while(start < end)             {                temp = *start;               *start = *end;               *end = temp;               start++;               end--;             }             start = end = ptr + 1;         }     }      start = src;     end = ptr - 2;     while(start < end)     {           temp = *start;           *start = *end;           *end = temp;           start++;           end--;     }     return src; }

用指针p去遍历字符串ptr中所有字符，当遇上空格时，用指针q通过字符串由后向前移一位来覆盖空格，不过这个算法有局限，当连续有两个空格时，就只能删除一个空格


Question: 字符串限制的问题

引用 1 楼 walkiz 的回复:这样数组溢出了，只是由于你的程序比较短小，恰好没有出现问题而已。你可以用更安全的scanf_s函数，另外装5个字符，需要6个字节，C语言的字符串是靠最后的'\0'来结尾的。  你看看你的 最后打印一下 i j 的值，　应该变了，　　越界给覆盖了　 黑客就可以利用这样的漏洞　来玩弄你的程序

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

数组越界的结果是不确定的。  不确定的结果的一种可能就是得到你想得到的结果。但你永远不可能知道什么时候可以得到你想得到的结果。

编译器为了提高程序在cpu中运行效率，在编译程序时，都会做字节码的对齐，int a[5]，它其实不是分配5个空间，有能分配32个空间，所以你数组越界几个字节，不会出错


Question: 大家可以帮我看下是怎么回事么？调试的时候老个有错误

typedef struct cmp  // 是否要加个结构体名 { double _real; //复数的实部 double _imag; //复数的虚部 } cpxNum;         //定义结构体类型cpxNum表示“复数”  printf("请输入第一个复数："); scanf_s("%lf%lf", &c1._real, &c1._imag); //double型输入 //assigna(c1, real, image); print(c1);  printf("请输入第er个复数："); scanf_s("%lf%lf", &c2._real, &c2._imag); //double型输入 //assigna(c2, real, image); print(c2);

至少下面有问题  printf("请输入第一个复数："); scanf_s("%d %d", &c1._real, &c1._imag); //这里 //assigna(c1, real, image); print(c1);  printf("请输入第er个复数："); scanf_s("%d %d", &c2._real, &c2._imag); //这里 //assigna(c2, real, image); print(c2);


Question: 对于无符号整形溢出的理解

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

引用For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they hav e the same representation as, respectively, the types intmax_t and uintmax_t defined in the header <stdint.h>. 167) 也就是说宏定义里的整形被看作intmax_t的，而整形字面量是int的


Question: 数据结构 队列操作 程序段错误

Deque CreateDeque() { Deque queue=(Deque)malloc(sizeof(struct DequeRecord)); PtrToNode head=(PtrToNode)malloc(sizeof(struct Node)); head->Next=NULL; queue->Front=head;  queue->Rear=head; }  并没有返回参数，但是你在main函数中是D = CreateDeque();这么用的


Question: 文本模式写入与读出问题

那是因为用%c读不出回车换行符，你得用二进制方式读写文本文件

fscanf的格式串中有空格的话,就会跳过所有空字符(空格,tab键,回车)

引用 1 楼 ant2012的回复:那是因为用%c读不出回车换行符，你得用二进制方式读写文本文件 不是有写入吗为什么取不出来？那如果我不把回车（stu[i].ch）写入文件，而是在格式说明里面的第一个%s前面加一个空格，第二行的第一个字符（102的1）会变成第一行的最后一个字符？


Question: 请问Window系统自带的ping.exe是那种开发语言编写的？其后台工作原理是？

引用 4 楼 fly_dragon_fly 的回复:ping 是icmp echo, 找这协议看就行了  嗯，谢谢，根据你的提示我找到这篇文章  ICMP协议之ping实现

引用 3 楼 zhao4zhong1 的回复:MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl 先下载安装MSDN98，再参考： MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\PING\PING.C  http://bbs.csdn.net/topics/390374955  谢啦，不过还是网上搜个ping.c文件方便些。  找到这两个源文件：  Apple ping.c Microsoft ping.c  使用了汇编

ping 是icmp echo, 找这协议看就行了

找到两篇文章。  Ping的原理及实现 Ping过程 原理 详解(图)

有源代码了看不懂是自己的问题. 自己要慢慢学习, 就跟一群人问c++怎么开发GUI程序一样, 一步一步来. 域名到ip地址的转换是 gethostbyname. 再底层地点就是操作系统干的事的, 上面只管调用.


Question: 【数据结构】PTA网站上的一个双端队列题

因为 某些编译器，会自动加上返回值， 或者不认为无返回值，是个错误. 最多给个警告，而警告很多时候会被忽略

引用 3 楼 user-1 的回复:1）函数 Deque CreateDeque() 没有返回任何值，显然写错了  大哥真乃神人也！！加了return D;以后直接满分啊！！感激涕零！  现在我唯一的疑问是：为何我没return在自家编译器上还过还能运行了呢？而且没有任何报错呢？  感觉离结贴进了。

从能够运行来看，是它自己加上返回值了，然而都不报告一下，害我纠结了一下午。

1）函数 Deque CreateDeque() 没有返回任何值，显然写错了

这个双端队列分明就是个双向链表啊。 而且持有首尾两个节点。 初始化为首尾皆指向空的头结点。 第一个节点。两个指针皆空。 前后插入数据方式一样，所不同的就是指针处理方式不同

交上去是段错误。


Question: 这个快排程序编译没问题，为什么在运行时自动停止了，求各位大神帮帮忙

下标越界？我猜的

#include <stdio.h> #include <stdlib.h> #include <time.h>  #define size 10  void quicksort(int *a, int left, int right) { 	int f, t; 	int rtemp, ltemp; 	ltemp = left; 	rtemp = right;  	int mid = (left + right) / 2; 	f = a[mid];  	while (ltemp < rtemp) 	{ 		while (a[ltemp] < f) 		{ 			++ltemp; 		} 		while (a[rtemp] > f) 		{ 			--rtemp; 		} 		if (ltemp < rtemp) 		{ 			t = a[ltemp]; 			a[ltemp] = a[rtemp]; 			a[rtemp] = t;  			--rtemp; 			++ltemp; 		} 	}    	if (left < ltemp - 1) 	{ 		quicksort(a, left, ltemp - 1); 	} 	 	if (rtemp + 1 < right) 	{ 		quicksort(a, rtemp + 1, right); 	} 	 	 }  void main() { 	int i; 	int a[size]; 	srand(time(NULL)); 	for (i = 0; i < size; i++) 	{ 		a[i] = rand() % 100; 	} 	printf("排序前：\n"); 	for (i = 0; i < size; i++) 	{ 		printf("%d ", a[i]); 	} 	printf("\n");  	quicksort(a, 0, size - 1); 	printf("排序后：\n"); 	for (i = 0; i < size; i++) 	{ 		printf("%d ", a[i]); 	} 	printf("\n"); }


Question: 如何实现高精度或无限精度的小数位的乘除法

补一句，用浮点数做基本数据结构来表示无限精度，代码太复杂了，还是用整数吧，这样精度的刻度划分是平均的，代码写起来比较容易。计算机运算速度应该要快一些吧？

提供一个算法思路，代码自己写。 我们知道浮点数的精度主要取决于它的尾数部分，如果尾数部分是23位，那么实际上就是在浮点数范围内，取实数的2^23个子集，构成计算机所有能表示的数。 对于某无理数a，假如a的值范围在该子集两个数字B,C之间，那么我们在把这两个数B,C之间的实数再次分为2^23份，然后再进行计算比较，得出a的值在C,D之间，如此循环操作下去，想要多少精度就有多少精度。当然，还要考虑计算机工作时间问题，不可能永远计算下去，差不多就行了吧。。。

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

引用 4 楼 lm_whales 的回复:ＩＥＥＥ754浮点数（数学）协处理器 主要不使用来做　+，-,*,/ 而是用硬件实现了各种数学函数，当然也实现了+，-,*,/

ＩＥＥＥ754

无限精度小数？ 别用浮点数了， 连分式表示就可以了。 理论上所有实数，都可以用连分式，有效的表示出来。 无理数，可以用有限循环连分式表示。  高精度小数，可以用数组表示， 一部分表示整数，一部分表示小数 ， 还可以一部分表示指数， 可以仿照754　表示方法，不过所有浮点运算，要自己设计算法。  浮点运算的效率，各种数学函数的高效实现。 才是问题所在。

这问题都没人回答么？CSDN都烂成这样了？

引用 2 楼 kkyyff2008 的回复:这问题都没人回答么？CSDN都烂成这样了？ 不好意思，让你久等。你问的问题有点难度。 两个整数相除的参考代码如下：   //copyright by x.&.x  #include <stdio.h> #define N 21  void chufa(int bc,int c) { 	int i,j,mod,w,cn=10,res[N]; 	for(i=0;c-cn>0;i++) 		cn*=10; 	for(w=0,mod=1;w<N&&mod!=0;w++) 	{ 		res[w]=bc/c; 		mod=bc%c; 		bc=mod*cn; 	} 	printf("%d.",res[0]); 	if(i==0) 	{ 		for(i=1;i<w;i++) 				printf("%d",res[i]); 	} 	else if(i==1) 	{ 		for(i=1;i<w;i++) 			printf("%02d",res[i]); 	} 	else if(i==2) 	{ 		for(i=1;i<w;i++) 			printf("%03d",res[i]); 	} 	else if(i==3) 	{ 		for(i=1;i<w;i++) 			printf("%04d",res[i]); 	}	         else 	{ 		printf("待续......"); 	} 	printf("\n"); }  int main() { 	int bc,c; 	printf("请输入被除数和除数:"); 	scanf("%d%d",&bc,&c); 	chufa(bc,c); 	return 1; } 希望对你有帮助。 测试部分如下:

自行实现大数逻辑或者借用别人写好的。无限精度是不可能的，不说算，你想想你写出来根号2的小数表示就需要无限长的时间和无限多的纸。


Question: 想请问一下，C语言中的调试可以后退一步吗？感觉只要走错了一步，就回不了头，

vc调试的可以试试拖拽箭头

不可以

为什么要后退一步？想要修改某个变量的值吗？


Question: 求助大神，为什么这段c语言函数是个死循环?

你这个递归函数怎么没有退出的条件啊

全部代码我已经没有了，因为我改过了，改过之后就没有死循环了，但是我只是想知道为什么以前那个函数(就是我发的那个)为什么会陷入死循环,现在全部代码如下  #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<time.h> #include<unistd.h>  //EXO1 //Definir le nombre de ligne standarde #define NB_LIGNES 4  #define random(x) (rand()%x)  void sep() {   puts("*********************************************************************"); }   //EXO2 //Affiher l'etat du jeu void afficher_etat(int tableau[]) {   int i = 0;   while(i<NB_LIGNES)     {       printf("Ligne %d ", i);       int m = 0;       while(m<tableau[i]) 	{ 	  char haha = '|'; 	  printf("%c", haha);  	  ++m; 	}       puts("");       ++i;     } }  //EXO3 //Générer aléatoirement un etat initial de jeu avec à partir d'un entier donne void generer_etat(int n, int tab[NB_LIGNES]) {   //coucou = [0,0,0,0];   int cpt=0;   while(!(cpt==n))     {       srand(clock());       int ligne = random(4);       tab[ligne]++;       cpt++;     }   afficher_etat(tab); }  //EXO4 //Determiner si l'etat actuel est un etat final bool est_un_etat_final(int tableau[NB_LIGNES]) {   int i = 0;   int somme = 0;   while(i<NB_LIGNES)     {       somme += tableau[i];       ++i;     }   if(somme>1)     return 0;   return 1; }  //EXO5 //Determiner si une application est possible sur l'etat du jeu bool est_applicable(int ligne, int nombre, int etat[]) {   return nombre>etat[ligne]?0:1; }  //EXO6 //Effectuer une application sur le jeu n'etant pas fini void appliquer(int ligne, int nombre, int * tableau) {   tableau[ligne] -= nombre; }  //EXO7 //Choisir aleatoirement un nombre de ligne pour effectuer une application int choix_aleatoire_ligne() {   return random(NB_LIGNES); }  //EXO8 //Choisir aleatoirement un nombre d'allumettes a enlever sur une ligne donnee int choix_aleatoire_nb_allum(int ligne, int * coucou) {   return 1+random(coucou[ligne]); }    //EXO9 //Simulation d'une partie void simulation_partie(int n){   int tabh[] = {0,0,0,0};   puts("État initial :");   generer_etat(n, tabh);   sep();   while(!(est_un_etat_final(tabh))) {       int ligne = choix_aleatoire_ligne();       while(tabh[ligne]==0) 	{ 	  srand(clock()); 	  ligne = choix_aleatoire_ligne(); 	}       printf("Linge choisie : %d\n", ligne);       int nombre = choix_aleatoire_nb_allum(ligne, tabh);       printf("Nombre choisi : %d\n", nombre);       appliquer(ligne, nombre, tabh);       afficher_etat(tabh);       sep();   }   puts("Game over ! HAHAHA !"); }    //EXO10 //Tester tous les fonctions deja definies void main() {   double start,finish;   start = clock();      srand(time(0));    puts("");   puts("EXO1");   printf("La valeur de NB_LIGNES est %d\n\n", NB_LIGNES);   sep();      puts("EXO2");   puts("Méthode : afficher_etat");   int t1[] = {1,2,3,4};   afficher_etat(t1);   puts("");   sep();       puts("EXO3");   puts("Méthode : generer_etat");   int tab0[] = {0,0,0,0};   generer_etat(9, tab0);   sep();      puts("EXO4");   puts("Méthode : est_un_etat_final\n");   int tableau1[] = {5,9,8,12};   afficher_etat(tableau1);   printf("\nC'est un état final ? : %s\n\n", est_un_etat_final(tableau1)==1?"oui !":"non !");   int tableau2[] = {0,1,0,0};   afficher_etat(tableau2);   printf("\nC'est un état final ? : %s\n\n", est_un_etat_final(tableau2)==1?"oui !": 	 "non !");   int tableau3[] = {0,0,0,0};   afficher_etat(tableau3);   printf("\nC'est un état final ? : %s\n\n", est_un_etat_final(tableau3)==1?"oui !": 	 "non !");   sep();         puts("EXO5");   puts("Fonction : est_applicable\n");   int tableau4[] = {4,5,6,7};   afficher_etat(tableau4);   printf("\nLinge choisie : 3\n");   printf("Nombre d'allumettes à retirer : 18\n");   printf("Applicable ? : %s\n\n", est_applicable(3, 18, tableau4)==1?"oui !":"non !");   printf("Linge choisie : 1\n");   printf("Nombre d'allumettes à retirer : 2\n");   printf("Applicable ? : %s\n", est_applicable(1, 2, tableau4)==1?"oui !":"non !");   sep();     puts("EXO6");   puts("Fonction : appliquer\n");   int tableau5[] = {4,5,6,7};   puts("Avant appliquer\n");   afficher_etat(tableau5);   printf("\nLingne choisie : 3\n");   printf("Nombre choisi : 3\n");   appliquer(3, 3, tableau5);   puts("\nAprès appliquer");   afficher_etat(tableau5);   sep();   puts("");         puts("EXO10");   simulation_partie(10);       /**   int tabb1[] = {0,0,1,3};   printf("%d\n", est_un_etat_final(tabb1));   int tabb2[] = {0,0,0,1};   printf("%d\n", est_un_etat_final(tabb2));   */    finish = clock();   printf("\nDurée d'exécution du program : %f seconds \n", (finish-start)/CLOCKS_PER_SEC);   }

你倒是把代码上全啊

兄弟你先单步一下看看卡在那里了吧，不然一会赵老师又会说，判断是否有成为程序员....，抄报纸之类的了

引用 2 楼 煦风之伤的回复:你这个递归函数怎么没有退出的条件啊 递归函数，递归调用在那里


Question: 链表头结点

引用 9 楼 lm_whales 的回复:链表有带头结点，和不带的 带头节点的，首节点就是头结点，可以存放长度，等信息，充分利用空间。 也可以不存放数据。 第二个节点才是第一个数据节点 不带头结点的链表，首节点就是第一个数据节点，每个节点都储存数据。  带头节点的链表，比不带的， 处理更方便，更统一。 但是多用一个节点。  恩，现在清楚啦，谢谢你啊~~

引用 7 楼 user-3 的回复:[quote=引用 6 楼 a904235765 的回复:] [quote=引用 4 楼 user-3 的回复:] 链表的头结点该不该存放数据，或者存放什么数据，是灵活的，没有标准，可以根据实际需要来设计。 从你的程序来看，应该是想创建一个链表，链表的长度由用户指定，链表头结点存放链表长度，同时head也指向头结点，并且打印每个结点地址。如果是这样，那程序需要改进： 1. 不需要传入参数head，head直接返回就可以了，如果想通过参数把head返回给caller，则需要定义双重指针，否则无效。 2. while循环体内的scanf("%d",&p1->num)多余的，链表的长度不可能每次创建一个结点都重置。 3. 循环体外的打印也是多余的。 修改程序如下： #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int num; 	node *next; }node;  struct node *creat() { 	struct node *p1 = NULL, *p2 = NULL; 	struct node *head = NULL; 	p1 = p2 = (struct node *)malloc(sizeof(struct node)); 	printf("0: %x\n", p1); 	printf("please enter list's length: "); 	scanf("%d", &p1->num); 	p1->next = NULL; 	int n = p1->num; 	int i = 0; 	while(n--) 	{ 		if(head == NULL) 		{ 			head = p1; 		} 		else 			p2->next = p1; 		p2 = p1; 		p1 = (struct node *)malloc(sizeof(struct node)); 		printf("%d: %x\n", ++i, p1); 		//scanf("%d",&p1->num); 	} 	//printf("p2->next=%d\n", p2->next); 	return head; }  int main() { 	node *n = creat(); 	return 0; }  第一个结点编号是0， 之后每个结点编号从1开始。函数返回head。 return head前要添加一句p2->next=NULL？ [/quote]  抱歉，刚才的程序有bug，首结点没有和后面的结点相连。我重新改了一下代码，简化了一下，把所有打印语句放在函数外面，算是调试。程序能运行。  #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int num; 	node *next; }node;  struct node *creat() { 	struct node *p1 = NULL, *p2 = NULL; 	struct node *head = NULL; 	head = p1 = p2 = (struct node *)malloc(sizeof(struct node)); 	//printf("0: %x\n", p1); 	//printf("please enter list's length: "); 	scanf("%d", &p1->num); 	p1->next = NULL; 	int n = p1->num; 	int i = 0; 	while(n--) 	{ 		/* 		if(head == NULL) 		{ 			head = p1; 		} 		else 			p2->next = p1;*/ 		//p2 = p1; 		p1 = (struct node *)malloc(sizeof(struct node)); 		p1->next = NULL; 		p2->next = p1; 		p2 = p1; 		//printf("%d: %x\n", ++i, p1); 		//scanf("%d",&p1->num); 	} 	//printf("p2->next=%d\n", p2->next); 	return head; }  int main() { 	node *p = creat(); 	int n = 0; 	printf("number of node/address of node/address of next node\n"); 	while(p) 	{ 		printf("     %d            0x%x           %x\n", n++, p, p->next); 		p = p->next; 	} 	return 0; }[/quote] 恩，明白了，谢谢你啊  那么耐心~~

引用 1 楼 lansong4 的回复:看需求是怎样的， 如果程序经常要用到线性表的长度，那么头节点可开个空间存储线性表的长度， 不过在线性表的 添加 和 删除 也要对头节点的长度进行相应的操作。  struct ListNode { ListNode* pNext; int nData; };  struct ListHead {    ListNode* pHead;    int nListLen; }； 那就是说在不需要统计链表的长度时，头结点可以不放数据？ 还有再麻烦你看看这段创建链表的代码： //创建链表 struct node *creat(struct node *head) {     struct node *p1,*p2; 	p1=p2=(struct node *)malloc(sizeof(struct node)); 	printf("%d",p1); 	scanf("%d",&p1->num); 	p1->next=NULL; 	while(p1->num>0) 	{       if(head==NULL) 	  { 	   head=p1; 	  } 	  else 		p2->next=p1;          p2=p1; 	  p1=(struct node *)malloc(sizeof(struct node)); 	  printf("p2=%d",p2); 	  scanf("%d",&p1->num); 	} 	printf("p2->next=%d",p2->next); 	return head; }  	printf("p2->next=%d",p2->next);这一句的输出结果为0，可是在程序中并没有这样的语句啊？输出怎么会是0？

//printf("please enter list's length: ");  注释去掉。

引用 6 楼 a904235765 的回复:[quote=引用 4 楼 user-3 的回复:] 链表的头结点该不该存放数据，或者存放什么数据，是灵活的，没有标准，可以根据实际需要来设计。 从你的程序来看，应该是想创建一个链表，链表的长度由用户指定，链表头结点存放链表长度，同时head也指向头结点，并且打印每个结点地址。如果是这样，那程序需要改进： 1. 不需要传入参数head，head直接返回就可以了，如果想通过参数把head返回给caller，则需要定义双重指针，否则无效。 2. while循环体内的scanf("%d",&p1->num)多余的，链表的长度不可能每次创建一个结点都重置。 3. 循环体外的打印也是多余的。 修改程序如下： #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int num; 	node *next; }node;  struct node *creat() { 	struct node *p1 = NULL, *p2 = NULL; 	struct node *head = NULL; 	p1 = p2 = (struct node *)malloc(sizeof(struct node)); 	printf("0: %x\n", p1); 	printf("please enter list's length: "); 	scanf("%d", &p1->num); 	p1->next = NULL; 	int n = p1->num; 	int i = 0; 	while(n--) 	{ 		if(head == NULL) 		{ 			head = p1; 		} 		else 			p2->next = p1; 		p2 = p1; 		p1 = (struct node *)malloc(sizeof(struct node)); 		printf("%d: %x\n", ++i, p1); 		//scanf("%d",&p1->num); 	} 	//printf("p2->next=%d\n", p2->next); 	return head; }  int main() { 	node *n = creat(); 	return 0; }  第一个结点编号是0， 之后每个结点编号从1开始。函数返回head。 return head前要添加一句p2->next=NULL？ [/quote]  抱歉，刚才的程序有bug，首结点没有和后面的结点相连。我重新改了一下代码，简化了一下，把所有打印语句放在函数外面，算是调试。程序能运行。  #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int num; 	node *next; }node;  struct node *creat() { 	struct node *p1 = NULL, *p2 = NULL; 	struct node *head = NULL; 	head = p1 = p2 = (struct node *)malloc(sizeof(struct node)); 	//printf("0: %x\n", p1); 	//printf("please enter list's length: "); 	scanf("%d", &p1->num); 	p1->next = NULL; 	int n = p1->num; 	int i = 0; 	while(n--) 	{ 		/* 		if(head == NULL) 		{ 			head = p1; 		} 		else 			p2->next = p1;*/ 		//p2 = p1; 		p1 = (struct node *)malloc(sizeof(struct node)); 		p1->next = NULL; 		p2->next = p1; 		p2 = p1; 		//printf("%d: %x\n", ++i, p1); 		//scanf("%d",&p1->num); 	} 	//printf("p2->next=%d\n", p2->next); 	return head; }  int main() { 	node *p = creat(); 	int n = 0; 	printf("number of node/address of node/address of next node\n"); 	while(p) 	{ 		printf("     %d            0x%x           %x\n", n++, p, p->next); 		p = p->next; 	} 	return 0; }

引用 4 楼 user-3 的回复:链表的头结点该不该存放数据，或者存放什么数据，是灵活的，没有标准，可以根据实际需要来设计。 从你的程序来看，应该是想创建一个链表，链表的长度由用户指定，链表头结点存放链表长度，同时head也指向头结点，并且打印每个结点地址。如果是这样，那程序需要改进： 1. 不需要传入参数head，head直接返回就可以了，如果想通过参数把head返回给caller，则需要定义双重指针，否则无效。 2. while循环体内的scanf("%d",&p1->num)多余的，链表的长度不可能每次创建一个结点都重置。 3. 循环体外的打印也是多余的。 修改程序如下： #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int num; 	node *next; }node;  struct node *creat() { 	struct node *p1 = NULL, *p2 = NULL; 	struct node *head = NULL; 	p1 = p2 = (struct node *)malloc(sizeof(struct node)); 	printf("0: %x\n", p1); 	printf("please enter list's length: "); 	scanf("%d", &p1->num); 	p1->next = NULL; 	int n = p1->num; 	int i = 0; 	while(n--) 	{ 		if(head == NULL) 		{ 			head = p1; 		} 		else 			p2->next = p1; 		p2 = p1; 		p1 = (struct node *)malloc(sizeof(struct node)); 		printf("%d: %x\n", ++i, p1); 		//scanf("%d",&p1->num); 	} 	//printf("p2->next=%d\n", p2->next); 	return head; }  int main() { 	node *n = creat(); 	return 0; }  第一个结点编号是0， 之后每个结点编号从1开始。函数返回head。 return head前要添加一句p2->next=NULL？

引用 3 楼 lansong4 的回复:[quote=引用 2 楼 a904235765 的回复:] [quote=引用 1 楼 lansong4 的回复:] 看需求是怎样的， 如果程序经常要用到线性表的长度，那么头节点可开个空间存储线性表的长度， 不过在线性表的 添加 和 删除 也要对头节点的长度进行相应的操作。  struct ListNode { ListNode* pNext; int nData; };  struct ListHead {    ListNode* pHead;    int nListLen; }； 那就是说在不需要统计链表的长度时，头结点可以不放数据？ 还有再麻烦你看看这段创建链表的代码： //创建链表 struct node *creat(struct node *head) {     struct node *p1,*p2; 	p1=p2=(struct node *)malloc(sizeof(struct node)); 	printf("%d",p1); 	scanf("%d",&p1->num); 	p1->next=NULL; 	while(p1->num>0) 	{       if(head==NULL) 	  { 	   head=p1; 	  } 	  else 		p2->next=p1;          p2=p1; 	  p1=(struct node *)malloc(sizeof(struct node)); 	  printf("p2=%d",p2); 	  scanf("%d",&p1->num); 	} 	printf("p2->next=%d",p2->next); 	return head; }  	printf("p2->next=%d",p2->next);这一句的输出结果为0，可是在程序中并没有这样的语句啊？输出怎么会是0？  [/quote] 看需求才觉得是否在头里加数据域。 你这段代码本身就有问题，应该是这样的，NULL的整数值就是0，所以输出是0：  struct node *creat(struct node *head) {     struct node *p1,*p2; 	p1=p2=(struct node *)malloc(sizeof(struct node)); 	printf("%d",p1); 	scanf("%d",&p1->num); 	p1->next=NULL; 	while(p1->num>0) 	{       if(head==NULL) 	  { 	   head=p1; 	  } 	  else 		p2->next=p1;          p2=p1;          p2->next=NULL;//加多这句 	  p1=(struct node *)malloc(sizeof(struct node)); 	  printf("p2=%d",p2); 	  scanf("%d",&p1->num); 	} 	printf("p2->next=%d",p2->next); 	return head; }  	printf("p2->next=%d",p2->next);[/quote] 恩，是要添加这一句的，现在明白了，谢谢你这么耐心的解答~~谢谢

引用 2 楼 a904235765 的回复:[quote=引用 1 楼 lansong4 的回复:] 看需求是怎样的， 如果程序经常要用到线性表的长度，那么头节点可开个空间存储线性表的长度， 不过在线性表的 添加 和 删除 也要对头节点的长度进行相应的操作。  struct ListNode { ListNode* pNext; int nData; };  struct ListHead {    ListNode* pHead;    int nListLen; }； 那就是说在不需要统计链表的长度时，头结点可以不放数据？ 还有再麻烦你看看这段创建链表的代码： //创建链表 struct node *creat(struct node *head) {     struct node *p1,*p2; 	p1=p2=(struct node *)malloc(sizeof(struct node)); 	printf("%d",p1); 	scanf("%d",&p1->num); 	p1->next=NULL; 	while(p1->num>0) 	{       if(head==NULL) 	  { 	   head=p1; 	  } 	  else 		p2->next=p1;          p2=p1; 	  p1=(struct node *)malloc(sizeof(struct node)); 	  printf("p2=%d",p2); 	  scanf("%d",&p1->num); 	} 	printf("p2->next=%d",p2->next); 	return head; }  	printf("p2->next=%d",p2->next);这一句的输出结果为0，可是在程序中并没有这样的语句啊？输出怎么会是0？  [/quote] 看需求才觉得是否在头里加数据域。 你这段代码本身就有问题，应该是这样的，NULL的整数值就是0，所以输出是0：  struct node *creat(struct node *head) {     struct node *p1,*p2; 	p1=p2=(struct node *)malloc(sizeof(struct node)); 	printf("%d",p1); 	scanf("%d",&p1->num); 	p1->next=NULL; 	while(p1->num>0) 	{       if(head==NULL) 	  { 	   head=p1; 	  } 	  else 		p2->next=p1;          p2=p1;          p2->next=NULL;//加多这句 	  p1=(struct node *)malloc(sizeof(struct node)); 	  printf("p2=%d",p2); 	  scanf("%d",&p1->num); 	} 	printf("p2->next=%d",p2->next); 	return head; }  	printf("p2->next=%d",p2->next);