Question: 怎么查看exe和dll文件的版本信息？

仅供参考：#pragma comment(lib,"version") #include <windows.h> #include <stdio.h> void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      len=(int)(*(WORD *)buf);     printf("0x%08X bytes:\n",len);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j+=2) {                 sprintf(binstr,"%s%C",binstr,(buf[j]<=0x20&&buf[j+1]==0)?L'.':*(wchar_t *)&buf[j]);             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j+=2) {             sprintf(binstr,"%s%C",binstr,(buf[j]<=0x20&&buf[j+1]==0)?L'.':*(wchar_t *)&buf[j]);         }         printf("%s\n",binstr);     } } int main(int argc,char **argv) {     DWORD             dwVerHnd;     DWORD             dwVerInfoSize;     VS_FIXEDFILEINFO *pFileInfo;     LPVOID            lpvMem;     HANDLE            hMem;     unsigned int      uInfoSize;     WORD              m_nProdVersion[4];      if (argc<2) {         printf("Usage: %s fullpathfilename.ext [dumpall]\n",argv[0]);         return 1;     }     dwVerInfoSize = GetFileVersionInfoSize(argv[1], &dwVerHnd);     if (dwVerInfoSize) {             hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);             lpvMem = GlobalLock(hMem);             GetFileVersionInfo(argv[1], dwVerHnd, dwVerInfoSize, lpvMem);             VerQueryValue(lpvMem,"\\",(void**)&pFileInfo, &uInfoSize);             m_nProdVersion[0]=HIWORD(pFileInfo->dwProductVersionMS);             m_nProdVersion[1]=LOWORD(pFileInfo->dwProductVersionMS);             m_nProdVersion[2]=HIWORD(pFileInfo->dwProductVersionLS);             m_nProdVersion[3]=LOWORD(pFileInfo->dwProductVersionLS);             printf("The file [%s]'s version: %d.%d.%d.%d\n",argv[1],                 m_nProdVersion[0],                 m_nProdVersion[1],                 m_nProdVersion[2],                 m_nProdVersion[3]);             if (argc>2) {//dumpall                 HexDump((char *)lpvMem,dwVerInfoSize,0);             }             GlobalUnlock(hMem);             GlobalFree(hMem);     } else {         printf("Can not GetFileVersionInfoSize(%s,...)!\n",argv[1]);     }     return 0; }

右键属性就可以啊

去下载一个PEID可以查看

我记的有！具体的名字忘了 exe dll 其实是pe格式的可执行文件，了解一下pe文件！


Question: 求组 为什么乱码

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

出现乱码的原因，应该是输入p->name时前加了&

#include<stdio.h> #include<malloc.h> #include<stdlib.h>  #define STUDENT struct stu  #define LEN sizeof(STUDENT)  STUDENT{     int num;     char name[16];     char sex;     int age;     double grade;     STUDENT *next; };  STUDENT *create() {     STUDENT *head,*p1;     p1 = (STUDENT *)malloc(LEN);     if (!p1)         exit(0);     scanf("%d%s %c%d%lf", &p1->num, p1->name, &p1->sex, &p1->age, &p1->grade);     head = NULL;     while(p1->num != 0){         p1->next=head;         head=p1;         p1=(STUDENT *)malloc(LEN);         scanf("%d%s %c%d%lf",&p1->num, p1->name,&p1->sex,&p1->age,&p1->grade);     }     free(p1);     return(head); }  void print(STUDENT *head) {     STUDENT *p;     p = head;      if(!head)         return;      do{         printf("%d%s%c%d%lf\n",p->num,p->name,p->sex,p->age,p->grade);         p=p->next;     }while(p!=NULL); }  STUDENT *del(STUDENT *head, int age) {     STUDENT *p1,*p2;      if(head==NULL){         printf("\nlist null! \n");         return(head);     }     p1 = head;     while(age != p1->age && p1->next!=NULL){         p2 = p1;         p1=p1->next;     }     if(age==p1->age){         if(p1 == head)             head = p1->next;         else             p2->next = p1->next;         printf("delete:%d\n",age);         free(p1);     }     else         printf("%d  not been found\n",age);     return(head); } int  main() {     STUDENT *head,*s;     int del_age;     head=create();     print(head);     printf("\ninput the deleted age:");     scanf("%d", &del_age);     if (del_age != 0){         head = del(head,del_age);         print(head);     }      system("pause");     return 0; } 参考一下吧  问题有多处，首先：scanf("%d%s %c%d%lf", &p1->num, p1->name, &p1->sex, &p1->age, &p1->grade);p->name前不需要&，因为数组名本身就是地址；建议在%s和%c中间加一个空格，这样再输入name之后输入sex（一个字节）之前可以加一个空格，然后再输入sex；grade定义的是double类型，因此输入和输出格式应该是%lf  第二个问题：删除操作时，del_age，age年龄没有定义成double，从结构体定义的int类型，因此为了保持一直，建议定义成int类型； 第三个问题：删除函数所在的循环里，应该用if而不是用while，因为若删除结束后,del_age还是原来的值，这样容易造成死循环； 第四个问题：删除操作时，应该是判断要删除的是头节点还是其他节点，因此判断头结点和其他节点是两个分支，因此要用else if(p1 == head)             head = p1->next;         else             p2->next = p1->next;


Question: 新人请教，鸡兔同笼代码问题

循环跑，符合条件停止

引用 4 楼 Lzinner 的回复:#include<stdio.h> int main() {int a,b,x,y; printf("输出的头和脚的总数分别为:"); scanf("%d %d",&x,&y); a=(4*x-y)/2; b=(y-2*x)/2; printf("鸡有%d只,兔有%d只",a,b);a,b;}   这样就可以了code block写的    没有#include<stdlib.h> system("pause");  scanf-s

兔子数=(腿数/2)-头数； 鸡数=头数-兔子数

https://zhidao.baidu.com/question/109971768.html 经典题，解法不唯一。

不用循环 直接砍掉2×头的腿数 /2 就得到兔


Question: 二维数组做参数如何不改变二维数组

请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？

引用 3 楼 cfjtaishan 的回复:要想不改变，那么定义的函数里不对数组做修改就是了。这个可以自己控制的。如果是别人的写的接口函数，还想不让他改变，那么你在传入参数之前拷贝一下，即用数组的副本作为实参传入函数里，即使函数里对副本做了修改，但也不会修改原本数组的内容； 还可以把形参加上const修饰，这样函数里对数组内容修改，会有提示，编译会提示；这样就不用数组副本了。

const int (*a)[maxsize] 呢？

你的 ispoint 函数为什么要改变数组值呢？可不可以修改ispoint函数里的代码，让他不要修改。如果不能的话，可以每次调用时复制一个数组给他


Question: Linux下用TCP做一个聊天小程序，结果客户端在使用登录功能再退出后导致服务器也退出

谢了，错误自己找到了，是由于客户端关闭套接子关闭，而服务器仍在接受无效的套接子，导致服务器崩溃。再读取套接字步骤加个判断条件就行

结构体定义呢？代码不全

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

从服务器代码里看不出有正常退出的接口，因此很有可能是链表操作的地方有逻辑问题，导致服务器异常退出；

服务器崩了？

我的服务器代码没有给出退出条件啊  没有给return也没有exit

以上为结果图，，在不使用登录的情况下退出，服务器不退出，但在使用登录功能之后再退出客户端将导致服务器退出


Question: 调用不同文件中的函数时总是build失败

把所有文件都添加到工程中，保证文件都在同一目录

文件（.h和.c）应该放在同一个目录下

应该是编译没有编译到function.c，或者没有找到function.c。确认一下是否加载function.c和编译function.c

把所有.c添加到当前项目的源文件中。


Question: 串口数据接收问题

定义一个缓冲区buffer，之后记得要加CRC校验。 数据总会接收完的吧，最后一个字节是以什么结尾，\r\n? 那不就简单了

不明白你想做什么，存数组和不存数组没有区别，都已经叫做串口了自然就是一个一个的发，一个一个的收，按照你规定好的通信协议，在把接受到的数据进行处理，可以设置串口的缓冲区，但那也是一个一个的收的，只是收完之后在一起给你，前提也是你知道接受多少数据之后来处理，如果数据的长度是可变的，还是每发送一个就接收一个的好

用类似modbus这样的协议吧..

好吧，我想复杂了，可以定义一个大些的数组，全部接收过来，再打印。还有一个方法是使用字符串类定义std::string strbuf；strbuf不断累加即可。

参考《编译原理》中的词法分析和有限状态自动机。

你这个问题问得是嵌入式程序处理吧？

1.一次把发送的数据全部接收 2.如果是一个字符一个字符接收，那当输入缓冲区为空的时候就代表接收完成了吧

引用 6 楼 qq_33462307 的回复:[quote=引用 5 楼 shaopengf 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] [quote=引用 1 楼 shaopengf 的回复:] 一次发的数据长度是不确定的 定义一个数组（由于长度不确定，那么定义一个可能的较大的），然后把要发送的数据放入里面。需要注意或者担心什么？[/quote]还要对接收的数据进行处理，比如串口一次发过来的是02 30 0A 0B 1A 08，我接收后想把02 30 0A 0B 1A 08放在数组里转发出去，数的长度和类型都不确定，不是一个字节一个字节转发，类似于串口助手的自动换行？[/quote]  长度不确定就用动态数组啊,用vector 类型不确定是什么鬼，数组就是用来存储同一种数据结构的，类型不同是搞什么..  我的意思是如果你能一次把数据接收下来，那数据的大小就有了，重新申请数组也行，你为什么这么纠结自动换行啊，不就是一个\n吗？[/quote]是，不用纠结换行，重点是能把一次发的数据放数组里，怎么判断把发送的数据都存放在动态数组里了呢，然后就可以使用这个动态数组了

引用 5 楼 shaopengf 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] [quote=引用 1 楼 shaopengf 的回复:] 一次发的数据长度是不确定的 定义一个数组（由于长度不确定，那么定义一个可能的较大的），然后把要发送的数据放入里面。需要注意或者担心什么？[/quote]还要对接收的数据进行处理，比如串口一次发过来的是02 30 0A 0B 1A 08，我接收后想把02 30 0A 0B 1A 08放在数组里转发出去，数的长度和类型都不确定，不是一个字节一个字节转发，类似于串口助手的自动换行？[/quote]  长度不确定就用动态数组啊,用vector 类型不确定是什么鬼，数组就是用来存储同一种数据结构的，类型不同是搞什么..  我的意思是如果你能一次把数据接收下来，那数据的大小就有了，重新申请数组也行，你为什么这么纠结自动换行啊，不就是一个\n吗？

引用 3 楼 cfjtaishan 的回复:[quote=引用 1 楼 shaopengf 的回复:] 一次发的数据长度是不确定的 定义一个数组（由于长度不确定，那么定义一个可能的较大的），然后把要发送的数据放入里面。需要注意或者担心什么？[/quote]还要对接收的数据进行处理，比如串口一次发过来的是02 30 0A 0B 1A 08，我接收后想把02 30 0A 0B 1A 08放在数组里转发出去，数的长度和类型都不确定，不是一个字节一个字节转发，类似于串口助手的自动换行？

引用 2 楼 qq_33462307 的回复:你增大缓冲区吧，一次把数据全部接收过来，然后进行处理，虽然这不是个好办法.. 暂时没能想到如何判断出这个一次发送数据我这边还要对数据进行处理，比如一次发的是02 30 0A 0B 1A 08，我接收后想把02 30 0A 0B 1A 08放在数组里转发出去，而不是一个字节一个字节转发，有好方法吗

引用 1 楼 shaopengf 的回复:一次发的数据长度是不确定的 定义一个数组（由于长度不确定，那么定义一个可能的较大的），然后把要发送的数据放入里面。需要注意或者担心什么？

一次发的数据长度是不确定的


Question: 课程设计中的问题

问题在下方。。

建议在必要位置设置断点，然后单步跟踪程序运行，观察变量变化情况与你期望的是否一致，分析原因

#include<stdio.h> #include<stdlib.h> #include<string.h>  #define LEN sizeof(struct list)  int n=0; struct list {     int num;     char name[20];     long tel;     char classify;     char email[50]; }list[200];  void save()//保存文件 {     FILE *fp;     int i;     if((fp=fopen("通讯录","wb"))==NULL)     {         printf("无法打开文件");         exit(0);     }     for(i=0;i<n;i++)         fwrite(&list[i],LEN,1,fp);      printf("保存成功\n");     fclose(fp); }  void creat()//增加联系人 {     int i,j;     printf("请输入信息，当输入姓名为end时停止录入\n");     for(i=0;;i++)     {         printf("姓名");         scanf("%s",list[i].name);         if(strcmp(list[i].name,"end")==0)         {system("cls");             break;}         printf("电话号码");         scanf("%ld",&list[i].tel);         printf("选择分类：Ａ办公类　Ｂ个人类　Ｃ商务类");         fflush(stdin);         getchar();    /* for '\n' */         scanf("%c",&list[i].classify);         printf("电子邮件");         fflush(stdin);         scanf("%s", list[i].email);         n=n+1;         list[i].num=n;         if (i > 0)         {             for(j=0;j<i;j++)                 if(strcmp(list[j].name,list[i].name)==0||(list[j].tel==list[i].tel))                 {                     printf("姓名和电话号码重复，请重新输入\n");                     n--;                     i--;                     break;                 }         }         if(n>15)         {             printf("存储空间已满，不能录入\n");system("pause");             return;         }     } } void show()//查看所有联系人 {     int i;      system("cls");     if(n==0)         printf("未输入数据！\n");     else printf("序号    姓名　　    电话号码　　　 分类　电子邮件\n");     for(i=0;i<n;i++)         printf("%d       %-12s%-15ld%-6c%s\n",list[i].num,list[i].name,list[i].tel,list[i].classify,list[i].email); } void search()//查找联系人 {     int i;     char sel;      printf("请选择要查找的分类：Ａ办公类　Ｂ个人类　Ｃ商务类");     getchar();    /* for '\n' */     scanf("%c", &sel);     printf("姓名　　    电话号码\n");     for(i=0;i<n;i++)         if(sel==list[i].classify)             printf("%-12s%-15ld\n",list[i].name,list[i].tel);  }  void repair()//修改联系人信息 {     int i,b;     char a[20];     char newname[20];     long newtel;     char newclassify;     char newemail[50];      printf("请输入要修改的姓名");     scanf("%s", a);     for(i=0;i<n;i++)     {         if(strcmp(a,list[i].name)==0)             break;     }     if (i >= n) {         printf("Can't find it!\n");         return;     }     printf("请选择修改的单项：１姓名２电话号码３分类４电子邮件");     scanf("%d", &b);     if(b==1)     {         printf("请输入新姓名");         scanf("%s",newname);         strcpy(list[i].name, newname);         printf("修改成功\n");     }     if(b==2)     {         printf("请输入新电话号码");         scanf("%ld", &newtel);         list[i].tel = newtel;         printf("修改成功");     }     if(b==3)     {         printf("请输入新分类");         getchar();         scanf("%c", &newclassify);         list[i].classify = newclassify;         printf("修改成功");     }     if(b==4)     {         printf("请输入新电子邮件");         scanf("%s",newemail);         strcpy(list[i].email,newemail);         printf("修改成功\n");     } }  void del()//删除联系人信息 {     int i,j,a;     int flag=0;     char delname[20];     printf("请输入要删除联系人的姓名");     scanf("%s", delname);     for(i=0;i<n;i++)     {         if(strcmp(delname,list[i].name)==0) {             a = i;             flag=1;         }     }     if(flag==1)     {         for(j=a;j < n - 1;j++)         {             list[j] = list[j+1];             /*                list[j].num=list[j+1].num;                strcpy(list[j].name,list[j+1].name);                list[j].tel=list[j+1].tel;                list[j].classify=list[j+1].classify;                strcpy(list[j].email,list[j+1].email);                */         }         n--;         printf("删除成功\n");     }     if(flag==0)     {         printf("未找到该联系人\n");         system("pause");         return;     } }  int main() {     int k;      while(1) {         printf("                    通讯录信息系统                    \n");         printf("                  请输入功能所对应的数字                 \n");         printf("|~~~~~~~~~~~~~~~~~~~~~~~~菜单~~~~~~~~~~~~~~~~~~~~~~|\n");         printf("|                  新增联系人信息(1)               |\n");         printf("|                查看所有联系人信息(2)             |\n");         printf("|                  查询联系人信息(3)               |\n");         printf("|                  修改联系人信息(4)               |\n");         printf("|                  删除联系人信息(5)               |\n");         printf("|                  保存联系人信息(6)               |\n");         printf("|~~~~~~~~~~~~~~~~~~~~退出系统(7)~~~~~~~~~~~~~~~~~~~|\n");         scanf("%d",&k);         switch(k)         {             case 1:             system("cls");             creat();             break;              case 2:             system("cls");             show();             system("pause");system("cls");             break;             case 3:             system("cls");             search();system("pause");system("cls");             break;             case 4:             system("cls");             repair();system("pause");system("cls");             break;             case 5:             system("cls");             del();system("pause");system("cls");             break;             case 6:             system("cls");             save();system("pause");system("cls");             break;             case 7:             {                 char a,b;                 system("cls");                 printf("确认退出？Ｙ／Ｎ\n");                 getchar();    /*for '\n' */                 scanf("%c",&a);                 if(a=='Y'||a=='y')                 {                     system("cls");                     printf("是否保存？Ｙ／Ｎ\n");                     getchar();    /*for '\n' */                     scanf("%c",&b);                     if(b=='Y'||b=='y')                     {                         save();                         exit(0);                     }                     if(b=='N'||b=='n')                     {                         exit(0);                     }                 }             }             break;             default : system("cls");                       printf("请输入1-7的数字！\n");         }     } } 参考一下吧  问题挺多的，代码风格个人感觉很不好，乱；不易阅读； 在你的基础上改了一下，将我发现的所有问题做了修改，测试暂时没问题，对比看一下吧

不要用c用s也就是字符串 用c要清缓存区比较麻烦


Question: 求大神告知gets函数为什么也会出现烫

在每个最后不带\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字符或回车换行，读取下一个字符。

记到起.  看到  烫烫烫烫烫   1.  说明可能内存未初始化, 在未初始时, 默认是0xCC, 而两上0xCC0xCC连接起来, 正好是汉字  烫  的编码.  或者越界访问(一般是字符串没有加\0结尾).  越界同理, 访问到了未初始化的内存,

scanf后面加个getchar接收到最后的换行符\n，否则gets实际接收到的内容为空，导致m并没有正确设置结束符，故输出乱码

引用 1楼自信男孩 的回复:#include<stdio.h> #include<string.h>  void gb(char *y,char *m,int i);  int main () {     int i;     char y[100],m[100];     printf("enter i\n");     scanf("%d",&i);     getchar();    /* for '\n' */     printf("enter former char\n");     gets(y);     gb(y,m,i);     puts(m);     return 0; } void gb(char *y, char *m,int start) {     y += start;     while(*y)         *m++ = *y++;     *m = 0; } 参考一下吧  主要问题：.gets是遇到换行符即退出，由于上次输入i时，会将换行符'\n'残留在输入缓存里，因此在调用gets时就会遇到'\n'，直接返回，相当于什么字符也没有刷到内存数组y里。受教了 谢谢您

引用 2楼Zhanganliu 的回复:gets和scanf都会吃回车，这是个小trick，你可以去查查。受教了 感谢您

gets和scanf都会吃回车，这是个小trick，你可以去查查。


Question: C语言文件操函数问题，求指导

就是第一次输入数据的时候，我该怎么办？我有些明白我的错了，我改一下再发上来

楼主的代码看不懂呢，不论是查询还是修改，那么都需要有数据，用户数据和房间信息的数据，但是并没有找到从文件里读的操作，没有读操作，查询和修改就没有意义。 作为初学者，不建议是用goto语句，能用其他方式替代的，尽量使用其他方式；  在查询和修改前，需要将数据从文件里读到内存里，然后在内存里操作读取和修改。


Question: 关于C语言的json库，jansson，其中的json_load_callback()函数是什么意思？

建议使用Json For Modern C++库


Question: 我的第一个socket代码错哪了？

我这里有一些，希望能有用： http://blog.sina.com.cn/s/articlelist_1595473800_2_1.html http://blog.sina.com.cn/s/articlelist_1595473800_6_1.html

学会使用抓包软件wireshark

有任何疑问就DEBUG，在recv哪里加个超时机制，看看每次recv返回值是多少

引用 6 楼 赵4老师的回复:不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545 赵老师这几句话都发了好几年了。。。好多帖子都有这句话。。。   我这应该是使用recv循环接收阻塞的问题吧？      跟数据接收不全是两码事吧

引用 4 楼 wodexiaojidan 的回复:[quote=引用 3 楼 wqte45 的回复:] [quote=引用 1 楼 wodexiaojidan的回复:]http是短链接，成功一次后要断开重新connect 不，你说的那是http 1.0年代的时候  现在都支持了，如果发一次，就重新连接太浪费资源了，而且手动提交数据后  还可以继续提交 也没看到服务器返回信息后 自动关闭连接啊  我觉得还是recv机制的问题[/quote]那你可以看下你的webservice服务端的源码，看下解析xml和生成xml的模块，我还第一次听说http不是短链接了[/quote]网上复制的“”但从 HTTP/1.1起，默认使用长连接，用以保持连接特性。使用长连接的HTTP协议，会在响应头有加入这行代码： Connection:keep-alive 在使用长连接的情况下，当一个网页打开完成后，客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭，如果客户端再次访问这个服务器上的网页，会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接，它有一个保持时间，可以在不同的服务器软件（如Apache）中设定这个时间。实现长连接要客户端和服务端都支持长连接。“”

引用 3 楼 wqte45 的回复:[quote=引用 1 楼 wodexiaojidan的回复:]http是短链接，成功一次后要断开重新connect 不，你说的那是http 1.0年代的时候  现在都支持了，如果发一次，就重新连接太浪费资源了，而且手动提交数据后  还可以继续提交 也没看到服务器返回信息后 自动关闭连接啊  我觉得还是recv机制的问题[/quote]那你可以看下你的webservice服务端的源码，看下解析xml和生成xml的模块，我还第一次听说http不是短链接了

引用 1 楼 wodexiaojidan的回复:http是短链接，成功一次后要断开重新connect 不，你说的那是http 1.0年代的时候  现在都支持了，如果发一次，就重新连接太浪费资源了，而且手动提交数据后  还可以继续提交 也没看到服务器返回信息后 自动关闭连接啊  我觉得还是recv机制的问题

建议在服务器端看一下是否收到了page为2,3的http包 另外，注意Sleep(200)是不是时间间隔较短；

http是短链接，成功一次后要断开重新connect


Question: 新手求助！C语言，二进制数据转换成十进制数

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <ctype.h>  int main() {     char a[17];     fgets(a, 17, stdin);     int len,i,sum=0,m,j;     len = strlen(a);     if (len < 17)         len -= 1;      m = 1;     while (a[i]) {         if (isdigit(a[i]))             sum += (a[i] - '0') * pow(2, len - i - 1);         i++;     }     printf("%d\n", sum);      /*     if(len<=16)     {         for(i=0;i<len;i++)         {             m=1;             if(a[i]=='1')             {                 for(j=1;j<=len-i-1;j++)                     m*=2;                 sum+=m;             }         }         printf("%d",sum);     }     */     return 0; } 参考一下吧～

char a[17]; gets(a); char *e; int i = strtol(a, &e, 2); printf("%d", i);

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

引用 1 楼 SameenTang 的回复:emmmm自己又编了一个 #include <stdio.h> #include <stdlib.h>  int main() {     char a[17];     gets(a);     int len,i,sum=0,m,j;     len=strlen(a);     if(len<=16)     {         for(i=0;i<len;i++)     {         m=1;         if(a[i]=='1')         {             for(j=1;j<=len-i-1;j++)                 m*=2;             sum+=m;         }     }     printf("%d",sum);     }     return 0; }   但是不知道为什么是这样的   有用PTA的吗 #include <stdio.h> //#include <stdlib.h> #include <string.h>   int main() {     char a[17];     gets(a);     int len,i,sum=0,m,j;     len=strlen(a);     if(len<=16)     {         for(i=0;i<len;i++)     	{         	m=1;         	if(a[i]=='1')         	{          		for(j=1;j<=len-i-1;j++)         		m*=2;             	sum+=m;         	}     	}     	printf("%d",sum);     }     return 0; } 头函数不包括strlen直接引用了。修改头函数后（修改见上）编译通过，运行了一楼的示例是正确的。


Question: 最大值和次最大值下标问题

#include <stdio.h>  #define N 1000   int first_idx, second_idx;  void getMax12(int*a, int n) { 	int first_max, second_max; 	int i, j; 	first_max = a[0]; 	first_idx = 0;  	for (i = 1; i < n; i++) { 		if (first_max < a[i]) { 			second_max = first_max; 			second_idx = first_idx; 			first_max = a[i]; 			first_idx = i; 			break; 		} else if (first_max > a[i]){ 			second_max = a[i]; 			second_idx = i; 			break; 		} 	}  	//printf("%d %d", first_idx, second_idx);  	for (j = i + 1; j < n; j++) { 		if (first_max < a[j]) { 			second_max = first_max; 			second_idx = first_idx; 			first_max = a[j]; 			first_idx = j; 			//printf("+++%d %d", first_idx, second_idx); 		} else if (first_max != a[j] && second_max < a[j]) 		{ 			//printf("---%d %d", first_idx, second_idx); 			second_max = a[j]; 			second_idx = j; 		} 	} } int main() { 	int a[N], n, i; 	scanf("%d", &n); 	for (i = 0; i<n; i++) 		scanf("%d", &a[i]); 	getMax12(a, n); 	printf("%d %d", first_idx, second_idx); 	printf("\n"); 	return 0; } 参考一下吧。 可以多做机组数据测试；比如使用以下测试用例： 3 100 100 80  建议变量名不要随便的一个字母命名，最好能做到见名知义；


Question: gcc编译器运行结果正确，网上在线评测运行结果错误

对的，昨天调试了一下，找到了这处错误

while(count > 0) 		putchar(result[--count]); 	putchar('\n'); 应该是cout==0导致的，其他地方没有问题。 注意前自减和自增都是先操作--或++

for (;count >= 0;) {	 putchar(result[--count]);}  当count等于0时--count为-1，越界了

题目和网上在线评测结果


Question: acm题目,提交超时，大佬们看看有什么可以改进的地方

#include <stdio.h> #include <stdlib.h> #include <string.h>  int GetOriNum(int data) { 	int tdata = data >= 0 ? data : -data; 	char s[16] = {0}; 	snprintf(s, sizeof(s), "%d", tdata); 	 	int len = strlen(s); 	int i, t, beg, retval = 0; 	 	int *a = malloc(len * sizeof(int));  	for(i = 0; i < len; ++i){ 		a[i] = s[i] - '0'; 	}  	int tag = 0; 	do{ 		for(i = 0; i < len - 1; ++i){ 			if(a[i + 1] < a[i]){ 				--a[i]; 				a[i + 1] +=10; 				tag = 1; 			} 		}  		if(tag == 0){ 			break; 		}; 		tag = 0; 	}while(1);  	retval = a[0] == 0 ? 0 : a[0]; 	for(i = 0; i < len - 1; ++i){ 		t = a[i + 1] - a[i];  		if(t >= 10){ 			return -1; 		}else{ 			retval = retval * 10 + t; 		} 	}  	retval = data >= 0 ? retval : -retval;  	free(a); 	a = NULL; 	 	return retval; }  int main(void) { 	int i, n;  	printf("Input:\n"); 	scanf("%d", &n); 	int *a = malloc(n * sizeof(int));  	for(i = 0; i < n; ++i){ 		scanf("%d", a + i); 	}  	printf("Output:\n"); 	for(i = 0; i < n; ++i){ 		printf("%d\n", GetOriNum(a[i])); 	}  	free(a); 	a = NULL;  	return 0; }  Input: 7 136 1 10 114514 1919 1107 1096 Output: 123 1 -1 103064 1729 999 989

n = (int)round(m / 1.111111111 + 0.5); 然后测试n、n + 1是否符合条件即可。

从那么多的文字里没有看出魔法数字的算法，建议提供一下求魔法数字的算法。


Question: scanf("%s",name);字符串数组输入带不带取地址符的问题

scanf读取的时候只看传过来的值，这两个参数在数值上是一样的，因此scanf能正确读写。但本质上name和&name是不一样的，数组名在运算时会转换成指针，所以name是指向第一个元素的指针，name+1则指向第二个元素，&name是整个数组的首地址，&name+1指向数组的后面

你这个并不是name和&name的区别，而是你对name+1、&name+1、(&name)+1三者的理解  第一个，name和&name一样，都代表数组的首地址，或者name[0]的地址，所以name+1代表name[1]的地址，注意&(name+1)的写法是错的，因为name+1已经表示地址了，再对地址取地址就是**了，但是&name里，name表示的是数组，是可以这么写的  二和三一样，表示下一个name[20]的首地址，+1的出现改变了&name原因的意义，同理+2就是下下个char数组的首地址  但是在指针里又不一样，比如如果是char *name；name+1表示指向name[1]的值， &name+1、(&name)+1表示name[1]的地址，而一个地址是四字节，所以是&name的值+4

学习了 &数组 就是数组指针了 的确也是

name在字符串中本就是该字符串的首地址，而不是int类型的，若加上&取址，就是把地址取了两次了

数组名可以被当作指针，好理解，但数组名并不是指针 &加数组名，那么这个得到的地址是整个数组的地址 不加 & ，那么这个地址是数组首元素的地址 int a[10]; p = a;     //p指向 a 数组的首元素 p+1 指向数组的第二个元素。p只指向一个int类型 p = &a; //p之指向a整个数组，p+1指向a[10] 越界。p指向10个int类型

都可以啊，标准应该是要有的，但是c语言提供了方便程序员操作的方式，不加也可以

比如有一个二维数组 char[20][20], 现在让name=& char[0][0]; 此时name 指向二维数组数组char[0][0]的首地址，是一个字符指针（指向二维数组的列数，name+1等于前进一列） &name  指向装有若干个数组的数组的第一个数组的地址（指向一个二维的行数，&name+1等于换行）

name  &name  都是地址，地址内容相同，即整个数组的首地址，数组第一个元素的首地址，但地址类型不同 一个 指向char，一个指向char数组 ，故做地址加1运算时偏移量为sizeof(type)*1

引用 4 楼 kuangbao9 的回复:[quote=引用 3 楼 sunflower_25 的回复:] [quote=引用 1 楼 kuangbao9 的回复:] 我瞎猜一下：首先name本身是数组的首地址， 而&name是整个数组的地址，所以理论上name和&name地址是一样的，都是指向数组首地址。 其次，name + 1表示的是数组第二个元素的地址，而(&name)+1表示的是数组最后一个元素的地址的下一个地址。  我试验name地址是FF20，但(&name)+1却是FF34。对于name是一个20个字节的数组。[/quote]  FF34这不正好是最后一个元素地址的下一个地址嘛。。。。[/quot]  地址是十六进制表示的

字符串数组不带&，如name[10]；输入字符串就是scanf（“%d”，name）； 因为数组名name本身就是数组的地址；

理解和讨论之前请先学会如何观察！  //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/2344 C语言指针与汇编内存地址-一.代码要素

引用 5 楼 paschen 的回复:正确的是使用name，name和&name仅仅只是地址相同，但他们是完全不同的类型，前者数组退化后的char*类型，后者是指向数组的指针，这也是为什么他们+1后的值不一样的原因，前者+1移动一个字符，后者则移动一个数组大小的长度 很详细，其实读取字符串一般不加地址符，数组名表示首地址

引用 3 楼 sunflower_25 的回复:[quote=引用 1 楼 kuangbao9 的回复:] 我瞎猜一下：首先name本身是数组的首地址， 而&name是整个数组的地址，所以理论上name和&name地址是一样的，都是指向数组首地址。 其次，name + 1表示的是数组第二个元素的地址，而(&name)+1表示的是数组最后一个元素的地址的下一个地址。  我试验name地址是FF20，但(&name)+1却是FF34。对于name是一个20个字节的数组。[/quote]  FF34这不正好是最后一个元素地址的下一个地址嘛。。。。

引用 1 楼 kuangbao9 的回复:我瞎猜一下：首先name本身是数组的首地址， 而&name是整个数组的地址，所以理论上name和&name地址是一样的，都是指向数组首地址。 其次，name + 1表示的是数组第二个元素的地址，而(&name)+1表示的是数组最后一个元素的地址的下一个地址。  我试验name地址是FF20，但(&name)+1却是FF34。对于name是一个20个字节的数组。

地址是一样的，但是类型是不一样的。name是数组名，可以理解位指针常量，是属于一维指针，而&name是属于二维指针。那么&name相当于name的地址，即&name + 1相当于偏移sizeof(name)个字节。而name + 1偏移是1个字节。


Question: Dijkstra算法最短路径问题！！！已经找到了最短路径长度，但不知道如何输出最短路径所经过的顶点出来！！！

引用 6 楼 sinat_37101089 的回复:在看《有趣的算法》一书中，也遇到这个问题，书中狄克斯特拉使用python实现，最终输出最短路径并没有提示。  思考后认为，狄克斯特拉优先处理最低消耗，处理完一个节点后进行记录，所以用来存储处理过节点的processed[]数组即为最短路径，供参考。  哈，很感谢帖子这么久了还关注呀， 你的方法可以一试。

纳入新结点更新路径的时候顺便记录一下结点名字

引用 3 楼 leetow2006 的回复:请教：图在计算机中怎么表示？  怎么表示？你是想把整个图表示出来？还是想把各个顶点的连接表示出来？

请教：图在计算机中怎么表示？

引用 1 楼 zhao4zhong1 的回复:百度搜相关关键字。 好的，突然来了灵感了

百度搜相关关键字。


Question: 嵌入式利用五向键改变日期

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


Question: 用栈和队将二进制转换为十进制

引用 3 楼 paschen 的回复:建议楼主学会调试，设置断点，单步跟踪程序运行，观察变量变化情况，看是哪与你期望的不一致，分析原因 调试的嵌套一多起来我就看晕了，不过我会耐心去学会调试的，感谢版主

引用 1 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h>  typedef struct node {     char data;     node* next; }NodeStack,*LinkStack;  //置空栈 LinkStack InsertEmpty(); //判断栈是否为空 bool IsStackEmpty(LinkStack LS); //进栈 void PushStack(LinkStack *LS, char data); //出栈 int PopStack(LinkStack *LS,char* data); //输出栈 void Print(LinkStack LS);    /*队*/ typedef struct Que {     char  data;     Que* next; }NodeQueue,*LinkQueue;  typedef struct {     LinkQueue front;     LinkQueue rear; }Queue;  //置空队 Queue* CreatNew(); //判断队是否为空 bool IsQueueEmpty(Queue* QE); //入队 void EnQue(Queue **Que, char data); //出队 void OutQue(Queue **Que, char* data);    //将二进制转为十进制 double Change(char* ss,LinkStack LS,Queue* QE);   /*****函数实现源文件*****/ /****function.cpp*****/  /* #include"headfile.h" #include<stdlib.h> #include<stdio.h> */ /*****************************栈************************/ //置空栈 LinkStack InsertEmpty() {     LinkStack LS = (LinkStack)malloc(sizeof(NodeStack));     LS->next = NULL;     LS->data = 0;     return LS; } //判断栈是否为空 bool IsStackEmpty(LinkStack LS) {     if (LS->next)         return true;     else         return false; } //进栈 void PushStack(LinkStack *LS, char data) {     LinkStack new_node = (LinkStack)malloc(sizeof(NodeStack));     new_node->data = data;     new_node->next = (*LS)->next;     (*LS)->next = new_node; } //出栈 int PopStack(LinkStack *LS, char* data) {     if (IsStackEmpty(*LS))     {         LinkStack p = (*LS)->next;         (*LS)->next = p->next;         *data = p->data;         free(p);         return 1;     }     else         return 0; }  //输出栈 void Print(LinkStack LS) {     if (LS->next)     {         LinkStack p = LS;         while (p->next)         {             printf("%c   ", p->next->data);             p = p->next;         }     }     else     {         printf("栈空\n");     } } /********************队*************************/ //置空队 Queue* CreatNew() {     Queue *new_one = (Queue*)malloc(sizeof(Queue));     LinkQueue node = (LinkQueue)malloc(sizeof(NodeQueue));     node->next = NULL;     node->data = 0;     new_one->front = new_one->rear = node;     return new_one; }  //判断队是否为空 bool IsQueueEmpty(Queue* QE) {     if (QE->front == QE->rear)         return true;     else         return false; }  //入队 void EnQue(Queue **Que, char data) {     LinkQueue LQ = (LinkQueue)malloc(sizeof(NodeQueue));     LQ->data = data;     LQ->next = NULL;     (*Que)->rear->next = LQ;     (*Que)->rear = LQ; }  //出队 void OutQue(Queue **Que, char * data) {      if ((*Que)->front->next == (*Que)->rear)     {         *data = (*Que)->front->next->data;         free((*Que)->front->next);         (*Que)->rear = (*Que)->front;     }     else     {         LinkQueue p = (*Que)->front->next;         *data = p->data;         (*Que)->front->next = p->next;         free(p);     } }         //将二进制转为十进制 double Change(char* ss, LinkStack LS, Queue* QE) {     bool flag = true;     char ch;     int i = 0;     double sum1 = 0, sum2 = 0,temp=0, k = 1, n = 1;     LinkStack p = LS;     Queue* q = QE;     /*如果字符串有小数点，则将字符串分为整数和小数两部分，       整数部分进栈，小数部分入队*/     for (i = 0; *(ss + i); i++)     {         if (*(ss + i) == '.') {             flag = false;             continue;         }         if (flag)         {             printf("%c +++\n", ss[i]);             PushStack(&LS, *(ss + i));         }         else         {             printf("%c ---\n", ss[i]);             EnQue(&QE, *(ss + i));         }     }     p = LS;     q = QE;     while (IsStackEmpty(p))     {         PopStack(&p, &ch);         printf("+++%c  ", ch);         temp = (double)(ch - '0');         printf("tmp = %lf\n", temp);         sum1 += temp * k;         k *= 2;     }     while (!IsQueueEmpty(q))     {         OutQue(&q, &ch);         printf("---%c  ", ch);         temp = (double)(ch - '0');         printf("---tmp = %lf\n", temp);         n *= 1.0 / 2;         sum2 += temp*n;         printf("&&&&\n");     }     printf("sum1=%lf\n", sum1);     printf("sum2=%lf\n", sum2);     return (sum1 + sum2);  }  /*******主函数************/ /* #include"headfile.h" #include<stdlib.h> #include<stdio.h> */ #define MAXSIZE     32 int main() {     LinkStack LS = InsertEmpty();     Queue* QE = CreatNew();     char ss[MAXSIZE];     printf("输入二进制:\n");     scanf("%s", ss);     printf("\n十进制是：%lf\n",Change(ss, LS, QE));     Print(LS);     return 0; }   参考一下吧  我将所有结构体，函数定义和声明放在一个文件里。若保持你的多文件操作，可以对比对应的函数修改，修改你的函数； 问题主要是出在传一重指针上，应该传二重指针。其他的修改，详见上面的代码； 建议对比看一下；  是的，要用二位指针保存变化的头指针，感谢，另外还有两个小问题是判断栈空的函数条件写反了，小数部分的1/2=0没有注意到

个人感觉注释没必要那么多，因为你的函数定义时函数名基本上能表示函数的作用和功能。


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

理解和讨论之前请先学会如何观察！  计算机组成原理→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

引用 12 楼 qq_40778536 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] //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]   《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！  So。。。你的《牛肉干》想表达什么？[/quote] 《Just for fun》

这两个运算符不能简单的用相反数来取代； 比如int *p = NULL; 这个是定义，不是引用。

可以，但这两个运算符在不同的情况下可能还有别的意思

因爲地址以一個整數表示，4字節衹是針對32位程序而言的，也就是尋址範圍最大是4294967296，所以我們看到Windows xp最大内存4G；而在64位程序中，地址就以8字節表示了。

我想问一下 指针是内存单元第一个字节的地址，但为什么占四个字节？ 刚学c，概念有点不清楚

嗯嗯，某些情况下，楼主理解还是对的，但是单纯的&a的话还要看在代码中的位置，有时候如果&a作为函数的参数，也有可能是引用的作用

&后面跟变量，是取地址的意思；*符号，如果是在定义时，表示是定义一个指针变量，比如：int *p; 否则是表示获取地址中的值；比如：int *p,a;a=12;p=&a;printf("%d\n",*p);

引用 11 楼 zhao4zhong1 的回复://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]   《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！  So。。。你的《牛肉干》想表达什么？

衹有首地址，沒有平均地址的概念。在數組的有小範圍内，系統是知道其大小的，但是作爲參數傳到一個函數裏時，大小往往是不確定的。

引用 1 楼 hzy_76 的回复:理解的很对！大部分时候，这确实是一对逆运算。但某些特殊情况例外，比如对一个数组进行&运算，得到的也是数组首地址。   char ss[256] = { 0 }; if (ss == &ss) { 	printf("Equal!\n"); }  您好，请问&arr就是对数组取地址会自动认为是取出来该数组的首个元素的地址可以看成是一个语法糖吗；int arr[10],就是声明了一个长度为10的int[10]类型的数组，10个元素是有地址的，我的另一个问题是：既然这里arr[10]数组作为一个整体而言的话，就是这10个元素的集合，是否可以找到这样一个地址，用来表示个10个元素的「平均地址」，这样以后用指针指向数组就默认的指向其平均地址好了，还是说整体的数组是不存在的，只有当单独的考虑某个特定的元素时才有地址，毕竟如果引入了默认地址的话，要操作具体的某个元素的话就不方便了

指针是C/C++的精华 int b = 10; int a = &b; int *p = &b;


Question: 求教如何从数组中读取用分号分开的数值，并转为整型传参

sscanf

可以尝试char转换int

vector<string> lst; boost::algorithm::split(list, a[i],   boost::is_any_of(":")); if(list.size() > 1) {       int a = (int)(list[0]);      int b = (int)(list[1]); }

可以使用sscanf，也可以使用strtok_r和atoi，当然也可以自己实现字符串转整型数的函数。


Question: 找不到源代码include的.h文件

还可以给对方发邮件要代码。 万一对方有空呢

继续百度、必应、谷歌、……

引用 3 楼 user-3 的回复:源代码竟然不包括.h?! 看看是不是不同版本相对路径调整了我搜索了所有代码，没有这个文件名的文件啊...是源代码不完整吗？

引用 2 楼 jiht594 的回复:还可以给对方发邮件要代码。 万一对方有空呢 其实我用的这个NetCDF是美国马里兰大学做的，貌似全球气象行业都在用这个...我估计联系人家是不会要到东西的...源代码里没有他引用的头文件是不是就是说代码不完整啊...

源代码竟然不包括.h?! 看看是不是不同版本相对路径调整了


Question: while(!feof(in))问题

在VC里，只有当文件位置指针到了文件末尾，然后再发生读/写操作时，标志位才会被置为含有_IOEOF，调用feof()才会得到文件结束的信息。正确写法参看：http://blog.csdn.net/woaisia/article/details/46441449

引用 1 楼 jtidni 的回复:请问，这个-1，是怎么来的？ 这个博客可以解决你的若干问题：  http://blog.csdn.net/qq_29350001/article/details/53100563

请问，这个-1，是怎么来的？


Question: 我的代码哪里错了啊？

因为你第二次查找是从上一次查找到的位置后移25，而不是从上一次开始查找的位置后移25

a+=25; 改成： a = (address - szUrl) + 25;

#include <stdio.h> #include <string.h> int main() {                	char szUrl[] = "{\"headerInfo\":{\"message\":\"成功\",\"code\":\"W_0000\",\"to404\":false},\"responseContent\":{\"dataList\":[{\"minAmount" 		"\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年8月22日-" 		"2017年10月24日\",\"phoneNumber\":\"18135601804\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省\",\"hl" 		"End\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"驻市\"},{\"m" 		"inAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年" 		"8月22日-2017年10月24日\",\"phoneNumber\":\"18135601874\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省" 		"\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"华东市" 		"\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期" 		"为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135601941\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\"" 		":\"山东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\"" 		":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\"" 		"\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602043\",\"status\":\"2\",\"provinceCode\":\"609904\",\"pr" 		"ovince\":\"华东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0," 		"\"city\":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"special" 		"Offers\":\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602804\",\"status\":\"2\",\"provinceCode\":\"6099" 		"04\",\"province\":\""; 	char numbers[12]; 	char *pos = szUrl;  	while(1) 	{ 		char *address = strstr(pos, "phoneNumber"); 		if (!address) 			break; 		strncpy(numbers,address+14,11); 		printf("%s\n",numbers); 		pos = address + 25; 	}    	return 0; }  参考一下吧；  有多次重复，原因是szUrl每次都加25，这个便宜并没有从第一次找到phoneNumber开始的25，所以第一个phoneNumber对应的数字出现了多次。若用address作为基础向后偏移就可以了。  为了提高效率，减少循环次数。可以不用计算a与strlen(szUrl)的比较。直接判断address是否为NULL即可。 其实整个循环也是因为address指向NULL退出的，a >= strlen(szUrl)条件满足前address已经指向了NULL了，所以直接用while(1)可以省去若干变量和对strlen的调用。

引用 2 楼 wqte45 的回复:[quote=引用 1 楼 user-3的回复:]#include <stdio.h> #include <string.h>  int main(void) {                    char szUrl[] = "{\"headerInfo\":{\"message\":\"成功\",\"code\":\"W_0000\",\"to404\":false},\"responseContent\":{\"dataList\":[{\"minAmount"                     "\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年8月22日-"                     "2017年10月24日\",\"phoneNumber\":\"18135601804\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省\",\"hl"                     "End\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"驻市\"},{\"m"                     "inAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年"                     "8月22日-2017年10月24日\",\"phoneNumber\":\"18135601874\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省"                     "\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"华东市"                     "\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期"                     "为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135601941\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\""                     ":\"山东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\""                     ":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\""                     "\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602043\",\"status\":\"2\",\"provinceCode\":\"609904\",\"pr"                     "ovince\":\"华东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,"                     "\"city\":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"special"                     "Offers\":\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602804\",\"status\":\"2\",\"provinceCode\":\"6099"                     "04\",\"province\":\"";     int len, off = 0;  	char numbers[12] = {0}; 	const char *sub = "\"phoneNumber\":\""; 	len = strlen(sub); 	     while(off < strlen(szUrl))     {         char *address = strstr(szUrl + off, sub);         if(address)          { 			if(strlen(address) >= 27){ 				strncpy(numbers, address + len, 11); 				printf("%s\n",numbers); 			}             off = (address - szUrl + 1);         }else{ 			break; 		}     }        return 0; }  18135601804 18135601874 18135601941 18135602043 18135602804 有没有更简单的实现方式？ 还有我写的代码哪里错了？我一直没找到  请告诉我吧[/quote]除了正则表达式没有更简单的。  a代表偏移量，所以a每次的值是原值加25这么来的，是匹配到的新的首地址减去原串首地址加上至少为1的偏移量后的值。

引用 1 楼 user-3的回复:#include <stdio.h> #include <string.h>  int main(void) {                    char szUrl[] = "{\"headerInfo\":{\"message\":\"成功\",\"code\":\"W_0000\",\"to404\":false},\"responseContent\":{\"dataList\":[{\"minAmount"                     "\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年8月22日-"                     "2017年10月24日\",\"phoneNumber\":\"18135601804\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省\",\"hl"                     "End\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"驻市\"},{\"m"                     "inAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期为2017年"                     "8月22日-2017年10月24日\",\"phoneNumber\":\"18135601874\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\":\"河北省"                     "\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\":\"华东市"                     "\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\":\"促销期"                     "为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135601941\",\"status\":\"2\",\"provinceCode\":\"609904\",\"province\""                     ":\"山东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,\"city\""                     ":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"specialOffers\""                     "\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602043\",\"status\":\"2\",\"provinceCode\":\"609904\",\"pr"                     "ovince\":\"华东省\",\"hlEnd\":0,\"cityCode\":\"8411700\",\"prepayMent\":0.0,\"tipText\":\"\",\"typeId\":\"\",\"hlStart\":0,"                     "\"city\":\"华东市\"},{\"minAmount\":0.0,\"salesProdId\":\"000000005930B3EE75FA596CE053AC1410AC221B\",\"level\":1,\"special"                     "Offers\":\"促销期为2017年8月22日-2017年10月24日\",\"phoneNumber\":\"18135602804\",\"status\":\"2\",\"provinceCode\":\"6099"                     "04\",\"province\":\"";     int len, off = 0;  	char numbers[12] = {0}; 	const char *sub = "\"phoneNumber\":\""; 	len = strlen(sub); 	     while(off < strlen(szUrl))     {         char *address = strstr(szUrl + off, sub);         if(address)          { 			if(strlen(address) >= 27){ 				strncpy(numbers, address + len, 11); 				printf("%s\n",numbers); 			}             off = (address - szUrl + 1);         }else{ 			break; 		}     }        return 0; }  18135601804 18135601874 18135601941 18135602043 18135602804 有没有更简单的实现方式？ 还有我写的代码哪里错了？我一直没找到  请告诉我吧


Question: 新手 求解

函数若不指明类型，那么默认是int类型，所以编译器认为类型不匹配。指明sum的类型为double即可。

把sum类型改成int类型或者改成double类型，统一double类型


Question: 课程设计中的一个问题

其次，scanf("%c", &list[i].classify); 前面加一具getchar接收掉留在缓冲区中的\n，否则将会被你的list[i].classify接收

if (k = 1) 改成 if (k == 1)

#include<stdio.h> #include<stdlib.h> #include<string.h>  #define LEN sizeof(struct list)  struct list {     char name[20];     long num;     char classify;     char email[53]; }list[200];  void save() {     FILE *fp;     if((fp=fopen("shuju","w"))==NULL)     {         printf("无法打开文件");         exit(0);     } }  int creat() {     int i;     printf("请输入信息，当输入姓名为end时停止录入\n");     for(i=0;;i++)     {         printf("姓名");         scanf("%s",list[i].name);         if(strcmp(list[i].name,"end")==0)             break;         printf("电话号码");         scanf("%ld",&list[i].num);         getchar();    /* for '\n' */         printf("选择分类：Ａ办公类　Ｂ个人类　Ｃ商务类");         scanf("%c",&list[i].classify);         printf("电子邮件");         //fflush(stdin);         scanf("%s", list[i].email);     }      return i; }  int main() {     int ch, cnt;     while(1)     {         printf("                    通讯录信息系统                    \n");         printf("                  请输入功能所对应的数字                 \n");         printf("|~~~~~~~~~~~~~~~~~~~~~~~~菜单~~~~~~~~~~~~~~~~~~~~~~|\n");         printf("|                  新增联系人信息(1)               |\n");         printf("|                查看所有联系人信息(2)             |\n");         printf("|                  查询联系人信息(3)               |\n");         printf("|                  修改联系人信息(4)               |\n");         printf("|                  删除联系人信息(5)               |\n");         printf("|~~~~~~~~~~~~~~~~~~~~退出系统(6)~~~~~~~~~~~~~~~~~~~|\n");         scanf("%d",&ch);         if(k==1) {             system("cls");             cnt = creat();         }     }      return 0; } 参考一下吧；  考虑结构体对齐，email定义成53字节。 考虑creat函数可以得到当前新增的个数，所以定义成有返回值，这个返回值可以被其他功能函数使用。 其他问题详见代码

有没有人啊 搞了一下午了

其他部分不要在意。。。刚开始做。


Question: 帮忙看一下这是个什么工程

下载安装Visual Fortran试试 .for文件应该是Fortran源代码，你可以用记事本或其他的文本编辑器打开看看

楼主可以打开里面的.exe文件，这是demo程序，看一下功能是怎么实现的

fortran语言？没用过。。。关注

就是fortran程序，看它这列表里没有工程文件，你按它的说明直接修改.for，保存，再重新编译。既然你已经安装了vs和ivf，在命令行输入nmake heat.mak就可以了。


Question: vs2013的注释出现洋红色波浪纹

逐个禁用各项，观察禁用哪一项后，注释中的红色波浪线消失。

引用 10 楼 weixin_40442612 的回复:怎样把拼写检查关掉 VS2010的，VS2013没用过。

怎样把拼写检查关掉

这个是拼写检查吧

将/* ... */ 替换为 #if 0 ... #endif 再试试？

我知道这不是错误，但是看着不舒服，就想去掉 我把intellisense改成了true,可是还是没用

#include <string.h> #include <ctype.h>

出现这些不一定是错误，是配置的问题。

拼写检查，高亮福利啊

VS2013开启了拼写检查，所以出现  试试: 工具—选项—文本编辑器—C/C++—高级—Intellisense—禁用波形曲线 选项值改为（True）

我没有按照番茄插件啊

在 VAssistX菜单栏->Visual Assist X Options->Underlines->underlines spelling errors in comments and strings using


Question: c语言

当i=1时： for(i=0;i<10;i++)中i=1; for(i=0;I++<10;)中i=2.

for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }

不等价，你可以考虑下边界条件，当i = 10的时候，左边不会自加， 但右边会自加

很明显不等价，这是因为i++造成的。 因为比较表达式每次都会执行， 比如i=0时，此时要比较i++<10不，此时i++表达式的值是0，满足条件，继续循环此时执行循环体，若循环体里运用i时，此时的i是1，因为i++;然后继续循环自增，此时i = 2; i++<10，此时i++是2，因此满足条件，此时i是3. 总之，若是第二个表达式那么循环体执行次数应该是减少一半。 建议此时一下，循环是打印"helloworld"，看看实际执行了几次。

循环都是十次，但是最后i的值不一样

你把for语句改成对应的while语句就明白了。


Question: [求助]c指向函数的指针问题,这两个错误怎么改?

引用 1 楼 hdt 的回复:函数指针声明 返回类型 (*指针变量名)(参数列表)； 所以你定义的是错误的语法  double fun(float,float,int,double (*)(double)); 谢谢,那后面那个G:\C语言\A\a1.cpp(24) : error C2064: term does not evaluate to a function怎么解决?

//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]


Question: 关于顺序表的合并的一个小程序，无法运行

问题1：scanf少& scanf("%d", &L.length); 	for(i=1;i<L.length;i++); 	{ 		printf("%d:",i+1); 		scanf("%d", &L.elem[i]); 	}   问题2： void InitList_Sq(Sqlist &L, int size)//构造一个空的顺序表 { 	L.elem=new ElemType[size];//为顺序表分配一个大小为MAXSIZE的数组空间 	if(!L.elem)  		exit(OVERFLOW);//存储失败 	L.length=0;//空表长度为零 	L.listsize = size; } lc顺序表没有初始化直接使用，考虑lc的顺序表空间需要是la.length和lb.length的长度和。所以将InitList增加了一个参数，即初始化的顺序表长度可变。  问题3：函数名不统一： void Initlist(Sqlist &L, int size); void InitList_Sq(Sqlist &L)//构造一个空的顺序表 当然还有Merger和Merge  问题4： for(i=1;i<L.length;i++); { printf("%d:",i+1); scanf("%d",L.elem[i]); } 去掉for括号后面的分号;，不然无法循环执行循环体，另外,i从0开始。  还有其他问题，不再罗列； 目前还有一个问题，就是排序，排序还有问题。如果想简单一些，建议使用冒泡或者选择排序。然后合并即可。目前只有排序还有问题，建议继续查一下排序的问题。 其他已经测试没问题。详见下面的代码：   #include<stdio.h> #include<stdlib.h>  #define MAXSIZE 100 /*顺序表的最大长度*/  typedef int KeyType; /*定义关键字类型为整形*/ typedef int Status; typedef int ElemType;  typedef struct key_val{ 	KeyType key; /*关键字项*/ }RedType; /*记录类型*/  typedef struct list{ 	RedType r[MAXSIZE+1]; /*r[0]闲置或用做哨兵单元*/ 	ElemType *elem; /*存储空间的基地址*/ 	int length; /*顺序表长度*/ 	int listsize; /*当前分配的存储容量*/ }Sqlist; /*顺序表类型*/  int OK=1; int OVERFLOW=0; int ERROR=0;  void Initlist(Sqlist &L, int size); /*初始化顺序表*/ void Creatlist(Sqlist &L); /*建立顺序表*/ void InsertSort(Sqlist &L); /*对顺序表进行排序*/ void Merge(Sqlist &la,Sqlist &lb,Sqlist &lc);/*将表A和表B合成表C*/ int ListInsert(Sqlist &L,int i,ElemType &e);/*将线性表L中第i个元素赋给e变量*/ void GetElem(Sqlist &L,int i,ElemType &e); /*取线性表L中第i个元素的值*/ void PrintList(Sqlist &L); /**/  int main() { 	Sqlist la,lb,lc; 	printf("开始创建顺序表A\n"); 	Initlist(la, MAXSIZE); 	Creatlist(la); 	printf("顺序表A数据输入完成\n*****************\n"); 	InsertSort(la); 	PrintList(la);  	printf("开始创建顺序表B\n"); 	Initlist(lb, MAXSIZE); 	Creatlist(lb); 	printf("顺序表B输入数据完成\n*****************\n"); 	InsertSort(lb); 	PrintList(lb); 	printf("将表A和表B合成顺序表C\n"); 	Initlist(lc, la.length + lb.length); 	Merge(la,lb,lc); 	printf("合成完毕。\n"); 	printf("输出顺序表C："); 	PrintList(lc); }  void Initlist(Sqlist &L, int size)//构造一个空的顺序表 { 	L.elem=new ElemType[size];//为顺序表分配一个大小为MAXSIZE的数组空间 	if(!L.elem)  		exit(OVERFLOW);//存储失败 	L.length=0;//空表长度为零 	L.listsize = size; }  void Creatlist(Sqlist &L) { 	int i,length; 	printf("请输入要创建顺序表中元素的个数：\t"); 	scanf("%d", &L.length); 	for(i= 0; i < L.length; i++) 	{ 		printf("%d:",i+1); 		scanf("%d", &L.elem[i]); 	} }  void InsertSort(Sqlist &L) { 	int i,j; 	for(i=2;i<=L.length;++i) 		if(L.r[i].key<L.r[i-1].key) /*“<”需将r[i]插入有序子表*/ 		{ 			L.r[0]=L.r[i]; /*将待插入的记录暂存到监视哨中*/ 			L.r[i]=L.r[i-1]; /*r[i-1]*/ 			for(j=i-2;L.r[0].key<L.r[j].key;--j) /*从后向前寻找插入位置*/ 				L.r[j+1]=L.r[j]; /*记录逐个后移，直到找到插入位置*/ 			L.r[j+1]=L.r[0]; /*将r[0]即原r[i]，插入到正确的位置*/ 		} }  int ListInsert(Sqlist &L,int i,ElemType &e)/*将线性表L中第i个元素赋给变量而后删除*/ { 	if((i<1)||(i>L.length))  		return ERROR; 	if(L.length==MAXSIZE)  		return ERROR; 	e = L.elem[i-1];  	return OK; }  Status GetElem(Sqlist L,int i,ElemType &e) /*将此两个线性表合并成一个，仍是数据由小到大排列的线性表，存储到另一个顺序表C中*/ { 	if(i<1||i>L.length)  		return ERROR; /*判断i值是否合理*/ 	e=L.elem[i-1];   /*elem[i-1]单元储存第i个数据元素*/ 	return OK; }  void Merge(Sqlist &la, Sqlist &lb, Sqlist &lc)/*将表A和表B合成表C*/ { 	int i=0,j=0,k=0; //i扫描A,j扫描B  	while(i< la.length && j< lb.length) 	{ 		if (la.elem[i] < lb.elem[j]) 		{ 			lc.elem[k] = la.elem[i]; 			i++;  			k++; 		} 		else 		{ 			lc.elem[k] = lb.elem[j]; 			j++;  			k++; 		} 	} 	while(i< la.length) { //若A未扫描完，则将A剩余的元素加到C中 		lc.elem[k] =la.elem[i]; 		i++; k++; 	} 	while(j< lb.length){ //若B未扫描完，则将B剩余的元素加到C中 		lc.elem[k] = lb.elem[j]; 		j++; k++; 	} 	lc.length = k; }  void PrintList(Sqlist &L) /*输出顺序表*/ { 	int i; 	for(i=0;i<L.length;i++) 		printf("%d",L.elem[i]); 	printf("\n"); }


Question: 递归思路问题

引用 7 楼 cfjtaishan 的回复:[quote=引用 6 楼 PpBearGoGoGo 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] [quote=引用 4 楼 PpBearGoGoGo 的回复:]  #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一[/quote]  小于0当然不行，等于0和小于0只是为 n=1或者2服务的[/quote] 不是针对你的代码不能运行，而是考虑代码有冗余，n < 0不会运行到。因为你的代码对于0， 1， 2的判断已经很明确了。 if (n == 1)         return 1;     else if (n == 2)         return 2; 遇到1,2就直接返回了，怎么还会让1,2在减1呢？[/quote] 就是递归到0,1后就直接返回了，不会继续递归了。所以，n < 0不会执行嘛

引用 6 楼 PpBearGoGoGo 的回复:[quote=引用 5 楼 cfjtaishan 的回复:] [quote=引用 4 楼 PpBearGoGoGo 的回复:]  #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一[/quote]  小于0当然不行，等于0和小于0只是为 n=1或者2服务的[/quote] 不是针对你的代码不能运行，而是考虑代码有冗余，n < 0不会运行到。因为你的代码对于0， 1， 2的判断已经很明确了。 if (n == 1)         return 1;     else if (n == 2)         return 2; 遇到1,2就直接返回了，怎么还会让1,2在减1呢？

引用 8 楼 cfjtaishan 的回复:[quote=引用 7 楼 cfjtaishan 的回复:] [quote=引用 6 楼 PpBearGoGoGo 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] [quote=引用 4 楼 PpBearGoGoGo 的回复:]  #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一[/quote]  小于0当然不行，等于0和小于0只是为 n=1或者2服务的[/quote] 不是针对你的代码不能运行，而是考虑代码有冗余，n < 0不会运行到。因为你的代码对于0， 1， 2的判断已经很明确了。 if (n == 1)         return 1;     else if (n == 2)         return 2; 遇到1,2就直接返回了，怎么还会让1,2在减1呢？[/quote] 就是递归到0,1后就直接返回了，不会继续递归了。所以，n < 0不会执行嘛[/quote] 嗯嗯 对

引用 7 楼 cfjtaishan 的回复:[quote=引用 6 楼 PpBearGoGoGo 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] [quote=引用 4 楼 PpBearGoGoGo 的回复:]  #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一[/quote]  小于0当然不行，等于0和小于0只是为 n=1或者2服务的[/quote] 不是针对你的代码不能运行，而是考虑代码有冗余，n < 0不会运行到。因为你的代码对于0， 1， 2的判断已经很明确了。 if (n == 1)         return 1;     else if (n == 2)         return 2; 遇到1,2就直接返回了，怎么还会让1,2在减1呢？[/quote]  哦！好像是没什么用，是我想多了，以为n为1的时候还需要的，写多了，小于零不会执行

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

引用 5 楼 cfjtaishan 的回复:[quote=引用 4 楼 PpBearGoGoGo 的回复:]  #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一[/quote]  小于0当然不行，等于0和小于0只是为 n=1或者2服务的

引用 4 楼 PpBearGoGoGo 的回复: #include <stdio.h>     double num(int n)//分子 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 2; 	else if (n == 1) 		return 2; 	else if (n == 2) 		return 3; 	else 		return  num(n - 1) + num(n - 2); } double den(int n)//分母 { 	if (n < 0) 		return 0; 	else if (n == 0) 		return 1; 	if (n == 1) 		return 1; 	else if (n == 2) 		return 2; 	else 		return  den(n - 1) + den(n - 2); }  double solve(int n) { 	double sum = 0; 	double temp = 0; 	for (int i = 1; i < n + 1; i++) 	{ 		temp =num(i) / den(i); 		sum += temp; 		printf("第%d项 = %f \n", i,temp); 	} 	return sum; }  int main() { 	while (true) 	{ 		int n; 		double sum = 0; 		printf("输入n:"); 		scanf_s("%d", &n, 1);//scanf("%d", &n);  		sum = solve(n); 		printf("前n项和: %f\n\n", sum);  		 	}   	system("pause"); 	return 0;   这样思路很清晰 n<0不可能递归到，因为n == 0 和n == 1时已经停止递归了； 另外，分子分母的递归有逻辑冗余，二者可以合二为一

#include <stdio.h>    int fab(int n) { 	if (n == 0 || n == 1) 		return 1; 	else 		return fab(n - 1) + fab(n - 2); }  double sum(int tm) { 	double total = 0; 	int i; 	 	for (i = 1; i <= tm; i++) { 		printf("a = %d\n", fab(i+1)); 		printf("b = %d\n", fab(i)); 		total += fab(i+1) * 1.0/fab(i); 	}  	return total; }    int main(void) { 	int n; 	scanf("%d", &n); 	printf("%lf\n", sum(n));     return 0; } 参考一下吧

#include <stdio.h>  float Fabonacci(int a, int b, int c, int d, int beg, int n, float sum) { 	if(beg < n){ 		printf("%d/%d + ", c, d); 		Fabonacci(c, d, a + c, b + d, beg + 1, n, sum + (float)c / (float)d); 	}else{ 		printf("\b\b= %f\n", sum); 		return sum; 	} }  int main(void) { 	Fabonacci(1, 1, 2, 1, 0, 5, 0.0); 	 	return 0; } 2/1 + 3/2 + 5/3 + 8/5 + 13/8 = 8.391666


Question: 这个程序怎么写

#include<iostream> #include<string> using namespace std;  void temp(char &a, char &b) { 	char temp; 	temp = a; 	a = b; 	b = temp; }  void temp_s(string &a, string &b) { 	string temp; 	temp = a; 	a = b; 	b = temp; }  int main() { 	string array[4]; 	for (auto &c : array) 	{ 		cin >> c; 	} 	//@1 	for (int i = 3; i != -1; --i) 	{ 		cout << array[i] << " "; 	} 	cout << endl; 	 	//@2 	for (int i = 0; i != 4; ++i) 	{ 		string::iterator Biter = array[i].begin(); 		string::iterator Eiter = array[i].end()-1;  		while (Eiter-Biter>1) 		{ 				temp(*Biter, *Eiter); 				++Biter; 				--Eiter; 		} 		if (Eiter - Biter == 1) 		{ 			temp(*Biter, *Eiter); 		} 	 	} 	for (auto &c : array) 	{ 		cout << c << " "; 	} 	cout << endl; 	 	//@3 	for (int i = 3; i != -1; --i) 	{ 		cout << array[i] << " "; 	} 	cout << endl; 	 	 	system("pause"); 	return 0; }

引用 11 楼 cfjtaishan 的回复:[quote=引用 10 楼 wodexiaojidan 的回复:] [quote=引用 9 楼 cfjtaishan 的回复:] [quote=引用 7 楼 wodexiaojidan 的回复:] memcpy是字拷贝， strcpy是字节拷贝， 你说哪个效率高。而且通常为了不发生溢出，是不推荐使用strcpy的。 我是store in reverse order，你要print  in reverse order，这只能说我俩策略不一样 strcpy怎么会溢出呢？你的输入是 scanf("%s%s%s%s", s[0], s[1], s[2], s[3]); 每个单词都是一个字符串，每个单词都是字符，memcpy第三个参数是要拷贝的字节个数，而不是字个数哦。 你看一下memcpy，拷贝了49个字节。那么用strcpy，对于am只需要拷贝3个字节，对于单词I只需要拷贝1个字节。请问那个效率高呢[/quote]  大哥，麻烦你看懂了再来回复好吗？memcpy的实现是按机器字长来拷贝的，汇编源码里面有。 我说strcpy会发生溢出不是针对这里，而是使用过程中经常会出现的，难道生活中你老师/领导没说让你禁止使用strcpy而要使用安全带边界的strncpy？ memcpy第三个参数可以用strlen，是不是？我这里省事这样写，你还真要吹毛求疵？[/quote]  不好意思，没有老师说过禁用strcpy，工作这么多年也没有同事说过禁用strcpy，用与不用看情况，如果知道strcpy的问题，即使用了又何妨，因为知道了什么时候不应该用。那么可以用的时候为什么不能呢。 我没说你第三参数不能用49，我不是说了吗？考虑效率，要用strcpy（或strncpy)；没有说不对哦，是不是看不得别人说出自己的问题，我也是过来人，但是更好的就是更好的，不是因为自己的接不接受而变化；  最后，你的程序没问题。我想告诉楼主可以在你的基础上让程序效率更高些。我们不能止于做出来了，运行没问题了，如果可我们可以考虑让程序运行的更快更稳定。[/quote]再见，不是一路人，不用回了。

引用 10 楼 wodexiaojidan 的回复:[quote=引用 9 楼 cfjtaishan 的回复:] [quote=引用 7 楼 wodexiaojidan 的回复:] memcpy是字拷贝， strcpy是字节拷贝， 你说哪个效率高。而且通常为了不发生溢出，是不推荐使用strcpy的。 我是store in reverse order，你要print  in reverse order，这只能说我俩策略不一样 strcpy怎么会溢出呢？你的输入是 scanf("%s%s%s%s", s[0], s[1], s[2], s[3]); 每个单词都是一个字符串，每个单词都是字符，memcpy第三个参数是要拷贝的字节个数，而不是字个数哦。 你看一下memcpy，拷贝了49个字节。那么用strcpy，对于am只需要拷贝3个字节，对于单词I只需要拷贝1个字节。请问那个效率高呢[/quote]  大哥，麻烦你看懂了再来回复好吗？memcpy的实现是按机器字长来拷贝的，汇编源码里面有。 我说strcpy会发生溢出不是针对这里，而是使用过程中经常会出现的，难道生活中你老师/领导没说让你禁止使用strcpy而要使用安全带边界的strncpy？ memcpy第三个参数可以用strlen，是不是？我这里省事这样写，你还真要吹毛求疵？[/quote]  不好意思，没有老师说过禁用strcpy，工作这么多年也没有同事说过禁用strcpy，用与不用看情况，如果知道strcpy的问题，即使用了又何妨，因为知道了什么时候不应该用。那么可以用的时候为什么不能呢。 我没说你第三参数不能用49，我不是说了吗？考虑效率，要用strcpy（或strncpy)；没有说不对哦，是不是看不得别人说出自己的问题，我也是过来人，但是更好的就是更好的，不是因为自己的接不接受而变化；  最后，你的程序没问题。我想告诉楼主可以在你的基础上让程序效率更高些。我们不能止于做出来了，运行没问题了，如果可我们可以考虑让程序运行的更快更稳定。

引用 9 楼 cfjtaishan 的回复:[quote=引用 7 楼 wodexiaojidan 的回复:] memcpy是字拷贝， strcpy是字节拷贝， 你说哪个效率高。而且通常为了不发生溢出，是不推荐使用strcpy的。 我是store in reverse order，你要print  in reverse order，这只能说我俩策略不一样 strcpy怎么会溢出呢？你的输入是 scanf("%s%s%s%s", s[0], s[1], s[2], s[3]); 每个单词都是一个字符串，每个单词都是字符，memcpy第三个参数是要拷贝的字节个数，而不是字个数哦。 你看一下memcpy，拷贝了49个字节。那么用strcpy，对于am只需要拷贝3个字节，对于单词I只需要拷贝1个字节。请问那个效率高呢[/quote]  大哥，麻烦你看懂了再来回复好吗？memcpy的实现是按机器字长来拷贝的，汇编源码里面有。 我说strcpy会发生溢出不是针对这里，而是使用过程中经常会出现的，难道生活中你老师/领导没说让你禁止使用strcpy而要使用安全带边界的strncpy？ memcpy第三个参数可以用strlen，是不是？我这里省事这样写，你还真要吹毛求疵？

引用 7 楼 wodexiaojidan 的回复:memcpy是字拷贝， strcpy是字节拷贝， 你说哪个效率高。而且通常为了不发生溢出，是不推荐使用strcpy的。 我是store in reverse order，你要print  in reverse order，这只能说我俩策略不一样 strcpy怎么会溢出呢？你的输入是 scanf("%s%s%s%s", s[0], s[1], s[2], s[3]); 每个单词都是一个字符串，每个单词都是字符，memcpy第三个参数是要拷贝的字节个数，而不是字个数哦。 你看一下memcpy，拷贝了49个字节。那么用strcpy，对于am只需要拷贝3个字节，对于单词I只需要拷贝1个字节。请问那个效率高呢

引用 6 楼 cfjtaishan 的回复:不好意思，我是小学毕业，英文一窍不通，但是能看懂要求，我想只要根据要求实现即可，没必要拘于方法，那种方法好实现，效率高就可以考虑使用那种方法； 另外，建议是用strcpy代替memcpy，这样效率高些，因为拷贝的数据减少了很多（起码对于example）。strcpy（或strncpy)是针对字符串拷贝的，memcpy是多多种类型进行拷贝，其中包括字符串。  [quote=引用 5 楼 wodexiaojidan 的回复:] [quote=引用 4 楼 cfjtaishan 的回复:] [quote=引用 3 楼 wodexiaojidan 的回复:] #include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {""}; 	int i;  	scanf("%s%s%s%s", s[0], s[1], s[2], s[3]);  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }  如果是输出: Pan Peter am I  这个不需要任何修改，下表从3到0输出即可。 所以不需要使用memcpy  因此对于逆序（单词为单位）不需要在单独做。只需要单词下表从3到0输出即可。 对于每个单词内部的逆序，可以考虑先将单词内逆序，若需要两个逆序（单词和单词内），那么需要讲单词内逆序后再讲单词从3输出到0.[/quote]看懂英文再来回复我[/quote][/quote]memcpy是字拷贝， strcpy是字节拷贝， 你说哪个效率高。而且通常为了不发生溢出，是不推荐使用strcpy的。 我是store in reverse order，你要print  in reverse order，这只能说我俩策略不一样。你要计较长度的话，先用strlen怎么样？

不好意思，我是小学毕业，英文一窍不通，但是能看懂要求，我想只要根据要求实现即可，没必要拘于方法，那种方法好实现，效率高就可以考虑使用那种方法； 另外，建议是用strcpy代替memcpy，这样效率高些，因为拷贝的数据减少了很多（起码对于example）。strcpy（或strncpy)是针对字符串拷贝的，memcpy是多多种类型进行拷贝，其中包括字符串。  引用 5 楼 wodexiaojidan 的回复:[quote=引用 4 楼 cfjtaishan 的回复:] [quote=引用 3 楼 wodexiaojidan 的回复:] #include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {""}; 	int i;  	scanf("%s%s%s%s", s[0], s[1], s[2], s[3]);  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }  如果是输出: Pan Peter am I  这个不需要任何修改，下表从3到0输出即可。 所以不需要使用memcpy  因此对于逆序（单词为单位）不需要在单独做。只需要单词下表从3到0输出即可。 对于每个单词内部的逆序，可以考虑先将单词内逆序，若需要两个逆序（单词和单词内），那么需要讲单词内逆序后再讲单词从3输出到0.[/quote]看懂英文再来回复我[/quote]

引用 4 楼 cfjtaishan 的回复:[quote=引用 3 楼 wodexiaojidan 的回复:] #include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {""}; 	int i;  	scanf("%s%s%s%s", s[0], s[1], s[2], s[3]);  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }  如果是输出: Pan Peter am I  这个不需要任何修改，下表从3到0输出即可。 所以不需要使用memcpy  因此对于逆序（单词为单位）不需要在单独做。只需要单词下表从3到0输出即可。 对于每个单词内部的逆序，可以考虑先将单词内逆序，若需要两个逆序（单词和单词内），那么需要讲单词内逆序后再讲单词从3输出到0.[/quote]看懂英文再来回复我

引用 3 楼 wodexiaojidan 的回复:#include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {""}; 	int i;  	scanf("%s%s%s%s", s[0], s[1], s[2], s[3]);  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }  如果是输出: Pan Peter am I  这个不需要任何修改，下表从3到0输出即可。 所以不需要使用memcpy  因此对于逆序（单词为单位）不需要在单独做。只需要单词下表从3到0输出即可。 对于每个单词内部的逆序，可以考虑先将单词内逆序，若需要两个逆序（单词和单词内），那么需要讲单词内逆序后再讲单词从3输出到0.

#include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {"I", "am", "Peter", "Pan"}; 	int i;  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }  Pan Peter am I  I ma reteP naP  naP reteP ma I

#include <stdio.h> #include <string.h>  void Reverse_char(char *s) { 	int i, end = strlen(s) - 1;  	for(i = 0; i <= end / 2; ++i){ 		char ch = s[i]; 		s[i] = s[end - i]; 		s[end - i] = ch; 	}  }  void Reverse_string(char (*s)[49], int size) { 	int i;  	for(i = 0; i <= (size - 1) / 2; ++i){ 		char p[49] = {0}; 		memcpy(p, s[i], 49); 		memcpy(s[i],s[size - 1 - i], 49); 		memcpy(s[size -1 - i], p, 49); 	} }  int main(void) { 	char s[4][49] = {"I", "am", "Peter", "Pan"}; 	int i;  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	Reverse_string(s, 4); 	for(i = 0; i < 4; ++i){ 		Reverse_char(s[i]); 		printf("%s ", s[i]); 	} 	printf("\n");  	return 0; }   Pan Peter am I  I ma reteP naP  Pan Peter am I


Question: 关于C语言动态规划时的声明

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出  在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。 容量大小从小到大：栈≤全局数据≤堆≤文件≤硬盘≤磁盘阵列≤云存储 当程序需要使用比如2GB～1TB左右的存储时，最简单的办法恐怕得是用文件读写模拟内存读写了吧。windows参考_fseeki64函数，linux参考fseeko64函数。 FILE *fA;fA=fopen("A","rb+");_fseeki64(fA,10000000000i64*sizeof(int),SEEK_SET);fputc(fA,0);//int A[10000000000]; int B; _fseeki64(fA,9999999999i64*sizeof(int),SEEK_SET);fread(&B,1,sizeof(int),fA);//B=A[9999999999]; _fseeki64(fA,9999999999i64*sizeof(int),SEEK_SET);fwrite(&B,1,sizeof(int),fA);//A[9999999999]=B; fclose(fA);

使用全局变量是考虑在其他模块里也是用，全局变量是多个模块都可见的。并且生命周期是从定义开始到程序结束。  全局变量也有自己的缺点，那就是不利于分析全局变量的数据变化，因为它是多个模块都可见和使用。


Question: 单片机 59秒定时器  c语言  调试不成功

写的太乱  有些寄存器都写错了

引用 5 楼 user-2 的回复:单片机C语言很久没写过了  但你按我那伪码写不就没问题了吗 key = 1 按下的话  你把时间归零  同时打开计时寄存器  开中断 key =0 弹上的话，你就时间暂停计数，关闭计时寄存器，关闭中断 好的，谢谢

if(key== 1){    if(condition){       //do something    }else{     //do something    } }else {   if(condition){     //do something    }else{     //do something    } }

引用 1 楼 user-2 的回复:主函数里面的开关事件问题太大了，你这样写，后面的key == 1或者key == 0怎么触发，永远只触发前面两个 请问应该如何修改呢？我的思路是开中断，关中断，重新计时

请问应该如何改呢？我的思路是开中断，关中断，重新计时


Question: dos系统下16为程序怎么提取

我猜可能是DOS下ZIP或ARJ或更老的压缩解压命令行工具软件创建的自解压文件。 所以你可以试试用“DOS下ZIP或ARJ或更老的压缩解压命令行工具”解压。

两种可能性： 1. 你的COBRA4I.exe中没有包括源代码 2. 没有给COBRA4I.exe输入正确的命令行参数

引用 22 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 按您的方法已经已经使用了。不过您可能没理解我的问题。您说的方法我已经用32位虚拟机实现了位系统。文件运行后的到两个TXT文件，一个是输入的一个是输出的。现在是这两个文件在没有变量输入时输入卡是空白的，输出卡只有一些固定的文字，但是但我编辑好输入卡运行exe文件时能得到想要的数据结果。 但是这不是我想要的（首先这个程序应该没问题），我想得到的是想最前面第二张图那样包含Fortran源代码的一些文件。（经过一段时间分析，我觉得第一位回答者应该是对的，只能反汇编脱壳之类的方法了） 虽然问题没有解决还是谢谢您。

不是;D:\mydir而是;C:\添加到PATH后面

楼主基础太差。

COBRA4I.EXE是DOS下的自解压程序。把它放在d:\mydir目录下 COBRA.EXE是DOS下的COBRA程序，把它以及它依赖的其它文件拷贝到d:\mydir\COBRA目录下 在DosBox下，在命令行直接输入以下命令： Z:\>MOUNT c d:\mydir Drive C is mounted as local directory d:\mydir  Z:>C:  C:\>MD TMP  C:\>CD TMP  C:\>set PATH=%PATH%;C:\COBRA  C:\TMP>..\COBRA4I 运行..\COBRA4I.exe将其解压到当前目录下  C:\TMP>exit   回到Windows，d:\mydir\tmp目录下内容即自解压文件d:\mydir\COBRA4I.exe解压后内容。  Windows系统的PATH和DosBox下的PATH不是一回事！

引用 18 楼 zhao4zhong1 的回复:不是;D:\mydir而是;C:\添加到PATH后面怎么还是不行啊？还麻烦您看看

引用 16 楼 zhao4zhong1 的回复:安装或拷贝完后，在PATH环境变量尾部添加corba.exe所在盘符和目录路径。 我按您的建议创建了d:\mydir 的文件夹并且把cobra程序放到该文件夹下面。 然后安装后复制cobra.exe 均可以实现 再将D:\mydir的路径也添加到了path里面。但是怎么还是显示cannnot find cobra.exe(please enter new program spec)？

引用 13 楼 weixin_40404402 的回复:[quote=引用 12 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 weixin_40404402 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 zhao4zhong1 的回复:] 在DosBox里面运行。 正解！[/quote] 不是要运行程序，程序用虚拟机WinXP能运行，想要想图二里面那样把程序提取出来进行修改。是不是只有反汇编的方法了，常见的解压方法都试过了[/quote] COBRA4I.EXE是DOS下的自解压程序。 比如COBRA4I.EXE这个文件目前在d:\mydir目录下，搜索下载安装DosBox虚拟机，并运行之， 在DosBox下，在命令行直接输入以下命令解压即可： Z:\>MOUNT c d:\mydir Drive C is mounted as local directory d:\mydir  Z:>C:  C:\>MD TMP  C:\>CD TMP  C:\TMP>..\COBRA4I  C:\TMP>exit   回到Windows，d:\mydir\tmp目录下内容即自解压文件d:\mydir\COBRA4I.exe解压后内容。[/quote] 使用您的方法电脑提示cannnot find cobra.exe(please enter new program spec) 这是怎么回事啊？ 文件是能运行的，我运行后会产生一个空白的输入txt和一个基本输出格式的txt[/quote] 在该DoxBox中安装或拷贝cobra.exe,可能这个压缩包解压时依赖cobra.exe

引用 12 楼 zhao4zhong1 的回复:[quote=引用 10 楼 weixin_40404402 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 zhao4zhong1 的回复:] 在DosBox里面运行。 正解！[/quote] 不是要运行程序，程序用虚拟机WinXP能运行，想要想图二里面那样把程序提取出来进行修改。是不是只有反汇编的方法了，常见的解压方法都试过了[/quote] COBRA4I.EXE是DOS下的自解压程序。 比如COBRA4I.EXE这个文件目前在d:\mydir目录下，搜索下载安装DosBox虚拟机，并运行之， 在DosBox下，在命令行直接输入以下命令解压即可： Z:\>MOUNT c d:\mydir Drive C is mounted as local directory d:\mydir  Z:>C:  C:\>MD TMP  C:\>CD TMP  C:\TMP>..\COBRA4I  C:\TMP>exit   回到Windows，d:\mydir\tmp目录下内容即自解压文件d:\mydir\COBRA4I.exe解压后内容。[/quote] 使用您的方法电脑提示cannnot find cobra.exe(please enter new program spec) 这是怎么回事啊？ 文件是能运行的，我运行后会产生一个空白的输入txt和一个基本输出格式的txt

引用 10 楼 weixin_40404402 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 zhao4zhong1 的回复:] 在DosBox里面运行。 正解！[/quote] 不是要运行程序，程序用虚拟机WinXP能运行，想要想图二里面那样把程序提取出来进行修改。是不是只有反汇编的方法了，常见的解压方法都试过了[/quote] COBRA4I.EXE是DOS下的自解压程序。 比如COBRA4I.EXE这个文件目前在d:\mydir目录下，搜索下载安装DosBox虚拟机，并运行之， 在DosBox下，在命令行直接输入以下命令解压即可： Z:\>MOUNT c d:\mydir Drive C is mounted as local directory d:\mydir  Z:>C:  C:\>MD TMP  C:\>CD TMP  C:\TMP>..\COBRA4I  C:\TMP>exit   回到Windows，d:\mydir\tmp目录下内容即自解压文件d:\mydir\COBRA4I.exe解压后内容。

那你到底有没有图里显示的cobra4i.exe，有的话运行就解开了。

引用 9 楼 zhao4zhong1 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 在DosBox里面运行。 正解！[/quote] 不是要运行程序，程序用虚拟机WinXP能运行，想要想图二里面那样把程序提取出来进行修改。是不是只有反汇编的方法了，常见的解压方法都试过了

引用 4 楼 zhao4zhong1 的回复:在DosBox里面运行。 正解！

程序是70年代的，但是这个压缩包应该是90年代建立的，就是一个DOS自解压exe，你在32位windows或者dosbox里运行就解开了。

不懂 帮顶

exe 又不是对源代码进行打包, 怎么提取... 只能进行反汇编成汇编代码, 用 IDA 的插件可以还原成 C 语言结构的代码, 但并不是编写程序时的源代码


Question: 求大神帮我解决小小问题  操作系统C语言

还不能运行的


Question: c中用指向结构体的指针动态创建结构体数组

#include<stdio.h> #include<stdlib.h>  struct student { 	int age; 	char sex; }; int main() {  	int n; 	//student student1; 	struct student *p; 	scanf("%d", &n); 	p =(struct student *)malloc(sizeof(struct student)*n); 	p[0].age = 1; 	printf("%d\n", p[0].age); 	free(p); 	return 0; } 注意结构体使用时需要加上结构体名。 结构体的使用建议从课本上多看看使用，书本上的例子还是自己敲敲，调试一下。

#include<stdio.h> #include<stdlib.h> struct student { int age; char sex; }; int main() { int n; struct student *p; scanf("%d",&n); p=(struct student*)malloc(sizeof(struct student)*n); p[0].age=1; printf("%d",p[0].age); free(p); return 0; }  http://wenda.so.com/q/1392799083065014?src=140


Question: 这是求完数的程序，怎么把输出数据的最后一个加号

退出循环后把printf("\n")换成pintf("\b \n");


Question: 这个程序怎么写，求教。

#include <stdio.h>  void GetCoins(int n) { 	if(n == 1){ 		printf("1"); 		return; 	}  	if(n == 2){ 		printf("2"); 		return; 	}  	if(n % 2){ 		GetCoins((n - 1) / 2); 		printf("1"); 	}else{ 		GetCoins((n - 2) / 2); 		printf("2"); 	} }  int main(void) { 	int n; 	scanf("%d", &n);  	GetCoins(n); 	printf("\n");  	return 0; }   下面这个对的

#include <stdio.h>  void GetCoins(int n) { 	if(n == 1){ 		printf("1"); 		return; 	}  	if(n == 2){ 		printf("2"); 		return; 	}  	GetCoins(n / 2);  	if(n % 2){ 		printf("1"); 	}else{ 		printf("2"); 	} }  int main(void) { 	int n; 	scanf("%d", &n);  	GetCoins(n); 	printf("\n");  	return 0; }


Question: 这个程序怎么写

#include <iostream>  int main() { 	char *p; 	char str; 	int result = 0; 	char recieve; 	int flag = 0; 	int forward = 0; 	while (true) 	{ 		recieve = getchar(); 		if (recieve != '\n') 		{ 			if (flag != 4) 			{ 				if (recieve == 'A'&&!result){ 					if (forward == -2){} 					else{ 						forward = 1; 						continue; 					} 					flag = 1; 				} 				else if (recieve == 'B'&&!result){flag = 2;} 				else if (recieve == 'C'&&!result){ 					if (forward == 2){} 					else{  						forward = -1;  						continue;  					} 					flag = 3; 				} 				else if (recieve != 'A'&&recieve != 'B'&&recieve!='C') 				{ 					flag = 4; 					result = 0; 				}  				switch (flag - 5 * result) 				{ 				case 1: 					if (forward == -2){ result = 1; flag = 0; forward = 0; } 					break; 				case 2: 					if (forward == 1){forward = 2;} 					else if (forward == -1){forward = -2;} 					break; 				case 3: 					if (forward == 2){ result = 1; flag = 0; forward = 0; } 					break; 				default: 					break; 				} 			} 		} 		else 		{ 			if (result)printf("true\n"); 			else printf("flase\n"); 			forward = 0; 			result = 0; 			flag = 0; 		} 	} 	return 0; }   写的有点复杂

你可以改用malloc生成动态数组

谢谢，先给你结帖吧，但题目要求不能使用数组呀。

#include <stdio.h> #include <string.h>  static const char *sub[] = {"ABC", "BCA", "CBA"};  int IsOkTheString(char *src, int sz) { 	int i;  	for(i = 0; i < sz; ++i){ 		if(src[i] < 'A' || src[i] > 'C'){ 			return -1; 		} 	}  	if(strstr(src, sub[0]) != NULL || strstr(src, sub[1]) != NULL || 			strstr(src, sub[2]) != NULL){ 		return 0; 	}else{ 		return -1; 	} }  int main(void) { 	char src[32] = {0}; 	fgets(src, sizeof(src), stdin); 	int len = strlen(src) - 1; 	src[len] = '\0'; 	 	if(IsOkTheString(src, len) == 0){ 		printf("true\n"); 	}else{ 		printf("false\n"); 	}  	return 0; }


Question: c primer plus 第十七章 第七题 c我认为有错误。

上下文呢？。前因后果?

左子树上所有结点的值均小于它的根结点的值

没有上下文，不知道你在说什么。书里给出的答案是哪一项？

引用 6 楼 weixin_40895538 的回复:[quote=引用 3 楼 hdt 的回复:] 上下文呢？。前因后果? 一个查找二叉树，你看ｃ。ｇａｔｅ用ｓｔｒｃｍｐ排列是在ｆｏｏｄ后面的。结果出现在了根的左子树。你需要前因后果呀？[/quote] 932页呢？？ 934页呢？？

引用 3 楼 hdt 的回复:上下文呢？。前因后果? 一个查找二叉树，你看ｃ。ｇａｔｅ用ｓｔｒｃｍｐ排列是在ｆｏｏｄ后面的。结果出现在了根的左子树。你需要前因后果呀？

引用 2 楼 destory27 的回复:左子树上所有结点的值均小于它的根结点的值 于是您把我的话重读了一遍？

引用 1 楼 hzy_76 的回复:左子树小于根节点，难道不是推出gate小于food？查找二叉树用于排序和搜索，它就是这么定义的！ #include<stdio.h> #include<string.h>  int main(void) {  printf("%d\n",strcmp("gate","food")); return 0; } 你回答我，你猜猜这里的值是大于０还是小于０？能不睁眼说瞎话吗？


Question: RAD studio XE2 如何编译一个C工程并调试运行和设置断点

仅供参考：  怎样用C++ Builder（BCB）6.0编译无窗体的C++控制台应用程序 http://blog.163.com/tab_98/blog/static/1192409720169533811118/  C++ Builder（BCB）调试程序：设置断点，单步执行，观察、修改变量的值   http://blog.163.com/tab_98/blog/static/119240972017618111845352/  C++ Builder的问题最好发在C++ Builder区。


Question: 链表排序问题

关于单链表的排序: 可以用冒泡排序法,先两个数据节点的数据域---进行比较,把大的往前或者往后排,比较n-1轮;数据就可以是从大到小排序了. 具体的交换顺序的方法就用指针存放的地址的改变实现交换位置: 但是冒泡法显然操作要比较多.

引用 3 楼 qq_30780133 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 链表可以考虑使用插入排序方法： 以下的例子仅供参考：  #include <stdio.h> #include <stdlib.h>  struct ListNode {     int data;     struct ListNode *next; };  struct ListNode *create_list(); struct ListNode *deletem(struct ListNode *L, int m); struct ListNode *my_deletem(struct ListNode *L, int m);  void Insertsort(struct ListNode **L);  void printlist(struct ListNode *L) {     struct ListNode *p = L;     while (p) {         printf("%d ", p->data);         p = p->next;     }     printf("\n"); }  int main(void) {     int m;     struct ListNode *L = create_list();      printlist(L);     Insertsort(&L);     printlist(L);      printf("Please input your delete number: ");     scanf("%d", &m);     L = deletem(L, m);     printlist(L);      return 0; }  /* 带哨兵的链表插入排序*/ void Insertsort(struct ListNode **L) {     struct ListNode *p,*q,*r,*u;     p = (*L)->next;     (*L)->next = NULL;     while(p!=NULL)     {         r = *L;         q = (*L)->next;         while(q !=NULL && q->data <= p->data)         {             r = q;             q = q->next;         }         u=p->next;         p->next=r->next;         r->next=p;         p=u;     } }  struct ListNode *create_list() {     struct ListNode *head,*p1,*p2;     int m;     int size = sizeof(struct ListNode);      printf("Input a interge (-1 stop input)\n");     p1 = (struct ListNode*)malloc(size);     scanf("%d", &m);     p1->data = m;     head = NULL;      while (p1->data != -1) {         if(head == NULL)             head = p1;         else             p2->next = p1;         p2 = p1;         scanf("%d", &m);         p1 = (struct ListNode *)malloc(size);         p1->data = m;     }     free(p1);     p2->next = NULL;      return head; }  struct ListNode *deletem( struct ListNode *L, int m ) {     struct ListNode *ptr, *ptr1;     while( L != NULL && ( L->data == m) )     {         ptr1 = L;         L = L->next;         free(ptr1);     }     if( L == NULL )         return NULL;     ptr = L;     ptr1 = L->next;     while( ptr1 != NULL)     {         if( ptr1->data == m )         {             ptr->next = ptr1->next;             free(ptr1);         }         else             ptr = ptr1;         ptr1 = ptr->next;     }     return L; }  链表创建，输出和删除某个节点，插入排序（带哨兵的） 这个代码好像有bug哦，输入的数中有0的话，0的顺序是错的[/quote] 恩，输入的第一个应该是哨兵。 建议只看带哨兵的插入排序吧，其他函数，比如链表创建，链表删除和链表输出都是针对不带哨兵的情况，但是这个排序是针对带哨兵的。

引用 2 楼 cfjtaishan 的回复:链表可以考虑使用插入排序方法： 以下的例子仅供参考：  #include <stdio.h> #include <stdlib.h>  struct ListNode {     int data;     struct ListNode *next; };  struct ListNode *create_list(); struct ListNode *deletem(struct ListNode *L, int m); struct ListNode *my_deletem(struct ListNode *L, int m);  void Insertsort(struct ListNode **L);  void printlist(struct ListNode *L) {     struct ListNode *p = L;     while (p) {         printf("%d ", p->data);         p = p->next;     }     printf("\n"); }  int main(void) {     int m;     struct ListNode *L = create_list();      printlist(L);     Insertsort(&L);     printlist(L);      printf("Please input your delete number: ");     scanf("%d", &m);     L = deletem(L, m);     printlist(L);      return 0; }  /* 带哨兵的链表插入排序*/ void Insertsort(struct ListNode **L) {     struct ListNode *p,*q,*r,*u;     p = (*L)->next;     (*L)->next = NULL;     while(p!=NULL)     {         r = *L;         q = (*L)->next;         while(q !=NULL && q->data <= p->data)         {             r = q;             q = q->next;         }         u=p->next;         p->next=r->next;         r->next=p;         p=u;     } }  struct ListNode *create_list() {     struct ListNode *head,*p1,*p2;     int m;     int size = sizeof(struct ListNode);      printf("Input a interge (-1 stop input)\n");     p1 = (struct ListNode*)malloc(size);     scanf("%d", &m);     p1->data = m;     head = NULL;      while (p1->data != -1) {         if(head == NULL)             head = p1;         else             p2->next = p1;         p2 = p1;         scanf("%d", &m);         p1 = (struct ListNode *)malloc(size);         p1->data = m;     }     free(p1);     p2->next = NULL;      return head; }  struct ListNode *deletem( struct ListNode *L, int m ) {     struct ListNode *ptr, *ptr1;     while( L != NULL && ( L->data == m) )     {         ptr1 = L;         L = L->next;         free(ptr1);     }     if( L == NULL )         return NULL;     ptr = L;     ptr1 = L->next;     while( ptr1 != NULL)     {         if( ptr1->data == m )         {             ptr->next = ptr1->next;             free(ptr1);         }         else             ptr = ptr1;         ptr1 = ptr->next;     }     return L; }  链表创建，输出和删除某个节点，插入排序（带哨兵的） 这个代码好像有bug哦，输入的数中有0的话，0的顺序是错的

将两个有序链表合并成一个有序链表 http://blog.csdn.net/lalor/article/details/7429989


Question: 【求解】C语言学习问题，希望大家给点建议

引用 1 楼 srhouyu 的回复:1. 一般自学编程的人很少去培训机构的。因为： a. 培训机构的老师水平并不怎么样，同时网上、书里高性价比的资源太多了。 b. 学习编程的过程中，“教”所占的分量很少，应当以“学”和“练”为主。“教”明显能起作用的时间至多是初入门的十几个小时。所以，即使学习班能够逼你去，你也收获有限。除非你惰性极强不逼不行。  2. 不懂C直接上C++完全可以。实际上还有好处，可以避免一些C时代的坏习惯。入门可以看《C++ Primer Plus 第六版》，配合《C++ Primer 第五版》。  3. 几乎不可能。PC平台上C语言和WinAPI手撸软件？除非你要做的软件几乎不需要界面。太麻烦了。初学者在PC上几乎不可能用C搞什么有用的开发。  自学编程还是找一个具体目标来驱动为好。如果你爱玩游戏，那么可以试试做游戏。实际上，我推荐以C#和Unity3D入门。最主要是C#容易而且Unity方便，所以开始几天内就能看到像模像样的成果，有助于顺利度过枯燥阶段。比如看《C#入门经典》、《Head First C#》，不止可以做游戏，也可以做桌面程序。学Unity网上有不少视频教程。  用C++和UE4的话，出成果还是要慢于C#和Unity的。  “培训机构的老师水平不怎么样” 这句话不赞同，能当老师的，尤其是在一个培训机构里，起码有几把刷子，如果自己都不懂怎么能教给别人的。如果自己有一定水平了，你可能会感觉老师讲的不怎么样，但是这个时候会有多少人去培训呢，占用时间和金钱；去培训的基本上是基础比较薄弱，所以是否选择培训要看自己缺的是哪方面（理论还是实践）。目前培训机构，一般会很抓实践，理论知识和实践的相结合，理论知识基本上在学校里学了一遍（如果用心学了）。从学校毕业后的学生，实践方面都是短板，所以通过培训可以在实践方面有一定的提高，至于提高多少要看自己的努力和领悟；  即使从培训机构里毕业了，那也只能让自己养成一个编程的习惯，好一点的能够学到一些编程思想，因为培训机构里的老师，至少有一些是有项目经验，所以在编程方面会给学生一些建议，但是这些建议只有自己在工作中逐步领悟和实践才行。所以，工作了也需要不停的学习和编程来总结经验和教训。

有问题： 翻书——上机实验——百度——论坛

引用 2 楼 in85803586 的回复:但是问题是不去培训机构的话，遇到问题没人解决，然后就学不下去了  即使你已经搞了好几年编程，仍然会不停地遇到问题且没人帮你解决。若是自学关过不了，自然不可能踏上编程之路。

看书 　　/  \    /    \ 练习——理解   有问题： 翻书——百度——论坛

但是问题是不去培训机构的话，遇到问题没人解决，然后就学不下去了

看视频，看书，论坛，百度。忘了说了，还有QQ群，豆瓣，百度贴吧等地可以。CSDN的vip下载资源挺多的。里面除了书还有代码。   编程就是和代码打交道。  好的视频把代码放在显眼位置。查书中的代码就比较烦。   你可以先打打基础，多看代码，然后厚积薄发写些练习的程序，不懂就到论坛上问。

C语言教程（附带C语言100例）http://download.csdn.net/detail/zhao4zhong1/8830817


Question: 结构体初始化

C++可以这样写，相当于赋值一个临时类对象（调用默认构造函数），C语言没有这种语法

引用 5 楼 a1193561652 的回复:C++语法上是可以的。但是还不如写成PCB b();，或者PCB b; 那个PCB b = PCB();像是先创建了一个对象b，然后又由PCB()创建了一个零时对象，然后在把零时对象复制到b上去。 然后我觉得你想要的是这个PCB* b = new PCB();不过这样记得最后自己delete。  是这样的，我一般在函数头部把变量都定义好 比如 PCB b; vector<xx> ls = vector<>(); 如果有循环的话 for(xx;xx;xx) {    b = PCB();   ls.push_back(b); } 如果像你所说，那就需要在循环中 PCB b = PCB(); 我想只定义一次PCB b这个变量; 另外这次又同样引用了 vector<xx> ls = vector<>(); 其实是一个症状， 就是作为java程序员认为 vector<xx> ls;这样只是定义 ls 变量，他像C里的野指针，完全不能用；虽然我知道C++里并不是这样， 但我还是按照java的语法写了如上的语句，不知有何不好或引起什么问题亦或者在某种环境下根本编译不过去，恳求各位给予详细指点。

C不行，但是C++完全没毛病，只是多此一举。编译器如果支持C++11以上的版本，你可以用PCB b{}这种定义， Java这样做敢情把声明和定义严格区分了。

还有，如果你要这样用的话，有时候可能要自己重写赋值操作符。

引用 6 楼 antiwise 的回复:[quote=引用 5 楼 a1193561652 的回复:] C++语法上是可以的。但是还不如写成PCB b();，或者PCB b; 那个PCB b = PCB();像是先创建了一个对象b，然后又由PCB()创建了一个零时对象，然后在把零时对象复制到b上去。 然后我觉得你想要的是这个PCB* b = new PCB();不过这样记得最后自己delete。  是这样的，我一般在函数头部把变量都定义好 比如 PCB b; vector<xx> ls = vector<>(); 如果有循环的话 for(xx;xx;xx) {    b = PCB();   ls.push_back(b); } 如果像你所说，那就需要在循环中 PCB b = PCB(); 我想只定义一次PCB b这个变量; 另外这次又同样引用了 vector<xx> ls = vector<>(); 其实是一个症状， 就是作为java程序员认为 vector<xx> ls;这样只是定义 ls 变量，他像C里的野指针，完全不能用；虽然我知道C++里并不是这样， 但我还是按照java的语法写了如上的语句，不知有何不好或引起什么问题亦或者在某种环境下根本编译不过去，恳求各位给予详细指点。[/quote] 不会引起什么错误，就是中间做了一些无用的操作而已。 对于上面的代码，在循环里可以不用b = PCB();直接ls.push_back(b);就好了。

我是之前一直写Java语言， 最近几年穿插着写点C++ ，像这样的用法我用了有好一段时间，有点强迫症的意思吧，我确认这样式可以的，只是求前辈指点这样的语句的标准说明

有没有自己试一下，如果试了可以或者不可以，询问问题可以的。 像这种不知道是否可行，建议自己先编程试一下。

C++中好像可以，C應該不行。


Question: EMMM求助C语言问题

除了函数名和变量名重名的问题之外，代码逻辑也有问题，以下是在你的基础上改的，参考一下吧  #include<stdio.h>  int zs(int); int sum(int a,int b); int s=0,i;  int main() {     int a,b;     printf ("输入两个数");     scanf ("%d%d",&a,&b);     s=sum(a,b);     printf ("%d-%d之间的所有质数的和为%d\n",a,b,s);      return 0; }  int sum(int a,int b) {     int s=0,i;     for(i=a;i<=b;i++)         if(zs(i)==1)             s+=i;     return s; } int zs(int n) {     int i ;     for (i=2;i<n;i++) {         if(n % i == 0)             return 0;     }     if(i >=n )         return 1; }

int a,b,sum; // sum换个变量名  s=sum(a,b);


Question: 怎么样将结果去重（子集和问题的结果）

#include <stdio.h> #include <algorithm>  int main() {     int myints[] = {10, 20, 20, 20, 30, 30, 20, 20, 10};      std::sort(myints, myints + 9);     auto pos = std::unique(myints, myints + 9);      for (auto ps = myints; ps != pos ; ps++) {         printf("%d\t", *ps);     }      return 0; }

1、为什么c_sum+num[i]出结果了就return？不考虑c_sum+num[j]（j>i）的情况了吗？ 2、swap(num[i],num[j])有什么用？


Question: 字符串降序排列不用冒泡法大佬们帮我看下这样为什么不行

void func(char *s1, char *s2 int n)     /* s1为字符串的起始地址，        s2为新字符串的起始地址，        n为字符串的长度。        要求：s1串不能发生改变，        s2串存放新的字符串。        */ {      for (i = 0; i < n; ++i)    /*将字符拷贝至s2，后面对s2排序*/         s2[i] = s1[i];  /*对s2进行冒泡排序，除了首字符和尾字符。*/     for (i = 1; i < n - 1; i++)         for (j = 1; j < n - 1 -i - 1; j++)             if (s2[j] > s2[j+1]) {                 char tmp = s2[j];                 s2[j] = s2[j+1];                 s2[j+1] = tmp;             } #if 0     int i,j;     char *max,*p1=s1;      for(i=1;i<=n;i++,max++)         for(j=1;j<n-1;j++,p++) {*max=*p1>=*(p1+1)? *p1:*(p1+1);}     s2=max; #endif } 参考一下吧； s2接收的实参是数组（或动态malloc申请的空间）；

建议提供一下实参，从形参看到都是指针，不清楚实参是数组还是指针。

max没有分配内存，肯定会崩掉，


Question: 关于输入缓存区的问题（图的邻接矩阵）

首先标准输入缓存是属于行缓存，因此需要回车结束输入并将数据刷到内存里（若不回车，即输入换行符，输入的内容还在缓存里） 因此每次的输入要刷到内存，需要输入换行符，即回车；但是，回车不会跟着进入内存，它还会残留在输入缓存里，若是%d接收，那么这个换行符'\n'不会与它匹配，但是若是%c就会与之匹配，所以若不加getchar();就会让第一个%c接收上次输入之后残留在输入缓存里的换行符'\n'，加上getchar();就是为了接收或者匹配输入缓存里的'\n'的。这样后面的%c就会匹配新输入的数据。 主要是%c是接收一个字符，'\n'正好是一个字符。

在每个最后不带\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字符或回车换行，读取下一个字符。

getchar接收了上一次输出后留在缓冲区中的换行符\n，否则会被接下来的scanf("%c",&(*G).vexs[i]);接收了，也就是说如果不用getchar接收掉，后面scanf接收到的字符为\n


Question: 求助为什么这个程序的print（）用不了？

引用 1 楼 hzy_76 的回复:什麽叫做“用不了”？粗略看了一下你的程序，你把一個局部變量的地址拿出來用了，要注意這塊内存的内容在InitStack函數結束後就變爲不確定了！你好我按照这个思路改后还是一样的，似乎是print的数字列那个地方的问题，注释掉后可以完成运行，但是在符号的那一个链栈中没有数据

引用 3 楼 cfjtaishan 的回复:初始化栈函数，返回局部变量，得到的栈信息是未定义的。因为stack是局部变量。 Stack* InitStack() {     Stack* a = (Stack *)malloc(sizeof(Stack));     if(!a) {         printf("fail!\n");         return NULL;     }         printf("success!\n");         a->opnd.base=NULL;         a->opnd.top=NULL;         a->optr.base=NULL;         a->optr.top=NULL;         return a; }你好我照着改了还是老样子

引用 2 楼 cfjtaishan 的回复:print用不了不一定是print的问题。这么长的代码，为什么不一个个功能写完就测试一下，保证写过的功能都没问题了，再继续写下一个功能。 如果等写完了，所有功能都“实现”了再去编译测试，如果有问题了，就很难知道是那块出了问题。因此，写代码可以考虑“稳打稳扎，步步为营“的策略。一个个功能写，一个个功能测试。最后出问题也能相对比较好的定位问题；我就是这么写的，测试发现是print函数读取数字列的时候好像读到了空指针


Question: C语言里定义变量

变量需要遵循一个原则：先声明（定义）后使用原则； 第二个出错的原因，是因为在scanf("%c", &x);之前找不到x的声明，定义；把char x声明和定义放在scanf后面，那么x的作用域在scanf之后，之前是未知的。因此会有error

你读取数的时候用的x，如果在读取语句之后在定义x变量就会出错

先声明后赋值， 还没声明值应该还没办法输进去吧， 再说，x值都有了，说明存在，还需声明吗

char x是声明变量，在scanf中有给x赋值的语句，所以可以理解为在执行需要x的语句的时候，没有声明变量，机器根本不知道这个“x”是什么，所以报错

都没有那个东西，怎么给它值呢？

同意4楼，来迟一步

变量使用前要先声明

学习了,谢谢

C语言中变量必须先声明后使用，这样编译器才知道为变量分配相应大小的内存，否则没有相应的内存数据怎么存储

举个例子：定义（char x）就好比数学中的定理，只有它存在，你才能去用它。不存在，你就不能用它。

不报错的是因为先定义的x后输入x的值 报错的那个是因为先输入x的值都定义x


Question: 想问这个程序错哪了？

int N,i,j,count=0,flag=1; int a[100]; scanf("%d",&a[N]);   首先int N后 N没有初始化，是随机值，很大的概率大于100； 你定义的数组a是100个成员，那么你直接scanf到a[N]里，数组99%以上会越界，程序直接就终止了。

代码不会说谎，错误的都是写代码的人

N没有赋值，所以N的结果是未定义的。

scanf("%d",&a[N]); 这句不好理解啊，N 是随机值，可能是一个很大的随机值，那么a[N];必定越界呢。越界程序就可以不能运行，直接异常退出； 另外，a[100]中的所有元素也都是随机值，那么下面的操作就不能理解了。 如果楼主是想做成，输入N和N个数组元素，然后求这N个元素中偶数的个数。可以考虑这样实现：  #include <stdio.h> #include <stdlib.h> #include <time.h>  int main(int argc, char *argv[]) {     int N,i,count=0;     int a[100];     scanf("%d", &N);      if (N > 100)         return 0;     srand(time(NULL));     for(i = 0; i < N; i++)     {         a[i] = rand() % 100;         printf("%d ", a[i]);         if (!(a[i] % 2))             count++;     }     putchar(10);     printf("total even numbers = %d\n", count);     return 0; }

数组不需要取地址符吧

单步调试、每走一步看看所有变量值、先确定哪里出错了。


Question: 关于数组名的疑问

引用 1 楼 user-1 的回复:a和&a仅仅只是指向的地址是相同的，但他们是完全不同类型的指针，前者是指向int类型的指针(int*)，后者是指向数组的指针（类型为int(*)[5]），在C++强类型的语言里，如果不强制转换，这样的代码直接不能通过编译，C允许指针的隐式转换，但多数编译器会给出警告，正确的写法是前者，数组名会退化为指向数组元素类型的指针。  谢谢斑竹大大的解惑.


Question: VS2015中FILE的结构体元素与之前版本的有区别吗？

https://docs.microsoft.com/en-us/cpp/porting/visual-cpp-change-history-2003-2015 在上面这个链接中，微软提到了很多 VS CRT API 的变更，其中有这么一段内容：引用FILE Encapsulation In previous versions, the FILE type was completely defined in <stdio.h>, so it was possible for user code to reach into a FILE and modify its internals. The stdio library has been changed to hide implementation details. As part of this, FILE as defined in <stdio.h> is now an opaque type and its members are inaccessible from outside of the CRT itself.

_Placeholder 就是占位的意思，说明真实结构被隐藏了。总之就是不要去引用，而是用 ftell、stat、fstat 去获取文件信息。

嗯，多谢指导，不过VS各版本的定义也会改变，这很令人疑惑

建议不要直接使用里面的成员，因为不同编译器（甚至同一编译器不同版本）的实现可能是完全不同的，这样写没有任何通用性，也不具备跨平台性。


Question: 新手问题，数组名，下标，偏移量

一个是地址，一个是值，当然不一样

p[ i ]前加一个取地址符&应该也可以吧

你可以理解为，在输入的int *p,这个p是地址，而p[i]是p偏移i后的值。前面都回答的不错，为什么没有给分呢？

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

p++打印的是指针地址作为10进制打印，p[i]打印指针指向的内容了，能一样吗

如果改成p+i就好了。因为p+i是地址，p[i]是p偏移i*sizeof(int)个字节后地址的内容；

&p[ i ]？


Question: C语言题目求解：写出程序的执行结果

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

#include <stdio.h> int main() {     int i, j, k=4;     for (int i=1;i<=k;i++)         printf("%c",'*');     printf("\n");     for (int i=1;i<=k-2;i++)     {         printf("%c",'*');         for (j=1;j<= k-2;j++)             printf(" ");         printf("*\n");     }     for (i=1;i<=k;i++)         printf("%c",'*');     printf("\n"); }  代码有中文字符，并且*不能是中文，否则需要是字符串了，因为一个中文字符至少占2个字符；

不知道你的那个符号是*还是＊，如果是*结果是 **** *  * *  * ****


Question: 怎么在这个代码的基础上改成去掉首尾空格？

引用 3 楼 my_dream_not_give_up 的回复:"自习男孩”    兄弟，你改的这个代码，干掉了我字符串里所有的空格。我要干掉首尾的空格。#include <stdio.h> #include <string.h>  void *remove_space(char *ptr) { 	int  beg, end; 	end = strlen(ptr) - 1;  	for(beg = 0; ptr[beg] == ' ' && beg <= end; ++beg); 	for(; ptr[end] == ' ' && end >= beg; --end);  	ptr[end + 1] = '\0';  	memcpy(ptr, ptr + beg, end - beg + 2);  	return ptr; }  int main(void) { 	char str[] = "   he  l l o   w or ld   !    "; 	remove_space(str);  	printf("str : %s, length = %d\n", str, strlen(str));  	return 0;  } str : he  l l o   w or ld   !, length = 23

#include <stdio.h> #include <string.h>  void *remove_space(char *ptr) { 	char *pret, *p, *pb, *pe; 	int size;  	for(pret = ptr; *pret == ' ' && *pret != '\0'; ++pret);  	pb = pe = p = pret; 	for(; *p != '\0'; ++p){ 		if(*(p - 1) != ' ' && *p == ' '){ 			pb = p; 		}  		if(*p != ' ' && *(p - 1) == ' '){ 			pe = p; 		}  		if(pb < pe){ 			size = strlen(pe) + 1; 			memcpy(pb, pe, size); 			p = pe = pb; 		} 	}  	if(pb > pe){ 		*pb = '\0'; 	} 	 	size = strlen(pret) + 1; 	memcpy(ptr, pret, size);  	return ptr; }  int main(void) { 	char str[] = "   he  l l o   w or ld   !    "; 	remove_space(str);  	printf("str : %s, length = %d\n", str, strlen(str));  	return 0;  }  str : helloworld!, length = 11

#include <stdio.h> #include <stdlib.h> //干掉字符串里所有的空格 void *remove_space(char *ptr) {     char *p1,*p2;     for(p1=ptr;*p1!='\0';p1++)     {         while(*p1==' ')//如果这里是if的话就只能去掉一个空格         {             for(p2=p1;*p2!='\0';p2++)             {                 *p2=*(p2+1);             }         }     }     return ptr; }  char *remove_spaces (char *str) {     char *ptmp, *pnew;      ptmp = pnew = str;     while (*ptmp) {         if (*ptmp != ' ')             *pnew++ = *ptmp;         ptmp++;     }     *pnew = 0;      return str; }  int main() {     char a[50];     gets(a);     //printf("%s\n",remove_space(a));     printf("%s\n", remove_spaces(a));     return 0; } 参考一下吧； 使用一层循环就可以解决问题；


Question: 求助，在LINUX写了一个查找的函数，查找英文没问题，查找中文的时候输出了全部

只要我输入汉字，所有汉字相关的数据都被输出了 ，不管我输入的是什么

引用 3 楼 jianwen0529 的回复:[quote=引用 2 楼 jianwen0529 的回复:] 需要支持中文最好改用wchar_t进行存储 然后把strlen，strchr，strcpy等字符串操作函数修改为针对wchar_t类型的版本 printf这个函数同样需要[/quote]搞定了 谢谢

引用 3 楼 jianwen0529 的回复:[quote=引用 2 楼 jianwen0529 的回复:] 需要支持中文最好改用wchar_t进行存储 然后把strlen，strchr，strcpy等字符串操作函数修改为针对wchar_t类型的版本 printf这个函数同样需要[/quote] 怎么改呢 查了一下char到wchar_t的转换 没怎么看明白 还是说直接把我程序里的char全改成wchar？

一个中文字符占两个字节的话

引用 2 楼 jianwen0529 的回复:需要支持中文最好改用wchar_t进行存储 然后把strlen，strchr，strcpy等字符串操作函数修改为针对wchar_t类型的版本 printf这个函数同样需要