Question: C语言编程练习

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }

不好意思忘了说了，老师要求不能调用系统函数该怎么写啊？


Question: 有了解Chirp Z的编程算法的不？帮我看看下面这个程序？？

百度搜相关关键字。

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


Question: C语言

s[i]就是*(s+i) 数组名s就是指向第一个数据的指针。

s[i] 等价于 *(s + i)

引用 1 楼 zhao4zhong1 的回复:A[B] *(A+B) *(B+A) B[A] //以上四行等价  "abc"[1] *("abc"+1) *(1+"abc") 1["abc"] //以上四行等价  A[0] *(A) 0[A] //以上三行等价   补充：二者区别在于是否分配了内存。

一个是通过下标取值，一个是通过偏移和引用取值。这两种形式功能是一样的。 s[i] 等价于 *(s+i);

因为s+i=&s[i]，两边同时进行*运算，所以*（s+i）=s[i]

s[i] 是 *(s + i) *s 是 s[0]


Question: 用串口助手向STC89C52发送字符串时，为什么第一个字符显示不了？？？

引用 6 楼 qq_36524366 的回复:[quote=引用 3 楼 Janxionwang 的回复:]  bit ReceiveString()     {     char * RecStr=buf_string;     char num=0;     unsigned char count=0;     loop:         *RecStr=SBUF;     count=0;     RI=0;         if(num < 11)  //数据包长度为11个字符,尝试连续接收11个字符-----你这里第10次跑完时候num = 10就进不来了，少了一次     {         num++;         RecStr++;             while(!RI)         {             count++;             if(count>130)return 0;          }         goto loop;     }        return 1; } 今天我的思想被误导了  我以为还会有一次num=10，因为当它等于9时，还不知道是不是小于10，所以会进行一次num=10的操作[/quote]  要习惯多方面看问题啊，可能你觉得组容易的地方就是最容易出错的，还有，给你一个建议，写代码一定要养成好习惯，比如buf_string这种宏，一般都写成大写，还有一般来说goto语句容易出问题，因为你goto的点可能变量没有初始化等等问题，早就不 提倡使用了，当然，只是各个意见

引用 3 楼 Janxionwang 的回复: bit ReceiveString()     {     char * RecStr=buf_string;     char num=0;     unsigned char count=0;     loop:         *RecStr=SBUF;     count=0;     RI=0;         if(num < 11)  //数据包长度为11个字符,尝试连续接收11个字符-----你这里第10次跑完时候num = 10就进不来了，少了一次     {         num++;         RecStr++;             while(!RI)         {             count++;             if(count>130)return 0;          }         goto loop;     }        return 1; } 今天我的思想被误导了  我以为还会有一次num=10，因为当它等于9时，还不知道是不是小于10，所以会进行一次num=10的操作

引用 4 楼 zhao4zhong1 的回复:“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，掰手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？哎呀  竟然犯这么低级的错误  瞬间无地自容

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

每次发11个字符，通过STC的串口助手，到单片机显示时，可以正常显示后面10位数据，第一位在1602上显示乱码


Question: 小百求助，关于简单链表的建立，求大神解答，谢谢！

仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*q1,*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;     }      //将整个链表逆序     if (head->next!=NULL && head->next->next!=NULL) {         p=head->next;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head->next=p;     }      //输出整个单链表     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; } //84->28->20->23->96->19->59->97->29->41-> //84->28->05->20->23->96->19->59->97->29->41-> //84->28->05->20->96->19->59->97->29->41-> //05->19->20->28->29->41->59->84->96->97-> //97->96->84->59->41->29->28->20->19->05-> //41->29->28->20->19->05->97->96->84->59-> //

scanf("%d ", &(ps ->Element));  改成：  scanf("%d", &(ps ->Element));  //没那个空格   否则你输入一个数后，它是不会立即显示的，要等再接收到一个非（空格、制表符、回车）的输入scanf语句才结束。

scanf("%d ", &(ps->Element)); 改为 scanf("%d", &(ps->Element)); //“%d后面不要空格  int main() {     //PrtToNode head;     PrtToNode head = NULL;     head = MakeList(head);     ShowList(head);     return 0; }

引用 3 楼 cfjtaishan 的回复: #include <stdio.h> #include <stdlib.h>  typedef struct Node List; typedef List *PrtToNode; typedef int ElementType;  struct Node{     ElementType Element;     PrtToNode next; };   PrtToNode MakeList(PrtToNode head); void ShowList(PrtToNode head);  PrtToNode Intersection(PrtToNode p1, PrtToNode p2); PrtToNode Union(PrtToNode p1, PrtToNode p2);  int main() {     PrtToNode head = NULL;    /* must initize */     head = MakeList(head);     ShowList(head);     return 0; }  PrtToNode MakeList(PrtToNode head) {     int i;     PrtToNode ps;     PrtToNode pend;      ps = (PrtToNode)malloc(sizeof(List));     pend = ps;     for(i = 0; i < 5; i++){         scanf("%d", &(ps ->Element));         if (!head)    /* use main's initization*/             head = ps;         else             pend ->next = ps;         pend = ps;         ps = (PrtToNode)malloc(sizeof(List));     }     pend ->next = NULL;     pend = pend->next;      free(ps);     //free(pend);     return head; }  void ShowList(PrtToNode head) {     PrtToNode ps = head;     while(ps){         printf("%d ", ps ->Element);         ps = ps->next;     }     //free(ps);  /* del this statement , ps is NULL*/ }   1. 循环次数的不对，可能是输入scanf中多的空格导致的。 2. main的head需要初始化，不然在MakeList中找不到head == NULL,因为不初始化，head就是一个野指针。其实这个函数不需要这个参数，完全可以去掉，在MakeList中定义一个头指针，然后初始化一下。最后返回头指针。 另外，ps和pend不要free，pend已经是NULL，free没有意义。ps需要free掉，因为你多申请了一个ps。（循环5次，申请5次，外面还有一次）. 3. show函数里一样，最后的ps不用释放，已经是NULL，释放也是没意义。 4。对于要释放整个链表，建议重新定义一个函数去做。  非常感谢，问题解决了

弄不清楚哪里错了，就重新整理下思路，然后一步一步的看。


Question: 大神求救！sos！

wl[nc]在是空格，tab键或者回车符时，这是对这些字符的前一个单词做的计数。当输入多个单词，若以空格隔开，那么每次遇到空格，都判定是一个单词的结束，那么他要对该单词进行计数。 程序有问题呢，wl数组没有初始化，并且没有对每隔单词机型计数，只是将单词的总数放在wl[1]里; 我想，你应该是想输入多个单词，然后将每隔单词出现的次数放到wl数组里

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

引用 2 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  您好，我用devC++，设置了断点，单步执行的时候，shell界面好像是卡了的样子，输入什么都不显示，隔十几分钟才能把刚才的输入显示出来，这是为什么啊？难道是因为代码太多了吗？


Question: 定义和声明的区别？

Grammar Summary This appendix describes the formal grammar of the C++ language, as implemented in the Microsoft C++ compiler. It is loosely organized around the chapter organization of this book as follows:   The Keywords section describes keywords, covered in Chapter 1, Lexical Conventions.    The Expressions section describes the syntax of expressions, described in Chapter 4, Expressions.    The Declarations section describes the syntax of declarations, described in Chapter 6, Declarations.    The Declarators section describes the syntax of declarators, covered in Chapter 7, Declarators.    The Classes section covers the syntax used in declaring classes, as covered in Chapter 8, Classes.    The Statements section covers the syntax used in writing statements, as covered in Chapter 5, Statements.    The Microsoft Extensions section covers the syntax of features unique to Microsoft C++. Many of these features are covered in Appendix B, Microsoft-Specific Modifiers.

这么说来，声明和定义的区别是是否为这个变量分配了存储空间

引用 3 楼 cfjtaishan 的回复:[quote=引用 1 楼 a393062456 的回复:] 没有给他赋值的是声明，给了初始值就是定义。 比如int a；这是声明 而int a=0；这就是定义了 http://blog.csdn.net/qq_21411985/article/details/44082831[/quote] 受教了

引用 1 楼 a393062456 的回复:没有给他赋值的是声明，给了初始值就是定义。 比如int a；这是声明 而int a=0；这就是定义了 http://blog.csdn.net/qq_21411985/article/details/44082831

对于函数： 主要是看有没有函数体，函数体是指函数的内容。 在main函数前定义的函数，也是声明，这就是定义时声明。 对于变量：请看这位朋友的博客，上面介绍的比较详细 http://blog.csdn.net/qq_21411985/article/details/44082831


Question: 有哪位大神来将这个有关链表的学生管理系统补全，求帮忙

引用 1 楼 cfjtaishan 的回复:对于学生成绩的类型，不建议使用double类型，建议使用float类型即可，因为不需要那么高的精度，用double会浪费些资源。 我输完“1”之后的信息它是显示“链表为空。将数据插入到链表头”，请问要怎么插入？


Question: 为什么我的VS不可以调试显示返回值为0就跳了出来

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0];

#include <stdio.h>  int main(int argc,char  *argv[]) {     int n = 0, i = 0, yu[16] = {0};      printf("请输入0-32767的数字:");     scanf("%d", &n);     for(i = 0; n > 0; i++)     {         yu[i] = n % 2;         n = n / 2;     }     for (i = 15; i >= 0; i--) {         printf("%d", yu[i]);         if(i%4==0) {             printf(" ");         }     }      return 0; } 去掉第二个for循环后面的;， 改一下第一个和第二个for循环的退出条件。 建议注意一下coding style.


Question: 指针问题

*(*t->course) 是悬垂指针，根本没有有效的指向

printf ("%s,%d"*(*t->course)->cName,*(*t->course)->grade);//这出错了，执行不了。 能编译通过吗？

结构体声定放在另一个头文件里的，不方便在这里写上，应该怎么改呢

应该是没有申请到有效的内存空间； 建议你修改一下代码风格，这样大家读起来不会太费劲。 很少看到有人把结构体声定放在main函数里，建议改掉这样的“陋习”。


Question: 求助一个netcat代码问题

C Function Definitions A function definition specifies the name of the function, the types and number of parameters it expects to receive, and its return type. A function definition also includes a function body with the declarations of its local variables, and the statements that determine what the function does.   Syntax  translation-unit :  external-declaration translation-unit external-declaration  external-declaration : /* Allowed only at external (file) scope */  function-definition declaration  function-definition : /* Declarator here is the function declarator */  declaration-specifiersopt attribute-seqopt declarator declaration-listopt compound-statement  /* attribute-seq is Microsoft Specific */  Prototype parameters are:  declaration-specifiers :  storage-class-specifier declaration-specifiers opt  type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt  declaration-list :  declaration declaration-list declaration  declarator :  pointeropt direct-declarator  direct-declarator : /* A function declarator */   direct-declarator ( parameter-type-list ) /* New-style declarator */ direct-declarator ( identifier-list opt ) /* Obsolete-style declarator */  The parameter list in a definition uses this syntax:   parameter-type-list : /* The parameter list */  parameter-list parameter-list , ...  parameter-list :  parameter-declaration parameter-list , parameter-declaration  parameter-declaration :  declaration-specifiers declarator declaration-specifiers abstract-declarator opt  The parameter list in an old-style function definition uses this syntax:  identifier-list : /* Used in obsolete-style function definitions and declarations */  identifier identifier-list , identifier  The syntax for the function body is:  compound-statement : /* The function body */   { declaration-list opt statement-list opt }  The only storage-class specifiers that can modify a function declaration are extern and static. The extern specifier signifies that the function can be referenced from other files; that is, the function name is exported to the linker. The static specifier signifies that the function cannot be referenced from other files; that is, the name is not exported by the linker. If no storage class appears in a function definition, extern is assumed. In any case, the function is always visible from the definition point to the end of the file.   The optional declaration-specifiers and mandatory declarator together specify the function’s return type and name. The declarator is a combination of the identifier that names the function and the parentheses following the function name. The optional attribute-seq nonterminal is a Microsoft-specific feature defined in Function Attributes.   The direct-declarator (in the declarator syntax) specifies the name of the function being defined and the identifiers of its parameters. If the direct-declarator includes a parameter-type-list, the list specifies the types of all the parameters. Such a declarator also serves as a function prototype for later calls to the function.   A declaration in the declaration-list in function definitions cannot contain a storage-class-specifier other than register. The type-specifier in the declaration-specifiers syntax can be omitted only if the register storage class is specified for a value of int type.   The compound-statement is the function body containing local variable declarations, references to externally declared items, and statements.   The sections Function Attributes, Storage Class, Return Type, Parameters, and Function Body describe the components of the function definition in detail.

引用 2 楼 jianwen0529 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] void bail (str, p1, p2, p3, p4, p5, p6)   char * str;   char * p1, * p2, * p3, * p4, * p5, * p6; {   o_verbose = 1;   holler (str, p1, p2, p3, p4, p5, p6); #ifdef WIN32   shutdown(netfd, 0x02);  /* Kirby */   closesocket (netfd); #else   close (netfd); #endif   sleep (1);   exit (1); } /* bail */  这是C语言吗？ 语法看着怪怪的，  K&R C标准的写法[/quote] so old~,与时俱进吧，建议用现代写法～ 当下标准C，指的是ANSI C，ISO C，C89，C90

引用 1 楼 cfjtaishan 的回复:void bail (str, p1, p2, p3, p4, p5, p6)   char * str;   char * p1, * p2, * p3, * p4, * p5, * p6; {   o_verbose = 1;   holler (str, p1, p2, p3, p4, p5, p6); #ifdef WIN32   shutdown(netfd, 0x02);  /* Kirby */   closesocket (netfd); #else   close (netfd); #endif   sleep (1);   exit (1); } /* bail */  这是C语言吗？ 语法看着怪怪的，  K&R C标准的写法


Question: calloc函数的使用

第一个问题，结构体可以直接赋值，即t[k] = b[j]；也可以分别赋值，但是对于字符数组num的赋值不能直接t[k].num = b[j].num; 需要借助字符串函数strncpy，既然结构体可以直接赋值，所以不用将结构体里的成员一一拷贝； 第二个问题，t[0],t[1]是可以，因为数组和指针可以互相用。即t[0] == *(t+0), t[1]就是*(t+1); 结构体你直接看成普通类型变量的操作即可，很多操作都是相近的，赋值，指针运用，数组运用。

t[k].num=b[j].num; 只是赋值num成员  t[k]=b[j] 是赋值整个对象  t[n] 等价于 *(t+n)


Question: 关于CreateProcess启动外部程序问题。

CreateProcess The CreateProcess function creates a new process and its primary thread. The new process executes the specified executable file.   BOOL CreateProcess(   LPCTSTR lpApplicationName,                          // pointer to name of executable module   LPTSTR lpCommandLine,  // pointer to command line string   LPSECURITY_ATTRIBUTES lpProcessAttributes,  // process security attributes   LPSECURITY_ATTRIBUTES lpThreadAttributes,   // thread security attributes   BOOL bInheritHandles,  // handle inheritance flag   DWORD dwCreationFlags, // creation flags   LPVOID lpEnvironment,  // pointer to new environment block   LPCTSTR lpCurrentDirectory,   // pointer to current directory name   LPSTARTUPINFO lpStartupInfo,  // pointer to STARTUPINFO   LPPROCESS_INFORMATION lpProcessInformation  // pointer to PROCESS_INFORMATION );   Parameters ……  Remarks The CreateProcess function is used to run a new program. The WinExec and LoadModule functions are still available, but they are implemented as calls to CreateProcess.   In addition to creating a process, CreateProcess also creates a thread object. The thread is created with an initial stack whose size is described in the image header of the specified program's executable file. The thread begins execution at the image's entry point.   The new process and the new thread handles are created with full access rights. For either handle, if a security descriptor is not provided, the handle can be used in any function that requires an object handle to that type. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process is not able to use the handle to gain access to the thread.   The process is assigned a 32-bit process identifier. The identifier is valid until the process terminates. It can be used to identify the process, or specified in the OpenProcess function to open a handle to the process. The initial thread in the process is also assigned a 32-bit thread identifier. The identifier is valid until the thread terminates and can be used to uniquely identify the thread within the system. These identifiers are returned in the PROCESS_INFORMATION structure.   When specifying an application name in the lpApplicationName or lpCommandLine strings, it doesn't matter whether the application name includes the filename extension, with one exception: an MS-DOS – based or Windows-based application whose filename extension is .COM must include the .COM extension.   The calling thread can use the WaitForInputIdle function to wait until the new process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronization between parent and child processes, because CreateProcess returns without waiting for the new process to finish its initialization. For example, the creating process would use WaitForInputIdle before trying to find a window associated with the new process.   The preferred way to shut down a process is by using the ExitProcess function, because this function notifies all dynamic-link libraries (DLLs) attached to the process of the approaching termination. Other means of shutting down a process do not notify the attached DLLs. Note that when a thread calls ExitProcess, other threads of the process are terminated without an opportunity to execute any additional code (including the thread termination code of attached DLLs).   ExitProcess, ExitThread, CreateThread, CreateRemoteThread, and a process that is starting (as the result of a call by CreateProcess) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means the following restrictions hold:   During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.  Only one thread in a process can be in a DLL initialization or detach routine at a time.  The ExitProcess function does not return until no threads are in their DLL initialization or detach routines.  The created process remains in the system until all threads within the process have terminated and all handles to the process and any of its threads have been closed through calls to CloseHandle. The handles for both the process and the main thread must be closed through calls to CloseHandle. If these handles are not needed, it is best to close them immediately after the process is created.   When the last thread in a process terminates, the following events occur:   All objects opened by the process are implicitly closed.  The process's termination status (which is returned by GetExitCodeProcess) changes from its initial value of STILL_ACTIVE to the termination status of the last thread to terminate.  The thread object of the main thread is set to the signaled state, satisfying any threads that were waiting on the object.  The process object is set to the signaled state, satisfying any threads that were waiting on the object.  If the current directory on drive C is \MSVC\MFC, there is an environment variable called =C: whose value is C:\MSVC\MFC. As noted in the previous description of lpEnvironment, such current directory information for a system's drives does not automatically propagate to a new process when the CreateProcess function's lpEnvironment parameter is non-NULL. An application must manually pass the current directory information to the new process. To do so, the application must explicitly create the =X environment variable strings, get them into alphabetical order (because the system uses a sorted environment), and then put them into the environment block specified by lpEnvironment. Typically, they will go at the front of the environment block, due to the previously mentioned environment block sorting.   One way to obtain the current directory variable for a drive X is to call GetFullPathName("X:",. .). That avoids an application having to scan the environment block. If the full path returned is X:\, there is no need to pass that value on as environment data, since the root directory is the default current directory for drive X of a new process.   The handle returned by the CreateProcess function has PROCESS_ALL_ACCESS access to the process object.   The current directory specified by the lpcurrentDirectory parameter is the current directory for the child process. The current directory specified in item 2 under the lpCommandLine parameter is the current directory for the parent process.  Windows NT: When a process is created with CREATE_NEW_PROCESS_GROUP specified, an implicit call to SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process; this means that the new process has ctrl+c disabled. This lets good shells handle ctrl+c themselves, and selectively pass that signal on to sub-processes. ctrl+break is not disabled, and may be used to interrupt the process/process group.   Windows CE: The name of the module to execute must be specified by the lpApplicationName parameter. Windows CE does not support passing NULL for lpApplicationName. The execution module cannot be specified in the command line string.  Windows CE searches the directories indicated by the lpApplicationName parameter in the following order:   The root of the PC Card if it exists  The windows (\windows) directory  The root (\ ) directory of the device  The following parameters are not supported and require the following settings:   lpProcessAttributes must be NULL  lpThreadAttributes must be NULL  bInheritHandles must be FALSE  lpEnvironment must be NULL  lpCurrentDirectory must be NULL  lpStartupInfo must be NULL  For Windows CE version 1.0, the dwCreationFlags parameter only supports the following values: CREATE_SUSPENDED and zero.   For Windows CE version 2.0, the dwCreationFlags parameter only supports the following values: CREATE_SUSPENDED, DEBUG_PROCESS, DEBUG_ONLY_THIS_PROCESS and zero.   Priority classes for processes are not supported.  The loader has a limited search path.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also Processes and Threads Overview, Process and Thread Functions, AllocConsole, CloseHandle, CreateRemoteThread, CreateThread, ExitProcess, ExitThread, GenerateConsoleCtrlEvent, GetCommandLine, GetEnvironmentStrings, GetExitCodeProcess, GetFullPathName, GetStartupInfo,GetSystemDirectory,GetWindowsDirectory, LoadModule, OpenProcess, PROCESS_INFORMATION, ResumeThread, SECURITY_ATTRIBUTES, SetConsoleCtrlHandler, SetErrorMode, STARTUPINFO, TerminateProcess, WaitForInputIdle, WaitForDebugEvent, WinExec

纠正下2 GetLastError看返回值

1.上代码比说故障更便于找错。 2.如果是使用P/Invoke，那么在DllImport属性中设置SetLastError=true。 然后就可以使用 Marshal.GetLastWin32Error来获取系统错误了。


Question: 关于getchar();getchar();

引用 1 楼 cfjtaishan 的回复:getchar()是等待用户输入一个字符，若不输入则程序不进行下面的执行； 之所以用两个getchar()，有可能因为上面还有输入的操作，第一个getchar()接收上次输入残留在输入缓存区里的回车符。第二个getchar()是需要输入一个字符（任意字符）才能继续进行。 刚才蠢了 没注意到程序上面还有操作 是接回车。。。谢谢


Question: 在绝对地址0xXXXXXXXX上写入字符’a’的语句是？

Windows下没准还得参考WinIO.sys

引用 4 楼 zhang_datong 的回复:这个逻辑我知道是啥意思，只是这个地址0Xf000ff00怎么出现的，题目也没有说啊 随便举个数字而已，我猜。 实际使用时，可以是比如0xB0000000、0xB8000000、0xA0000000、……，具体请参考相关BIOS、显卡、视频采集卡、……的相关手册。

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

((unsigned char *)0xF000FF00)[0]='a';//这样写是不是更好理解呢？

前一个是给指针赋值一个内存地址，然后将'a'字符放到这个内存地址中。 类似这样的， unsigned char ch; unsigned char *p = &ch;    /*类似是unsigned char *p = (unsigned char *)0xF000FF00; */ *p = 'a';


Question: c文件操作中的问题

引用 1 楼 自信男孩的回复:实际上也只读到了一个5，原因是t的值保存的上次读到的5，这次没读成功。你可以通过一下方式验证一下我的推测： #include<stdio.h> #include<stdlib.h>  int main() {     int a[5] = {1,2,3,4,5};     int i = 0, t, ret;     FILE *fp;      fp=fopen("c.txt","rb+");     if(!fp) {         printf("ERROR");         exit (0);     }     fwrite(&a[0], 4, 1, fp);     for (i = 1; i < 5; i++) {         fseek(fp, 0l, SEEK_SET);         fwrite(&a[i], 4, 1, fp);      }     fseek(fp, 0l, SEEK_SET);     while(!feof(fp)){         ret = fread(&t,4,1,fp);         printf("ret = %d, %d\t", ret, t);         t = 0;     }     fclose(fp);     return 0;  } 原因出在feof,参考一下这个文章： http://blog.csdn.net/qq_29350001/article/details/53100563 蟹蟹 很有用 我觉得书上的答案解析是错了 他说把数组的内容倒序保存在文件里 结果我后来用循环输出文件内容也没有啊？求解答

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


Question: 求大佬帮忙看看哪里出错了！！

就是这个warning警告，求解啊啊

#include<stdio.h> #include<string.h> #include<malloc.h> #define SIZE 10 typedef struct Node { 	int Value; 	char name[SIZE]; 	struct Node *next; }SeqList; int main() { 	SeqList *create(); 	SeqList *Typein();  //   SeqList Insert(SeqList *L); 	SeqList Printf(SeqList *L); 	int i; 	SeqList *L; 	printf("\n/*****************************Welcome!******************************/"); 	printf("\n/                 Input  1  To InitList Linear List                 /"); 	printf("\n/                 Input  2  To Type-in Students Name                /"); 	printf("\n/                 Input  3  To Insert New Student Name              /"); 	printf("\n/                 Input  4  To Delete Student Name                  /"); 	printf("\n/                 Input  5  To Search Student                       /"); 	printf("\n/                 Input  6  To Print Students Name                  /"); 	printf("\n/                 Input  7  To Inversion Linked List                /"); 	printf("\n/                 Input  0  Exit                                    /\n"); 	printf("\nThe Value: "); 	scanf("%d",&i); 	switch(i) 	{ 	case 1:L=create();main();break; 	case 2:L=Typein();printf("\n%s %d\n",L->next->name,L->Value);main();break; //	case 3:Insert(L);main();break; 	case 6:Printf(L);main();break; 	case 0:exit();break; 	default :system("cls");printf("\nInput Error!\n");main();break; 	} } SeqList *create() { 	SeqList *p; 	p=(SeqList*)malloc(sizeof(SeqList)); 	p->next=NULL; 	p->Value=0; 	if(p->next==NULL) 	{ 		system("cls"); 		printf("\nCreate To Complete!\n"); 		return p; 	} 	else 	{ 		system("cls"); 		printf("\nError!\n"); 		return NULL; 	} } SeqList *Typein() { 	SeqList *head,*current,*next; 	char str[SIZE],flag='Y'; 	int i=0; 	head=(SeqList*)malloc(sizeof(SeqList)); 	current=head; 	system("cls"); 	while(flag=='Y'&&flag!='N') 	{ 		++i; 		printf("Please Input The No.%d Student's Name: ",i); 		scanf("%s",str); 		next=(SeqList*)malloc(sizeof(SeqList)); 		strcpy(next->name,str); 		current->next=next; 		current=next; 		getchar(); 		printf("Continue? Y/N-> "); 		scanf("%c",&flag); 	} 	current->next=NULL; 	head->Value=i; 	system("cls"); 	if(head->Value==i) 	{ 		printf("\nType-in Name To Complete!\n"); 		printf("Only %d Students\n",head->Value); 		return head; 		free(head); 	} 	else 	{ 		printf("\nError!\n"); 		return NULL; 	} } SeqList Printf(SeqList *L) { 	SeqList *p; 	system("cls"); 	printf("\nThe Students:\n"); 	p=L->next; 	while(1) 	{ 		printf("\n%s",p->name); 		if(p->next!=NULL)p=p->next; 		else 			break; 	} 	printf("\n\nOnly %d Students\n",L->Value); } 代码在这

#include <stdio.h> #include <string.h> #include<malloc.h>  #define SIZE 10 typedef struct Node {     int Value;     char name[SIZE];     struct Node *next; }SeqList;  /*Function statements */ SeqList *create(); SeqList *Typein(); //SeqList Insert(SeqList *L); SeqList Printf(SeqList *L);  int main() {     int ch;      SeqList *L = NULL; /*Initize link.*/      while (1) {         printf("\n/*****************************Welcome!******************************/");         printf("\n/                 Input  1  To InitList Linear List                 /");         printf("\n/                 Input  2  To Type-in Students Name                /");         printf("\n/                 Input  3  To Insert New Student Name              /");         printf("\n/                 Input  4  To Delete Student Name                  /");         printf("\n/                 Input  5  To Search Student                       /");         printf("\n/                 Input  6  To Print Students Name                  /");         printf("\n/                 Input  7  To Inversion Linked List                /");         printf("\n/                 Input  0  Exit                                    /\n");         printf("\nThe Value: ");         scanf("%d", &ch);         switch(ch)         {             case 1:                 L = create();                 //main();    /* what's this?*/                 break;              case 2:                 L = Typein();                 printf("\n%s %d\n", L->next->name, L->Value);                 //main();                 break;                  // case 3:Insert(L);main();break;             case 6:                 Printf(L);                 //main();                 break;              case 0:                 exit(0);                 break;              default :                 system("cls");                 printf("\nInput Error!\n");                 //main();                 break;         }     } }  SeqList *create() {     SeqList *p;     p=(SeqList *)malloc(sizeof(SeqList));     p->next = NULL;     p->Value = 0;     if(p->next == NULL)     {         system("cls");         printf("\nCreate To Complete!\n");         return p;     }     else     {         system("cls");         printf("\nError!\n");         return NULL;     } }  SeqList *Typein() {     SeqList *head, *current, *next;     char str[SIZE], flag='Y';     int i = 0;      head = (SeqList*)malloc(sizeof(SeqList));     current = head;     system("cls");     while(flag == 'Y' && flag != 'N')     {         ++i;         printf("Please Input The No.%d Student's Name: ", i);         scanf("%s",str);         next = (SeqList*)malloc(sizeof(SeqList));         strcpy(next->name,str);         current->next=next;         current=next;         getchar();         printf("Continue? Y/N-> ");         scanf("%c", &flag);     }     current->next = NULL;     head->Value = i;     system("cls");     printf("\nType-in Name To Complete!\n");     printf("Only %d Students\n", head->Value);     return head; } SeqList Printf(SeqList *L) {     SeqList *p;     system("cls");     printf("\nThe Students:\n");     p = L->next;     while (p)     {         printf("\n%s", p->name);         p = p->next;     }     printf("\n\nOnly %d Students\n",L->Value); } 那个警告是main函数定义的变量L没有初始化; 程序中的问题： 1. 编程这么长时间，第一次看到有对main函数做递归的。能用递归的也可以用迭代实现，在外层加一个while或者for循环就可以，用main递归，真的很少有人这样做，对于不是很了解递归的，递归有自己的缺点 ； 2. 函数声明，不要放到main函数里，很少有人这么做了，这样的”陋习“建议改掉，能放到函数外或者用头文件都可以。 3. create()没看出有什么用途，调用了，但是后面没有用呢。建议去掉或者改改其他函数功能，Typein函数做了create函数应该做的事情；既然重复，那就删掉冗余的代码； 4. Print输出链表，完全可以做的简单些，没必要在while中再做判断； 5. typein函数里，current->value = i;下面为啥还要判断current->value==i呢?要验证上面的赋值是否正确吗？不用验证，是没问题的。所以，这块也是多余，要么就是你有其他的想法。  最后，注意下coding style.


Question: 不知道哪里出错 有大神指点吗

引用 9 楼 zbreezeH 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] [quote=引用 3 楼 zbreezeH 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] /*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢 [/quote] 你输入0xf245的时候，程序里是%hu个数输入的吗？[/quote]那个测试的程序不知道去哪了，书上的这个用的有符号的short型，而且直接用0xf245赋值给 short型。还一个问题，那个十六进制表示的如何知道是负数，是要加负号吗？  //书上的代码 void main(){      short a=0xf245, b ,c;  b = a<<8; c = a>>8; c = c&0x00ff; a =b+c;  printf("a=%x",a); } [/quote] 要看你用什么类型接收那个十六进制数，在内存里都是0101这样存储的，没有正负之分，只有你以什么类型去读取和输出

引用 4 楼 cfjtaishan 的回复:[quote=引用 3 楼 zbreezeH 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] /*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢 [/quote] 你输入0xf245的时候，程序里是%hu个数输入的吗？[/quote]那个测试的程序不知道去哪了，书上的这个用的有符号的short型，而且直接用0xf245赋值给 short型。还一个问题，那个十六进制表示的如何知道是负数，是要加负号吗？  //书上的代码 void main(){      short a=0xf245, b ,c;  b = a<<8; c = a>>8; c = c&0x00ff; a =b+c;  printf("a=%x",a); }

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

引用 6 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0];请问为什要写成下面这样呢 ？  这样不是跟占用内存空间吗？

仅供参考：#include <stdio.h> unsigned short int ui;   signed short int si; int main() { 	ui=(unsigned short int)0x8000u; 	si=(  signed short int)0x8000; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si); 	ui=ui>>1; 	si=si>>1; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si);  	printf("--------------\n"); 	ui=(unsigned short int)0x8000u; 	si=(  signed short int)0x8000; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si); 	ui=((  signed short	int)ui)>>1; 	si=((unsigned short	int)si)>>1; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si);  	return 0; } //ui=32768 //si=-32768 //ui=16384 //si=-16384 //-------------- //ui=32768 //si=-32768 //ui=49152 //si=16384

引用 9 楼 zbreezeH 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] [quote=引用 3 楼 zbreezeH 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] /*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢 [/quote] 你输入0xf245的时候，程序里是%hu个数输入的吗？[/quote]那个测试的程序不知道去哪了，书上的这个用的有符号的short型，而且直接用0xf245赋值给 short型。还一个问题，那个十六进制表示的如何知道是负数，是要加负号吗？  //书上的代码 void main(){      short a=0xf245, b ,c;  b = a<<8; c = a>>8; c = c&0x00ff; a =b+c;  printf("a=%x",a); } [/quote] 直接赋值没有问题，主要是如果是scanf("%hu", &a);你不能直接输入0xf245，这个输入是一个十六进制数，而scanf接收的是无符号短整形，所以它不会识别。

引用 3 楼 zbreezeH 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] /*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢 [/quote] 你输入0xf245的时候，程序里是%hu格式输入的吗？

引用 3 楼 zbreezeH 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] /*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢 [/quote] 你输入0xf245的时候，程序里是%hu个数输入的吗？

引用 2 楼 cfjtaishan 的回复:/*     编写一程序要求任意输入四位十六进制的整数，以反序的方式输出该十六进制数。     例如 ：输入9AF0， 则输出 0FA9 */  #include<stdio.h>  int main() {     unsigned short a,b,c;    //改成有符号为什么结果不一样      printf("输入任意四位的十六进制:\n");     scanf("%hu", &a);           //0x9AF0    ,为何用 %h 会有奇怪的结果  输入0xf245 结果就对      printf("a = %#x\n", a);     b = a>>8;   //的高位由符号位填充，有可能为1，必须清零     c = a<<8;     //c的低位一律补零     b = 0x00ff&b;     printf("输出倒序后的b :%#x\n",b);     printf("输出倒序后的c :%#x\n",c);      a = b|c;     printf("输出倒序后的a :%#x\n",a);      return 0; } 应该使用%hu，无符号短整形； 另外，使用%hu就不能再输入的时候加上a-f中的字符了，它不识别。 即使使用%hu，你可以%#x 输出你输入的数据，然后在反转。  书上有可以直接把十六进制赋给short的，而且为什么输入0xf245没问题呢

int main(int argc, char *argv[]) {     unsigned short a,b,c, d;    //改成有符号时会当成负数处理0xFFFF????          printf("input data:\n");     scanf("%x",&a);           //0x9AF0    ,scanf应该不支持%h      d = a & 0x000f;     a >>= 4;     c = a & 0x000f;     a >>= 4;     b = a & 0x000f;     a >>= 4;      printf("d :%#x\n",d);     printf("c :%#x\n",c);     printf("b :%#x\n",b);     printf("a :%#x\n",a);      a = (d<<12)|(c<<8)|(b<<4)|a;      printf("a :%#x\n",a);      return 0;  }


Question: 求大神帮助解决一下关于==和！=在代码中顺序的问题

not(A and B) 等价于 (not A) or (not B)  not(A or B) 等价于 (not A) and (not B)  这是什么定律来着？

引用 1 楼 cfjtaishan 的回复:#include <stdio.h>   int main() {     int c,lastc;     while ((c=getchar()) != EOF) {         if (c != ' '||c != '\t'){             putchar(c);         }         if(c == ' '|| c == '\t') {             putchar('\n');         }     }     return 0; } 因为if else是相反的。if的条件相反就是c == ' ' & c == '\t' 所以把else去掉就可以了。 上面的那个可以正常断开单词，道理是一样的。if else是两个相反的  谢谢啦

if (c != ' '||c != '\t') 这逻辑是什么鬼？这不相当于写了个 if (true)


Question: 求助C代码改错

应该是你把   static const char *months[] 定义在函数里面了，放到函数外面全局就可以用了。

感谢回复   我改了一下translateForm 发现 temp->month=months[m]; 不能用诶 请问是怎么回事 应该怎么调用const char 好一些

static int cmp_dates(const void*a, const void*b) {     time first = *(time *)a;     time second = *(time *)b;  结构可以这样初始化吗？既然用到指针，就用指针吧，     time *first = (time *)a;     time *second = (time *)b; 以后用first->year..等来访问

translateForm可以这么写吧：  static time *translateForm(int y,int m,int d) {     time *temp = malloc(1*sizeof(time));     temp->month=months[m];     temp->year=y;     temp->day=d;     return temp; }

typedef struct {     char *month;     int day;     int year; }time;   一点小建议： 1、 结构名最好用time以外的名字，比如time_struct，系统里面有time.h。避免混淆，当然可能没有问题。 2、month也用int吧。既然你定义了char *months[]的静态数据，需要用到月份字符串时，用months[timeInstance.month]即可，尽量避免用指针，尽快指针看起来很酷。 3、orig_month函数里面exit退出程序不是好用法。return一个0或者负数都可以。调用程序判断返回值吧。


Question: 关于显示打印\\的问题

引用 4 楼 caine12345 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] C++ Character Constants Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.  Microsoft Specific   For Microsoft C++, the source and execution character sets are both ASCII.  END Microsoft Specific  There are three kinds of character constants:   Normal character constants   Multicharacter constants   Wide-character constants  Note   Use wide-character constants in place of multicharacter constants to ensure portability.  Character constants are specified as one or more characters enclosed in single quotation marks. For example:  char ch = 'x';          // Specify normal character constant. int mbch = 'ab';        // Specify system-dependent                         //  multicharacter constant. wchar_t wcch = L'ab';   // Specify wide-character constant.  Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  any member of the source character set except the single quotation mark ('), backslash (\), or newline character escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \' \" \? \\ \a \b \f \n \r \t \v  octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit  Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)  The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:  char schar = 'x';               // Normal character constant wchar_t wchar = L'\x81\x19';    // Wide-character constant  Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.  Table 1.2   C++ Reserved or Nongraphic Characters  Character ASCII  Representation ASCII  Value Escape Sequence  Newline NL (LF) 10 or 0x0a \n  Horizontal tab HT 9 \t  Vertical tab VT 11 or 0x0b \v  Backspace BS 8 \b  Carriage return CR 13 or 0x0d \r  Formfeed FF 12 or 0x0c \f  Alert BEL 7 \a  Backslash \ 92 or 0x5c \\  Question mark ? 63 or 0x3f \?  Single quotation mark ' 39 or 0x27 \'  Double quotation mark " 34 or 0x22 \"  Octal number ooo — \ooo  Hexadecimal number hhh — \xhhh  Null character NUL 0 \0    If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.  Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.  Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:  wchar_t och = L'\076a';  // Sequence terminates at a char    ch = '\233';     // Sequence terminates after 3 characters  Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.  Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)  谢谢大神，这么多会看到头疼[/quote] 除恶务尽！

跟printf("\")一样

引用 1 楼 cfjtaishan 的回复:其实真正输出的是四个\中的偶数位的\，四个\，奇数个的\都是转义符。 第一个和第三个是转义符 谢谢啦！这样就会很好理解了

引用 3 楼 zhao4zhong1 的回复:C++ Character Constants Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.  Microsoft Specific   For Microsoft C++, the source and execution character sets are both ASCII.  END Microsoft Specific  There are three kinds of character constants:   Normal character constants   Multicharacter constants   Wide-character constants  Note   Use wide-character constants in place of multicharacter constants to ensure portability.  Character constants are specified as one or more characters enclosed in single quotation marks. For example:  char ch = 'x';          // Specify normal character constant. int mbch = 'ab';        // Specify system-dependent                         //  multicharacter constant. wchar_t wcch = L'ab';   // Specify wide-character constant.  Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  any member of the source character set except the single quotation mark ('), backslash (\), or newline character escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \' \" \? \\ \a \b \f \n \r \t \v  octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit  Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)  The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:  char schar = 'x';               // Normal character constant wchar_t wchar = L'\x81\x19';    // Wide-character constant  Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.  Table 1.2   C++ Reserved or Nongraphic Characters  Character ASCII  Representation ASCII  Value Escape Sequence  Newline NL (LF) 10 or 0x0a \n  Horizontal tab HT 9 \t  Vertical tab VT 11 or 0x0b \v  Backspace BS 8 \b  Carriage return CR 13 or 0x0d \r  Formfeed FF 12 or 0x0c \f  Alert BEL 7 \a  Backslash \ 92 or 0x5c \\  Question mark ? 63 or 0x3f \?  Single quotation mark ' 39 or 0x27 \'  Double quotation mark " 34 or 0x22 \"  Octal number ooo — \ooo  Hexadecimal number hhh — \xhhh  Null character NUL 0 \0    If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.  Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.  Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:  wchar_t och = L'\076a';  // Sequence terminates at a char    ch = '\233';     // Sequence terminates after 3 characters  Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.  Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)  谢谢大神，这么多会看到头疼


Question: for循环遍历条件大于数组长度

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

那么用 while(*p) {    p++; } 这种方式也不会只正确遍历数组元素?

C语言是不处理的，要输出几个就输出几个，越界输出，越界的内存里有什么就输出什么。如果越界之后的内存是不可以访问的，那么就是报段错误。 所以，越界需要自己判定，编译器是不会告知的，因为运行时内存的情况编译器预判不了（是否越界之后的内存是否可读可写是不可知的）

只有6个数据 ，你为什么要小于10？不直接<6呢？我是新手不知道叫什么机制。 只知道，c++里面未赋值的指针会是各种奇怪数据,,所以不要未赋值就使用它.


Question: 如何初始化结构体数组（内嵌结构体）

typedef struct _bag{ 	int playerId; 	int count; 	int max; 	Prop props[8]; }Bag;  typedef struct _player{ 	int id; 	char name[50]; 	char pass[50] ;	 	double gold; 	Bag bag;  //嵌套上一个结构体 	double sysee; }Player;   Player playerArray[] = {  	[0] = {  		.id = 1,  		.name = "张三",  		.pass = "123456",  		.gold = 50000,  		.bag = {  			.max = 8  		},  		.sysee = 1  	},  	{2,"李四","123456",15000,{0,0,8},2},  	{3,"王五","123456",25000,{.max=8},3},  	{4,"星河","123456",50000,0,0,8,} };

typedef struct _bag{ int playerId; int count; int max; //Prop props[8]; }Bag;  typedef struct _player{     int id;     char name[50];     char pass[50];	     double gold;     Bag bag;     double sysee; }Player;  Player playerArray[] = {     {1, "张三", "123456", 50000, {0, 0, .max = 8}, 0},     {2, "李四", "123456", 15000, {0, 0, .max = 8}, 0},     {3, "王五", "123456", 25000, {0}, 0},     {4, "星河", "123456", 50000, 0, 0} }; 试试这种形式

上面写错了，应该是 {2,"李四","123456",15000,0,.bag={.max=8,}},//这样也应该可以的。  你不妨试试

二楼是对的，结构体初始化和数组初始化是用{}，如果嵌套还是用{ ,,,{}}....多层，不想初始化的变量可以空着。还有一种方法是用小数点: {2,"李四","123456",15000,0,{Bag bag.max=8}},//这样也报错 改成 {2,"李四","123456",15000,0,{.max=8,}},//这样也报错

{2,"李四","123456",15000,0,{5, 3, 8, "HAHA"}} 这样子呢？


Question: 求助C代码改错

请问怎么去掉空格和换行 输出 1_3_4_2_5_6_8_7_10_9_\n 输出 1_3_4_2_5_6_8_7_10_9

非常感谢 完美解决问题

留个脚印，这个问题我想搞明白

#include <stdio.h> #include <stdlib.h> #include <string.h>   typedef int (*pfunc)(int );  int isEven(int temp) {     if(temp % 2 == 0)         return 1;     return 0; }  int isOdd(int temp) {     if(temp % 2 == 1)         return 1;     return 0; }  void sort(int num, int temp[])//对temp中的num个数进行排序 {     int i, j, t;     int swap;      for(i = 0; i < num; i ++)     {         swap = 0;         for(j = 1; j < num - i; j ++)         {             if(temp[j - 1] > temp[j])             {                 t = temp[j - 1];                 temp[j - 1] = temp[j];                 temp[j] = t;                 swap = 1;             }         }         if(swap == 0)             break;     } } void sort_odd(int n,int arr[])//对T中的数进行要求的排序，偶数位置不变，奇数排序 {     int i;     int x =0, y = 0,z = 0,b = 0;     int change[100];     int position[100];      for(i = 0; i < n; i ++)     {         if(isEven(arr[i]) == 1)         {             position[x] = i;             x++;         }         else         {             change[y] = arr[i];             y++;         }     }      sort(y, change);//对奇数排序     for( i = 0; i < n; i ++)     {         if(position[z] == i && z != x)         {             z++;         }         else         {             arr[i] = change[b++];         }     } }  void sort_even(int n,int arr[])//对T中的数进行要求的排序，奇数位置不变，偶数排序 {     int i;     int x =0, y = 0,z =0, b = 0;     int change[100];     int position[100];      for(i = 0; i < n; i ++)     {         if(isOdd(arr[i]) == 1)         {             position[x] = i;             x++;         }         else         {             change[y] = arr[i];             y++;         }     }     sort(y, change);//对偶数排序     for( i = 0; i < n; i ++)     {         if(position[z] == i && z != x)         {             z++;         }         else         {             arr[i] = change[b++];         }     } }   void select_sort(int *arr, int num, pfunc chk_func) {     int i, j;     int min, tmp;      for (i = 0; i < num; i++) {         if (!chk_func(arr[i]))             continue;         min = i;         for (j = i+1; j < num; j++) {             if (!chk_func(arr[j]))                 continue;             if (arr[min] > arr[j])                 min = j;         }         if (min != i) {             tmp = arr[min];             arr[min] = arr[i];             arr[i] = tmp;         }     } }  void bubble_sort(int *arr, int num) {     int i, j;     int tmp;      for (i = 0; i < num; i++)         for (j = 0; j < num - i - 1; j++)             if (arr[j] > arr[j+1]) {                 tmp = arr[j];                 arr[j] = arr[j+1];                 arr[j+1] = tmp;             }  }  void print_arr(int *arr, int len) {     int i;      for (i = 0; i < len; i++)         printf("%d  ", arr[i]);     putchar(10); }  //#define BUBBLE_SORT  int main() {     int i, n, k, cnt;     char word[16];     int num[100], *arr = NULL;      while (scanf("%s", word) != EOF) {         printf("Please input the number of array: ");         scanf("%d", &n); #ifdef BUBBLE_SORT         arr = (int *)malloc(sizeof(int) * n);         if (!arr) {             fprintf(stderr, "malloc error!\n");             exit(1);         }         if(strcmp(word,"odd") == 0) {             printf("%s\n", word);              for (i = 0, cnt = 0; i < n; i++) {                 scanf("%d", &num[i]);                 if (isOdd(num[i]))                     arr[cnt++] = num[i];             }             bubble_sort(arr, cnt);             for (i = 0, k = 0; k < cnt && i < n; i++)                 if (isOdd(num[i]))                     num[i] = arr[k++];             free(arr);         } else if (strcmp(word, "even") == 0) {             printf("%s\n", word);              for (i = 0, cnt = 0; i < n; i++) {                 scanf("%d", &num[i]);                 if (isEven(num[i]))                     arr[cnt++] = num[i];             }              bubble_sort(arr, cnt);              for (i = 0, k = 0; k < cnt && i < n; i++)                 if (isEven(num[i]))                     num[i] = arr[k++];             free(arr);         } #else         if(strcmp(word, "odd") == 0) {             printf("%s\n", word);             for (i = 0; i < n; i++)                 scanf("%d", &num[i]);             select_sort(num, n, isOdd);         } else if (strcmp(word, "even") == 0) {             printf("%s\n", word);             for (i = 0; i < n; i++)                 scanf("%d", &num[i]);             select_sort(num, n, isEven);         } #endif         printf("Show all numbers: \n");         print_arr(num, n);     }     return 0; }  以上是我的demo，可以测试一下； 使用了两种方法：select_sort是选择排序，bubble_sort是冒泡排序；一个是以时间换空间，一个是以空间换时间； 使用到了函数指针； 另外，改了一下原有代码中出现的bug;s 比如输入scanf第二个参数应该是地址，&n;

int main() {     int i,n;     //char *word;     char word[10];

弄个冒泡排序就好勒呀，两个循环均跳过那些数字就好，就当不存在


Question: c语言大神们求助

浮点数是不精确的保存的

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

引用 2 楼 qq_37873843 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] 建议看一下浮点数的表示。它是分为小数部分和整数部分，每部分的占32位里的位数。 不懂。。。可以详细解释一下吗[/quote]http://blog.chinaunix.net/uid-26983295-id-3279324.html 看一下这个链接里解释的～

引用 1 楼 cfjtaishan 的回复:建议看一下浮点数的表示。它是分为小数部分和整数部分，每部分的占32位里的位数。 不懂。。。可以详细解释一下吗

建议看一下浮点数的表示。它是分为小数部分和整数部分，每部分的占32位里的位数。


Question: 二维数组里的指针

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组

a是一个二维数组，并且a 的列数是5； *(*(p+i)+j)=data++; /*equal: *(p[i]+j) = data++;*/ p[i]是指第i行的首地址。 通过下面的一行输出可以查看一下，三个地址值之间是否相差：5 * sizeof(int)个字节


Question: 这个while循环终止了却跳不出来为什么

引用 15 楼 aimasa 的回复:是因为sizeof返回的是字节大小，所以不行？（一本正经的胡说八道）我也不知道 这个系列要的“缓冲区大小”指的是“能容纳的字符个数”而不是“字节个数”。 窄字符版本要的是char的个数，宽字符版本要的是wchar_t的个数。 所以对于数组缓冲区（buf），直接sizeof(buf)是错误的；sizeof(buf)/sizeof(buf[0])、_countof(buf)之类才是正确的。 而对于单个字符的缓冲区，1个char c的大小就是1，1个wchar_t c的大小也是1；sizeof(c)一则多余，二则对于后者是错误的。

你可以选择用if语句来循环

听说fflush(stdin)在Linux下不灵。

引用 14 楼 idzeta的回复:scanf_s要指定每个对应“c”、“s”以及传说中的“[”格式的缓冲区的大小。  char c; scanf_s("%c", &c, 1); // 思考题：为什么不用sizeof？ [quote=引用 13 楼 aimasa 的回复:] [quote=引用 12 楼 赵4老师的回复:] //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; 诶，这段代码没看懂，为什么啊？[/quote] 本意是为了“吃”掉换行,和在之后加fflush(stdin)的做法类似（但fflush“吃”得更多）。 然而这“都”字散发着浓郁的经验主义（教条主义）的气息。 [/quote] 是因为sizeof返回的是字节大小，所以不行？（一本正经的胡说八道）我也不知道

scanf_s要指定每个对应“c”、“s”以及传说中的“[”格式的缓冲区的大小。  char c; scanf_s("%c", &c, 1); // 思考题：为什么不用sizeof？ 引用 13 楼 aimasa 的回复:[quote=引用 12 楼 赵4老师的回复:] //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; 诶，这段代码没看懂，为什么啊？[/quote] 本意是为了“吃”掉换行,和在之后加fflush(stdin)的做法类似（但fflush“吃”得更多）。 然而这“都”字散发着浓郁的经验主义（教条主义）的气息。

引用 12 楼 赵4老师的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; 诶，这段代码没看懂，为什么啊？

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

引用 7 楼 lilimite的回复:我感觉还是缓存的问题，char型是占一个字节的，每次输入之后的回车键缓存在里面会被下次的scanf直接扫描，我用的是vc， #include<stdio.h> main(){     char a;     scanf("%c", &a); fflush(stdin);     while (a!= '@')     { 		 printf("kek \n");         scanf("%c", &a); 		fflush(stdin);      }     printf("oo "); }  可以用F10单步看一看每一次输入之后a的值变化 诶，我一会去看看，谢谢你啦

引用 9 楼 aimasa的回复:[quote=引用 7 楼 lilimite的回复:]我感觉还是缓存的问题，char型是占一个字节的，每次输入之后的回车键缓存在里面会被下次的scanf直接扫描，我用的是vc， #include<stdio.h> main(){     char a;     scanf("%c", &a); fflush(stdin);     while (a!= '@')     { 		 printf("kek \n");         scanf("%c", &a); 		fflush(stdin);      }     printf("oo "); }  可以用F10单步看一看每一次输入之后a的值变化 诶，我一会去看看，谢谢你啦[/quote] 奥难道是软件的问题，我用的是visual studio ，这样输入以后连kak都不出来了

引用 5 楼 自信男孩的回复:[quote=引用 2 楼 aimasa 的回复:] 我试了，可是还是不行，它就是跳不出循环 你是如何输入的？ 说一下你的尝试样例[/quote] 我输入是123@，输出是     kak    然后……运行到这里，就停止运行了

引用 2 楼 aimasa 的回复:我试了，可是还是不行，它就是跳不出循环 你是如何输入的？ 说一下你的尝试样例

增加fflush(stdin)清除缓存即可，或者用getchar（）也行 #include<stdio.h> #include<stdlib.h> main(){     char a;     scanf_s("%c", &a); 	fflush(stdin);     while (a!= '@')     {          printf("请重新输入： "); 		scanf_s("%c", &a); 		fflush(stdin);         printf("kek ");     }     printf("oo "); }

引用 1 楼 自信男孩的回复:#include<stdio.h>  int main() {     char a;     scanf_s("%c", &a);     getchar();     while (a != '@')     {         scanf_s("%c", &a);         getchar();         printf("kek ");     }     printf("oo "); } while判断条件是输入@字符才能退出循环； 另外，为了避免多次循环，加一句getchar 我试了，可是它还是跳不出循环

我试了，可是还是不行，它就是跳不出循环


Question: 参数执行顺序问题

引用 18 楼 xsklld 的回复:[quote=引用 17 楼 cfjtaishan 的回复:] [quote=引用 16 楼 xsklld 的回复:] [quote=引用 13 楼 cfjtaishan 的回复:] [quote=引用 11 楼 xsklld 的回复:] [quote=引用 10 楼 paschen 的回复:] 默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。[/quote] 对于楼主的这个函数参数是有关系的，从右向左压栈就是func(8,8)，从左向右就是func(6,8)[/quote] 你指的是求值顺序，和压栈顺序没有关系。 见：calling convention and evaluation order[/quote] 入栈顺序决定了楼主这个函数调用的求值顺序[/quote] 依据呢？[/quote] func(8,8)

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  不要写连自己也预测不了结果的代码！

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

引用 11 楼 xsklld 的回复:[quote=引用 10 楼 paschen 的回复:] 默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。[/quote] 对于楼主的这个函数参数是有关系的，从右向左压栈就是func(8,8)，从左向右就是func(6,8)

引用 17 楼 cfjtaishan 的回复:[quote=引用 16 楼 xsklld 的回复:] [quote=引用 13 楼 cfjtaishan 的回复:] [quote=引用 11 楼 xsklld 的回复:] [quote=引用 10 楼 paschen 的回复:] 默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。[/quote] 对于楼主的这个函数参数是有关系的，从右向左压栈就是func(8,8)，从左向右就是func(6,8)[/quote] 你指的是求值顺序，和压栈顺序没有关系。 见：calling convention and evaluation order[/quote] 入栈顺序决定了楼主这个函数调用的求值顺序[/quote] 依据呢？

不确定，不要这样写。

引用 16 楼 xsklld 的回复:[quote=引用 13 楼 cfjtaishan 的回复:] [quote=引用 11 楼 xsklld 的回复:] [quote=引用 10 楼 paschen 的回复:] 默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。[/quote] 对于楼主的这个函数参数是有关系的，从右向左压栈就是func(8,8)，从左向右就是func(6,8)[/quote] 你指的是求值顺序，和压栈顺序没有关系。 见：calling convention and evaluation order[/quote] 入栈顺序决定了楼主这个函数调用的求值顺序

引用 13 楼 cfjtaishan 的回复:[quote=引用 11 楼 xsklld 的回复:] [quote=引用 10 楼 paschen 的回复:] 默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。[/quote] 对于楼主的这个函数参数是有关系的，从右向左压栈就是func(8,8)，从左向右就是func(6,8)[/quote] 你指的是求值顺序，和压栈顺序没有关系。 见：calling convention and evaluation order

引用 10 楼 paschen 的回复:默认的调用约定中函数参数是从右向左进行压栈的 压栈顺序和求值顺序并没有什么关系，我完全可以先从左往右求值，（然后存下求得的值），再从右往左压栈。

引用 楼主 qq_18888869 的回复:#include<stdio.h>  fun(int a ,int b) { int c; c=a+b; return c; } main() { int x=6,r; r=func(x,x+=2); printf("%d\n",r); } 结果是16先求了右边的参数，为什么不是x=6带进去，第二个x+2=8带进去呢？求大神指点  那你应该func(x, x+2);

调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx

引用 3 楼 vnvlyp 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 这是函数栈参数压栈的顺序决定的，从右开始依次压入栈，栈是先进后出，最后压栈的第一个参数会第一个出栈。 如果楼主不想将计算后的值作为第一个参数，那么建议在调用函数前先保存，然后在传入；  这就是个表达式顺序点的问题，和栈有什么关系？ gcc现在都会检查这种问题并且警告 warning: unsequenced modification fastcall调用方式甚至都不一定用到栈，编译器完全可以从左到右计算参数，然而这样写依然是未定义行为。[/quote] 虽然是表达式，但是参数传递，传递的是值，那么它需要将计算结果传过去。我看fastcall的参数从左到右传递也不是所有参数，是有条件的 http://blog.csdn.net/shenwansangz/article/details/50965415

默认的调用约定中函数参数是从右向左进行压栈的

引用 2 楼 cfjtaishan 的回复:这是函数栈参数压栈的顺序决定的，从右开始依次压入栈，栈是先进后出，最后压栈的第一个参数会第一个出栈。 如果楼主不想将计算后的值作为第一个参数，那么建议在调用函数前先保存，然后在传入；  这就是个表达式顺序点的问题，和栈有什么关系？ gcc现在都会检查这种问题并且警告 warning: unsequenced modification fastcall调用方式甚至都不一定用到栈，编译器完全可以从左到右计算参数，然而这样写依然是未定义行为。

引用 7 楼 vnvlyp 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] [quote=引用 3 楼 vnvlyp 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] 这是函数栈参数压栈的顺序决定的，从右开始依次压入栈，栈是先进后出，最后压栈的第一个参数会第一个出栈。 如果楼主不想将计算后的值作为第一个参数，那么建议在调用函数前先保存，然后在传入；  这就是个表达式顺序点的问题，和栈有什么关系？ gcc现在都会检查这种问题并且警告 warning: unsequenced modification fastcall调用方式甚至都不一定用到栈，编译器完全可以从左到右计算参数，然而这样写依然是未定义行为。[/quote] 虽然是表达式，但是参数传递，传递的是值，那么它需要将计算结果传过去。我看fastcall的参数从左到右传递也不是所有参数，是有条件的 http://blog.csdn.net/shenwansangz/article/details/50965415[/quote]  我不是要说fastcall是从左到右，我是说标准并没有规定函数参数的计算顺序，任何人完全可以写一个编译器是按照随机顺序入栈而依然符合语言标准。宣传从右到左或者从左到右都有点误导别人的成分。 https://timsong-cpp.github.io/cppwp/n3337/expr.call#8 N3337说： The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another.[/quote] 我感觉这样做没有实在意义，不按照编译器的执行。

引用 4 楼 cfjtaishan 的回复:[quote=引用 3 楼 vnvlyp 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] 这是函数栈参数压栈的顺序决定的，从右开始依次压入栈，栈是先进后出，最后压栈的第一个参数会第一个出栈。 如果楼主不想将计算后的值作为第一个参数，那么建议在调用函数前先保存，然后在传入；  这就是个表达式顺序点的问题，和栈有什么关系？ gcc现在都会检查这种问题并且警告 warning: unsequenced modification fastcall调用方式甚至都不一定用到栈，编译器完全可以从左到右计算参数，然而这样写依然是未定义行为。[/quote] 虽然是表达式，但是参数传递，传递的是值，那么它需要将计算结果传过去。我看fastcall的参数从左到右传递也不是所有参数，是有条件的 http://blog.csdn.net/shenwansangz/article/details/50965415[/quote]  我不是要说fastcall是从左到右，我是说标准并没有规定函数参数的计算顺序，任何人完全可以写一个编译器是按照随机顺序入栈而依然符合语言标准。宣传从右到左或者从左到右都有点误导别人的成分。 https://timsong-cpp.github.io/cppwp/n3337/expr.call#8 N3337说： The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another.

首先求值顺序是不确定的 参数有两个表达式 x x += 2 它们的先后求值顺序并不确定，所以是一个未定义行为 有可能是6 8， 8 8甚至是其他（x+=2求值过程取x）  跟压栈顺序并没有很大关系


Question: 一个小问题

查MSDN是Windows程序员必须掌握的技能之一。    Preprocessor Directives Preprocessor directives, such as #define and #ifdef, are typically used to make source programs easy to change and easy to compile in different execution environments. Directives in the source file tell the preprocessor to perform specific actions. For example, the preprocessor can replace tokens in the text, insert the contents of other files into the source file, or suppress compilation of part of the file by removing sections of text. Preprocessor lines are recognized and carried out before macro expansion. Therefore, if a macro expands into something that looks like a preprocessor command, that command is not recognized by the preprocessor.  Preprocessor statements use the same character set as source file statements, with the exception that escape sequences are not supported. The character set used in preprocessor statements is the same as the execution character set. The preprocessor also recognizes negative character values.   The preprocessor recognizes the following directives:  #define #error #import #undef  #elif #if #include    #else #ifdef #line    #endif #ifndef #pragma      The number sign (#) must be the first nonwhite-space character on the line containing the directive; white-space characters can appear between the number sign and the first letter of the directive. Some directives include arguments or values. Any text that follows a directive (except an argument or value that is part of the directive) must be preceded by the single-line comment delimiter (//) or enclosed in comment delimiters (/*  */). Lines containing preprocessor directives can be continued by immediately preceding the end-of-line marker with a backslash (\).  Preprocessor directives can appear anywhere in a source file, but they apply only to the remainder of the source file.

算！百度下你就了解了

宏定义是指以#define，#ifdef ... #else ...#endif等等这样的;  #include不算是吧。


Question: 求解，看不出来错误

第一个是输出，scanf换成printf; 最后printf("..... ",n);

第一个scanf换成printf

额，说错了，前面那句应该改成printf，把n的定义移动到它前面

把n的定义移到scanf那句上面试试，c语言必须把定义放到语句块儿最前面

1:行4 scanf换为printf，这才是打印  2:行7 8 9 a += b+= c+=全部换成 n +=  3:行8  * 6 改为 *8  4:最后一行 把右引号（“）提到逗号前面  等错误


Question: 谁能通俗一点说一下C语言！小白一个。新人报到！

引用 3 楼 qq_37871430 的回复:什么是二级视频.. 二级视频就是C语言二级的视频啊，http://www.51zxw.net/list.aspx?cid=329

那以后拜托各位大神提携小弟一下  小弟会努力学习的，书本这两天就到。希望我能成功！

看着本书，建议将书上的程序都编译，测试一遍，并将后面的作业题都保质保量的完成；这样完全的看一本书，也差不多了。 但是遇到问题，要多上网查，多问问身边的老师或者同学。 多动手，多思考，多总结～

什么是二级视频..

如果没有任何基础，看看二级视频还是可以考虑一下的，入门嘛，最好走正道

把书上的例子程序敲进去，调通。就行了。


Question: 【C】关于二维数组的指针

http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组

谢谢大家不知道怎么回复各位，是因为没有回复对方的机制么

float (*z)[MONTHS];  z = rain;

int (*z)[MONTHS];  z = rain; 这样是可以的。你要定义数组指针，而不是指针数组。

怎么一直乱码。。。 *(z)[MONTHS]--->(*z)[MONTHS]//指针数组与数组指针的区别


Question: 计算快乐值我不知哪里错了，求大神们教？

#include <stdio.h> #include <stdlib.h>  #define MAXPOW 1999  int gethappy[55]; int losepow[55]; int dp[55][MAXPOW];  int main(void) {     int i, j;     int n;      scanf("%d",&n);      for (i = 0; i < n; i++)         scanf("%d", &gethappy[i]);     for (i = 0; i < n; i++)         scanf("%d", &losepow[i]);      for (j = 0; j < MAXPOW; j++)         dp[0][j] = losepow[0] <= j ? gethappy[0] : 0;      for (i = 1; i < n; i++) {         for (j = 0; j < MAXPOW; j++) {             if (losepow[i]>j) {                 dp[i][j] = dp[i-1][j];             } else {                 if (dp[i-1][j]>dp[i-1][j-losepow[i]]+gethappy[i])                     dp[i][j] = dp[i-1][j];                 else                     dp[i][j] = dp[i-1][j-losepow[i]] + gethappy[i];             }         }     }     printf("%d", dp[n-1][MAXPOW-1]+1);      return 0; } 参考一下这个吧。 http://blog.csdn.net/timpcfan/article/details/52966493

引用 3 楼 cfjtaishan 的回复:[quote=引用 2 楼 qq_36338022 的回复:] 我的程序能正常运行，但是就是过不了题目 我用测试用例测试的，没有问题，能够输出77; 你说的过不了题目是什么题目？[/quote] 样例测的没错，但是换组数据就不符合题目要求了 例如： 输入 4 15 60 70 40 500 400 1500 500 正确的输出结果是 131 但是这个程序输出的是 116 我想问怎样修改才能正确，符合上面的题目要求。

引用 2 楼 qq_36338022 的回复:我的程序能正常运行，但是就是过不了题目 我用测试用例测试的，没有问题，能够输出77; 你说的过不了题目是什么题目？

我的程序能正常运行，但是就是过不了题目

#include <stdio.h>  #define     MAX_SIZE    32  int main() {     int n, i, e = 2000, h =1,j,m;     int happy[MAX_SIZE],low[MAX_SIZE];     double a[MAX_SIZE], t;      scanf("%d",&n);      for(i=0;i<n;i++)     {         scanf("%d",&happy[i]);     }      for(i=0;i<n;i++)     {         scanf("%d",&low[i]);     }     for(i=0;i<n;i++)     {         a[i]=happy[i]/low[i];      }     for(i=0;i<n-1;i++)     {         for(j=0;j<n-i-1;j++)         {             if(a[j] > a[j+1])             {                 t=a[j];a[j]=a[j+1];a[j+1]=t;                 m=low[j];low[j]=low[j+1];low[j+1]=m;                 m=happy[j];happy[j]=happy[j+1];happy[j+1]=m;             }         }     }     for(i=n-1;i>=0;i--)     {         h=happy[i]+h;         e=e-low[i];         if(e<0) {             e=e+low[i];             h=h-happy[i];         }     }     printf("%d\n", h);      return 0;  }  测试了你的程序，能够正常输出。提示的是什么问题？ 建议：在C语言中不支持可变数组，建议申请固定数组长度；也要注意下coding  style.


Question: printf的本质是什么？

Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt  C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c  源码面前，了无秘密。

我觉得他就是一个格式化的输出吧，可以利用格式控制符输出字符%c，数字%d，字符串%s等,而且还能控制宽度，位数。格式化是他区别于其他输出字符的主要区别。

建议看一下printf的实现，并不是简单的转成字符串；这部分是可变参数实现的。

printf的本质是啥，不同层次的程序员是有不同理解的，楼主的理解也是一种不错的解释

格式化字符串，当然要考虑类型，它只对内置类型，字符串和指针进行有效的格式化


Question: 用C语言创建单链表为什么总是失败？？求解？？

初始化就有问题，初始化应该是带头结点的尾插法链表，然后输入数据的时候用的是printf("%d",l->next);不应该是scanf("%d",&l->next);

仅供参考：//不带表头结点的单向链表 #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=v;             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=v;                 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) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     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-> //

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

两处问题：  1、if(i=50)  应该是 ==  2、while(l!=NULL)     {         l=l->next;         printf("%d",l->data);     }  里面需要换下顺序，否则l->next为null时还在取数据

p1=(LinkList)malloc(sizeof(LNode)); p2->next=p1; p2=p1;  调换下顺序

#include<stdio.h> #include<stdlib.h>  #define INIT_SIZE  50  typedef struct LNode {     int data;     struct LNode *next; }LNode,*LinkList;  LinkList InitList_L(); //void  ListInsert_L(LinkList &L, int i, int e);  int main() {     LinkList l;     l = InitList_L();      while(l)     {         printf("%d ", l->data);         l=l->next;     }     putchar(10);     return 0; }  LinkList  InitList_L() {     int i;     LinkList head, p1, p2;      for(i = 0; i < INIT_SIZE + 1; i++)     {         if(i == 0)         {             p1 = (LinkList)malloc(sizeof(LNode));             p1->data = i+1;             head = p1;             p2 = head;             //p1 = (LinkList)malloc(sizeof(LNode));         }         else         {             p1 = (LinkList)malloc(sizeof(LNode));             p1->data = i+1;             p2->next = p1;             p2 = p1;         }         if(i == INIT_SIZE)    /*replace =  with == */         {             p2->next = NULL;         }     }     return head; }  改了一下你的创建链表的方式，你的方式也没多大问题，但是注意会多申请一个节点的空间，但是这个节点没有加到你的链表里，你可以推演一下你的申请过程。


Question: 帮我看下这个程序哪里出错了

引用 1 楼 cfjtaishan 的回复:#include<stdio.h>  #define CHARS 10 #define ROWS 6  int main(void) {     int row;     char ch = 0;      for (row = 0; row < (ch + ROWS); row++)   /*ch未初始化*/     {         for (ch = 'A'; ch < ('A' + CHARS); ch++)    /*for循环里是分号;,此行末尾的分号去掉*/         printf("%c", ch);         printf("\n");     }     return 0; } 这活不细心的人 十个也顶不上一个细心的人.....有时候 一个x==1,写成x=1，能查一下午...

for (ch = 'A', ch < ('A' + CHARS); ch++);  改成：  for (ch = 'A'; ch < ('A' + CHARS); ch++);  其次，你的ch没有初始化就使用了

一个ch未初始化，一个for()循环少一个分号。


Question: 一个小问题

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

字符串中显示小数点？ 要是读取数据的话，内存存储都是一样的只是看如何读取。

你想怎么判断 在纸上直接看能看出来 有小数点， 程序的话abs(f - (int)f）看看是否是零

因为在内存中都是0101存储的，不分是什么类型的。

这种需求很少遇到吧，一般都是确定其类型（基本类型），然后从该变量中获取值； 比如，知道浮点型数据a,得到其整数部分的值或者小数部分的值等等，很少遇到你这样的需求。

if（(int)a == a)

不就是小数点的区别啊，做判断啊，再判断所有字符是否0到9

一个字符串？  1： 有小数点 有 e字符 的是浮点数，这个判断主要是明面上的  2：这个判断方法主要是内存值方面的，假设不把诸如 1.0000 当做浮点数的情况 char str[16];//你的字符串 double f = atof(str); // 减去整数部分，看小数后面的数是不是在某个范围内来判断是不是整数 bool bInt = abs(f - (int)f) < 1e-6;  //bool bInt = abs(f - (int)f) < 1e-10


Question: 为什么第二个malloc执行时会错啊

transcript->course没有初始化，是NULL;  *transcript->course = (Course*)malloc(sizeof (Course));//就这没法执行  相当于： *NULL=  (Course*)malloc(sizeof (Course));  你需要先分配transcript->course;

你那个类型不对的，课程用二级指针是说明有很多课程吗？如果是要这么写  transcript->course = (Course**)malloc(sizeof (Course)*numOfCourse);//就这没法执行  for(int i=0; i<numOfCourse; i++){ (transcript->course)[i] = (Course*)malloc(sizeof (Course)); }


Question: 一道作业题，帮忙看看哪里错了

多谢多谢啦~长知识了，现在运行没问题了。

我刚刚试了一下，好像scanf直接赋值给a也可以，两种写法结果竟然一样。

问题1： scanf函数接受的是变量的地址，而不是变量。 你要把字符串赋值给字符数组，而不是把字符串中的字符赋给a中的元素，字符串本身是个指针，数组名其实也是个指针，所以是把指针的值赋给另外一个指针变量，所以应该是scanf("%s",&a);  问题2： 为什么while语句和大括号之间要加分号呢？  问题3： i的取值应该是从0开始吧，a[0]表示的才是第一个元素。

while(a[i]!='\0'); 后面多了一个分号  后面的那个while 也是  把分号去掉就可以了，否则你的while的循环部分是个空语句


Question: 两个小问题

引用 2 楼 user-3 的回复:[quote=引用 1 楼 自信男孩的回复:]fun(x+y,(e1,e2),fun(xy,d,(a,b))); 参数是3个，不过挺诡异，因为函数调用中用本函数调用的返回值作为实参。 参数传递都是值传递，不过会有人迟疑，那么传递地址呢，其实也是值传递，因为这个值是地址值； 这么说后面的fun函数也是实参。[/quote] 是fun函数的返回值

引用 1 楼 cfjtaishan 的回复:fun(x+y,(e1,e2),fun(xy,d,(a,b))); 参数是3个，不过挺诡异，因为函数调用中用本函数调用的返回值作为实参。 参数传递都是值传递，不过会有人迟疑，那么传递地址呢，其实也是值传递，因为这个值是地址值； 为什么被调函数里的参数fun()里边的xy,d,(a,b)不算是参数呢，他们也是参数，只是不算是调用函数的参数而已呀。 这个个数计算为什么不算里边的那个函数的参数。

引用 1 楼 自信男孩的回复:fun(x+y,(e1,e2),fun(xy,d,(a,b))); 参数是3个，不过挺诡异，因为函数调用中用本函数调用的返回值作为实参。 参数传递都是值传递，不过会有人迟疑，那么传递地址呢，其实也是值传递，因为这个值是地址值； 这么说后面的fun函数也是实参。


Question: VS2015 基础问题  strcpy编译报错

#pragma warning(disable:4996) ……

因为这个函数是不安全，可能造成缓冲区溢出，所以现在建议用strcpy_s来代替 如果仍想用可以选择以下任何一种方法： 1、新建项目时不要勾选安全开发生命周期检查 2、在项目属性C/C++命令行中加上 /D _CRT_SECURE_NO_WARNINGS

我是按照Linux的函数来解释的，你可以按照windows的函数去处理。比如strcpy_s

程序没问题，但是编译器提出了2点：gets的使用和strcpy的使用； gets的使用不安全，fgets的使用相对gets的使用是安全的，为什么呢，char *fgets(char *s, int size, FILE *stream); 主要在fgets的第二个参数上，它定义了缓存接收多少个字节；输入多了，没关系，它只将输入的size个字节放到缓存里，其他丢掉；gets不会，它是你输入多少个，它就往缓存里放多少个，越不越界它不管。 strcpy一样，如果str1的缓存如果小于str2字符串的长度，strcpy也不管，它只负责将str2的所有字符拷贝至str1中。 strncpy不一样，char *strncpy(char *dest, const char *src, size_t n);它有第三个参数，这个参数用来限制拷贝多少个至dest，如果dest只有30个字节的空间，第三个参数输入30，那么即使src有50个字符也没关系，只要29+1个，其他丢掉。  另外，注意fgets的输入可能会将回车符算作有效字符放到缓存里。

新手小白  求教   具体步骤