Question: 有懂c++和java的么？ 求翻译下c代码

@gspUser  你的翻译是正确的，我校验截取错了

那是你的C函数代码错了，你的C函数的计算结果和工业上常用 Modbus A001 的CRC16计算结果对不上。 用你的说的数据用你的C函数计算出来的CRC校验码，也和你说的校验码不一样， 你给的测试数据与工业用的校验结果也对不上. 用楼上的CRC校验函数得到的校验码也和你给的数据的校验码不一样  unsigned char d[15]={0x7e,0xfe,0x10,0x02,0x21,0x04,0x0b,0x00,0x00,0x00,0x0a,0x24,0x00,0x00,0x00};  printf("0x%04hX\n",exampleOfUseCRC16(d,15));//0x11FB printf("0x%04hX\n",crc16l(d,15));//0x61C9  不知道你的CRC是用什么样的表达式， 也可能是你的数据需要的校验起始字节不是从第一个字节开始的 有没有协议

仅供参考：/***** crc16.c *****/ #include <stdio.h>  #define CRC16_DNP   0x3D65u     // DNP, IEC 870, M-BUS, wM-BUS, ... #define CRC16_CCITT 0x1021u     // X.25, V.41, HDLC FCS, Bluetooth, ...  //Other polynoms not tested #define CRC16_IBM   0x8005u     // ModBus, USB, Bisync, CRC-16, CRC-16-ANSI, ... #define CRC16_T10_DIF   0x8BB7u     // SCSI DIF #define CRC16_DECT  0x0589u     // Cordeless Telephones #define CRC16_ARINC 0xA02Bu     // ACARS Aplications  #define POLYNOM     CRC16_DNP   // Define the used polynom from one of the aboves  // Calculates the new crc16 with the newByte. Variable crcValue is the actual or initial value (0). unsigned short crc16(unsigned short crcValue, unsigned char newByte) {     int i;      for (i = 0; i < 8; i++) {         if (((crcValue & 0x8000u) >> 8) ^ (newByte & 0x80u)){             crcValue = (crcValue << 1)  ^ POLYNOM;         } else {             crcValue = (crcValue << 1);         }         newByte <<= 1;     }     return crcValue; }  unsigned short exampleOfUseCRC16(unsigned char *Data, int len){      unsigned short crc;     int aux = 0;      crc = 0x0000u; //Initialization of crc to 0x0000 for DNP     //crc = 0xFFFFu; //Initialization of crc to 0xFFFF for CCITT      while (aux < len){         crc = crc16(crc,Data[aux]);         aux++;     }      return (~crc); //The crc value for DNP it is obtained by NOT operation      //return crc; //The crc value for CCITT }  int main() {     unsigned char d[10]={0,1,2,3,4,5,6,7,8,9};      printf("0x%04hX\n",exampleOfUseCRC16(d,10));//0x1078     return 0; }

7efe100221040b0000000a24000000  ca05 05  crc校验和应该是 ca05,但是算出来的不对 啊 能帮忙看下么

java和C++的代码很相似，小小改动就可以了，运行结果和C++的是一样的  public static int CRC16(byte[] buf,int len) 	{ 	    int crc=0x0000;          short c,i;  		int mindex=0;         while(len!=0)          {           c=buf[mindex++];           for(i=0;i<8;i++)           {            if(((crc ^ c) & 1)>0)               crc=(crc>>1)^0xa001;            else                crc>>=1;           c>>=1;          }           len--;                  }        return crc;  	}


Question: 调用函数之前能够改变函数中的语句吗

不能  因为这个函数编译后形成的二进制文件是固定的，指令都定型了 你没法改

这个问题问得好啊！

不能，编译后的二进制是固定的并且不能改变。除非是暴力的手段直接修改系统运行时候的内存，但是你想要的效果是可以实现的！  int nCompareLower = 0; int Func(int a,int b) {         if(nCompareLower  && a < b)return 1;         else if(!nCompareLower  && a > b) return 2; return 0; }

能

不能。上楼有正解。代码编译后就定了。

笼统的说，硬要改变已编译好的写死的2进制文件， 也不是不可以， 参考hook  如果只讨论你这个例子，想直接改变你这行代码里的 这个 > 变 < ，代码是不能改的，但是你要的效果是可以实现的， 就是把这个比较运算符，抽象成变量，作为函数参数传进去，你传的是大于， 就按大于比较，你传的是小于， 就按小于比较  bool CmpGreater(int a, int b) { 	return a > b; } bool CmpLess(int a, int b) { 	return a < b; }  typedef bool (*CmpFun)(int, int);  int Func(int a, int b, CmpFun fun) { 	if (fun(a, b)) 		return 1; }  int main(int argc, char* argv[]) { 	CmpFun pGreater = CmpGreater; 	CmpFun pLess = CmpLess;  	Func(1, 2, pGreater); // 按a > b比较 	Func(1, 2, pLess); // 按a < b比较 }


Question: 求教，有个题不会

这个是要知道结构体内各变量是如何占用内存的，c和c++中是按照变量声明的先后顺序，定义的结构体数组中，每个数组元素占int的4个字节和结构体指针的4个字节共8个字节 a指向结构体数组的首地址，那么a+1代表的就是从a向后跳8个字节，那么a+1指向的就是a[1]的位置，以此类推。就建立起了一个单链表。for循环中是输出单链表的前两个结点的x的值。

百度：C 链表，学习相关知识点

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


Question: c新手问一个数组指针的问题

C语言规定数组的名字就是数组的首地址； 不要纠结这种问题

引用 3 楼 yangbomoto 的回复:#include<iostream> #include<string> #include<stdio.h> using namespace std;  int main(){  	int a[3] = { 1,2,3 }; 	cout << sizeof(int) << endl; 	cout << "a: " << a <<endl; 	cout << "a+1: " << a + 1 << endl; 	cout << "&a: " << &a << endl; 	cout << "&a+1: " << &a + 1 << endl;       cout<<"Hello....."<<endl;     system("pause");     return 0; }  由此可值，a代表的是数组的首地址，a+1向后跳int的字节，&a代表的是指向这真个数组（其值也是数组首地址），&a+1向后跳整个数组所占的字节。 +1

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

引用 7 楼 qq_24947841 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] 类型不同，a是int *类型（数组可以理解为指针常量），但是&a是int **类型。 因此：a + 1和&a + 1代表的长度不一样：a + 1表示基于a向后偏移sizeof(int)个字节，但是&a + 1是表示基于a向后偏移3 * sizeof(int)个字节。 类型是不同   但&a应该是 int (*)[3]类型[/quote] 对

&a是整个数组的首地址，a是数组首元素的首地址

引用 1 楼 cfjtaishan 的回复:类型不同，a是int *类型（数组可以理解为指针常量），但是&a是int **类型。 因此：a + 1和&a + 1代表的长度不一样：a + 1表示基于a向后偏移sizeof(int)个字节，但是&a + 1是表示基于a向后偏移3 * sizeof(int)个字节。 类型是不同   但&a应该是 int (*)[3]类型

int a[3] a 表示  &a[0] 这个没错,是首地址 &a 表示  int (*) [3] 这个,是一个指针指向有3个元素的结构  a  和 &a 的结构大小不回 a 是 int     &a 是 int (*)[3]

谢谢大神们的指教。

a是数组  第一个元素  的地址，与&a[0] 一样；     &a是 数组 的 首地址。  取一个数组名的地址（&a）所产生的是一个指向 数组 的指针，跟a（一个指向a[0]的指针）在指针的类型上是有区别的。

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


Question: 大佬帮忙看一下

#include <string.h> #include <stdio.h> #include <stdlib.h> #include <malloc.h>  typedef struct{     int num;     char name[10];     int zw; }DATATYPE;  typedef struct node{     DATATYPE data;     struct node *next; }NODE;  int FullList(); void SeekList(NODE* head); void InsertList(NODE* head); void DeleteList(NODE* head); void ChangeList(NODE* head); void AllList(NODE* head);  int main() {     NODE *head,*p,*s;     int tm;     head=(NODE*)malloc(sizeof(NODE));     head->next=NULL;     s = head;     printf("请输入学生人数：\n");     scanf("%d", &tm);     while(tm--){         printf("请依次输入 学号 姓名 座号\n");         p=(NODE*)malloc(sizeof(NODE));         scanf("%d%s%d",&p->data.num,p->data.name,&p->data.zw);         s->next = p;         s = p;     }     p->next=NULL;      while(1){         switch(FullList()){             case 1:                 InsertList(head);                 break;             case 2:                 SeekList(head);                 break;             case 3:                 DeleteList(head);                 break;             case 4:                 ChangeList(head);                 break;             case 5:                 AllList(head);                 break;             default:                 break;         }     }     return 0; } int FullList(){     int t;     printf("     --------------------------|----------------|--------------------------\n");     printf("     --------------------------|学生宿舍管理系统|--------------------------\n");     printf("     --------------------------|----------------|--------------------------\n");     printf("     ----------------------------1.插入学生信息----------------------------\n");     printf("     ----------------------------2.查询学生信息----------------------------\n");     printf("     ----------------------------3.删除学生信息----------------------------\n");     printf("     ----------------------------4.更改学生信息----------------------------\n");     printf("     ----------------------------5.查看全部信息----------------------------\n");     printf("请输入序号：\n");     while(1){         scanf("%d", &t);         if(t >= 6||t<1)             printf("请重新输入\n");         else             break;     }     return t; } void SeekList(NODE* head){     int x;     char t;     int numm;     char xmm[12];     NODE *p;     p=head->next;     printf("请输入1.姓名或2.学号：\n");     while(1){         scanf("%d",&x);         if(x==1){             scanf("%s",xmm);             while(strcmp(xmm,p->data.name)!=0){                 p=p->next;             }             printf("%d,%s,%d\n",p->data.num,p->data.name,p->data.zw);         }else if(x==2){             scanf("%d",&numm);             while(numm!=p->data.num){                 p=p->next;             }             printf("%d,%s,%d\n",p->data.num,p->data.name,p->data.zw);         }else             printf("输入错误！\n");         printf("结束输入时请输入:N/n\n");         scanf("%c",&t);         if(t=='n'||t=='N')             break;     } } void InsertList(NODE *head){     NODE *s,*p;     int j=0;     p = head;     s = (NODE *)malloc(sizeof(NODE));     if (!s)         exit(0);     printf("请输入学号 姓名 座号：\n");     scanf("%d%s%d",&s->data.num,s->data.name,&s->data.zw);     while(j<s->data.num-1 && p){         p = p->next;         j++;     }     if(p==NULL){         printf("无法插入数据！\n");     }else{         s->next = p->next;         p->next = s;         printf("数据插入成功！\n");     } }  void DeleteList(NODE* head) {     NODE *p, *s;     int num;      printf("请输入要删除的数据(学号）：\n");     s = head;     p = head->next;     scanf("%d",&num);      while (p && num != p->data.num) {         p = p->next;         s = s->next;     }     if (!p) {         printf("无法删除数据！\n");     } else {         s->next = p->next;         free(p);     }     /*     while(j<h.data.num-1&&p!=NULL){         p = p->next;         j++;     }     if(h==NULL)         printf("无法删除数据！\n");     else         p->next=p->next->next;     */ }  void AllList(NODE* head){      NODE *p;     p=head->next;     while(p) {         printf("学号：%d 姓名：%s 座号：%d\n",p->data.num,p->data.name,p->data.zw);         p = p->next;     } } void ChangeList(NODE* head) {     NODE *p;     DATATYPE y;      p = head->next;     printf("请输入您要更改的信息：学号，姓名，座号\n");     scanf("%d%s%d",&y.num,y.name,&y.zw);      while (p && p->data.num != y.num) {         p = p->next;     }     if (!p) {         printf("没有找到!\n");     } else {         memcpy(&p->data, &y, sizeof(DATATYPE));     }     /*     while(t<y->data.num-1&&p!=NULL){         p=p->next;         t++;     }     y->next=p->next->next;     p->next=y;     */     printf("修改成功！\n"); } 参考一下吧

什么问题？问题不是靠猜出来的，建议详细说明一下你的问题。


Question: 学生宿舍管理系统（单链表）

void DeleteList(NODE* head){     NODE *h,*p;     int j=0;     printf("请输入要删除的数据：\n");     p=head;     scanf("%d%s%d",&h->data.num,h->data.name,&h->data.zw);     while(j<h->data.num-1&&p!=NULL){         p=p->next;         j++;     }     if(h==NULL)         printf("无法删除数据！\n");     else         p->next=p->next->next; } 删除操作，h是野指针，不能直接用h->data.name等等； 对于删除操作，建议如下：  void DeleteList(NODE* head) {     NODE *p, *s, *pdel;     int j=0, num;      printf("请输入要删除的数据(学号）：\n");     s = head;     p = head->next;     scanf("%d",&num);      while (p && num != p->data.num) {         p = p->next;         s = s->next;     }     if (!p) {         printf("无法删除数据！\n");     } else {         s->next = p->next;         free(p);     }     /*     while(j<h.data.num-1&&p!=NULL){         p = p->next;         j++;     }     if(h==NULL)         printf("无法删除数据！\n");     else         p->next=p->next->next;     */ }  多处有用到野指针。以下的代码是修改后的参考一下吧  #include <string.h> #include <stdio.h> #include <stdlib.h> #include <malloc.h>  typedef struct{     int num;     char name[10];     int zw; }DATATYPE;  typedef struct node{     DATATYPE data;     struct node *next; }NODE;  int FullList(); void SeekList(NODE* head); void InsertList(NODE* head); void DeleteList(NODE* head); void ChangeList(NODE* head); void AllList(NODE* head);  int main() {     NODE *head,*p,*s;     int tm;     head=(NODE*)malloc(sizeof(NODE));     head->next=NULL;     s = head;     printf("请输入学生人数：\n");     scanf("%d", &tm);     while(tm--){         printf("请依次输入 学号 姓名 座号\n");         p=(NODE*)malloc(sizeof(NODE));         scanf("%d%s%d",&p->data.num,p->data.name,&p->data.zw);         s->next = p;         s = p;     }     p->next=NULL;      while(1){         switch(FullList()){             case 1:                 InsertList(head);                 break;             case 2:                 SeekList(head);                 break;             case 3:                 DeleteList(head);                 break;             case 4:                 ChangeList(head);                 break;             case 5:                 AllList(head);                 break;             default:                 break;         }     }     return 0; } int FullList(){     int t;     printf("     --------------------------|----------------|--------------------------\n");     printf("     --------------------------|学生宿舍管理系统|--------------------------\n");     printf("     --------------------------|----------------|--------------------------\n");     printf("     ----------------------------1.插入学生信息----------------------------\n");     printf("     ----------------------------2.查询学生信息----------------------------\n");     printf("     ----------------------------3.删除学生信息----------------------------\n");     printf("     ----------------------------4.更改学生信息----------------------------\n");     printf("     ----------------------------5.查看全部信息----------------------------\n");     printf("请输入序号：\n");     while(1){         scanf("%d", &t);         if(t >= 6||t<1)             printf("请重新输入\n");         else             break;     }     return t; } void SeekList(NODE* head){     int x;     char t;     int numm;     char xmm[12];     NODE *p;     p=head->next;     printf("请输入1.姓名或2.学号：\n");     while(1){         scanf("%d",&x);         if(x==1){             scanf("%s",xmm);             while(strcmp(xmm,p->data.name)!=0){                 p=p->next;             }             printf("%d,%s,%d\n",p->data.num,p->data.name,p->data.zw);         }else if(x==2){             scanf("%d",&numm);             while(numm!=p->data.num){                 p=p->next;             }             printf("%d,%s,%d\n",p->data.num,p->data.name,p->data.zw);         }else             printf("输入错误！\n");         printf("结束输入时请输入:N/n\n");         scanf("%c",&t);         if(t=='n'||t=='N')             break;     } } void InsertList(NODE *head){     NODE *s,*p;     int j=0;     p = head;     s = (NODE *)malloc(sizeof(NODE));     if (!s)         exit(0);     printf("请输入学号 姓名 座号：\n");     scanf("%d%s%d",&s->data.num,s->data.name,&s->data.zw);     while(j<s->data.num-1 && p){         p = p->next;         j++;     }     if(p==NULL){         printf("无法插入数据！\n");     }else{         s->next = p->next;         p->next = s;         printf("数据插入成功！\n");     } }  void DeleteList(NODE* head) {     NODE *p, *s;     int num;      printf("请输入要删除的数据(学号）：\n");     s = head;     p = head->next;     scanf("%d",&num);      while (p && num != p->data.num) {         p = p->next;         s = s->next;     }     if (!p) {         printf("无法删除数据！\n");     } else {         s->next = p->next;         free(p);     }     /*     while(j<h.data.num-1&&p!=NULL){         p = p->next;         j++;     }     if(h==NULL)         printf("无法删除数据！\n");     else         p->next=p->next->next;     */ }  void AllList(NODE* head){      NODE *p;     p=head->next;     while(p) {         printf("学号：%d 姓名：%s 座号：%d\n",p->data.num,p->data.name,p->data.zw);         p = p->next;     } } void ChangeList(NODE* head) {     NODE *p;     DATATYPE y;      p = head->next;     printf("请输入您要更改的信息：学号，姓名，座号\n");     scanf("%d%s%d",&y.num,y.name,&y.zw);      while (p && p->data.num != y.num) {         p = p->next;     }     if (!p) {         printf("没有找到!\n");     } else {         memcpy(&p->data, &y, sizeof(DATATYPE));     }     /*     while(t<y->data.num-1&&p!=NULL){         p=p->next;         t++;     }     y->next=p->next->next;     p->next=y;     */     printf("修改成功！\n"); }


Question: 帮忙看一下

代码相当于 b+=(c++)-d+(--e)/(-f); a=b;  不熟悉运算符优先级和结合顺序时可以自己钻钻牛角尖，实际写代码这么搞的话，就需要好好反省了

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

如果依然在校，考试需要用到。可以在考前着重理解一下。如果是找工作，别人面试问道了这个问题，我觉得可以直接坦言，说这个表达式意义不大。自己实际一尝试就能得到答案。

可以直接跳过类似这样的表达式，不给自己也不给别人找麻烦。平时项目中如果用这样的表达式，还会被批评。

这种没必要去研究，用来考试的题， 编译能过说明语法正常的，然后把看起来连续的不合理符号拆成++，或者--，或者负号， 所以代码相当于 b+=(c++)-d+(--e)/(-f); a=b;

实际项目中，敢这么写代码的人，会被拉出去弹jj弹到死的。

个人认为这么复杂的运算，可读性很差，不建议去写。 根据实际逻辑，建议分开写。


Question: 求助:单链表插入节点出现问题

问题比较多，建议改成带头节点的单链表，逻辑上会简单点

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

单步跟踪程序运行，观察每一步变量变化情况，看是哪里与你期望的不一致，分析原因

引用 2 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h>  struct node {     int num;     struct node* next; };   struct node* create(int n) {     struct node* head,*p, *point;     p = head = NULL;     int i;     for(i=0;i<n;i++)     {         point=(struct node*)malloc(sizeof(struct node));         if (!point)             exit(0);         point->num=i;         if(0==i)         {             head=point;         }         else         {             p->next=point;         }         p = point;     }     point->next=NULL;     return head; }    struct node* insert_node(struct node* head,struct node* p)   //插入节点,head为链表的头结点,p为需要插入的节点. {     if (!head)     {         head = p;         p->next=NULL;         return head;     }      struct node* p1,*p2;     p1 = head;      while(p1 && p->num > p1->num)     {         p2 = p1;         p1 = p1->next;     }      if(p->num <= p1->num)     {         if(head == p1) /* head 和 p1比较，怎么可以和p比较呢*/         {             head = p;             p->next = p1;         }         else         {             p2->next = p;             p->next = p1;         }     }     else     {         p1->next = p;         p->next = NULL;     }      return head; }  void show_nodes(struct node *head) {     struct node* foreach;     for(foreach = head;foreach!=NULL;foreach = foreach->next)     {         printf("%d\t",foreach->num);     }     putchar(10); }   int main() {     struct node *head = create(9);     show_nodes(head);     struct node* pp = (struct node*)malloc(sizeof(struct node));     if (!pp)         return -1;     pp->num = -1;     head = insert_node(head, pp);     show_nodes(head);      return 0; } 参考一下吧 有多出错误，建议对比查找原因。 比如：insert_node函数，如果插入的位置是head前，那么head就会被更新，就需要返回新的head。 for(foreach=head;foreach!=NULL;foreach->next=foreach)    {         printf("%d\t",foreach->num);    } 建议显示功能单独用一个函数实现。另外foreach->next=foreach应该改成foreach = foreach->next; 其他问题建议对比代码找原因，如果还有不明白的，可以继续提问   我发现最关键的地方就在把p->num < p1->num  改成p->num <= p->num就不会出现这个问题,如果仅仅是< ,则不会执行添加插入节点的操作,只会执行最后p1->next=p;p->next=NULL;就是这个地方出现问题;非常感谢你的解答.


找到原因了,原来是窗口大小没设置好,我把它设置为100x100窗口就出来了.小弟新手,各位见笑了.

个人觉得SDK纯API方式编写GUI程序已经过时了，效率太低，了解一下原理就可以了，主要是消息机制。  图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。  　　C++ Builder是真正的可视化的开发工具。C++ Builder可以用鼠标拖拉控件加上设置属性轻松的“设计”出一个程序的图形用户界面，利用可视的组件/控件像“搭积木”一样，以“所见即所得”的方式搭建应用程序的界面，这也是C++ Builder这个名字中Builder的概念。这样，只需要用C++语言编写业务逻辑代码，类似于DOS下文本界面编程，只要专注于实现业务逻辑功能就可以了，代码非常简洁。数据的输入和表现，都在图形用户界面，非常直观、易用。这就是RAD开发（Rapid Application Development，快速应用程序开发）。  书籍推荐： 《C++Builder 6程序设计教程（第二版）》 （陆卫忠，刘文亮　等编著 /2011-04-01 /科学出版社）（当当网） 《C++Builder 6编程实例精解》（赵明现），PDF，是数字版的，非扫描版的，里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》（台湾 吴逸贤），里面有10几个简单小游戏的实现，可以自己看懂以后再重写，才是自己掌握的。 《C++ Builder 5高级编程实例精解》（刘滨 编著）都是较大的实用的程序。

用了这个风格后窗口就没了,是变全透明了还是根本没有我也不清楚

WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP 试试可行。  http://bbs.csdn.net/topics/90181689

求教,在网上找了好久一无所获


Question: 文件读写，怎样将文件数据读到链表？求助帮忙修改读取函数（read)，不胜感谢

引用 9 楼 自信男孩的回复:int main() {     STUDENT *head = NULL;     head = read(head);     //head = init();       int nam,secret;        /*登录操作使用的变量*/     printf("\n\n\n\n");     printf("\t------------------------学生学学籍管理系统------------------------\n");     printf("\n\n");     printf("\t\t\t\t账号：");     scanf("%d", &nam);     printf("\n");     printf("\t\t\t\t密码：");     scanf("%d", &secret);     //system("cls");      if(nam == 172021 && secret==172021)     {         printf("\n\n");         printf("\t\t\t\t登录成功!!!\n\n");          for(;;)         {             switch(menu_select())             {                 case 1:                     head = create(head);//注册                     break;                  case 2:                     search(head);//查询                     break;                  case 3:                     revise(head);//修改                     break;                 case 4:                     head=del(head);//删除                     break;                 case 5:                     printstu(head);//显示信息                     break;                 case 6:                     exit(0);//退出系统                     break;                 default:                     printf("输入错误");                     break;              }         }     }     else     {         printf("输入错误，请重新登录");     }    }  main  STUDENT *create(STUDENT *head)//创建链表，注册学生信息 {     char answer;     STUDENT *p, *pcur;     STUDENT *last = NULL;      pcur = last = head;     //system("cls");     do     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         printf("\n\n");         printf("----------学生信息录入---------- \n");         printf("\n");         printf("------请输入：\n");         printf("\t学号：");         scanf("%s", p->num);         printf("\t姓名：");         scanf("%s", p->name);         printf("\t性别：");         scanf("%s", p->sex);         printf("\t年龄：");         scanf("%d", &p->age);         printf("\t户籍：");         scanf("%s", p->addr);         printf("\t专业：");         scanf("%s", p->major);         printf("\t系别：");         scanf("%s", p->xb);         printf("\n");         printf("\t是否继续录入?(Y or N):   ");         getchar();   /* for '\n' */         scanf("%c", &answer);          while (pcur) {             if (pcur->num == p->num) {                 free(p);                 continue;             }             last = pcur;             pcur = pcur->next;         }           if(last) {             last->next = p;             last = last->next;         } else {             last = p;             head = last;         }     } while(answer=='Y'||answer=='y');      last->next = NULL;      save(head);    /* store infor into file */     printf("\n");     printf("\t保存成功！！！\n\n");     return head; }   create STUDENT *read(STUDENT *head)//读取文件函数（读文件） {     int ret;     FILE *fp;     STUDENT *p, *prev;      p = head;     if ((fp = fopen("student.txt","r"))==NULL)     {         printf("failed to open the file!!");         exit(1);     }      while (1)     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         ret = fscanf(fp,"%s %s %s %d %s %s %s", p->num, p->name,p->sex, &p->age,p->addr,p->major,p->xb);         if (ret < 7)             break;         if (!head) {             head = p;             prev = head;         } else {             prev->next = p;             prev = p;         }     }     free(p);     prev->next = NULL;      fclose(fp);      return head; } 修改的部分建议对比一下，作为一个参考吧 太谢谢你啦，我再仔细想想

引用 5 楼 Hhq128 的回复:[quote=引用 4 楼 Hhq128的回复:][quote=引用 2 楼 自信男孩的回复:]很纳闷，create函数里已经创建了链表（在内存里），为啥save之后还要read呢？并且read函数里传入的head已经是已经有文件的数据（因为刚把内存里的数据写入文件--save函数操作的）。 重新运行是head会初始化为NULL，read函数只是读取第一次save存储的student.txt文件，在第二次运行时直接用printfstu输出[/quote] 现在就是不知道怎样将第一次存储的txt文件读出来显示[/quote] read功能，建议你每次程序启动后先从文件里去读取，第一次去读时，文件为空。第二次启动后就有新数据了。 不能刚save就去read，这相当于把苹果从手里放入袋子里，然后马上又从袋子里拿出来。

引用 6 楼 赵4老师的回复:不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  仅供参考：//NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %31[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8   能帮我修改下吗，就是要求要第二次重启时直接可以显示数据

引用 4 楼 Hhq128的回复:[quote=引用 2 楼 自信男孩的回复:]很纳闷，create函数里已经创建了链表（在内存里），为啥save之后还要read呢？并且read函数里传入的head已经是已经有文件的数据（因为刚把内存里的数据写入文件--save函数操作的）。 重新运行是head会初始化为NULL，read函数只是读取第一次save存储的student.txt文件，在第二次运行时直接用printfstu输出[/quote] 现在就是不知道怎样将第一次存储的txt文件读出来显示

引用 2 楼 自信男孩的回复:很纳闷，create函数里已经创建了链表（在内存里），为啥save之后还要read呢？并且read函数里传入的head已经是已经有文件的数据（因为刚把内存里的数据写入文件--save函数操作的）。 重新运行是head会初始化为NULL，read函数只是读取第一次save存储的student.txt文件，在第二次运行时直接用printfstu输出

百度里面的题目设定不一样啊，，

百度搜相关关键字。

引用 10 楼 Hhq128的回复:[quote=引用 9 楼 自信男孩的回复:]int main() {     STUDENT *head = NULL;     head = read(head);     //head = init();       int nam,secret;        /*登录操作使用的变量*/     printf("\n\n\n\n");     printf("\t------------------------学生学学籍管理系统------------------------\n");     printf("\n\n");     printf("\t\t\t\t账号：");     scanf("%d", &nam);     printf("\n");     printf("\t\t\t\t密码：");     scanf("%d", &secret);     //system("cls");      if(nam == 172021 && secret==172021)     {         printf("\n\n");         printf("\t\t\t\t登录成功!!!\n\n");          for(;;)         {             switch(menu_select())             {                 case 1:                     head = create(head);//注册                     break;                  case 2:                     search(head);//查询                     break;                  case 3:                     revise(head);//修改                     break;                 case 4:                     head=del(head);//删除                     break;                 case 5:                     printstu(head);//显示信息                     break;                 case 6:                     exit(0);//退出系统                     break;                 default:                     printf("输入错误");                     break;              }         }     }     else     {         printf("输入错误，请重新登录");     }    }  main  STUDENT *create(STUDENT *head)//创建链表，注册学生信息 {     char answer;     STUDENT *p, *pcur;     STUDENT *last = NULL;      pcur = last = head;     //system("cls");     do     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         printf("\n\n");         printf("----------学生信息录入---------- \n");         printf("\n");         printf("------请输入：\n");         printf("\t学号：");         scanf("%s", p->num);         printf("\t姓名：");         scanf("%s", p->name);         printf("\t性别：");         scanf("%s", p->sex);         printf("\t年龄：");         scanf("%d", &p->age);         printf("\t户籍：");         scanf("%s", p->addr);         printf("\t专业：");         scanf("%s", p->major);         printf("\t系别：");         scanf("%s", p->xb);         printf("\n");         printf("\t是否继续录入?(Y or N):   ");         getchar();   /* for '\n' */         scanf("%c", &answer);          while (pcur) {             if (pcur->num == p->num) {                 free(p);                 continue;             }             last = pcur;             pcur = pcur->next;         }           if(last) {             last->next = p;             last = last->next;         } else {             last = p;             head = last;         }     } while(answer=='Y'||answer=='y');      last->next = NULL;      save(head);    /* store infor into file */     printf("\n");     printf("\t保存成功！！！\n\n");     return head; }   create STUDENT *read(STUDENT *head)//读取文件函数（读文件） {     int ret;     FILE *fp;     STUDENT *p, *prev;      p = head;     if ((fp = fopen("student.txt","r"))==NULL)     {         printf("failed to open the file!!");         exit(1);     }      while (1)     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         ret = fscanf(fp,"%s %s %s %d %s %s %s", p->num, p->name,p->sex, &p->age,p->addr,p->major,p->xb);         if (ret < 7)             break;         if (!head) {             head = p;             prev = head;         } else {             prev->next = p;             prev = p;         }     }     free(p);     prev->next = NULL;      fclose(fp);      return head; } 修改的部分建议对比一下，作为一个参考吧 太谢谢你啦，我再仔细想想[/quote] 以结帖，谢谢你啊！！我在需要读取文件的函数之前加了read函数，这样就不用改变原来的指针顺序了。可以运行，谢谢


Question: c语言中(double)clock()，（double）在这里是什么功能？

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

楼上的“大约等于”四个字是手抖打出的废话，可以无视

强制类型转换，大约等于 详细可以参考http://zh.cppreference.com/w/c/language/cast double k； k  =  （double）clock（）； 相当于 double k; clock_t c = clock(); k = (double) c;

把函数返回值强制转换为double类型，clock函数返回值为clock_t类型

这个是属于强制类型转换，double类型是8字节，可以表示的值比clock（）原有产生的数据类型表示的范围更大。这样是属于强制提高clock()的返回值类型。防止数据溢出或者丢掉；

类型强制转换     clock返回的是一个整数，把它强制转换成浮点数


Question: 我特么就懵逼了，我这行char name[40];怎么输出四十个烫字？

https://zhidao.baidu.com/question/123882045.html  这个里面讲了scanf和scanf_s的区别。  你如果还是想用scanf函数，在文件头加上下面这句代码，可以把C4996错误给屏蔽掉。   #pragma warning(disable:4996)

引用 7 楼 qq_30519247 的回复:[quote=引用 5 楼 paschen 的回复:] [quote=引用 3 楼 狼二羊的回复:][quote=引用 1 楼 wanggui2015 的回复:] Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; }  vs2015.我又写了几行，当我输入名字的时候，就闪退了。[/quote] scanf_s输入字符串还需要一个参数为缓冲区的大小  此外，最后输入留下的换行符\n仍在输入缓冲区中，会被你getchar接收导致程序直接结束，比如可以最后用两个getchar，其中一个用于接收掉\n   #include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	//printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name, 40); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	getchar(); 	return 0; } [/quote] 为什么后面要加40[/quote]  因为scanf_s是微软封装的安全函数接口，40是name的长度，scanf_s对于%s输入时需要字符串空间长度，这样保证输入字符串超过40时，不会导致越界溢出。

引用 5 楼 paschen 的回复:[quote=引用 3 楼 狼二羊的回复:][quote=引用 1 楼 wanggui2015 的回复:] Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; }  vs2015.我又写了几行，当我输入名字的时候，就闪退了。[/quote] scanf_s输入字符串还需要一个参数为缓冲区的大小  此外，最后输入留下的换行符\n仍在输入缓冲区中，会被你getchar接收导致程序直接结束，比如可以最后用两个getchar，其中一个用于接收掉\n   #include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	//printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name, 40); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	getchar(); 	return 0; } [/quote] 为什么后面要加40

引用 4 楼 wanggui2015 的回复:scanf_s("%s", name, 40);  [quote=引用 3 楼 qq_30519247 的回复:] [quote=引用 1 楼 wanggui2015 的回复:] Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; } vs2015.我又写了几行，当我输入名字的时候，就闪退了。[/quote][/quote] 为什么后面要加40

引用 3 楼 狼二羊的回复:[quote=引用 1 楼 wanggui2015 的回复:] Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; }  vs2015.我又写了几行，当我输入名字的时候，就闪退了。[/quote] scanf_s输入字符串还需要一个参数为缓冲区的大小  此外，最后输入留下的换行符\n仍在输入缓冲区中，会被你getchar接收导致程序直接结束，比如可以最后用两个getchar，其中一个用于接收掉\n   #include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	//printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name, 40); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	getchar(); 	return 0; }

scanf_s("%s", name, 40);  引用 3 楼 qq_30519247 的回复:[quote=引用 1 楼 wanggui2015 的回复:] Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; } vs2015.我又写了几行，当我输入名字的时候，就闪退了。[/quote]

引用 1 楼 wanggui2015 的回复:Visual Studio中，未初始化的栈空间用0xCC填充，而未初始化的堆空间用0xCD填充。 而0xCCCC和0xCDCD在中文GB2312编码中分别对应“烫”字和“屯”字。#include <stdio.h> #include <string.h> #define DENSITY 62.4 int main() { 	float weight, volume; 	int size, letters; 	char name[40];  	printf(name); 	printf("你叫啥\n"); 	scanf_s("%s", name); 	printf("%s,多大了\n", name); 	scanf_s("%f", &weight);  	getchar(); 	return 0; } vs2015.我又写了几行，当我输入名字的时候，就闪退了。

char name[40];局部变量未初始化


Question: 投诉对回复者不尊重的提问者

我个人习惯是对所有回复者都给不等的分数，我不喜欢那种一个人获得全部得分的提问者。

引用 1 楼 ysclxl 的回复:大家一起谴责这种臭不要脸的，  可以去客服专区投诉，管理员有强制结贴权限的 哎，真是的，既然做了这个板块，不想继续开放了通知一下啊。我的损失谁来解决，只能说"丑的都不要脸了”。

大家一起谴责这种臭不要脸的，  可以去客服专区投诉，管理员有强制结贴权限的


Question: 求助大佬帮忙修改代码，怎样将文件数据读入到链表，在第二次运行程序时不用手动输入直接读取显示

STUDENT *read(STUDENT *head)//读取文件函数（读文件） {     int ret;     FILE *fp;     STUDENT *p, *prev;      p = head;     if ((fp = fopen("student.txt","r"))==NULL)     {         printf("failed to open the file!!");         exit(1);     }      while (1)     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         ret = fscanf(fp,"%s %s %s %d %s %s %s", p->num, p->name,p->sex, &p->age,p->addr,p->major,p->xb);         if (ret < 7)             break;         if (!head) {             head = p;             prev = head;         } else {             prev->next = p;             prev = p;         }     }     free(p);     prev->next = NULL;      fclose(fp);      return head; } STUDENT *create(STUDENT *head)//创建链表，注册学生信息 {     char answer;     STUDENT *p, *pcur;     STUDENT *last = NULL;      pcur = last = head;     //system("cls");     do     {         p = (STUDENT *)malloc(sizeof(STUDENT));         if (!p)             exit(0);         printf("\n\n");         printf("----------学生信息录入---------- \n");         printf("\n");         printf("------请输入：\n");         printf("\t学号：");         scanf("%s", p->num);         printf("\t姓名：");         scanf("%s", p->name);         printf("\t性别：");         scanf("%s", p->sex);         printf("\t年龄：");         scanf("%d", &p->age);         printf("\t户籍：");         scanf("%s", p->addr);         printf("\t专业：");         scanf("%s", p->major);         printf("\t系别：");         scanf("%s", p->xb);         printf("\n");         printf("\t是否继续录入?(Y or N):   ");         getchar();   /* for '\n' */         scanf("%c", &answer);          while (pcur) {             if (pcur->num == p->num) {                 free(p);                 continue;             }             last = pcur;             pcur = pcur->next;         }           if(last) {             last->next = p;             last = last->next;         } else {             last = p;             head = last;         }     } while(answer=='Y'||answer=='y');      last->next = NULL;      save(head);    /* store infor into file */     printf("\n");     printf("\t保存成功！！！\n\n");     return head; } int main() {     STUDENT *head = NULL;     head = read(head);     //head = init();       int nam,secret;        /*登录操作使用的变量*/     printf("\n\n\n\n");     printf("\t------------------------学生学学籍管理系统------------------------\n");     printf("\n\n");     printf("\t\t\t\t账号：");     scanf("%d", &nam);     printf("\n");     printf("\t\t\t\t密码：");     scanf("%d", &secret);     //system("cls");      if(nam == 172021 && secret==172021)     {         printf("\n\n");         printf("\t\t\t\t登录成功!!!\n\n");          for(;;)         {             switch(menu_select())             {                 case 1:                     head = create(head);//注册                     break;                  case 2:                     search(head);//查询                     break;                  case 3:                     revise(head);//修改                     break;                 case 4:                     head=del(head);//删除                     break;                 case 5:                     printstu(head);//显示信息                     break;                 case 6:                     exit(0);//退出系统                     break;                 default:                     printf("输入错误");                     break;              }         }     }     else     {         printf("输入错误，请重新登录");     }    }

谢谢你啊，我对你给的答案做了调整，主函数我并没有改动，而是在显示函数和搜索函数之前先读一遍，这样就可以不用改变原来的结构。然后退出时做一次保存，这样也可以，谢谢你给我的参考！ int main() {     STUDENT *head;     head = init();          int nam,secret;        /*登录操作使用的变量*/     printf("\n\n\n\n");     printf("\t------------------------学生学学籍管理系统------------------------\n");     printf("\n\n");     printf("\t\t\t\t账号：");     scanf("%d", &nam);     printf("\n");     printf("\t\t\t\t密码：");     scanf("%d", &secret);     //system("cls");       if(nam == 172021 && secret==172021)     {     	printf("\n\n");         printf("\t\t\t\t登录成功!!!\n\n");           for(;;)         {             switch(menu_select())             {                 case 1:                     head = create();//注册                     break;                   case 2:                 	head=read(head);                     search(head);//查询                     break;                   case 3:                     revise(head);//修改                     break;                 case 4:                     head=del(head);//删除                     break;                 case 5:                 	head=read(head);                     printstu(head);//显示信息                     break;                 case 6:                 	save(head);                     exit(0);//退出系统                     break;                 default:                        printf("输入错误");                        break;               }         }     }     else     {        printf("输入错误，请重新登录");     }

求帮忙修改 read 函数


Question: memset 函数

参考一楼的回复，楼主想要打出来全是7，那就应该： void main() {     char name[]="2018/3/7 星期三";           // memset(name,0,4);     memset(name,'7',4);//注意7两边的单引号     printf("name  is %s\n",name);       system("pause"); }

这个我回复过你，int型就只能设置0或-1。我刚才试了一下7，是乱码，好像就不支持 引用 23 楼 qq_36088602 的回复:[quote=引用 22 楼 qq_35876885 的回复:] 我大概明白你的意思了。ch代表的是你要替换的值。因为你是char型数组，ch是int型，所以ch就是对应ASCII值的值。就相当于你这么定义： char a=0;char b=7;  这时候a其实是Null,b其实Bel. [quote=引用 11 楼 qq_36088602 的回复:] [quote=引用 6 楼 qq_35876885 的回复:] memset函数按字节对内存块进行初始化，所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。 我也是刚百科回来的，大概应该是，就不能设置为7，，，  谢谢兄弟 有心了。。。。。。。。。。  但是  memset 我看到别人有用7  故纳闷   我一般都是用它清空内存[/quote][/quote]   对 我也是根据“自信男孩”的 然后我在ASCII才看明白   那依你意思：  我要是设置int类型的数组 那么此时的7 会发生什么了？ [/quote]

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 我还提供观察用的工具。  理解和讨论之前请先学会如何观察！

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

运行不出来是因为？？？

#include<stdio.h> void main() {     char name[]="2018/3/7 星期三";                  //memset(name,7,4);      printf("name  is %s\n",name);       printf("pause"); } 这个才能运行啊，这个是不是不完整？？？？

引用 20 楼 paschen 的回复:[quote=引用 18 楼 ambition_阿彬的回复:][quote=引用 16 楼 paschen 的回复:] [quote=引用 12 楼 ambition_阿彬的回复:][quote=引用 7 楼 paschen 的回复:] [quote=引用 3 楼 ambition_阿彬的回复:][quote=引用 1 楼 paschen 的回复:] 内存中的7是不可打印字符，所以是看不到的，而字符'7'对应的ascii码并不是7，而是55   那把第二个参数ch设置为7的作用是？[/quote] 作用就是把这块内存每个字节用7填充而已，只不过7是不可打印字符，你输出这个字符串看到的并不是'7'[/quote]   那这块内存用0填充 和用7填充有什么区别？。。。。。。。[/quote] 填充的内容不同啦，你看不到并不代表它是0，虽然你结果看似是相同的，但内存上的值是不同的，如果用7填充，他的每个字节是7，用0填充他每个字节是0  此外，字符串是要求以\0结尾的，7并不是字符串的结尾标志  所以你上面的结果，当填充7时还多输出了："/3/7 星期三" , 因为你的字符串并没有结束，只是输出的你看不到而已，而填充0相当于直接是个空字符串[/quote]  也就是说 我输入7的时候内存中的数据不会丢失？ 这样做的好处是？ [/quote] 不存在什么好处，关键是看你程序需要哪种行为，也不存在数据丢失，只不过字符串是以0 结尾，7不是结尾，输出字符串时，遇到0就停止不在输出了，即使这个0后面还有其他有效字符，但遇到7，会继续向后输出（即使是无效字符），直到遇到最后的0[/quote]   明白了 谢谢版主

我大概明白你的意思了。ch代表的是你要替换的值。因为你是char型数组，ch是int型，所以ch就是对应ASCII值的值。就相当于你这么定义： char a=0;char b=7;  这时候a其实是Null,b其实Bel. 引用 11 楼 qq_36088602 的回复:[quote=引用 6 楼 qq_35876885 的回复:] memset函数按字节对内存块进行初始化，所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。 我也是刚百科回来的，大概应该是，就不能设置为7，，，  谢谢兄弟 有心了。。。。。。。。。。  但是  memset 我看到别人有用7  故纳闷   我一般都是用它清空内存[/quote]

通常对于字符串，很少有填充7的实际用处，memset并不是只能用于填充字符串，他可以填充任意用处的一块内存，关键是看你需要什么就用什么的语句

引用 22 楼 qq_35876885 的回复:我大概明白你的意思了。ch代表的是你要替换的值。因为你是char型数组，ch是int型，所以ch就是对应ASCII值的值。就相当于你这么定义： char a=0;char b=7;  这时候a其实是Null,b其实Bel. [quote=引用 11 楼 qq_36088602 的回复:] [quote=引用 6 楼 qq_35876885 的回复:] memset函数按字节对内存块进行初始化，所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。 我也是刚百科回来的，大概应该是，就不能设置为7，，，  谢谢兄弟 有心了。。。。。。。。。。  但是  memset 我看到别人有用7  故纳闷   我一般都是用它清空内存[/quote][/quote]   对 我也是根据“自信男孩”的 然后我在ASCII才看明白   那依你意思：  我要是设置int类型的数组 那么此时的7 会发生什么了？

引用 15 楼 mstlq 的回复:回楼主，这个就是类似下面的区别  int main() {        int i =-1;        i = 0;  // 类比memset(name, 0, 4);        printf("%d",i);        i = 7; //类比memset(name, 7, 4);        printf("%d",i); }  楼主别想太复杂  666  我已知 ，谢谢！

引用 16 楼 paschen 的回复:[quote=引用 12 楼 ambition_阿彬的回复:][quote=引用 7 楼 paschen 的回复:] [quote=引用 3 楼 ambition_阿彬的回复:][quote=引用 1 楼 paschen 的回复:] 内存中的7是不可打印字符，所以是看不到的，而字符'7'对应的ascii码并不是7，而是55   那把第二个参数ch设置为7的作用是？[/quote] 作用就是把这块内存每个字节用7填充而已，只不过7是不可打印字符，你输出这个字符串看到的并不是'7'[/quote]   那这块内存用0填充 和用7填充有什么区别？。。。。。。。[/quote] 填充的内容不同啦，你看不到并不代表它是0，虽然你结果看似是相同的，但内存上的值是不同的，如果用7填充，他的每个字节是7，用0填充他每个字节是0  此外，字符串是要求以\0结尾的，7并不是字符串的结尾标志  所以你上面的结果，当填充7时还多输出了："/3/7 星期三" , 因为你的字符串并没有结束，只是输出的你看不到而已，而填充0相当于直接是个空字符串[/quote]  也就是说 我输入7的时候内存中的数据不会丢失？ 这样做的好处是？

引用 18 楼 ambition_阿彬的回复:[quote=引用 16 楼 paschen 的回复:] [quote=引用 12 楼 ambition_阿彬的回复:][quote=引用 7 楼 paschen 的回复:] [quote=引用 3 楼 ambition_阿彬的回复:][quote=引用 1 楼 paschen 的回复:] 内存中的7是不可打印字符，所以是看不到的，而字符'7'对应的ascii码并不是7，而是55   那把第二个参数ch设置为7的作用是？[/quote] 作用就是把这块内存每个字节用7填充而已，只不过7是不可打印字符，你输出这个字符串看到的并不是'7'[/quote]   那这块内存用0填充 和用7填充有什么区别？。。。。。。。[/quote] 填充的内容不同啦，你看不到并不代表它是0，虽然你结果看似是相同的，但内存上的值是不同的，如果用7填充，他的每个字节是7，用0填充他每个字节是0  此外，字符串是要求以\0结尾的，7并不是字符串的结尾标志  所以你上面的结果，当填充7时还多输出了："/3/7 星期三" , 因为你的字符串并没有结束，只是输出的你看不到而已，而填充0相当于直接是个空字符串[/quote]  也就是说 我输入7的时候内存中的数据不会丢失？ 这样做的好处是？ [/quote] 不存在什么好处，关键是看你程序需要哪种行为，也不存在数据丢失，只不过字符串是以0 结尾，7不是结尾，输出字符串时，遇到0就停止不在输出了，即使这个0后面还有其他有效字符，但遇到7，会继续向后输出（即使是无效字符），直到遇到最后的0

引用 14楼自信男孩 的回复:0和7，即memset第二个参数是0和7时的问题。memset的功能是将对应的字节数上每个字节用第二个值去覆盖。是0时已经理解了，那么是7时，可以看一下ASCII的十进制是7的符号是那个，如下：  Oct   Dec   Hex   Char                        Oct   Dec   Hex   Char        ────────────────────────────────────────────────────────────────────────        000   0     00    NUL '\0' (null character)   100   64    40    @        001   1     01    SOH (start of heading)      101   65    41    A        002   2     02    STX (start of text)         102   66    42    B        003   3     03    ETX (end of text)           103   67    43    C        004   4     04    EOT (end of transmission)   104   68    44    D        005   5     05    ENQ (enquiry)               105   69    45    E        006   6     06    ACK (acknowledge)           106   70    46    F        007   7     07    BEL '\a' (bell)             107   71    47    G   [quote=引用 13 楼 qq_36088602 的回复:] [quote=引用 10 楼 cfjtaishan 的回复:] [quote=引用 9 楼 cfjtaishan 的回复:] 7和'7'不是一个值，后面的'7'是0x30 + 7, 即48 + 7 = 56; 第一个memset(name, 0, 4);由于将name的前4个字节用0替换了，所以什么也不输出。因为%s遇到'\0'停止输出，name在memset之后第一个字节就是0（0与'\0'相等），因此什么也不输出。 应该是48 + 7即55[/quote]   额。。 说明白了memset(name, 0, 4);这个问题  但是 我想问的是 ch 是7 的时候  同上： 我想问的是在内存中我用0填充和用7填充有什么区别 而不是什么打印啥的 可能是我一开给的图片让大家以为我是要打印吧 我只能想说 ： 不明白0和7的区别 所以去打印 发现不同，又没搞明白 所以来请教大家 [/quote][/quote]明白

引用 12 楼 ambition_阿彬的回复:[quote=引用 7 楼 paschen 的回复:] [quote=引用 3 楼 ambition_阿彬的回复:][quote=引用 1 楼 paschen 的回复:] 内存中的7是不可打印字符，所以是看不到的，而字符'7'对应的ascii码并不是7，而是55   那把第二个参数ch设置为7的作用是？[/quote] 作用就是把这块内存每个字节用7填充而已，只不过7是不可打印字符，你输出这个字符串看到的并不是'7'[/quote]   那这块内存用0填充 和用7填充有什么区别？。。。。。。。[/quote] 填充的内容不同啦，你看不到并不代表它是0，虽然你结果看似是相同的，但内存上的值是不同的，如果用7填充，他的每个字节是7，用0填充他每个字节是0  此外，字符串是要求以\0结尾的，7并不是字符串的结尾标志  所以你上面的结果，当填充7时还多输出了："/3/7 星期三" , 因为你的字符串并没有结束，只是输出的你看不到而已，而填充0相当于直接是个空字符串

引用 10 楼 cfjtaishan 的回复:[quote=引用 9 楼 cfjtaishan 的回复:] 7和'7'不是一个值，后面的'7'是0x30 + 7, 即48 + 7 = 56; 第一个memset(name, 0, 4);由于将name的前4个字节用0替换了，所以什么也不输出。因为%s遇到'\0'停止输出，name在memset之后第一个字节就是0（0与'\0'相等），因此什么也不输出。 应该是48 + 7即55[/quote]   额。。 说明白了memset(name, 0, 4);这个问题  但是 我想问的是 ch 是7 的时候  同上： 我想问的是在内存中我用0填充和用7填充有什么区别 而不是什么打印啥的 可能是我一开给的图片让大家以为我是要打印吧 我只能想说 ： 不明白0和7的区别 所以去打印 发现不同，又没搞明白 所以来请教大家

0和7，即memset第二个参数是0和7时的问题。memset的功能是将对应的字节数上每个字节用第二个值去覆盖。是0时已经理解了，那么是7时，可以看一下ASCII的十进制是7的符号是那个，如下：  Oct   Dec   Hex   Char                        Oct   Dec   Hex   Char        ────────────────────────────────────────────────────────────────────────        000   0     00    NUL '\0' (null character)   100   64    40    @        001   1     01    SOH (start of heading)      101   65    41    A        002   2     02    STX (start of text)         102   66    42    B        003   3     03    ETX (end of text)           103   67    43    C        004   4     04    EOT (end of transmission)   104   68    44    D        005   5     05    ENQ (enquiry)               105   69    45    E        006   6     06    ACK (acknowledge)           106   70    46    F        007   7     07    BEL '\a' (bell)             107   71    47    G  引用 13 楼 qq_36088602 的回复:[quote=引用 10 楼 cfjtaishan 的回复:] [quote=引用 9 楼 cfjtaishan 的回复:] 7和'7'不是一个值，后面的'7'是0x30 + 7, 即48 + 7 = 56; 第一个memset(name, 0, 4);由于将name的前4个字节用0替换了，所以什么也不输出。因为%s遇到'\0'停止输出，name在memset之后第一个字节就是0（0与'\0'相等），因此什么也不输出。 应该是48 + 7即55[/quote]   额。。 说明白了memset(name, 0, 4);这个问题  但是 我想问的是 ch 是7 的时候  同上： 我想问的是在内存中我用0填充和用7填充有什么区别 而不是什么打印啥的 可能是我一开给的图片让大家以为我是要打印吧 我只能想说 ： 不明白0和7的区别 所以去打印 发现不同，又没搞明白 所以来请教大家 [/quote]

引用 7 楼 paschen 的回复:[quote=引用 3 楼 ambition_阿彬的回复:][quote=引用 1 楼 paschen 的回复:] 内存中的7是不可打印字符，所以是看不到的，而字符'7'对应的ascii码并不是7，而是55   那把第二个参数ch设置为7的作用是？[/quote] 作用就是把这块内存每个字节用7填充而已，只不过7是不可打印字符，你输出这个字符串看到的并不是'7'[/quote]   那这块内存用0填充 和用7填充有什么区别？。。。。。。。


Question: sift算法如何在原图上标记特征点

百度搜相关关键字。


Question: 内存分配的疑问

对，应该是这样，他这样弄也是为了内存好管理。  引用 5 楼 u013861540 的回复:[quote=引用 3 楼 wanggui2015 的回复:] 从你给的代码看，我猜测是WSARecv这个函数需要这样的结构体WSABUF接收数据，WSABUF里面的数据类型就是指针，所以把WSABUF和存储数据的buffer封装到一个结构体里了。  [quote=引用 2 楼 u013861540 的回复:] [quote=引用 1 楼 wanggui2015 的回复:]  ioInfo->buffer 是存储数据的内存空间啊，ioInfo->wsaBuf.buf 仅是一个指针，指向了上面的内存空间。 这个我懂，但是这么做有什么意义吗[/quote][/quote] 哦，那么，如果不指向 ioInfo->buffer而是用malloc分配同样大小的空间也是可以的喽？[/quote]

引用 3 楼 wanggui2015 的回复:从你给的代码看，我猜测是WSARecv这个函数需要这样的结构体WSABUF接收数据，WSABUF里面的数据类型就是指针，所以把WSABUF和存储数据的buffer封装到一个结构体里了。  [quote=引用 2 楼 u013861540 的回复:] [quote=引用 1 楼 wanggui2015 的回复:]  ioInfo->buffer 是存储数据的内存空间啊，ioInfo->wsaBuf.buf 仅是一个指针，指向了上面的内存空间。 这个我懂，但是这么做有什么意义吗[/quote][/quote] 哦，那么，如果不指向 ioInfo->buffer而是用malloc分配同样大小的空间也是可以的喽？

ioInfo->wsaBuf.buf是一個指針，而且它可能會指向其他地方，衹是在這裏它直接指向了ioInfo->buffer。另有一個可能性是ioInfo->wsaBuf.buf是歷史遺留的，爲了兼容性才給保留，但後來的代碼都直接指向了ioInfo->buffer。

从你给的代码看，我猜测是WSARecv这个函数需要这样的结构体WSABUF接收数据，WSABUF里面的数据类型就是指针，所以把WSABUF和存储数据的buffer封装到一个结构体里了。  引用 2 楼 u013861540 的回复:[quote=引用 1 楼 wanggui2015 的回复:]  ioInfo->buffer 是存储数据的内存空间啊，ioInfo->wsaBuf.buf 仅是一个指针，指向了上面的内存空间。 这个我懂，但是这么做有什么意义吗[/quote]

引用 1 楼 wanggui2015 的回复:ioInfo->buffer 是存储数据的内存空间啊，ioInfo->wsaBuf.buf 仅是一个指针，指向了上面的内存空间。 这个我懂，但是这么做有什么意义吗


Question: C多维数组指针相关

引用 2 楼 INNATEKING的回复:一维数组的数组名是首地址，二维数组名指向二维数组的第一行，二维数组名[0]指向二维数组第一行的第一个元素，二维数组名+0指向二维数组的第二行，二维数组名[0]+1指向二维数组第二行的第一个元素，这个听起来有点烦，但是应该没错，二维数组分行地址，列地址，详细的你百度下吧，万一我有说错的，别笑话我啊 没错的。。。。。。。

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

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

int a[3][3]; 如果要用指针来指向它 正确的语法是 int (*p)[3]=a; 意思是 p 是一个指针他指向了一个包含3个元素的数组

建议看看这个，对c+多维数组深入解析：https://blog.csdn.net/sinat_22991367/article/details/76408197

Str指的是str[0][0] str[0]指的是数组第一行

引用 10 楼 qq_34994282 的回复:#include<stdio.h>  int main(){ int a[3][4]={1},*p; p=a; printf("%d",*p);   return 0; }  试了一下，，可以的啊，这个是对的，输出的是第一个元素 对，c的可以，c++不行

类型不一样，虽然地址值一样的。 str是int (*)[10]; p是int *类型。

引用 10 楼 qq_34994282 的回复:#include<stdio.h>  int main(){ int a[3][4]={1},*p; p=a; printf("%d",*p);   return 0; }  试了一下，，可以的啊，这个是对的，输出的是第一个元素 地址值一样，但是类型是不同的。 你用的编译器检查的不严格。另外，地址输出应该用%p或%u，而不是%d

str的类型是int**，str[1]的类型是int*，str[1][1]的类型是int。所以结果很明显。

是类型不同  一个二维的 一个一维的


Question: 5重循环如何赋值？拿50分谢谢啦

你定义数组的时候就初始化了，假设后面的所谓的循环正确的话 他所做的也就是你已经做过的初始化工作，反而现在你的循环将所有元素都变为了0 你后面又判断他们等不等于5，全是0 ，哪来的5，好好理顺一下逻辑吧。

sum = b1[a] + b2[b] + b3[c] + b4[d] + b5[e]; 这儿的sum的值是0，因为b1[a]。。。b5[e]都是0。因为下标是从0开始，而不是1开始。 所以上面的sum = b1[a] + b2[b] + b3[c] + b4[d] + b5[e];等价sum = b1[9] + b2[9] + ... + b5[9]; b1[9] ... b5[9]都是0。

for (a = 1; a <= 8; a++) { b1[a] = 1; b1[a] = 4; b1[a] = 3; b1[a] = 4; b1[a] = 5; b1[a] = 6; b1[a] = 7; b1[a] = 0; } 这个循环有很多冗余的操作 等价与下面的  for (a = 1; a <= 8; a++) { b1[a] = 0; } 所以要么你的循环写的有问题，要么就是逻辑考虑的有问题 下面的几个循环都是这样的问题

比如int b1[9]; int a[9]={1,3,5,7,9,0,2,4,6}; for(int i=0;i<9;i++) {     b1[i]=a[i]; } 不过一般a[9]是其他表达式或函数获得

#include "stdafx.h" #include<stdio.h>  #define MAX 8  int main(void) { 	int a, b, c, d, e, i = 0; 	int sum = 0; 	int b1[MAX] = { 1,4,3,4,5,6,7,0 }; 	int b2[MAX] = { 1,1,3,4,5,3,7,0 }; 	int b3[MAX] = { 1,7,3,4,5,6,7,0 }; 	int b4[MAX] = { 1,1,3,4,5,4,7,0 }; 	int b5[MAX] = { 1,1,3,4,5,6,7,0 };  	for (a = 0; a < MAX; a++) { 		for (b = 0; b < MAX; b++) { 			for (c = 0; c < MAX; c++) { 				for (d = 0; d < MAX; d++) { 					for (e = 0; e < MAX; e++) { 						sum = b1[a] + b2[b] + b3[c] + b4[d] + b5[e]; 						if (5 == sum) { 							printf("A:%2d B:%2d C:%2d D:%2d E:%2d ", b1[a], b2[b], b3[c], b4[d], b5[e]); 							i++; 							if (i % 1 == 0) 								printf("\n"); 						} 					} 				} 			} 		} 	}  	printf("共有%d种办法\n", i);  return 0; }

引用 5 楼 qq_35876885 的回复:数组赋值:如果是常量的话直接赋值就好了，而且你已经赋过了。非要用循环的话，要是变量。比如 for(int i=0;i<8;i++) {       b1[i]=变量; }很明显，他要得是每个数组元素里面有不同的值，怎么用循环赋值？

你知道你这里计算的是什么 sum = b1[a] + b2[b] + b3[c] + b4[d] + b5[e];   在你的代码里这里算的是 sum = b1[9] + b2[9] + b3[9] + b4[9] + b5[9]=0，接着if循环判断为假，继续执行printf("共有%d种办法\n", i);  这里的i值为0.。。。。


Question: 一个程序Program received signal SIGSEGV, Segmentation fault看了一天了！求救！！！

假设我输入的年份是1990 那么oneday.year * 365就是708440，按楼主这么原始的做法 work[240000],rest[120000]这两个数组还不够大哟！！ 240000+120000<708440 这就是你崩溃的原因，但不应该用增大分配内存的方式来解决这个问题。因为就你的题目而言，根本没有必要用这么耗时耗内存的方法计算，7楼的方法多好呀

// 某年是否是闰年 bool isLeapYear(int y) { 	return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); }  // 某年某月有多少天 int daysOfMonth(int y, int m) { 	static int dm[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  	return dm[m] + ((m == 2 && (isLeapYear(y)) ? 1 : 0)); }  // 某日期在该年的哪一天（即在该年的累计天数） int daysInYear(int y, int m, int d) { 	while (--m > 0) 		d += daysOfMonth(y, m);  	return d; }  // 某年一共有多少天 int totalDaysInYear(int y) { 	return isLeapYear(y) ? 366 : 365; }  // 计算两天相差多少天 int daysBetweenTwoDates(int y0, int m0, int d0, int y1, int m1, int d1) { 	// 如果同年，直接两年的总天数相减 	if (y0 == y1) 		return daysInYear(y1, m1, d1) - daysInYear(y0, m0, d0);  	int days = 0;  	// 不同年，计算除了这两年，中间年份的天数 	for (int y = y0 + 1; y < y1; ++y) 		days += (365 + isLeapYear(y));  	// 计算在这两年里的天数 	days += (daysInYear(y1, m1, d1) + totalDaysInYear(y0) - daysInYear(y0, m0, d0));  	return days; }  // 某人从1990年1月1日起开始"三天打鱼两天晒网"，问这个人在以后的某一天中，是在打鱼还是在晒网？ bool isFishing(int y, int m, int d) { 	return daysBetweenTwoDates(1990, 1, 1, y, m, d) % 5 < 3; }    我尝试写了一个，对所有输入的日期没有做合法性判断，计算两天相差天数也没对日期前后进行判断，你想加上也很容易。 逻辑很简单的，你可以参考下。  其实完全可以写一个日期类，然后重载减号运算符求两个日期之间的天数。通过这个日期类再去实现你的相关需求会很简单。

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

Cal n, work[240000],rest[120000]; 这条语句申请的是栈上的空间，栈上的空间是有限的，并且是很少的。一下子申请这么多空间，你是每个都使用了吗？ 如果使用的空间不确定，建议使用动态申请(malloc/free)。 导致段错误的原因也是因为申请这么大的空间导致了越界。

你程序的错误是在函数的堆栈溢出。不明白为啥你分配了那么大空间，没细看你的代码。  如果你用的是VS，想调试你的代码，你可以把“工程属性”->"链接器"->"系统”->"堆栈保留大小”，改大一点，这个数的单位是Byte，1M=1048576Byte。 另外，你的需求很简单啊，为什么代码会这么复杂。

重点是两个日期相差天数, 这个函数网上随处可见, 原理是 基姆拉尔森计算公式 #include <stdio.h>  int day_diff(int year_start, int month_start, int day_start, int year_end, int month_end, int day_end) { 	int y2, m2, d2; 	int y1, m1, d1;  	m1 = (month_start + 9) % 12; 	y1 = year_start - m1/10; 	d1 = 365*y1 + y1/4 - y1/100 + y1/400 + (m1*306 + 5)/10 + (day_start - 1);  	m2 = (month_end + 9) % 12; 	y2 = year_end - m2/10; 	d2 = 365*y2 + y2/4 - y2/100 + y2/400 + (m2*306 + 5)/10 + (day_end - 1);  	return (d2 - d1); }  int main(void) { 	int year, month, day; 	int diff; 	 	scanf("%d %d %d", &year, &month, &day); 	 	diff = day_diff(1990, 1, 1, year, month, day); 	diff %= 5; 	 	if (diff < 3) {printf("fish\n");}  	else {printf("net\n");}  	return 0; }

引用 1 楼 qq_24947841 的回复:没太看懂你Judge函数里的逻辑，只是判断某一天打鱼还是晒网，可以这么做： 比如1995年3月2日，判断这一天到1990年1月1日一共多少天，先看年份（注意判断是否闰年），计算到95年1月1日多少天，再看月份，天数（注意2月），最后求总天数与5的余数，通过余数来判断打鱼还是晒网 恩。。明白你的意思 我的逻辑和你正好相反，我是先用count计数器从1计算到95年1月1日的总天数把他们分别以结构体形式分类到日期里 然后判断是否是3或5的余数，分类为工作日和休息日顺便判断是否是输入天数


Question: C语言中，程序A不断在写文件1.txt，程序B此时能读取1.txt吗？

引用 8 楼 zhao4zhong1 的回复:不看zhao4zhong1回帖，你会浪费一大段青春。 看了，赵4老师太强，小弟能力太差啊！

百度搜“IPC”

不看zhao4zhong1回帖，你会浪费一大段青春。

引用 6 楼 xian_wwq 的回复:A不断的写入具体是什么形式？ 一直追加还是覆盖模式？ B在读取的时候建议先复制文件，然后读取复制的文件  A程序不断追加。就是A程序每秒钟都会向1.txt中追加新计算出来的结果，现在要将这个结果通过界面实时显示出来

综上所述，最佳办法是通过两个文件名不同的文件轮转“A写这个，B读那个；然后A写那个，B读这个。”

引用 7 楼 qq_40669149 的回复:[quote=引用 6 楼 xian_wwq 的回复:] A不断的写入具体是什么形式？ 一直追加还是覆盖模式？ B在读取的时候建议先复制文件，然后读取复制的文件  A程序不断追加。就是A程序每秒钟都会向1.txt中追加新计算出来的结果，现在要将这个结果通过界面实时显示出来[/quote] 那就是要显示增量数据， 起个线程比对文件的长度变化，一旦有变化，就复制该文件。 可以根据上一轮记录的文件长度，seek到指定位置，读取附加的新数据就行。 ----- 顺便补一句，这个A程序如果不清理1.txt的数据，迟早会出现文件过大打不开的情况

//test.c 本程序演示两个进程之间通过临时文本文件交换数据实现间接调用 //A将请求数据写到文件a.txt，写完后改名为aa.txt //B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt //A发现bb.txt存在时，读取其内容，读完后删除bb.txt #include <io.h> #include <stdio.h> #include <windows.h> int main(int argc,char **argv) {     int d,r;     FILE *f;     char cmdstr[512];      if (argc<2) {         sprintf(cmdstr,"cmd /c \"%s\" B",argv[0]);         WinExec(cmdstr,SW_HIDE);         for (d=1;d<=5;d++) {//共使用1..5调用B 5次             //A将请求数据写到文件a.txt，写完后改名为aa.txt             f=fopen("a.txt","w");             fprintf(f,"%d\n",d);             fclose(f);             rename("a.txt","aa.txt");             printf("call with %d\n",d);             //A发现bb.txt存在时，读取其内容，读完后删除bb.txt             while (1) {                 Sleep(100);                 if (_access("bb.txt",0)!=-1) {                     f=fopen("bb.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     remove("bb.txt");                     break;                 }             }             printf("result:%d\n",r);         }         return 0;     }     if (argv[1][0]=='a'||argv[1][0]=='A') {//A         for (d=1;d<=5;d++) {//共使用1..5调用B 5次             //A将请求数据写到文件a.txt，写完后改名为aa.txt             f=fopen("a.txt","w");             fprintf(f,"%d\n",d);             fclose(f);             rename("a.txt","aa.txt");             printf("call with %d\n",d);             //A发现bb.txt存在时，读取其内容，读完后删除bb.txt             while (1) {                 Sleep(100);                 if (_access("bb.txt",0)!=-1) {                     f=fopen("bb.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     remove("bb.txt");                     break;                 }             }             printf("result:%d\n",r);         }     } else {//B         while (1) {             //B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt             while (1) {                 Sleep(100);                 if (_access("aa.txt",0)!=-1) {                     f=fopen("aa.txt","r");                     fscanf(f,"%d",&r);                     fclose(f);                     r=r*10;                     f=fopen("b.txt","w");                     fprintf(f,"%d\n",r);                     fclose(f);                     remove("aa.txt");                     rename("b.txt","bb.txt");                     break;                 }             }             if (r==50) break;         }     }     return 0; } //C:\tmp\test>test //call with 1 //result:10 //call with 2 //result:20 //call with 3 //result:30 //call with 4 //result:40 //call with 5 //result:50 // //C:\tmp\test>start /B test B // //C:\tmp\test>test A //call with 1 //result:10 //call with 2 //result:20 //call with 3 //result:30 //call with 4 //result:40 //call with 5 //result:50 // //C:\tmp\test>

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，再将b.txt改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？ 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话，文本文件的格式问题可参考json或xml  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！

你先试试能不能打开文件吧

建议不要这么做  很容易出问题

B可以去读取，但是有个情况：若程序B读取的快，A还没写入，此时B读取的是文件末尾，其实现在A还会继续写入此时B读取到的文件末尾是临时的，不是真实的，因此需要考虑到这种情况。


Question: vc++开发dll问题

dll 导出函数名的那些事 关键字：　VC++ 　DLL  导出函数　 经常使用VC6的Dependency查看DLL导出函数的名字，会发现有DLL导出函数的名字有时大不相同，导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系。 VC++支持两种语言：即C/C++，这也是造成DLL导出函数差异的根源 我们用VS2008新建个DLL工程，工程名为"TestDLL" 把默认的源文件后缀 .CPP改为.C（C文件） 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 1. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 2. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： _MyFunction@4 __stdcall会使导出函数名字前面加一个下划线，后面加一个@再加上参数的字节数，比如_MyFunction@4的参数（int iVariant）就是4个字节 __fastcall与 __stdcall类似，不过前面没有下划线，而是一个@，比如@MyFunction@4 __cdecl则是始函数名。 小结：如果要导出C文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 下面我们来看一下C++文件 我们用VS2008新建个DLL工程，工程名为"TestDLL" 默认的源文件后缀为 .CPP （即C++文件）。 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 3. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 4. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： ?MyFunction@@YGHH@Z 可以看到 第二种方法得到的 导出函数名 并不是我们想要的，如果在exe中用显示方法（LoadLibrary、GetProcAddress）调用 MyFunction 肯定会失败。 但是用引入库(*.LIB)的方式调用，则编译器自动处理转换函数名，所以总是没有问题。 解决这个问题的方法是： 用VC 提供的预处理指示符 "#pragma" 来指定链接选项。 如下： #pragma comment(linker, "/EXPORT:MyFunction=?MyFunction@@YGHH@Z") 这时，就会发现导出的函数名字表中已经有了我们想要的MyFunction。但我们发现原来的那个 ?MyFunction@@YGHH@Z 函数还在，这时就可以把 __declspec() 修饰去掉，只需要 pragma 指令即可。 而且还可以使如下形式： #pragma comment(linker, "/EXPORT:MyFunction=_MyFunction@4,PRIVATE") PRIVATE 的作用与其在 def 文件中的作用一样。更多的#pragram请查看MSDN。 小结：如果要导出C++文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 同时可以用#pragma指令（C 中也可以用）。 总结： C++编译器在生成DLL时，会对导出的函数进行名字改编，并且不同的编译器使用的改编规则不一样，因此改编后的名字也是不同的（一般涉及到C++ 中的重载等）。 如果利用不同编译器分别生成DLL和访问DLL的exe程序，后者在访问该DLL的导出函数时就会出现问题。如上例中函数MyFunction在C++编译器改编后的名字是?MyFunction@@YGHH@Z。我们希望编译后的名字不发生改变，这里有几种方法。 第一种方法是通过一个称为模块定义文件DEF来解决。 LIBRARY TestDll EXPORTS MyFunction LIBRARY 用来指定动态链接库内部名称。该名称与生成的动态链接库名一定要匹配，这句代码不是必须的。 EXPORTS说明了DLL将要导出的函数，以及为这些导出函数指定的符号名。 第二种是定义导出函数时加上限定符：extern "C" 如：#define DLLEXPORT_API extern "C" _declspec(dllexport) 但extern "C"只解决了C和C++语方之间调用的问题(extern "C" 是告诉编译器，让它按C的方式编译)，它只能用于导出全局函数这种情况 而不能导出一个类的成员函数。 同时如果导出函数的调用约定发生改变，即使使用extern "C"，编译后的函数名还是会发生改变。例如上面我们加入_stdcall关键字说明调用约定（标准调用约定，也就是WINAPI调用约定）。 #define DLLEXPORT_API extern "C" _declspec(dllexport) 01 DLLEXPORT_API int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 编译后函数名MyFunction改编成了_MyFunction@4 通过第一种方法模块定义文件的方式DLL编译后导出函数名不会发生改变。 DLL(动态库)导出函数名乱码含义 C++编译时函数名修饰约定规则：   __stdcall调用约定：   1、以"?"标识函数名的开始，后跟函数名；    2、函数名后面以"@@YG"标识参数表的开始，后跟参数表；    3、参数表以代号表示：   X--void   D--char   E--unsigned char   F--short   H--int   I--unsigned int   J--long   K--unsigned long   M--float   N--double   _N--bool   ....   PA--表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以"0"代替，一个"0"代表一次重复；   4、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型,指针标识在其所指数据类型前；    5、参数表后以"@Z"标识整个名字的结束，如果该函数无参数，则以"Z"标识结束。   其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ"，例如                       int Test1(char *var1, unsigned long)-----"?Test1@@YGHPADK@Z"                      void Test2()-----"?Test2@@YGXXZ"    __cdecl调用约定：   规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YA"。   __fastcall调用约定：   规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YI"。   如果要用DEF文件输出一个"C++"类，则把要输出的数据和成员的修饰名都写入.def模块定义文件   所以...   通过def文件来导出C++类是很麻烦的,并且这个修饰名是不可避免的

extern "C"  __stdcall 两者是冲突的，extern "C"将会使用__cdcel进行导出，去掉__stdcall，DLLEXPORT_API是需要用的 extern "C"只有在C++编译的情况才需要，如果是C编译，则无需这个

2楼的我也看了，没搞明白.def文件是如何使用的，后来找了篇文章详细介绍一步步操作，现在可以调用了。 http://blog.csdn.net/supermanking/article/details/5347763 分享这个链接，初学者一看就明白了


Question: 杭电1002题目oj通不过为什么，两个代码只有一行位置不同，第一个却通不过

因为第二个定义在for循环内，每次循环后， int a[1001]={0},b[1001]={0},total[1001]={0}; a, b, total变量都会被初始化为0， 但是第一个不会，每次循环后第一个的a, b, total还保留着上次计算（赋值给a, b, total)的值。


Question: C中的error：conflicting types for

引用 5 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。 这个方法好

因为你前面的函数使用了后面的结构体，这时候应该前置声明或者直接把定义前置

因为getgrade的定义涉及struct student，但是在此之前没有定义或说明struct student

引用 1 楼 qq_30918465 的回复:使用vc++编译通过，楼主可以试着把结构体定义放在前面 感谢 把定义前置就好了 可是为什么呢……

代码不全，但从目前贴出来的代码编译是没问题的。 建议贴出完整代码

使用vc++编译通过，楼主可以试着把结构体定义放在前面

不出意外的话，应该是student*p连在一起了，应该是student *p

你应该是有什么结构体、变量什么的冲突吧


Question: c语言进阶书籍推荐

《C和指针》应该够了，建议你去www.kernel.org下个linux内核代码看看

谢谢~我去看看

C Primer Plus中文第六版，很厚，真的不错。。。

C primer plus 比较基础 当字典用不错

学习编程语言是为了编程， 还是多看看大型的代码，体会其中的思想，我就是这么走过来的， 学习别人的代码理解别人的思想比啃书有用多了

C Primer Plus 很多人推荐，可惜我没有看过，不知道是讲得什么

<<C语言程序设计的现代方法>>

楼主如果想用C玩玩图形、小游戏编程，可以了解一下EasyX，EasyX是Windows平台最简单的绘图函数库（名副其实），兼容BC和TC的绘图函数，在VC下用EasyX来编程跟在TC下编程绘图差不多是完全一样的。EasyX既可以绘图，也支持图像显示和处理。  下载一个EasyX包，里面有完整的函数手册EasyX_Help.chm，有示例。EasyX官网有很多网友上传的实例，包括游戏。  仅供参考： 用绘图语句画机器猫（初学C语言的同学必看） http://blog.163.com/tab_98/blog/static/1192409720150316223680/

C Primer Plus  C语言程序设计：现代方法：第2版(被誉为"近10年来最好的一部C语言著作") C和指针 或者谭浩强《C程序设计》 以上任选一本就差不多了，以下为参考书： 《深入理解C指针》 《C语言点滴》 《C陷阱与缺陷》 《C专家编程》

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语言指针与汇编内存地址-四.三维数组

当当网计算机类搜索排名，《C语言从入门到精通》， 《C Primer Puls》。。。

个人建议多做一些习题，学习一些算法。 网上有一些编程练习网站（比赛之类）的。可以试试写写，如果遇到困难，写不出来。说明基础学习的还欠扎实，建议回归课本复习，这样学习起来获取更快些。不会写的，也建议从网上搜一搜，然后看看别人写的，自己试着改改，调试一下。


Question: C语言实训，要每一行注释，

0.0慢慢看吧

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

每一行加注释，没必要。如果真需要每行都加注释，那么不如翻开书本好好复习一下语法知识。  建议多运行几次（真是语法知识不牢固，建议翻课本复习一下），加一些调试打印了解程序的运行流程。

将学生信息保存在类似的结构体数组中 struct  student {     int number;    char name[NAME_MAX];    int  score[M]; }student_array[N];  将学号作为索引， 通过学号可以查询输出学生的基本信息和各科成绩。

有什么问题吗


Question: floating point exception 报错 gcc 编译通过

引用 1 楼 steedhorse 的回复:问题可能不止一个。 但首先i应该从1开始。从0开始的话，第一步“a % i”就有问题。   厉害厉害    ，作为初学者，我走入误区了，只是在纠结程序本身，而没有去验证公式，多谢大神


Question: 大神帮忙支个招呗  编程小白  谢谢

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

注意运算符的优先级，赋值优先级比!=优先级要低。所以，c = getchar() != '\n'则得到的结果是c = (getchar() != '\n').即c得到是判断结果（0或1，真或假），因此需要加括号改变其运算规则（运算优先级）：(c = getchar()) != '\n'

优先级!=高于=，(｡ì _ í｡)

(c=getchar())!='\n'

为什么会出现白色方框


Question: 大神帮讲解一下上面代码可以吗？

这里也有一个 http://blog.csdn.net/phunxm/article/details/5082744

这是一个很基础的Win32 API窗口程序，《Windows程序设计 第5版》中有详细介绍，网上也有详细注解版 https://www.cnblogs.com/huhu0013/archive/2010/09/26/1836008.html 关于如何修改菜单，看看这句 wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WIN20180202); 你看看.rc文件的相关内容即可 IDC_WIN20180202是菜单的标识

个人觉得SDK纯API方式编写GUI程序已经过时了，效率太低，了解一下原理就可以了，主要是消息机制。  图形用户界面（GUI）编程可以学习C++ Builder，架构先进（和C#一样拖控件），入门比较容易。  　　C++ Builder是真正的可视化的开发工具。C++ Builder可以用鼠标拖拉控件加上设置属性轻松的“设计”出一个程序的图形用户界面，利用可视的组件/控件像“搭积木”一样，以“所见即所得”的方式搭建应用程序的界面，这也是C++ Builder这个名字中Builder的概念。这样，只需要用C++语言编写业务逻辑代码，类似于DOS下文本界面编程，只要专注于实现业务逻辑功能就可以了，代码非常简洁。数据的输入和表现，都在图形用户界面，非常直观、易用。这就是RAD开发（Rapid Application Development，快速应用程序开发）。  书籍推荐： 《C++Builder 6程序设计教程（第二版）》 （陆卫忠，刘文亮　等编著 /2011-04-01 /科学出版社）（当当网） 《C++Builder 6编程实例精解》（赵明现），PDF，是数字版的，非扫描版的，里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》（台湾 吴逸贤），里面有10几个简单小游戏的实现，可以自己看懂以后再重写，才是自己掌握的。 《C++ Builder 5高级编程实例精解》（刘滨 编著）都是较大的实用的程序。

我现就是在了解它


Question: 牛顿迭代法求多元方程近似根

引用 4 楼 JL_Xie的回复:应该会有四个解吧
三个，说错了

应该会有四个解吧

百度搜相关关键字。


Question: 关于一个特别简单的链表。。。

//#include "stdafx.h" #include <stdio.h> #include <stdlib.h>  typedef struct list {     int num;     struct list *next; }ty;  //链表的初始化 ty *creat_list() {     int u;     ty *i, *o, *p;     p = (ty *)malloc(sizeof(ty));     i = p;     printf("输入链表的值，输入-1以退出：");     scanf_s("%d", &u);     while (u != -1)     {         o = (ty *)malloc(sizeof(ty));         o->num = u;         i->next = o;         i = o;         scanf_s("%d", &u);     }     i->next = NULL;      return p; } //链表的打印 void print_list(ty *head) {     ty *p;     p = head->next;     if (!p)         return;     printf("head");     do {         printf("-->%d", p->num);         p = p->next; \     } while (p);     printf("-->end"); } //向链表插入数值 void add_list(ty *head, int key, int pos) {     ty *u, *p, *q,*s;      u = (ty *)malloc(sizeof(ty));//为u申请空间     u->num = key;      q = head;     p = head->next;      //s = (ty *)malloc(sizeof(ty));      while (p && p->num != pos) {         q = p;         p = p->next;     }      if (!p) {         q->next = u;         u->next = NULL;     } else if (p->num == pos) {         u->next = p;         q->next = u;     } } int main() {     ty *head;     int key, pos;     head = creat_list();     print_list(head);     printf("输入你想插入的值和位置");     scanf_s("%d %d", &key, &pos);     add_list(head, key, pos);     print_list(head);     return 0; } 参考一下吧  问题是出现了段错误，原因是：若要插入到链表末尾，那么p为NULL，那么p->num == o就会出现段错误，因为NULL->num导致段错误； 另外，程序有两处判断条件需要调换一下，否则会导致段错误； 比如其一： while ((p->num != o) && (p != '\0')) { 此处若p为NULL了，那么先判断p->num != o岂不是会导致段错误。上面的代码我已做了修改；  另外，建议注意下命名规则，一个函数里o命名位结构体指针，又在另一个函数里作为int类型。这样大大减少了代码的可读性，引起歧义性。 另外，next不是'\0'，而是NULL。'\0'是字符串结束符，虽然没问题，因为'\0'是数值0，数值0类型转换之后位(void *)0为NULL。不过这样赋值p->next = '\0'还会有误导性。 建议以后编程时注意。虽然是一个简单的链表编程，但是不是“特别”简单。如果特别简单，不会出现这样的问题哦。加油吧～～～

else if (p == '\0') { p->next = u; u->next = NULL; } 这里在对p这个空指针操作，应改为q->next=u;  while ((p->num != o) && (p != '\0'))   这个改成 while ((p != 'NULL)&&(p->num != o) )

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

请大家忽略那个s指针。。。而且其他没问题的地方我没写注释。。。


Question: 求思路，怎样运费最少的问题

结合业务加了一些分组等优化逻辑，终于OK了。 核心还是递归全组合，谢谢大家了！

递归，在全组合里找最优解，代码是实现了，数据量稍微大一点结果都出不来。。。哭晕了

递归，回溯，全遍历求最优解吗， 可能确实是没有什么好方法， 感觉没有什么规律性在里面来走捷径啊， 实际不像举例数据量这么少。。。

仅供参考：//qplw.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> int v=0; int w=0; int m;//记录字符串长度 int n;//记录字符串中的字符种类数 char map[256];//记录是哪几种字符 int count[256];//记录每种字符有多少个 int stack[1000];//递归用的栈，并记录当前生成的排列 void Make_Map(char *str) {//统计字符串的相关信息     int s[256];     int i;     memset(s,0,sizeof(s));     memset(count,0,sizeof(count));     m=strlen(str);     if (w<1 || m<w) w=m;     while(*str) {         s[*str]++;         str++;     }     n=0;     for (i=0;i<256;i++)         if (s[i]) {             map[n]=i;             count[n]=s[i];             n++;         } } void Find(int depth) {//递归式回溯法生成全排列     if (depth==w) {         int i;         for (i=0;i<depth;i++) putchar(map[stack[i]]);         putchar('\n');     } else {         int i;         if (v && depth>0) {             for (i=0;i<depth;i++) putchar(map[stack[i]]);             putchar('\n');         }         for (i=0;i<n;i++)             if (count[i]) {                 stack[depth]=i;                 count[i]--;                 Find(depth+1);                 count[i]++;             }     } } void main(int argc,char**argv) {     if (argc<2) {         printf("%s 要产生全排列的字符串 [限定长度|-1]\n",argv[0]);         return;     }     if (argc>=3) w=atoi(argv[2]);     if (-1==w) v=1;     Make_Map(argv[1]);     Find(0); } //C:\test>qplw //qplw 要产生全排列的字符串 [限定长度|-1] // //C:\test>qplw 123 //123 //132 //213 //231 //312 //321 // //C:\test>qplw 123 2 //12 //13 //21 //23 //31 //32 // //C:\test>qplw 122333 3 //122 //123 //132 //133 //212 //213 //221 //223 //231 //232 //233 //312 //313 //321 //322 //323 //331 //332 //333 // //C:\test>qplw 123 -1 //1 //12 //123 //13 //132 //2 //21 //213 //23 //231 //3 //31 //312 //32 //321 //

你的思路都出来了，那么接下来就是 if else 了。

解释一下，A,B,C,D是4批货物送往4个地点，单独配送的费用是     A ：  500      B ：  400      C ：  300      D ：  200  通过价格表计算可以知道下面几种合并运送的方式比单独送费用低，   A+B+C ：  1101  （比单独各自运输节省99）   A+B ：       840    （比单独各自运输节省60）   B+C ：       620    （比单独各自运输节省80）   C+D ：       460    （比单独各自运输节省40）  ×××这里上面写的360，算错了×××  单独看，A+B+C节省最多，如果作为最优方案保留的话，结果就是A+B+C和D单独，费用1101+200 = 1301 但是整体看，如果采用A+B和C+D费用是840+460= 1300，其实是最优的，   平时很少接触算法，这个问题的模型考虑不清楚，最短路？背包？线性规划？  真心有点懵，还请给个思路

这种数据量少的，无非就是遍历所有可能情况，选取最优结果

可以像赵老师中的C:\test>qplw 123 -1，把8种费用所有组合都检查一遍，再选个最小的。


Question: 求助 这个step怎么减少的

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

引用 2 楼 jacob_KK 的回复:引用 1 楼 jianwen0529 的回复:if (step == n + 1){ return; } 这个是递归的结束条件，step不是递减，而是递增dfs(step + 1);不是呀 你看他第一次将step加到n+1后 去输出数据 然后return回来 step不是还是n+1吗 但是运行又变小了 这是怎么回事呢 这是递归，step是参数，而且每次调用它们不是同一个值。最内层的调用是最大的，然后一层层退出，step依然还是step


Question: 在VC6.0中可以AC但是在VS2015就会死循环（程序简单）

#include<stdio.h> #include<string.h> int main() {     char a[100];     int i, j, k, n, l;     while (scanf_s("%d", &n))     {         for (i = 0; i < n; i++)         {             scanf_s("%s", a, sizeof(a));             l = strlen(a);             k = 0;              for (j = 0; j < l; j++)             {                 if (a[j] != a[l - j - 1])                     k++;             }             if (k == 0)                 printf("yes\n");             else                 printf("no\n");         }      }     return 0; } 参考一下吧； scanf_s("%d", &n)的返回值若正常读取，返回1，读取失败返回0；所以，这场读取时，不会进入while循环，若非正常读取时，进入while循环，此时n还是随机值，不是死循环，而是n是一个很大的随机数，所以会出现看似死循环的操作;  另外，scanf_s("%s", a);缺少参数，需要第三个参数：scanf_s("%s", a, sizeof(a));

Enter、Ctrl+Z、Enter退出while循环。


Question: 为什么在循环内，内存映射文件的过程，只执行一次就结束了？怎样解决

可能是被编译器优化掉了。

你怎么判断只执行了一次，建议单步跟踪程序运行，观察程序执行流程，分析原因

异常退出也是一种崩溃。

感觉就是运行一次，就直接跳出循环了

没有崩溃，直接程序运行结束，电脑也没有任何提示

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


Question: OJ题目求助，本地过了OJ却老是提示WA

百度搜相关关键字。


Question: 请教一个关于librdkafka的问题

百度搜相关关键字。


Question: 杭电2034题 提交的时候出现的Runtime Error (ACCESS_VIOLATION)  各位大佬给小弟看看，谢谢。。

在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。

int i,j,min,a[100],b[100],c[100],count=0; 数组开大些，a,b,c都改成a[110],b[110],c[110]试下

#include <stdio.h> int main() {     int m,n;     while(scanf("%d%d",&n,&m)!=EOF)     {         if(n>0&&n<=100&&m>0&&m<=100)         {             int i,j,min,a[100],b[100],c[100],count=0;         for(i=0;i<n;i++)             scanf("%d",&a[i]);             for(i=0;i<m;i++)                 scanf("%d",&b[i]);         for(i=0;i<n;i++)             for(j=0;j<m;j++)             if(a[i]==b[j])               {count++;a[i]=2000;j=m;}               else                 continue;                 i=0;                 if(count==n)                     printf("NULL\n");                 else                   {                     for(i=0,j=0;i<n;i++)                         if(a[i]!=2000)                     {                         c[j]=a[i];                         j++;                     }                     for(i=0;i<n-count;i++)                         for(j=i+1;j<n-count;j++)                         if(c[i]>c[j])                         {                             min=c[j];                             c[j]=c[i];                             c[i]=min;                         }                         for(i=0;i<n-count;i++)                             if(i!=n-count-1)                             printf("%d ",c[i]);                         else                             if(i==n-count-1)                             printf("%d\n",c[i]);                 }         }        else         if(m==0&&n==0)         break;        else         continue; }     return 0;  } 这是改过的代码    ，帮忙看下这个就行，提交还是错误，尴尬癌都出来了！！！


Question: Linux TCP 连接问题

服务端回复 ack 之后， 说明客户端到服务器的链接建立好了， 客户端回复 ack 之后， 说明服务器到客户端的链接建立好了，  你可以看什么时候变成ESTABLISHED状态了，就是什么时候建立好了

引用 2 楼 zilaishuichina 的回复:tcp3次握手成功后 就是 ESTABLISHED状态， 这个链接已经建立好了，放在全连接队列里了（lz可以去搜TCP 半连接队列和全连接队列，了解一下），  accept只是从这个队列里将建立好的链接取出来而已。   所以即使你上层逻辑在recv那阻塞了， TCP底层该接受链接还是接受链接，直到这个队列满了为止。  客户端向服务器发送一个SYN，服务器接收到后，这时候是不是说明了服务器到客户端的连接已经建立好了？ 客户端想服务器发送一个ACK，服务器接收到后，是否说明客户端到服务器的连接已经建立好了？

引用 2 楼 zilaishuichina 的回复:tcp3次握手成功后 就是 ESTABLISHED状态， 这个链接已经建立好了，放在全连接队列里了（lz可以去搜TCP 半连接队列和全连接队列，了解一下），  accept只是从这个队列里将建立好的链接取出来而已。   所以即使你上层逻辑在recv那阻塞了， TCP底层该接受链接还是接受链接，直到这个队列满了为止。 谢谢！

百度搜相关关键字。


Question: C语言为什么输入有时会跳过，即使加了getchar()也没用

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #include<windows.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef struct person {     char name[9];  /* 人名 */     char gender[3]; /* 性别 */     char number[15]; /* 学号 */  } Borrower;  /* 借书人信息 */ typedef struct library {     char title[101]; /* 书名 */      char price[11];   /* 价格 */     char author[9]; /*作者*/     char state[5];     Borrower s ; } Library; Library book[2000]; typedef struct Node {     int value;     Library company;     struct Node *next; } Node; void save(Library book[],int end); void menu1(); void menu2(); int insert(Library first[],int end1); void delete1(Library first[],int end1); void change(Library first[],int end1); void show(Library first[]); int sll_insert(Node *current,int new_value ); int gainchar(char *A,int min,int max);//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度 int gainint(int *p,int a,int b);//输入int *p直至满足(a,b)输入结束，并返回*p的值 void menu1() {     puts("1、信息录入");     puts("2、信息帮助");     printf("3、一个汉字两个字节\n");     printf("\n"); } void save(Library book[],int end) {     FILE *fp;     int i;     if((fp = fopen("library.txt","w")) == NULL)     {         printf("文件无法打开\n");         return;     }     for(i=0; i<end; i++)         if(fwrite(&book[i],sizeof(Library),1,fp)!= 1)             printf("file write error\n");     fclose(fp); } void menu2() {     puts("1.信息删除");     puts("2、信息修改");     puts("3、信息查找"); }   int sll_insert(Node *current,int new_value ) {     Node *previous;     Node *New;      while(current->value < new_value)     {         previous = current;         current = current->next;     }      New = (Node*)malloc(sizeof(Node));     if(New == NULL)         return FALSE;     New->value = new_value;      New->next = current;     previous->next = New;     return TRUE; }  int insert(Library first[],int end1) {     int j;     int i = 0;     for(j=0; j<end1; j++)     {         printf("请输入\n");         printf("书名：   ");          gainchar(first[j].title,1,100);         printf("价格：  ");         gainchar(first[j].price,1,10);         printf("作者：  ");         gainchar(first[j].author,1,8);          printf("\n");         printf("在借or未接  ");         gainchar(first[j].state,4,4);          printf("\n");         printf("您的姓名：   ");         gainchar(first[j].s.name,2,8);          printf("\n");         printf("您的性别：   ");         gainchar(first[j].s.gender,2,2);          printf("\n");         printf("您的学号：  ");         gainchar(first[j].s.number,6,14);         i++;         printf("\n这是您存的第%d本书\n",i);     }     return i; }  void delete1(Library first[],int end1) {     int b;     int i;     printf("您要删除第几本书？[1,%d]\n",end1);     gainint(&b,1,end1);     for(i=b; i<end1; i++)         first[i] = first[i+1]; } void change(Library first[],int end1) {     int b1,b11;     printf("您要修改第几本书？\n");     gainint(&b1,1,end1);     printf("您要修改哪个信息？\n");     puts("1、书名");     puts("2、作者");     puts("3、价格");     puts("4、状态");     puts("5、您的姓名");     puts("6、您的性别");     puts("7、您的学号");     gainint(&b11,1,7);     switch(b11)      {     case 1:     {         gainchar(first[b1-1].title,1,100);         break;     }     case 2:     {         gainchar(first[b1-1].author,2,8);         break;     }     case 3:     {         gainchar(first[b1-1].price,1,10);          break;     }     case 4:     {          gainchar(first[b1-1].state,4,4);         break;     }     case 5:     {         gainchar(first[b1-1].s.name,2,8);         break;     }     case 6:     {          gainchar(first[b1-1].s.gender,2,2);         break;     }     case 7:     {         gainchar(first[b1-1].s.number,6,14);         break;     }     default:     {         printf("ERROR\n");         break;     }     break;     }      } void show(Library first[]) {     int b2;     printf("您要查询哪本书?\n");     scanf("%d",&b2);     puts(first[b2-1].title );     puts(first[b2-1].author);     puts(first[b2-1].price);     puts(first[b2-1].s.name);     puts(first[b2-1].s.gender );     puts(first[b2-1].s.number ); }    int main(void) {      Library first[2000];     Node book;      int input ;     int t,end1;     int i = 0;      menu1();       scanf("%d",&input);     printf("\n");     memset(first ,0,sizeof(first));     switch(input)     {     case 1:     {            printf("您要存几本书：");          scanf("%d",&end1);          if(end1>2000)         {             printf("抱歉，我无法存超过两千本书\n");          }           i = insert(first,end1);         book.value = i;           menu2();         scanf("%d",&t);         switch(t)         {         case 1:         {             delete1(first,end1);              break;         }         case 2:         {             change(first,end1);             break;         }         case 3:         {             show(first);             break;         }         default:         {             printf("ERROR \n");             break;         }           }          save(first,end1);         break;     }           case 2:     {         printf("     本图书管理系统最多存2000本书，可以存图书的书名，价格，作者等信息，您也必须输入您的相关信息。\n其中系统会自动显示您存储书的编号以方便查找。您也可以对您的信息进行修改。 \n" );         break;     }     default:         printf("抱歉，系统还在维修……\n");     }      system("pause");      return 0; } int gainint(int *p,int a,int b)//输入int *p直至满足(a,b)输入结束，并返回*p的值 {     do     {         *p=a-1;    //此处是为了减少意外情况的发生 虽然那种意外情况不常见         scanf("%d",p);         while(getchar()!='\n');         if(*p>b||*p<a)             printf("输入有误,请重新输入[%d--%d]:",a,b);     }     while(*p>b||*p<a);     return *p; } int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度 {     int B,C;     do     {         A[max]=B=C=0;         while((A[B++]=getchar())!='\n'&&B<max);         if(A[B-1]!='\n')while(getchar()!='\n'&&++C);         else A[--B]=0;         if(C||B&&B<min)             printf("您录入的字符串长度:%d字节\n只录入(%d--%d)个字节!\n",B+C,min,max);     }     while(C||B<min);     return B; }  这是我改过得，你看看  另外如果你想让你的 图书管理系统 gengwanshan 更完善包括 名字的检测 等等 加我QQ 2423824433

http://blog.csdn.net/zhagoodwell/article/details/77422530  里面的第一个代码   把输入的字符串的函数  都改为Getchar函数  就行～而且那个函数很不错

fflush(stdin);

建议去掉所有getchar();并且insert函数了gets都改成scanf；换成scanf("%s", xxx);就可去掉所有getchar(); getchar()主要针对gets和scanf("%c", xxx);的。  还有一种办法，就是去掉insert函数里所有getchar();只在insert调用前加一个getchar();即可，其他地方的getchar()也一并去掉；


Question: 动态分配数组之后，不能输出任何变量

引用 4 楼 u013129143 的回复:[quote=引用 1 楼 sdghchj 的回复:] 数组的下标是0到n-1，而不是1到n  我的意思是无论将那个 输出的参数 改成什么变量都会崩溃程序。    而将参数改成常数的话能输出[/quote] 数组的下是0到n-1，循环终止条件是 <=n，那么f[n]已经越界。

引用 5 楼 u013129143 的回复:引用 2 楼 user-4 的回复:测试过了 不报错 不知道你那边报什么错误 我用的是vs2012编译器不是语法问题，是程序执行的时候崩溃了   f[n] 已经越界了，越界操作是未定义行为，未定义行为表示可能崩溃，也可能不崩溃，就算不崩溃也说明不了什么问题

#include <stdio.h> #include <stdlib.h>  #define max 1000001 #define mod 10007  int main(int argc, char *argv[]) {     int i,n;     int *f;     scanf("%d",&n);     if (n < 2)         return 0;      f = (int *)malloc(sizeof(int)*n);     if (!f)         exit(0);     f[0] = 1;     f[1] = 1;     for(i = 2; i < n; i++)         f[i] = (f[i-1] + f[i-2]) % mod;     printf("%d\n",f[n-1]);     free(f);     return 0; } 参考一下吧  注意越界，若n输入的是1，则会导致越界； 另外，输入n是，下标应该是从0开始，并且是[0, n-1]

引用 2 楼 user-4 的回复:测试过了 不报错 不知道你那边报什么错误 我用的是vs2012编译器 不是语法问题，是程序执行的时候崩溃了

引用 1 楼 sdghchj 的回复:数组的下标是0到n-1，而不是1到n  我的意思是无论将那个 输出的参数 改成什么变量都会崩溃程序。    而将参数改成常数的话能输出

引用 2 楼 user-4 的回复:测试过了 不报错 不知道你那边报什么错误 我用的是vs2012编译器 DEV C++

用vs运行部崩溃

测试过了 不报错 不知道你那边报什么错误 我用的是vs2012编译器

数组的下标是0到n-1，而不是1到n


Question: 同一个程序，多次输出结果不同，请大佬帮忙

没读懂你的逻辑，但语法上应该是queue分配的空间不够，多分配一些就可以保证语法没问题了，但不保证逻辑没问题

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

代码可读性很差，逻辑不明确。 建议将需求贴出来，以便对照需求看代码或许能看出问题所在。

单步跟踪程序运行，观察变量变化情况，分析原因


Question: 求解 offsetof 宏

我觉得应该跟编译器有关： typedef struct{     int b;     int c; }tmp;  int main(int argc, char *argv[]) {     int *a1 = (int*)0;     tmp *a2 = (tmp*)0; //    printf("%d\n",*a1);  //  报错     printf("%d\n",&(*a1)); //正常运行  输出0 //    printf("%d\n",a2->c); // 报错     printf("%d\n",&(a2->c)); //正常运行 输出4     return 0; } 感觉可以理解为执行&(a2->c)时并未去访问c的内容，而是编译器直接将取地址和按地址访问优化了直接得到 c的地址，也就是相对于0的偏移量

是在编译阶段确定的，因为每个member的偏移量在编译期间就确定了，没崩溃是因为这样只是根据member的名字计算出它对于结构体起始地址的偏移量，并没有读写这块儿内存

肯定编译期就可以得出，知道结构体起始位置，编译器肯定能知道对应成员的地址，而这个起始地址是0，得到的相当于是对于头的一个偏移量

是在編譯時就展開了

访问说的是要解引，这里只是获得这个成员的地址的值，并没有去访问这个成员


Question: 数据结构单链表，关于指针、引用的使用

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

引用 3 楼 u012536120 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] &引用用法是C++的用法，C语言编译器不识别该用法，因此建议形参用二重指针； 我试了下，编译能通过了。 那main里的&L，是指对L取地址，不是对L的引用？[/quote] 对，main函数里的&是取地址，而不是引用。

引用 2 楼 cfjtaishan 的回复:&引用用法是C++的用法，C语言编译器不识别该用法，因此建议形参用二重指针； 我试了下，编译能通过了。 那main里的&L，是指对L取地址，不是对L的引用？

#include<stdio.h> #include<stdlib.h> #include<malloc.h>  #define OK 1 #define ERROW -1 #define OVERFLOW -2  #define LEN sizeof(struct Lnode) #define LN  LNode *  typedef int Status; typedef int ElemType;  typedef struct Lnode {     ElemType num;     struct Lnode *next; }LNode,*LinkList;  /*链表的初始构建函数*/ Status InitList(LinkList *L) {     *L = (LN)malloc(LEN);     if(*L == NULL)         exit(OVERFLOW);     (*L)->next = NULL;     return OK; }  int main() {     LinkList L = NULL;     InitList(&L);      return 0; } 参考一下吧  Status InitList(LinkList &L) &引用用法是C++的用法，C语言编译器不识别该用法，因此建议形参用二重指针；


Question: 拉格朗日乘数法问题1111

百度搜相关关键字。


Question: 想请教一下，输入法是英文没错，但还是编译不出来是为什么

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

程序没问题，应该是环境配置问题。

程序没有问题   1.一种情况是你工程没建队 2，另外一个就是vc编译器的问题，你先不管哪个错误，直接运行看结果能出来不 3.你换成vs环境把你代码放进去

cl.exe是VC使用真正的编译器（编译程序），其路径在“VC根目录/VC98/Bin”下面， 你可以到相应的路径下找到这个应用程序。   因此问题可以按照以下方法解决：打开vc界面 点击VC“TOOLS（工具）”—>“Option（选择）” —>“Directories（目录）”重新设置“Excutable Fils、Include Files、 Library Files、Source Files”的路径。很多情况可能就一个盘符的不同 （例如你的VC装在C，但是这些路径全部在D），改过来就OK了。  又：遇到问题应该先去网上搜一下。


Question: 简单数组问题

int *p[3] = a; 是错误的语法,应该是 int (*p)[3] = a;

https://zhidao.baidu.com/question/190369972.html 建议从网上搜关键字，可以找到很多这样的信息。

压扁数组是针对多维数组说的：如二维数组 array[3][3] 1 2 3 4 5 6 7 8 9 要遍历这个数组一般用数组指针int *p[3] = array ;  *(*(p+i)+j)来表示二维数组里的元素，压扁数组是用一个一维指针q = &array[1][1] ,然后*(q++),这样来遍历二维数组，&array[1][1],虽然是一个二维数组元素地址，但说白了，也就是一个普通地址，普通地址个一个指针完全说的通。但这样就丢失了二维数组列宽的概念了，数据在内存里都是顺序存储的。这种现象成为压扁数组。


Question: 单链表的初始化函数为什么会影响单链表的删除函数

引用 1 楼 hdt 的回复:传入一个函数的指针，在函数中改变了它的地址，函数结束后，这个指针还是原来的值！ 请问关于循环单链表的初始化(*head)->next = head;为什么是head而不是*head????

用指针的指针（struct type **root）不就是为了记录链表的第一个节点么，当你要在链表第一个节点前插值的话不就要保存新的节点作为链表第一个元素，  不知道你说的运行不了是什么意思

void List_Initiate(SLNode **head)       //单链表的初始化 {      *head = malloc(sizeof(SLNode));   //申请头结点  (*head)->next = NULL;               //设置元素个数为0个 } 建议初始化函数改成二重指针，调用时注意在原来的实参基础上加上& 形参定义成二重指针的目的是能够获取初始化的头结点，否则不能获取头结点的malloc空间和对头结点的next初始化。

引用 5 楼 hdt 的回复:[quote=引用 4 楼 qq_26602805 的回复:] [quote=引用 1 楼 hdt 的回复:] 传入一个函数的指针，在函数中改变了它的地址，函数结束后，这个指针还是原来的值！ 请问关于循环单链表的初始化(*head)->next = head;为什么是head而不是*head????[/quote] 你的代码有不少错误，我就不仔细讲了。 * 代表取的指针指向的值。[/quote] 恩恩，这个问题你一说大概明白问题了，还有个问题是：关于循环单链表的初始化(*head)->next = head;为什么是head（书上写的head）而不是*head????

引用 4 楼 qq_26602805 的回复:[quote=引用 1 楼 hdt 的回复:] 传入一个函数的指针，在函数中改变了它的地址，函数结束后，这个指针还是原来的值！ 请问关于循环单链表的初始化(*head)->next = head;为什么是head而不是*head????[/quote] 你的代码有不少错误，我就不仔细讲了。 * 代表取的指针指向的值。

传入一个函数的指针，在函数中改变了它的地址，函数结束后，这个指针还是原来的值！