Question: 求大神给代码句子标上详细的注释，万分感谢

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


Question: 老问题，指针寻址问题，我知道意思，但是不能用代码完整表示出来

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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

打印地址用%p  引用 楼主 u013085807 的回复:#include<stdio.h>  void main() { 	int i = 10; //假设&i = 0x1000 	printf("%0x\n",&i);//0x1000 	int a = &i; //假设&a = 0x2000 	printf("%0x\n",a);//0x1000 	int p = &a; //假设&p = 0x3000 	printf("%0x\n",p);//0x2000         /*现在问题是我想用指针指向a的内存地址0x2000，打印出来的是i的地址0x1000,怎么表示*/ 	int *p;? 	printf("%0x\n",*p);?? 	 }

引用 1 楼 derekrose 的回复:现在问题是我想用指针指向a的内存地址0x2000，打印出来的是i的地址0x1000,怎么表示  。。。指向a 就是int* pa = &a; 打印出来是i的地址1000？printf("%x", *p);没想到这里，昨天晚上脑子懵了。还是你们厉害！

引用 2 楼 turingo 的回复:打印地址用%p  [quote=引用 楼主 u013085807 的回复:] #include<stdio.h>  void main() { 	int i = 10; //假设&i = 0x1000 	printf("%0x\n",&i);//0x1000 	int a = &i; //假设&a = 0x2000 	printf("%0x\n",a);//0x1000 	int p = &a; //假设&p = 0x3000 	printf("%0x\n",p);//0x2000         /*现在问题是我想用指针指向a的内存地址0x2000，打印出来的是i的地址0x1000,怎么表示*/ 	int *p;? 	printf("%0x\n",*p);?? 	 }[/quote]


Question: error C2664: 'wcscpy' : cannot convert parameter 1 from 'char [255]' to 'wchar_t

引用 2 楼 u012162828 的回复:d:\my porject\twain\src\project\twain_passport\twain_passport\btnview.cpp(589) : error C2664: 'wcscpy' : cannot convert parameter 1 from 'char [255]' to 'wchar_t *' 1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 算了，简单点吧 _tcscpy(temp,szBuffer);改成 strcpy(temp,szBuffer); 下面的其它也改掉。

编译时把_tcscpy会转化成strcpy还是wcscpy，看来你的工程属性是UNICODE了， wcscpy的参数必须是wchar_t，解决方法： 1.char改成TCHAR，这样都是T的形式存在，让编译器决定用char还是wchar 或 2._tcscpy改成strcpy  另外再建议下你，用strcpy_s吧，安全。


Question: 为何Array中未指定的element显示出来不是0呢？

引用 1 楼 user-1 的回复:未初始化的内存，里面的值是不确定的， 改在 int values[10] = {0};//默认全部清0原来如此，感谢！


Question: 不停报错，说我的OnpaintBackground没有合适方法重写.

C#,发到C#那问问吧。

你觉得这是c语言？


Question: win7与vc6.0不兼容怎么办，复选框上面勾过了

先下载Win-TC，然后参考C:\Win-TC\tcstudy.chm

各位大神有没有打包的适合c语言初学者敲的程序代码啊，求支援啊，这是我的邮箱liliyao330@163.com

VS2005吧，觉得这个比VC6.0方便很多。

可以安装虚拟机。

嗯嗯，灰常感谢大家啊，

你都没建立工程，相关的文件也还没创建，都没东西可编译，那些按钮当然都是不可用状态。。。

我刚才把我的Vc6.0卸载了，又重新安装了，下面是一系列图片——  你看，在最后一个图片中，即刚安装完后就运行，那是界面，你看红色矩形部分，就是编译链接执行的按钮啊，不知你那个是咋回事

说实话，不清楚你那儿是怎么回事，我装的时候就直接在外边啊，就在上图的1处，其实即使直接看不到，在上面的“组建”里也有编译、链接和执行，实在不行，同时按下Ctrl和F7，就是编译，然后再同时按下Ctrl和F5，这是执行，我再看看，看能不能把这两个键放外面

这个在上面的组建里，没有拿出来，稍等啊，我找找看怎么弄出来

这是我装的vc6.0和vs2010，vc6.0工具栏里没有编译啊，这是为什么啊

我也觉着我们的教材都跟不上时代，我先入入门，用vs2010在网上看视频学，破老师讲的一口方言我也听不懂，

用VS2003或以后的版本。最大的问题是VC6很多地方都不符合C++标准，与任何其他编译器都有很大区别，你在VC6下习惯的用法以后在其他编程环境下也很可能不能用。 至于你们用VC6的教材，只能说是误人子弟，买本新一点的书吧

引用 楼主 u013720580 的回复:win7与vc6.0不兼容怎么办，复选框上面勾过了 ，本人c语言初学者，要是vc6.0不能用该用什么软件代替vc6.0  vc6.0 早该丢到茅坑里的东西了 微软的工具或多或少的都要关联微软的自己的东西，如今都已经到windows8了你还在用给n年前的工具，敢不敢大胆的换成2010 2012？

引用 23 楼 u013720580 的回复:[quote=引用 21 楼 u012421456 的回复:] [quote=引用 20 楼 u013720580 的回复:] 嗯嗯，那个我装上了，vs2010也下好了 装上就好，那个视频讲课用的是Vc6.0，平时学习还是用VS比较好[/quote]你说说看郝斌老师的视频学，用vs2010也可以吗[/quote] 我的意思是，看视频时你不敲代码吗？那时用vc6.0，毕竟那老师用的是这个，平时学习时用vs比较好，vs方便，好用，功能也较全面

引用 24 楼 vipcxj 的回复:既然LZ是初学，不是被强制用vc6，那就换个其他的编译器嘛，高版本的vs就不错。至于你教程用的是vc6，导致有些代码新版本的vs编译不过，这是好事啊，正好让你知道这些旧教材坑爹在哪里，免得以后再杯具。举个例子 有些旧教材，喜欢 #include <iostream.h> 不过你用新编译器可能就编译不过，因为这个头文件木有了，你得用iostream代替嗯嗯，虽然现在不太懂，不过感谢指点，朝高手方向努力谢了

引用 21 楼 u012421456 的回复:[quote=引用 20 楼 u013720580 的回复:] 嗯嗯，那个我装上了，vs2010也下好了 装上就好，那个视频讲课用的是Vc6.0，平时学习还是用VS比较好[/quote]你说说看郝斌老师的视频学，用vs2010也可以吗

dev C++很好用可以试试

引用 20 楼 u013720580 的回复:嗯嗯，那个我装上了，vs2010也下好了 装上就好，那个视频讲课用的是Vc6.0，平时学习还是用VS比较好

嗯嗯，那个我装上了，vs2010也下好了


Question: 余弦

引用 4 楼 mousestuman 的回复:书上的原话是这样的y=cos(x),则x=acos(y),而 acos(y)=cos(负一）(y)   负一在cos的右上角  上面的右值等于1/cos（y）吗？如果想等，那么我的问题就是对的 应该是y=cos(x),则x=arccos(y)，应该是楼主的书印刷错误

cos^(-1)y=(cosy)^(-1)=1/cosy; 因为类似x^(-1)=1/x

引用 2 楼 mousestuman 的回复:我在书上看x=acos(y),而acos(y)=1/cos(y),所以应该是正确的呀你在哪本书看到的？贴出来看看。

acos(y)=1/cos(y)  是绝对不等的  举个例子  cos π/3  =  1/2  可推得   arccos 1/2  = π/3   那么  请问   π/3  =  2 么？

acos(y)=1/cos(y) 是谁告诉你的？ 如果是书上写的那书可以撕了  百度反三角函数吧......

不正确...    x = arccos（y）  不谢~


Question: C语言如何调用库中的函数

引用 7 楼 misakamm 的回复:gcc "-LE:\\Cworkspace\\test2\\ffmpeg\\lib" 这怎么看着怪怪的，为什么不是 gcc -L"E:\\Cworkspace\\test2\\ffmpeg\\lib"  同样的看法

引用 22 楼 hxingz 的回复:请问，你有include头文件吗？ 当然有了

gcc -v可以看看当初编译工具的构建参数。或者，你试试编译参数里加入-m64要求64位输出，如果不支持会有对应的错误提示，只能编32位的...

谁帮忙看一下

请问，你有include头文件吗？

把库文件的名字加到你链接时候用的库里面。

引用 13 楼 Smoke_1988 的回复:开发包是在网上下载的最新开发包 给个地址看看你下的是啥版本...

引用 12 楼 zhao4zhong1 的回复:将错误信息中出现的标识符放在google里面搜一下， 看其在哪个.h中，然后在本地硬盘上搜索该.h,如果没有，在网上搜索相关库或模块下载安装，然后将其所在目录填写到“附加包含路径”中，将其.h添加到包含到.c或。cpp中,重新编译; 看其在哪个.lib或库中，然后在本地硬盘上搜索该.lib或.a或.so,如果没有，在网上搜索相关库或模块下载安装，然后将其所在目录填写到“附加依赖库所在目录”中，将其名字添加到“附加依赖库”中，重新连接。 .h文件应该是没有问题的，因为编译器已经能够识别出函数，只是在编译时出现问题。 ffmpeg的库全在lib文件夹下，已经添加到eclipse中了。

引用 11 楼 angel_su 的回复:感觉跟编译命令参数关系不大，都已经顺利编译只是链接出错，库名也确实加了。估计开发包版本搞错了... 开发包是在网上下载的最新开发包

引用 9 楼 misakamm 的回复:你自己配错了环境？  该怎么配呢？ 我没动过

引用 19 楼 angel_su 的回复:你这包是64位的，估计你的mingw是32位的，应该下32位ffmpeg，不能乱套... 怎么看mingw的版本啊？

引用 16 楼 bijiaoben 的回复:把库文件的名字加到你链接时候用的库里面。 链接了啊

引用 15 楼 angel_su 的回复:给个地址看看你下的是啥版本... http://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-20140221-git-76dd01e-win64-dev.7z

引用 2 楼 nadleeh123 的回复:错误是你自己的好吧,../src/test2.c 未定义的引用 av_register_all 这个意思就是库文件没加载上呗？ 怎么加载库文件呢？

引用 1 楼 turingo 的回复:参考http://ffmpeg.gusari.org/viewtopic.php?f=8&t=942  I saw this article. But I didn't use makefile. If I don't use it, what should I do? Do I have to use it?

引用 楼主 Smoke_1988 的回复:我用的环境是windows eclipse mingw 我想调用ffmpeg中的函数 我下载了ffmpeg的sdk，将lib加载到-L，.a文件加载-l下但是没有找到函数 提示信息：  gcc "-IE:\\Cworkspace\\test2\\ffmpeg\\include" -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\test2.o" "..\\src\\test2.c"  gcc "-LE:\\Cworkspace\\test2\\ffmpeg\\lib" -o test2.exe "src\\test2.o" -lavcodec -lavformat -lavutil -lavdevice -lavfilter -lswscale -lpostproc -lswresample  src\test2.o: In function `main': E:\Cworkspace\test2\Debug/../src/test2.c:19: undefined reference to `av_register_all' collect2.exe: error: ld returned 1 exit status  什么地方出现错误了？C语言应该如何载入库？  错误是你自己的好吧,../src/test2.c 未定义的引用 av_register_all

引用 8 楼 Smoke_1988 的回复:[quote=引用 7 楼 misakamm 的回复:] gcc "-LE:\\Cworkspace\\test2\\ffmpeg\\lib" 这怎么看着怪怪的，为什么不是 gcc -L"E:\\Cworkspace\\test2\\ffmpeg\\lib"  我也不知道，我从eclipse里拷出来的[/quote] 你自己配错了环境？


Question: TCP/IP编程问题，求各位大牛指教？

注意解析就好！其他没啥

1、是在数据链路层截取TCP数据包，要对TCL数据进行重组才能得到HTTP报文。 2、原来发过来的HTTP请求要被RESET，修改报文的某些信息后，要基于当前HTTP报文重新发起HTTP请求 这两个问题libcurl能解决吗？

c +  liburl


Question: C语言操作字符串:在:号后和;号前添加"　请教各位

引用 4 楼 zhao4zhong1 的回复:字符串操作的功力不是体现在 给出正确的输入能得到正确的输出 而是体现在 给出各种错误的输入也能得到合理的输出。 比如： ◆未按格式要求输入（无规定间隔符，规定间隔符全角、半角、编码错误……，子内容为空或非法或溢出有效范围） ◆空输入 ◆超长输入 ◆错误编码的字符串 ◆Ctrl+C或Ctrl+Break或Ctrl+Z等signal相关输入 ◆中途强行结束处理（进程意外退出，结束进程，关机，掉电……） ◆……  比如本题，内容里面有引号冒号分号大括号咋办？

给分结贴，感谢２楼。 也透漏一个最终方案：商定了一下用json有点小题大做了。就把原字符串交给java，然后直接按照;号截取字符串，再按照:号分号提取字段名字和内容。因为json有一个缺点是如果某一个字段不存在的话就会出错。所以对于不同的内容的字符串解析出来问题就会比较多一些。  引用 2 楼 KenZhang1031 的回复:#include <iostream> #include <string>  using std::string;  string Str2Json(string &s) { 	int pos = 0;  	 // :后增加" 	 while((pos = s.find(':',pos)) != (-1)) 	 { 		 pos++; 		 s.insert(pos, 1, '"'); 	 }  	 // ;前增加" 	 pos = 0; 	 while((pos = s.find(';',pos)) != (-1)) 	 { 		 s.insert(pos, 1, '"'); 		 pos = pos + 2; 	 }  	 // 头尾增加{} 	 s = "{" + s + "}";  	 // 去除最后的; 	 if((pos = s.find_last_of(';')) != (-1)) 	 { 		 s.erase(pos, 1); 	 }  	 return s; }   int main()  { 	 using std::cout; 	 using std::endl;  	 string s = ";MFG:HP;MDL:Deskjet 1010 series;DES:CX015D;DevNode:/dev/usb/lp0;NULL:;";  	 cout << Str2Json(s) << endl;  	 return 0;  }

String src = "MFG:HP;MDL:Deskjet 1010 series;DES:CX015D;DevNode:/dev/usb/lp0;NULL:"; 		 		//1.去掉最后一个";" 		String tmp1 = src.substring(0, src.length()-1); 		//2.":"后和";"号前添加""" 		String tmp2 = tmp1.replace(":", ":\""); 		String tmp3 = tmp2.replace(";", "\";"); 		//3.添加大括号 		String dest = "{" + tmp3 + "}"; 		 		Log.d("HAHA", dest);  抛给java层来做了，c做起来着实麻烦，我相信sun公司。:)


Question: 怎么将数组作为参数传入

谢谢大家的耐心解答

引用 1 楼 adlay 的回复: #include<stdio.h> int sum(int *p, int len){     int s=0;     int i;     for(i=0;i<len;i++){         s+=*(p+i);     }     return s; } void main() {     int array[]={1,2,3,4};     printf("%d\n",sum(array, sizeof(p)/sizeof(int)))); }    你好，不好意思 最近没上网 所以没及时回复 谢谢你

核心上面说了,就是 数组作为表达式的时候是就是一个指针

引用 1 楼 adlay 的回复: #include<stdio.h> int sum(int *p, int len){     int s=0;     int i;     for(i=0;i<len;i++){         s+=*(p+i);     }     return s; } void main() {     int array[]={1,2,3,4};     printf("%d\n",sum(array, sizeof(p)/sizeof(int)))); }  sizeof(array)/sizeof(int)

#include<stdio.h> int sum(int *p, int len) { 	int s = 0

添加一个行参，作为数组的长度

再加一个入参，把长度也传进去

另一个方案：  int sum(int* beg, int* end);

参考二楼写法，增加一个形参用来记录数组的大小

int len=sizeof(p)/sizeof(int); sizeof(p)有问题；

怎么将整个互联网内容作为参数传入？！

指针，数组做为形参时，都会变成一个指针，sizeof就是指针的大小，32位程序为4. 所以就只有一个元素了，数组长度你可以做为参数传递进去

当数组作为函数的参数的形式传递的时候，它和指针是一样的！ 所以直接用sizeof的话，它的大小是固定的！

int sum(int *p) 这样定义，函数中处理的只是一个指针类型，因此int len=sizeof(p)/sizeof(int); 指针的长度为4，int的长度也为4，所以获取的长度是1，结果也就只处理array中的一个元素了

需加一个数组长度参数信息进去，你那样求数组长度是不行的。


Question: 萌妹子 求大神

char * _log[3];  int i=0; char ch_line[3][500];  while (1) {     if (NULL==fgets(ch_line[i],500,file_log)) break;     printf("%s",ch_line[i]);     _log[i]=(char *)ch_line[i];     printf("%s\n",_log[i]);     i++;     printf("%d",i);     if (i>=3) break; } for (int j=0;j<i;j++) {     printf("%s,%d\n",_log[0],strlen(_log[0]));     printf("%s,%d\n",_log[1],strlen(_log[1]));     printf("%s,%d\n",_log[2],strlen(_log[2])); }

// strcpy(_log[i],ch_line);//这个不可以呢。。 因为_log[i] 没有分配内存地址的，所以直接这样拷贝数据的话，内存出错   _log[i]=ch_line;//请注意这行！！ 因为这里不是申请空间，只是把ch_line的内存地址赋值给_log[i]，所以每次都是相同地址了

引用 2 楼 stephenhawke 的回复:// 调整现有代码 // _log[i]只是指针，先申请空间（最好判断是否成功）。 _log[i]=(char *)malloc(sizeof(char)*strlen(ch_line)+1); // _log[i]=ch_line;//请注意这行！！！！申请的空间地址会丢失，指向ch_line strcpy(_log[i],ch_line);//这才是字符串拷贝  strcpy(_log[i],ch_line);//这才是字符串拷贝   这个不报错 但是最后会停止运行！

引用 1 楼 user-4 的回复:char ch_line[500];是全局的 所以都指向了它  使用动态申请的数组存get到的字符串 能详细说明一下么 ？？


Question: 数据结构  hash表

搜“暴雪哈希算法”

Glib是不是开源的？


Question: C 求助 有关函数相互调用 改变顺序

引用 17 楼 iamkconghua 的回复:那应该是对你的环境而言，OFFSET的值要变化一下。你如果换成Release版本，还根本运行不了呢。代码都有了，自己搞清楚思想就OK了。 嘿嘿！多谢指点

//环境: XP + VC6.0 + Debug/Release模式下通过 #pragma comment(linker, "/SECTION:.text,RW") #ifdef _DEBUG 	#define OFFSET 0x1E #else 	#define OFFSET 0x05 #endif  #include <stdio.h>  void func1(); void func2(); void func3();  int main() { 	func1(); 	printf("\n"); 	return 0; }  void func1() { 	func2(); 	printf("aaa "); }  void func2() { 	func3(); 	printf("bbb "); }  void func3() { 	//int x; 	// your code here 	char *fAddr1 = (char *)func1;	//fAddr1为func1实际代码的首地址 	if (*((char*)func1) == (char)0xE9) 		fAddr1 = (char *)((int)func1 + *((int *)((char *)func1 + 1)) + 5);  	char *fAddr2 = (char *)func2; 	if (*((char*)func2) == (char)0xE9) 		fAddr2 = (char *)((int)func2 + *((int *)((char *)func2 + 1)) + 5);  //	printf("func1	IAT地址: %08x	实际地址: %08x\n", func1, fAddr1); //	printf("func2	IAT地址: %08x	实际地址: %08x\n", func2, fAddr2); //	printf("\n");  	int *pa1 = (int *)(fAddr1 + OFFSET);	//"aaa "的地址 	char *ps1 = (char *)(*pa1);  	int *pa2 = (int *)(fAddr2 + OFFSET);	//"bbb "的地址 	char *ps2 = (char *)(*pa2);  	//交换"aaa "与"bbb "的地址 	*pa1 = int(ps2); 	*pa2 = int(ps1); }

引用 13 楼 iamkconghua 的回复: //环境: XP + VC6.0 + Debug模式下通过 #pragma comment(linker, "/SECTION:.text,RW") #ifdef _DEBUG #define OFFSET1 0x0236 #define OFFSET2 0x028B #endif  #include <stdio.h>  void func1(); void func2(); void func3();  int main() { 	func1(); 	printf("\n"); 	return 0; }  void func1()	//0x00401028 { 	func2(); 	printf("aaa ");	//0040125D+1 }  void func2()	//0x00401023 { 	func3(); 	printf("bbb ");	//004012AD+1 }  void func3() { 	//int x; 	// your code here  	int *pa1 = (int *)((char *)func1 + OFFSET1); 	char *ps1 = (char *)(*pa1);  	int *pa2 = (int *)((char *)func2 + OFFSET2); 	char *ps2 = (char *)(*pa2);  	*pa1 = int(ps2); 	*pa2 = int(ps1); }  顺便向赵大侠致敬. 不是吧，我怎么看到运行结果还是这种情况——

很多代码都是和编译环境有关的，不同的环境，即使代码完全一样，结果也可能不同。例如：以下代码在VC6.0的Debug模式和Relase模式以及VS2008下的结果都有所不同。  #include <stdio.h> void main() { 	int n = 0; 	printf("%d %d %d\n", ++(++n), ++(++n), ++(++n)); }

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 11 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390627329 V5

用macro有可能实现吗

唉，惭愧，想了好久就是没想出来，看楼下有人知道不？

无聊................................................................................................................................

不能用任何输出语句！

那就用puts了。但我估计lz本意不是这样的。   void func3()  {   int x;   puts("aaabbb");  exit(0); }

可以啊，怎么不可以

puts行不？

bu neng you printf ya...

楼主说不能出现printf。。。

void func3()  {   int x;   printf("aaabbb");  exit(0); }  这个？


Question: 菜鸟问题：如果想定义一个子程序，返回的值为字符串类型，应该如何定义呢？

最好用参数传一个buffer进去 如：int program1（char * buffer）；

惭愧，还没学到指针……

std::string program1( void ); string不是字符数组

谢谢各位指点！

char *strfun(int v) {  static char rv[100];  sprintf(rv,"%d",v);  return (char *)rv; }


Question: 取两个整数的平均值

对二进制数abcd和pqrs，有 abcd = a*2的3次方 + b*2的2次方 + c*2的1次方 + d*2的0次方 pqrs = p*2的3次方 + q*2的2次方 + r*2的1次方 + s*2的0次方 所以 abcd + pqrs = (a+p)*2的3次方 + (b+q)*2的2次方 + (c+r)*2的1次方 + (d+s)*2的0次方 对于某二进制数位相加，对应的和的位结果都是“(x+y)*2的n次方”，如果x!=y，即一个为0，另一个是1，那么可以通过“(x^y)*2的n次方”得到结果，与的部分为0；如果x==y，即都为0或1，那么结果可以通过“((x & y)<<1))*2的n次方”得到结果，异或部分为0。 因此： abcd + pqrs = ((abcd & pqrs) << 1) + (abcd ^ pqrs)，因此： 平均数 = (abcd + pqrs) >> 1 = (abcd & pqrs) + (abcd ^ pqrs) >> 1

1.baichi4141点错了溢出这个关键点，而且还给出了很明确的实例，所以给了最多的25分； 2.Falleyes解释了表达式是如何得到平均值的，很浅显，给10分； 3.KenZhang1031，你的描述有点复杂啊，不过你这么热心，给5分^_^。  谢谢大家啦。

引用 10 楼 wwwzys 的回复:这么麻烦，为什么不这样写   int begin = 0, end = 100, mid; mid = (begin>>1) + (end>>1);  这样多简单啊，你们说是不是啊？  的确不对啊，int 类型

奇技淫巧！！

引用 6 楼 C_226 的回复:防溢出这个我倒是没想到，谢谢baichi4141，不过为了防溢出而使用这样的晦涩的代码，是否合理？我第一眼看到的时候就没明白代码是做什么的。 这是取舍的问题 大多数情况下，代码的可读性的确比效率技巧等等更重要，但也有时候不得不由高级程序员来手动调整成最佳状态 例如大多数情况下，编译器的优化比程序员要简单高效，因此程序员不需要太关注运算效率，但有时最核心使用频率最高的那一部分代码，不仅不能依赖编译器的优化，甚至连c/c++都不能使用，必须内嵌汇编来提高效率    引用 10 楼 wwwzys 的回复:这么麻烦，为什么不这样写  int begin = 0, end = 100, mid; mid = (begin>>1) + (end>>1);  这样多简单啊，你们说是不是啊？ int begin = 1, end = 1, mid; mid = (begin>>1) + (end>>1); 别问别人，问自己

如2楼所说，如果两个数接近int 的最大值时，相加就溢出了 引用 2 楼 baichi4141 的回复:防止溢出用 如果0xFFFFFFFF和0xFFFFFFFF取平均值，( begin & end ) + ( ( begin ^ end ) >> 1 )可以得到正确的结果0xFFFFFFFF，而( begin + end ) / 2得到的就是0x7FFFFFFF

学习了，这个很有用啊，以前一直为两个数相加会溢出而不得不把类型定义成更大数据的类型。

好像是有点复杂， 我能想到的一般是 (a+b)>>1 来算平均值

这样来理解，求平均就是把两个数相加，然后除以2 数字相加有两个部分，一个是相加得到的本位，一个是相加得到的进位，我们可以计算的时候把他们分开。 首先，&得到的数字位，只有两个1才得到1，就是进位的1，而本该向前进一位的1待在了本位。实际上应该让得到的结果左移1（让进位的1进到合适的位置），然后再右移1（除以2），得到进位的平均数。 然后，^得到的数字位，实际得到的是本位得到的结果（不包括进位），让他右移1，得到本位的平均数。 两个平均数相加，得到整个数完整的平均数。  设本位为a，进位为b， 那么(a1+a2+b)/2=(a1+a2)/2+b/2。

引用 2 楼 baichi4141 的回复:防止溢出用 如果0xFFFFFFFF和0xFFFFFFFF取平均值，( begin & end ) + ( ( begin ^ end ) >> 1 )可以得到正确的结果0xFFFFFFFF，而( begin + end ) / 2得到的就是0x7FFFFFFF  防溢出这个我倒是没想到，谢谢baichi4141，不过为了防溢出而使用这样的晦涩的代码，是否合理？我第一眼看到的时候就没明白代码是做什么的。

溢出是知道的，但是那个平均值是怎嘛算的？

引用 2 楼 baichi4141 的回复:防止溢出用 如果0xFFFFFFFF和0xFFFFFFFF取平均值，( begin & end ) + ( ( begin ^ end ) >> 1 )可以得到正确的结果0xFFFFFFFF，而( begin + end ) / 2得到的就是0x7FFFFFFF学习了！


Question: 主进程如何监控子进程状态？如果子进程非正常退出呢？

或者直接捕捉“SIGCHLD”信号？

谢谢楼上各位了。 测试了下。 决定采取响应SIGCHLD来确定。

void sig_chld(int signo) {        pid_t pid;        int stat;                 while((pid = waitpid(-1, &stat, WNOHANG)) > 0){                printf("child %d terminated\n", pid);        }         return; }  感觉这方法靠谱

前排围观学习。 以前，在用SDK写程序的时候，我也遇到过这种情况，当时自己的做法是（仅供参考）： 主进程创建子进程后，在创建一个线程，并把子进程的句柄传递到这个线程里，然后就 WaitForSingleObject吧。（一旦子进程结束，它就变成已通知状态了） 接下来再判断子进程的退出代码。 …… http://blog.csdn.net/ubiter/article/details/10363601

共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……

先让子进程每隔比如30秒打开某个日志文件，往最后添加一行信息，关闭； 再在主进程中每隔比如90秒检查这个日志文件的最后修改日期时间，如果和上次检查获得的日期时间相比没有变化，就说明被监视的子进程挂死或非正常退出了。

引用 2 楼 u011339091 的回复:类似如下SIGCHLD的响应函数的话，应该不会阻塞了吧。 void sig_chld(int signo) {        pid_t pid;        int stat;                 while((pid = waitpid(-1, &stat, WNOHANG)) > 0){                printf("child %d terminated\n", pid);        }         return; }  linux 和fork相关函数都能通过一些手段得到子进程的状态，话说回来活要见人死要见尸。


Question: 求教 c语言相关问题  不求作业只是寻求方向    希望从事此工作的大神给个指示

说的很好 正在愁这个事情

多谢大家的解答  我还是先把我现在看的书弄明白了再想其他的吧!

千万别看谭老的书，害了一代又一代人！

你好  不知道实际项目是什么呢  能举个例子吗  我感觉书上写的那些是不是就是了  比如编写一个记忆测试游戏，还有就是怎么才能达到去公司工作的水平，如何自我检测呢

我的观点是光对着书学习是不行的， 应该是学习了书本的基础之后，通过实际项目的锻炼才会有提高，同时学习别人的优秀代码。 这跟学习一门外语一样，多练是王道。。。

不知道你有没有c基础，没有的话建议你买一本谭浩强的《c语言程序设计》，如果有一点c基础的话给你推荐两本书《windows 核心编程》和《unix环境高级编程》这两本书你选一本一个是windows方向的，一个是linux方向的，认真看完并动手敲完书上所有例子和习题的代码，你就可以出山找工作了。

引用 9 楼 fengliang12345 的回复:如果想以找到c的工作为标准的话   至少需要学网络编程  多线程        我刚毕业  刚找到做c的工作   也祝你好运你面试的时候都用到什么知识啦，还有在公司工作都要用到什么啊  麻烦说一下吧！我对这一行一无所知啊

引用 7 楼 zhao4zhong1 的回复:引用 6 楼 li19900210 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 li19900210 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] 《Linux C编程一站式学习》学这个就够了吗？能不能达到就职水平啊 先学了再说。 有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。 [/quote]我现在纠结于是自学c语言然后找工作，还是去培训班呢，培训班好像稳妥点，但是四个月的时间似乎不能学到多少东西啊，还有就是如果自学的话找工作会不会有太多的学历限制啊，真的很纠结[/quote] 上培训班的主要作用不是学到技能，而是扩大人脉以增加找到工作的可能性。[/quote]  引用 7 楼 zhao4zhong1 的回复:引用 6 楼 li19900210 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 li19900210 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] 《Linux C编程一站式学习》学这个就够了吗？能不能达到就职水平啊 先学了再说。 有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。 [/quote]我现在纠结于是自学c语言然后找工作，还是去培训班呢，培训班好像稳妥点，但是四个月的时间似乎不能学到多少东西啊，还有就是如果自学的话找工作会不会有太多的学历限制啊，真的很纠结[/quote] 上培训班的主要作用不是学到技能，而是扩大人脉以增加找到工作的可能性。[/quote]哦 这样啊，那像我们这样没有基础的即使工作了但是什么都不会那也不行啊，还有就是什么培训机构靠谱点呢

引用 6 楼 li19900210 的回复:引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 li19900210 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] 《Linux C编程一站式学习》学这个就够了吗？能不能达到就职水平啊 先学了再说。 有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。 [/quote]我现在纠结于是自学c语言然后找工作，还是去培训班呢，培训班好像稳妥点，但是四个月的时间似乎不能学到多少东西啊，还有就是如果自学的话找工作会不会有太多的学历限制啊，真的很纠结[/quote] 上培训班的主要作用不是学到技能，而是扩大人脉以增加找到工作的可能性。

引用 5 楼 zhao4zhong1 的回复:引用 4 楼 li19900210 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 《Linux C编程一站式学习》学这个就够了吗？能不能达到就职水平啊 先学了再说。 有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。 [/quote]我现在纠结于是自学c语言然后找工作，还是去培训班呢，培训班好像稳妥点，但是四个月的时间似乎不能学到多少东西啊，还有就是如果自学的话找工作会不会有太多的学历限制啊，真的很纠结

引用 4 楼 li19900210 的回复:引用 3 楼 zhao4zhong1 的回复:《Linux C编程一站式学习》学这个就够了吗？能不能达到就职水平啊 先学了再说。 有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。

《Linux C编程一站式学习》


Question: 图书管理系统

来接点分~

引用 2 楼 user-9 的回复:多么亲切的系统啊 呵呵，每一个自学的程序员，都是从它开始的，我当初写的才1000行，当时就特高兴了，现在看起来就一个链表，啥都没有。

目测是课程设计吧 0-0.

百度里边有好多这样的程序，可以参考参考。

楼主是想干什么？

难道是传说的课程设计，话说我当时做的是超市管理系统..

真的很熟悉呀，不过还是有点不相同。

哪个培训机构的项目？？

多么亲切的系统啊


Question: 飞机订票管理系统 用C语言

LZ也太懒了吧，这都想要现成的，有了等的时间，自己都做完了！

我是其他专业的 这个不会····

这么简单 自己慢慢研究

木有兴趣要你的分分，自己写不是挺好么，你都说简单了。。。~

引用 5 楼 derekrose 的回复:http://sourceforge.net/p/oabs/discussion/224410/thread/c102020e/ 这个不错


Question: 学生学籍信息管理系统设计

引用 2 楼 user-2 的回复:不要再写这种没用的东西了，一般这种东西都是要使用数据库的，哪个学校会使用几个文本文件来存储这些数据？你写这种东西，不如直接创建一个数据库，再开发一个带界面的程序客户端去使用它更有实用价值。 一年一度的课程设计时间到了，你懂得......

http://download.csdn.net/detail/n_sev7/4324932 我大一写的，可以参考一下


Question: 数字转换成bitmap的问题

第一，OpenIL不是绑定windows平台的，有源代码，你可以自己编译。  第二，如果你要数字转图像数据的话，如果是纯数字或者较少的英文字母、文字，你可以自己搞个图片字库，然后自己取数据。BMP的文件结构和数据结构搞明白了很简单。如果你涉及的文字很多，很全面，可以使用freetype，这个在linux下应用很多，跨平台的。  你用那个库，不通过DC，都要自己处理图像数据，这是DC操作底层的东西。

你不用DC， 那就是自己做点阵呗，把你自己的1234567890的点阵存成一个数组，然后往BMP里面填了

Tiff,jpg 和 png ，gif 可以跨Winodws,linux 平台  其实直接使用简单的数据，8 Bits 灰度图， 24位,32位彩色位图就可以了 32位彩色位图，不需要数据对齐，其他都需要 里面可以直接放数据  8 Bits 灰度图  图像的亮度直接为 0~255 就可以了  24位,32位彩色位图 不需要颜色信息，也可设为类似灰度图像那种，每种颜色直接0～255即可  其实 4，8，16 Bits 位图最麻烦。 4，8Bits可能会压缩存储，可以还需要调色板 16Bits 分几种模式 5：5：5 ；5：6：5 据说还有4：4：4：4 格式的  1位的单色图像也很简单的。

自己做字体，或者自绘了！！

1）直接读取字库数据自己画 2）像赵老师那样，自己做字模 3）做字模利用windows 或者linux 字体     用API画出数字，并导出 数字字模或者笔画，导出为文件，    然后像赵老师那样处理

仅供参考#include <stdio.h> char *m[77]={ "      ", "      ", "      ", "  --- ", "      ", "      ", "      ", "  --- ", " |   |", " |   |", " |   |", " |   |", " |   |", "  --- ", "      ", "     |", "     |", "     |", "     |", "     |", "      ", "  --- ", "     |", "     |", "  --- ", " |    ", " |    ", "  --- ", "  --- ", "     |", "     |", "  --- ", "     |", "     |", "  --- ", "      ", " |   |", " |   |", "  ---|", "     |", "     |", "      ", "  --- ", " |    ", " |    ", "  --- ", "     |", "     |", "  --- ", "  --- ", " |    ", " |    ", " |--- ", " |   |", " |   |", "  --- ", "  --- ", "     |", "     |", "     |", "     |", "     |", "      ", "  --- ", " |   |", " |   |", " |---|", " |   |", " |   |", "  --- ", "  --- ", " |   |", " |   |", "  ---|", "     |", "     |", "  --- ", }; char s[11]; char p[7][67]; int d,y,x,r,c,L; void LEDprint(int num) {     L=sprintf(s,"%d",num);     for (c=0;c<L;c++) {         for (y=0;y<7;y++) {             sprintf(p[y]+c*6,"%s",m[((s[c]!='-')?s[c]-'0'+1:0)*7+y]);         }     }     for (y=0;y<7;y++) printf("%s\n",p[y]); } int main() {     scanf("%d",&d);     LEDprint(d);     return 0; } //-1234567890 //              ---   ---         ---   ---   ---   ---   ---   --- //           |     |     | |   | |     |         | |   | |   | |   | //           |     |     | |   | |     |         | |   | |   | |   | //  ---      |  ---   ---   ---|  ---  |---      | |---|  ---| |   | //           | |         |     |     | |   |     | |   |     | |   | //           | |         |     |     | |   |     | |   |     | |   | //              ---   ---         ---   ---         ---   ---   --- //

后面就是图像颜色数据啊, 要按你的图像的每像素占bit数来确定.  http://hi.baidu.com/zj41342626/item/e4d0bdfcb36dbe17ff3582a6  你自己也可以要网上搜索下.  如果你完全不使用GDI或者其它现成的东西帮你绘制文字, 那么你就需要字库, 然后自己处理文字的点阵数据,放到位图数据中.

再怎么也是要扯到GetGlyphOutline的。。。然后矩阵到图片就找libbmp好了，github一搜能搜几十个这个库。

是跨平台的，优先支持的是linux，其次才是windows  引用 5 楼 fang098 的回复:引用 1 楼 turingo 的回复:用OpenIL(http://openil.sourceforge.net)库。  [quote=引用 楼主 fang098 的回复:] 请问要将数字比如(123456)之类的转换成bitmap图片，也就是要在内存中画这个bitmap图片，不使用任何windows方面DC之类的操作处理。请问这个要怎么弄，我先谢谢了。  我查了下你给的那个库是绑定widnows平台的，我现在需要的是在linux下也要能用，可能得重新再找找了，不过还是谢谢你。 [/quote]

引用 3 楼 xiaohuh421 的回复:这需要你了解位图格式. 比如24bit位图.格式为:ＢＭＰ文件头+_位置信息头+BGR排列的位图数据. ＢＭＰ文件头(14 byte)+_位置信息头(40 byte) + 调色板(4 byte) + 文字信息(这个文字信息是要怎么组织写下去)我是将数据接在调色板后面直接写的，这样是肯定不行的，还请xiaohuh421告知下要怎么弄，谢谢！

引用 1 楼 turingo 的回复:用OpenIL(http://openil.sourceforge.net)库。  引用 楼主 fang098 的回复:请问要将数字比如(123456)之类的转换成bitmap图片，也就是要在内存中画这个bitmap图片，不使用任何windows方面DC之类的操作处理。请问这个要怎么弄，我先谢谢了。  我查了下你给的那个库是绑定widnows平台的，我现在需要的是在linux下也要能用，可能得重新再找找了，不过还是谢谢你。


Question: 求问用C语言去解析公式，提取所有变量的运算符号，例如a-(b+(d-e)+f)

引用 10 楼 hollin1988 的回复:[quote=引用 4 楼 baihacker 的回复:] 1.递归下降生成语法树。 2.遍历语法树。  或者  在递归下降生成语法树的同时维护符号信息，然后遇到一个结点就根据从上而下维护的符号信息知道 对应的符号了。  用一个struct Node来表示语法树的结点，Node可以表示一个变量，比如a，b，c。 另外Node还可以是一个运算符：加法运算或减法运算，这个时候Node有两个指针Node* l, *r， 表示参运算的结点。 char buff[1024]; // 需要解析的表达式 int curr; // 当前解析位置 Node* parse1(); Node* parse0() {   Node* ret = parse1(curr);   while (buff[curr] == '+' || buff[curr] == '-')   {     根据buff[curr]生成结点x，x的左子树是ret，右结点通过调用parse1()生成。     ret = x;   }   return ret; } Node* parse1() {   if (buff[curr] == '(')   {     Node* ret = parse0();     ++curr;     return ret;   }   else if (buff[curr] 是字母)   {    生成一个变量结点并返回   }   return NULL; // 出错了 }  这样，生成的一定是一个二叉树，内部结点是+或-，叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-，可以计算出变量前的符号。   显然，可以引入一个参数来描述这若干个+或-，不用生成语法树就可以完成解析。 你这程序略复杂啊，没看懂 a+b-(c+(a-(d+e+(f-a))+m),这个通过你程序正常解析出来了没？解析出来就万分感谢，分数就送上了[/quote]  这个是一般的递归下降解析，即使有乘除法，甚至很多一般的语法都没有问题。 但是应用于你的问题还有很多更简单的方法，如9楼所说。

引用 9 楼 misakamm 的回复:来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b，初始都是0 要确定f的符号，从f向前一个一个字符扫描，如果遇到-号，同时b为0，那么s = 1 - s 如果遇到)号，那么b++ 遇到(号，那么b-- 扫描完以后，s为0就是正，s为1就是负  你这个思路我明白了，确实可以实现，我懂了：应该是变量的符号决定s的值，正是0，负数是1，然后每到一个(号判断，他跟前面遍历的）号是否匹配，如果匹配，那么（号前面的值不影响的s值，如果（号的数目>)号的数目，每到（号，并且（号前面的符号是负号，那么s=1-s,如此循环遍历完整个字符串，就取出来变量的值

引用 9 楼 misakamm 的回复:来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b，初始都是0 要确定f的符号，从f向前一个一个字符扫描，如果遇到-号，同时b为0，那么s = 1 - s 如果遇到)号，那么b++ 遇到(号，那么b-- 扫描完以后，s为0就是正，s为1就是负  而且根据你这个判断。f是正吧，第一个负号的时候,b=1,s=0不变，第二个-号，b=-1,s=0不变，所以s=0的值始终没变，判断出来f是正，这明显错了吧。还是我理解错了啊？

引用 9 楼 misakamm 的回复:来一个最笨但最容易实现的 比如 a-(b+(d-e)+f) 需要两个标志量s和b，初始都是0 要确定f的符号，从f向前一个一个字符扫描，如果遇到-号，同时b为0，那么s = 1 - s 如果遇到)号，那么b++ 遇到(号，那么b-- 扫描完以后，s为0就是正，s为1就是负  我现在做的程序解析带1个括号的是没问题的，基本也是按这种方法的，但是多层的，怎么确定括号的范围，怎么保留每层括号外面的符号，怎么判断变量在那个括号范围内，没有理清楚里面的思路

引用 5 楼 derekrose 的回复:使用递归  我也知道用递归，就是不知道怎么去写，方法之类的我也很清楚。。。

引用 4 楼 baihacker 的回复:1.递归下降生成语法树。 2.遍历语法树。  或者  在递归下降生成语法树的同时维护符号信息，然后遇到一个结点就根据从上而下维护的符号信息知道 对应的符号了。  用一个struct Node来表示语法树的结点，Node可以表示一个变量，比如a，b，c。 另外Node还可以是一个运算符：加法运算或减法运算，这个时候Node有两个指针Node* l, *r， 表示参运算的结点。 char buff[1024]; // 需要解析的表达式 int curr; // 当前解析位置 Node* parse1(); Node* parse0() {   Node* ret = parse1(curr);   while (buff[curr] == '+' || buff[curr] == '-')   {     根据buff[curr]生成结点x，x的左子树是ret，右结点通过调用parse1()生成。     ret = x;   }   return ret; } Node* parse1() {   if (buff[curr] == '(')   {     Node* ret = parse0();     ++curr;     return ret;   }   else if (buff[curr] 是字母)   {    生成一个变量结点并返回   }   return NULL; // 出错了 }  这样，生成的一定是一个二叉树，内部结点是+或-，叶子结点是变量。 从根到叶子结点的路径上会有若干个+或-，可以计算出变量前的符号。   显然，可以引入一个参数来描述这若干个+或-，不用生成语法树就可以完成解析。 你这程序略复杂啊，没看懂 a+b-(c+(a-(d+e+(f-a))+m),这个通过你程序正常解析出来了没？解析出来就万分感谢，分数就送上了

你确定只有+-号和括号？如果是的话那灰常容易，一遍分析就出结果了

编译原理中的波兰树语法分析树问题，呵呵

使用递归

或者说如何把这里面所有括号去除，变成正常的表达式

引用 1 楼 user-7 的回复:http://wenku.baidu.com/view/3ef2f26b25c52cc58bd6be97.html 版主大哥，他这个有局限啊：中缀表达式（可以带括号，但不允许冗余括）或后缀表达式（不带括号）  。 我要的是任意，可能多层括号，有可能诸如 a+b-(c+(a-(d+e+(f-a))+m),就有冗余的括号啊，他这个实现不了吧


Question: sprintf()格式化字符串的时候，多出一个"-"具体的原因是什么？

引用 1 楼 jerry_dqh 的回复:heroId 这个值是-1吧 是的 -1，改了  耳环

To set a breakpoint when a variable heroId changes value   From the Edit menu, click Breakpoints. Click the Data tab of the Breakpoints dialog box. In the Expression text box, type the name of the variable heroId. Click OK to set the breakpoint.

heroId值可能被改了，改成-1，所以才会输出-1，你单步调试一下。

heroId可能是个返回值之类的，上一次使用被赋值为-1了。单步调试一下就知道了

你这个32好紧哟, herold  稍大些, 就要越界了, 你就悲剧了.

herold  被改了吧

heroId的类型是int吗？断点跟踪一下heroId的值

herold 值为 -1

看看heroId的值在哪里做了修改，导致不符合你的预期。

heroId 这个值是-1吧


Question: 字符串数组最后一个值去哪儿了

引用 10 楼 007remember 的回复:n--之后，n=5 试了下，还是有问题，我再仔细看下  补充下：原程序的for循环中，有操作 index++，对for循环的判定条件 n - index作了改变，程序就不可能正常运行。

不好意思，可能跟我用的一个工具（loadrunner）有关 我在c编译环境下面运行是正确的。 多谢大家！

n--之后，n=5 试了下，还是有问题，我再仔细看下

嗯，谢谢tatata000！ 已经修改了

如8楼所述，循环判断有问题。 举几个例子： n=6 index = 0时，n-index=6，即a<6；循环6次:a=0,1,2,3,4,5 index = 1时，n-index=5，即a<5;循环5次：a=0,1,2,3,4 index = 3时，n-index=3，即a<3；循环3次：a=0,1,2 index = 5时，n-index=1，即a<1；循环1次：a=0  不管哪一个例子，都会涉及到strcpy(str[5],str[6])的问题。 而str[5]就已经是最后一个字符串来，str[6]出数组边界了。

应该还是循环次数的问题，在最后一个for循环那里,改成 if (index != 0) {        b = n - index;        for (a=0; a<b; a++)             {                    strcpy(str[index],str[index+1]);                    index++;             } } 再试试

多声明了个j，请忽略

char str[6][15]={"aa","bb","cc","dd","ee","ff"}； int a,index,j; int n = 6;  	n--; //get a rand index in a string array 	index = rand()%n;  	if (index != n) {  		for (a=0;a<n-index;a++) {  			strcpy(string[index],string[index+1]);   			index++; 		} 	}

多谢大家的回复！ 没有多循环呢，马上贴代码

最好贴出你的代码。 以下代码纯属猜测： index = 3; i = 0; while(i<=2) { //估计循环判断的时候实际上循环了3次，这里应该把等号去掉。     strcpy(str[index+i],str[index+i+1]);     i++; }

应该是多循环了一些index，造成覆盖现象。  引用 楼主 007remember 的回复:大家好，我有个小程序：实现随机从一个字符串数组里面取一个值，取完然后，从取值这个下标开始就把后面的值依次赋给前面的，相当于随机从数组里面删除了值，然后数组重新排列。 比如数组 str[6][15]={"aa","bb","cc","dd","ee","ff"}, 随机取了第4个值，str[3] ="dd", 然后 循环2次 strcpy（str[index],str[index+1]）, 重新排列的数组不是应该是 str[6][15]={"aa","bb","cc","ee","ff","ff"}吗？  但是实际的结果是最后数组只剩下5个元素（str[6][15]={"aa","bb","cc","ee","ff"}）了，请问原来那个str[5]去哪儿了？

你最好能把你的程序贴出来， 引用 楼主 007remember 的回复:大家好，我有个小程序：实现随机从一个字符串数组里面取一个值，取完然后，从取值这个下标开始就把后面的值依次赋给前面的，相当于随机从数组里面删除了值，然后数组重新排列。 比如数组 str[6][15]={"aa","bb","cc","dd","ee","ff"}, 随机取了第4个值，str[3] ="dd", 然后 循环2次 strcpy（str[index],str[index+1]）, 重新排列的数组不是应该是 str[6][15]={"aa","bb","cc","ee","ff","ff"}吗？  但是实际的结果是最后数组只剩下5个元素（str[6][15]={"aa","bb","cc","ee","ff"}）了，请问原来那个str[5]去哪儿了？

楼主，与"dd"相对应的数组下表应该是str[0][3],吧


Question: C语言socket编程如何避免SIGPIPE问题

引用 14 楼 u013591397 的回复:[quote=引用 13 楼 mxgsgtc 的回复:] [quote=引用 11 楼 u013591397 的回复:] [quote=引用 9 楼 mxgsgtc 的回复:] [quote=引用 5 楼 u013591397 的回复:] [quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧[/quote]恩，话说我加上了怎么还是这个问题呢。。。[/quote] 嗯？ 我的是好用的啊，你在哪加的？ 不是在client代码加的吗？，还有，你给的代码client的s没有被定义[/quote]额，不好意思。。。复制修改的时候把s给修改没了。。。。我又改了一下，发现这次可以了，其实我一直很不明白为什么我总是会遇到这个问题，不管是pipe还是socket。。。很是苦恼啊。。。[/quote] 没事儿，多用用就好了，c/s结构都是先让server端先起来的

引用 15 楼 mxgsgtc 的回复:[quote=引用 14 楼 u013591397 的回复:] [quote=引用 13 楼 mxgsgtc 的回复:] [quote=引用 11 楼 u013591397 的回复:] [quote=引用 9 楼 mxgsgtc 的回复:] [quote=引用 5 楼 u013591397 的回复:] [quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧[/quote]恩，话说我加上了怎么还是这个问题呢。。。[/quote] 嗯？ 我的是好用的啊，你在哪加的？ 不是在client代码加的吗？，还有，你给的代码client的s没有被定义[/quote]额，不好意思。。。复制修改的时候把s给修改没了。。。。我又改了一下，发现这次可以了，其实我一直很不明白为什么我总是会遇到这个问题，不管是pipe还是socket。。。很是苦恼啊。。。[/quote] 没事儿，多用用就好了，c/s结构都是先让server端先起来的[/quote]恩，我现在也注意到了，谢谢你的耐心帮助哈

引用 7 楼 gpshq 的回复:http://www.cnblogs.com/caosiyang/archive/2012/07/19/2599071.html 感谢你的回答，我想再问一下，如果这么做在导致SIGPIPE的那一次写入不就不能成功了么，可是我需要那一次写入成功呀。

程序加上	signal(SIGPIPE, SIG_IGN);

引用 3 楼 mxgsgtc 的回复:33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。

嗯，刚试了一下，就是那个原因，可能你的addr程序还没有执行read的时候你的客户端程序就开始写了，先让服务端处在read阻塞状态就可以了，33行加个sleep(5)，让客户端晚一点访问

33行添一下 sleep(5)试试

引用 13 楼 mxgsgtc 的回复:[quote=引用 11 楼 u013591397 的回复:] [quote=引用 9 楼 mxgsgtc 的回复:] [quote=引用 5 楼 u013591397 的回复:] [quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧[/quote]恩，话说我加上了怎么还是这个问题呢。。。[/quote] 嗯？ 我的是好用的啊，你在哪加的？ 不是在client代码加的吗？，还有，你给的代码client的s没有被定义[/quote]额，不好意思。。。复制修改的时候把s给修改没了。。。。我又改了一下，发现这次可以了，其实我一直很不明白为什么我总是会遇到这个问题，不管是pipe还是socket。。。很是苦恼啊。。。

引用 11 楼 u013591397 的回复:[quote=引用 9 楼 mxgsgtc 的回复:] [quote=引用 5 楼 u013591397 的回复:] [quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧[/quote]恩，话说我加上了怎么还是这个问题呢。。。[/quote] 嗯？ 我的是好用的啊，你在哪加的？ 不是在client代码加的吗？，还有，你给的代码client的s没有被定义

引用 10 楼 mujiok2003 的回复:被另外一边关闭了可否说的稍微细致一点，我明白这个确实是一边关闭了，但是我很想搞清楚这是为什么。。。

引用 9 楼 mxgsgtc 的回复:[quote=引用 5 楼 u013591397 的回复:] [quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧[/quote]恩，话说我加上了怎么还是这个问题呢。。。

被另外一边关闭了

引用 5 楼 u013591397 的回复:[quote=引用 3 楼 mxgsgtc 的回复:] 33行添一下 sleep(5)试试 非常感谢你的帮助~ 我想问除了sleep还有什么方法能实现adder端晚一点关闭，刚刚问了一下说不允许用sleep。。因为后面需要循环向adder传输指令。。。。[/quote] ？ 循环向adder传输指令跟第33行添加sleep没有冲突吧

引用 1 楼 user-5 的回复:没仔细看，但感觉你的代码里面没一个循环，也没一个select或者是线程之类的，SIGPIPE这不是一方已经把套接字关闭了吗? 是不是你有一个程序运行都结束了啊  我就把最简单地实验代码放上来了，就想实现互相传一个信息然后输出出来。。。对socket很是不懂，我想问的就是如何能让那个先关闭的端不要那么早关闭，让write操作完成


Question: C程序设计语言的练习1-19，又莫名出错了

呵呵，编程这东西真的是要不得半点马虎，否则失之毫厘谬以千里。谢了，钻研一下您给出的参照帖子去。

引用 3 楼 u013696899 的回复:[quote=引用 2 楼 sr1992102 的回复:] int reverse(char str1[], char str2[]) //翻转字符串的子程序  {     int i;     for (i = strlen(str1); i >= 0; i--){    //strlen(*)计算数组长度不会计算'\0'，所以不需要-1         str2[strlen(str1) - 1 - i] = str1[i];     }         str2[strlen(str1) ] = '\0'; //给字符串2加上结束标志，str2没有结束标志，所以不能直接用strlen(*)来计算str2的长度，可间接地通过计算str1的长度得到str2的长度。                return 0; } 您一针见血指出了问题之所在。关键果然是str2没有\0的时候，取其长度是不准确的。改为取str1的长度后，计算结果正确了。 但还有一事不明。您提到上面一句不需要 -1，我把 -1 去掉以后，计算的结果也是正确的，不过有一点尚不理解。 举例说明。假如str1的值是“abcdefgh”，则其长度是8。那么第五行：str2[strlen(str1) - 1 - i] = str1[i]; 在计算的时候，strlen(str1) - 1 - i = 8 - 1 - 8 = -1，赋值就变成了str2[-1] = str1[8]。为字符数组并不存在的-1位赋值，为什么系统不会出错呢？ 谢谢！[/quote]  引用 3 楼 u013696899 的回复:[quote=引用 2 楼 sr1992102 的回复:] int reverse(char str1[], char str2[]) //翻转字符串的子程序  {     int i;     for (i = strlen(str1); i >= 0; i--){    //strlen(*)计算数组长度不会计算'\0'，所以不需要-1         str2[strlen(str1) - 1 - i] = str1[i];     }         str2[strlen(str1) ] = '\0'; //给字符串2加上结束标志，str2没有结束标志，所以不能直接用strlen(*)来计算str2的长度，可间接地通过计算str1的长度得到str2的长度。                return 0; } 您一针见血指出了问题之所在。关键果然是str2没有\0的时候，取其长度是不准确的。改为取str1的长度后，计算结果正确了。 但还有一事不明。您提到上面一句不需要 -1，我把 -1 去掉以后，计算的结果也是正确的，不过有一点尚不理解。 举例说明。假如str1的值是“abcdefgh”，则其长度是8。那么第五行：str2[strlen(str1) - 1 - i] = str1[i]; 在计算的时候，strlen(str1) - 1 - i = 8 - 1 - 8 = -1，赋值就变成了str2[-1] = str1[8]。为字符数组并不存在的-1位赋值，为什么系统不会出错呢？ 谢谢！[/quote]  那里的确是我想错了，想当然的去掉了 -1，造成了数组越界。 关于数组越界，LZ可以参照这个帖子  http://bbs.csdn.net/topics/300215352

引用 6 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 所言极是。在下当埋头钻研，遇到实在无法解决的有价值问题再做必要询问。谢谢。

第四行赋值的时候，如果赋为strlen(str1)，比起赋值为strlen(str1) - 1要多经历一次循环，而就是这第一次循环过程中出现的str2[-1]让我不解。是不是这一次循环因为是对数组本身并不存在的 -1 位进行赋值而被系统跳过了，所以两种方案的计算结果都是正确的呢？

引用 2 楼 sr1992102 的回复:int reverse(char str1[], char str2[]) //翻转字符串的子程序  {     int i;     for (i = strlen(str1); i >= 0; i--){    //strlen(*)计算数组长度不会计算'\0'，所以不需要-1         str2[strlen(str1) - 1 - i] = str1[i];     }         str2[strlen(str1) ] = '\0'; //给字符串2加上结束标志，str2没有结束标志，所以不能直接用strlen(*)来计算str2的长度，可间接地通过计算str1的长度得到str2的长度。                return 0; } strlen(*)不计算‘\0’的长度没错，但我们需要计算遍历字符数组，其下标是从0-strlen(*)-1。因此，第四行i赋值为strlen(str1)-1才是是正确的。

引用 2 楼 sr1992102 的回复:int reverse(char str1[], char str2[]) //翻转字符串的子程序  {     int i;     for (i = strlen(str1); i >= 0; i--){    //strlen(*)计算数组长度不会计算'\0'，所以不需要-1         str2[strlen(str1) - 1 - i] = str1[i];     }         str2[strlen(str1) ] = '\0'; //给字符串2加上结束标志，str2没有结束标志，所以不能直接用strlen(*)来计算str2的长度，可间接地通过计算str1的长度得到str2的长度。                return 0; } 您一针见血指出了问题之所在。关键果然是str2没有\0的时候，取其长度是不准确的。改为取str1的长度后，计算结果正确了。 但还有一事不明。您提到上面一句不需要 -1，我把 -1 去掉以后，计算的结果也是正确的，不过有一点尚不理解。 举例说明。假如str1的值是“abcdefgh”，则其长度是8。那么第五行：str2[strlen(str1) - 1 - i] = str1[i]; 在计算的时候，strlen(str1) - 1 - i = 8 - 1 - 8 = -1，赋值就变成了str2[-1] = str1[8]。为字符数组并不存在的-1位赋值，为什么系统不会出错呢？ 谢谢！

char string2[MAX];这句没给变量初始化，可以这么写char string2[MAX]={0};


Question: 判断文件是否读取完

楼上详解！  学习ing

/* C语言测试文件尾的方法   首先先谈一般的，普通的 asc 文件 feof（FILE*）遇到文件尾时返回非0。但是feof测试文件尾，需要慎用，经常不小心会出现最后重复读取的错误。因为feof返回值是根据statement来决定的。当fgetc getc fgets fread返回失败的时候，才会修改statemnet，然后feof时候就会返回一个 非0值 说明已经到了文件尾了，该杀的时候了。我测试了windows和linux。其中windows每次都返回16， linux返回1，遇到文件尾的时候。总之返回非0就是遇到文件尾了，该杀了。。。   所以检测文件尾的时候最好要少用feof，暂时我也没发现用他的好方法。   判断尾巴的方法：   1. int ch = fgetc(fp);    if(ch == EOF)break; 2. fgets返回NULL 3. fread返回0   还有适当的配合文件指针来使用 文件指针从0开始到size-1（其中size尾文件大小），其中后面还有一个虚拟的指针size位置（文件尾） 打开文件时候，指针指向0。 ps：文件指针到底指向哪呢？实际上就是指向将要读取的一个字节的地址，以前读过的就不算了。所以刚开始打开文件的时候，文件指针的偏移量就是，指向文件的第一个字节，因为它还没有被读取。fseek(fp, 0, SEEK_END)就是跳过整个文件，指向文件尾巴。那个实际不存在的地方。如果此时getc的话就会返回-1出错了。但是此时调用feof是不会返回非0（遇到文件尾的），因为feof只是返回系统的一个statment的值，它是要getc gets fread等等系统调用修改的。所以再三强调feof不是一个好方法。   fseek(fp, 0, SEEK_END)后文件指针指向size,如果此时feof(fp)的话，是不会返回非0的，原因就是根本没有系统调用改变了那个statment的值。所以还是返回0，这样如果不做判断直接getc的话，就会获得一个-1到自己的程序中就会出错了。当然也因为这个-1（虽然你么有判断，但是系统害是该了你的statment）所以下一次调用feof的时候就会返回非0，然后才停止读取数据。但是已经错误了，所以大家要小心了啊  */

fscanf, fwscanf Read formatted data from a stream.  int fscanf( FILE *stream, const char *format [, argument ]... );  int fwscanf( FILE *stream, const wchar_t *format [, argument ]... );  Function Required Header Compatibility  fscanf <stdio.h> ANSI, Win 95, Win NT  fwscanf <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. If an error occurs, or if the end of the file stream is reached before the first conversion, the return value is EOF for fscanf or WEOF for fwscanf.  Parameters  stream  Pointer to FILE structure  format  Format-control string  argument  Optional arguments  Remarks  The fscanf function reads data from the current position of stream into the locations given by argument (if any). Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. format controls the interpretation of the input fields and has the same form and function as the format argument for scanf; see scanf for a description of format. If copying takes place between strings that overlap, the behavior is undefined.  fwscanf is a wide-character version of fscanf; the format argument to fwscanf is a wide-character string. These functions behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _ftscanf fscanf fscanf fwscanf    For more information, see Format Specification Fields – scanf functions and wscanf Functions.  Example  /* FSCANF.C: This program writes formatted  * data to a file. It then uses fscanf to  * read the various data back from the file.  */  #include <stdio.h>  FILE *stream;  void main( void ) {    long l;    float fp;    char s[81];    char c;     stream = fopen( "fscanf.out", "w+" );    if( stream == NULL )       printf( "The file fscanf.out was not opened\n" );    else    {       fprintf( stream, "%s %ld %f%c", "a-string",                 65000, 3.14159, 'x' );        /* Set pointer to beginning of file: */       fseek( stream, 0L, SEEK_SET );        /* Read data back from file: */       fscanf( stream, "%s", s );       fscanf( stream, "%ld", &l );        fscanf( stream, "%f", &fp );       fscanf( stream, "%c", &c );        /* Output data read: */       printf( "%s\n", s );       printf( "%ld\n", l );       printf( "%f\n", fp );       printf( "%c\n", c );        fclose( stream );    } }   Output  a-string 65000 3.141590 x   Stream I/O Routines  See Also   _cscanf, fprintf, scanf, sscanf

int r; while(1)  ///<  这里怎么判断文件是否读取完毕  feof()函数实现不了      {          r=fscanf(fp, "%s %s %d", filte_info->file_name, filte_info->function_name, &filte_info->line_no);          if (r==3)          printf("%s\n%s\n%d\n", filte_info->file_name, filte_info->function_name, filte_info->line_no);          else if (r==EOF) break;          else printf("Format Error after %s %s %d!\n",filte_info->file_name, filte_info->function_name, filte_info->line_no);      }      fclose(fp);

引用 2 楼 zhao4zhong1 的回复:请判断fscanf函数的返回值。 while(feof(fp)) 中 feof(fp)为0  进不了循环。

额。已解决。   在while 之前加上 fseek(fp, 0, SEEK_SET);

请判断fscanf函数的返回值。

if(fread(buffer, sizeof(buffer), 1, fp) < 1) {     if(feof())     {         printf("read to file tail\n");     }     else     {         do something;     } }


Question: 一道面试题引发的疑问

指针存储的是地址，地址是一个16进制的数。实际上，这相当于指针直接赋值地址，编译器自动把10进制的3转换为16进制的3，然后给指针。

问题是这面试题其实只是错误的渣渣  结果不保证一定是你以为的这样

引用 1 楼 user-3 的回复:改动一下就很清楚了 S s;  s.p = malloc(sizeof(int)); //此时s.p是一个很大的数 int *p=&s.i;  p[0]=4; //即s.i = 4 p[1]=3; //即s.p = 3，如果访问s.p，则崩溃  对不起.我不是很明白您的意思。 这样改动貌似只是说明了p[1]=3确实对s.p进行了赋值。。。 而我的问题是p+1是个int型指针，所以p[1]是个int型数据，而&p[1]这个地址存放的是个结构体s的int型指针，数据类型不对啊？？？他们怎么实现数据类型转换的？

指针本身也是放着栈上的


Question: 菜鸟请教一下在for语句中赋值和在for之前赋值的区别

lz还是要多看看、多试试for循环啊，楼上的说的不错了，就不重复了

运行结果当然不同啦，第二种情况下，每次进第二层和第三层循环b和c的值都会重新初始化的呀。

引用 2 楼 derekrose 的回复:for (a=1;a<=3;a=a+1)         {             for(b=1;b<=3;b=b+1)             {                 for (c=1;c<=3;c=c+1)  等于 int a=1; for (;a<=3;a=a+1)         {             int b=1;             for(;b<=3;b=b+1)             {             int c=1;                 for (;c<=3;c=c+1) 非常感谢

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

引用 3 楼 u012421456 的回复:[quote=引用 楼主 u013704298 的回复:]                             if (a!=1&&b!=1&&c!=3&&a!=b&&a!=c&&b!=c)                             if (a!=1&&c!=1&&c!=3&&a!=b&&a!=c&&b!=c) lz你这两行代码咋不一样啊！[/quote] 不好意思，一开始写错了，改了一下，忘了全部改了。

引用 1 楼 user-6 的回复:运行结果不同是因为每次a循环，b都会重新赋值b = 1，每次循环 c都会重新复制 c = 1. 如果全部放在前面，a、b、c都只会被复制一次。 看来你还不了解循环。 恩，看来是我还没理解，非常感谢。

引用 4 楼 starytx 的回复:主要区别是b和c写的位置引起的，第一种b和c都是在外边初始化一次，之后一直就是循环中的旧值，而第二种，每次最外层循环一次，b就被重置为1一次，同样，b循环进行一次，c就没重置一次。 有点明白了，非常感谢，顺便问一下，为什么我显示的用户名是类似UID的呢？我想显示我UID下面的那个名字，请教如何设置

引用 4 楼 starytx 的回复:主要区别是b和c写的位置引起的，第一种b和c都是在外边初始化一次，之后一直就是循环中的旧值，而第二种，每次最外层循环一次，b就被重置为1一次，同样，b循环进行一次，c就没重置一次。被

引用 楼主 u013704298 的回复:if (a!=1&&b!=1&&c!=3&&a!=b&&a!=c&&b!=c)                             if (a!=1&&c!=1&&c!=3&&a!=b&&a!=c&&b!=c) lz你这两行代码咋不一样啊！


Question: 菜鸟求教，简单的C程序，去引用问题求教

引用 楼主 weidu23 的回复:我们知道，int *p = &i ；那么*p就是对p去引用的过程！所以*p得到了i的值 。 但是，到了结构上，为什么就不行了呢？ ---------- 假设一个结构： typedef struct{ 	char * name ; 	int age ; }Person; 我们在main函数中这么来： 	Person *person = (Person*)malloc(sizeof(Person)); 这样分配了一段内存，这段内存被person指向！ 那么*person 不就去引用，获取了实际开辟的Person么？ 那么(*Person).name = "abc"；就设置了内存中name的内容么？ -------- 不，实际上，这样报错了！ 正确的写法是person->name = "abc" ; -----------------------------------分割线--------------------- 问题：     为什么这样的去引用方式是错的？可是我的分析看是正确啊？求指教！！！ 我昨天写链表的时候刚看了这个问题，C primer plus专门有写了这个问题的注意事项

引用 5 楼 user-4 的回复:或者说，你free的是person所指向的堆空间，而不是person本身。person变量本身是在栈中的，你free时, person还没销毁呢。 同意楼上的观点！

指针即地址 引用即别名  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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

引用 3 楼 weidu23 的回复:[quote=引用 2 楼 user-4 的回复:] 按照微软的命名规范，应该这样命名结构体(类型名大写)：  #include <stdio.h> #include <stdlib.h>  typedef struct tagPERSON { 	char *szName; 	int iAge; } PERSON, *PPERSON;  void main() { 	PERSON *person = (PERSON*)malloc(sizeof(PERSON)); 	(*person).szName = "abc"; 	free(person); }   哦，这样，刚刚没注意，谢谢你的提醒！ ---------- 想再请教一个问题： #include <stdio.h> typedef struct{ 	char * name ; 	int age ; }Person; int main(int argc, char *argv[]) { 	Person *person = (Person*)malloc(sizeof(Person)); 	(*person).name = "abc" ; 	(*person).age  = 5 ; 	printf("%u",sizeof(*person)); 	free(person); 	printf("\n"); 	printf("%u",sizeof(*person)); 	return 0; }  为什么free前和free了之后，结果都是8，内存没有释放？[/quote]   你去三亚旅游，订了一个能住8个人的家庭套房(malloc)，该房间容量为8.你退房(free)后，该房间容量依然为8，当然不会变了。 只是你住房时，住的是你的家人，退房后，没住人了，住的是空气或者其他人，但容量依然不变啊。

引用 2 楼 user-4 的回复:按照微软的命名规范，应该这样命名结构体(类型名大写)：  #include <stdio.h> #include <stdlib.h>  typedef struct tagPERSON { 	char *szName; 	int iAge; } PERSON, *PPERSON;  void main() { 	PERSON *person = (PERSON*)malloc(sizeof(PERSON)); 	(*person).szName = "abc"; 	free(person); }   哦，这样，刚刚没注意，谢谢你的提醒！ ---------- 想再请教一个问题： #include <stdio.h> typedef struct{ 	char * name ; 	int age ; }Person; int main(int argc, char *argv[]) { 	Person *person = (Person*)malloc(sizeof(Person)); 	(*person).name = "abc" ; 	(*person).age  = 5 ; 	printf("%u",sizeof(*person)); 	free(person); 	printf("\n"); 	printf("%u",sizeof(*person)); 	return 0; }  为什么free前和free了之后，结果都是8，内存没有释放？

(*person).name = "abc"; person->name = "abc";  这2种写法都可以的。 你第一个Person的p大写了。


Question: 如何剔除s1字符串里与s2一致的字符？？

知道为啥了 s1[k]=s1[++k];其实就等于 s1[k+1]=s1[k+1]; 应该写成 s1[k]=s1[k+1];

仅供参考#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //

#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<sys/types.h>   #define STR_SIZE 512   int main(int argc, char* argv[]) { 	       char str[STR_SIZE]     = {0};     char substr[STR_SIZE]  = {0};     char deststr[STR_SIZE] = {0};     char *phead = NULL;     char *ptail = NULL;               printf("input the first string!\n");     scanf("%s", str);          printf("input the second string!\n");     scanf("%s", substr);          if((phead = strstr(str, substr)) != NULL)     {         strncpy(deststr, str, phead-str);         strcpy(deststr+strlen(deststr), phead+strlen(substr));         printf("the string:%s, after delete the substr:%s, the left string:%s\n", str, substr, deststr);     }     else     {         printf("the second string is not a sub string int the first string!\n");     }          return 0; }


Question: windows程序设计的一些疑问

亲，满意的话请给分哈~

谢谢，我懂了。解释的非常好

HANDLE WINAPI LoadImage(   _In_opt_  HINSTANCE hinst,   _In_      LPCTSTR lpszName,   _In_      UINT uType,   _In_      int cxDesired,   _In_      int cyDesired,   _In_      UINT fuLoad );  MSDN上说： If the hinst parameter is NULL and the fuLoad parameter omits the LR_LOADFROMFILE value, the lpszName specifies the OEM image to load. The OEM image identifiers are defined in Winuser.h and have the following prefixes.  OEM就是预定义好的图像，在Winuser.h这个文件里面能找到，上面说有如下的前缀值： Prefix（前缀）  Meaning（含义） OBM_      OEM bitmaps OIC_      OEM icons OCR_      OEM cursors


Question: C 的EOF 问题

Enter,Ctrl+Z,Enter

嗯，刚才确认了一下用vs 2010，ctrl+z一次就退出了，vc++ 6.0问题就是多。。

Linux下不是Ctrl+Z是Ctrl+D

我认为这是编译器的事儿，我用的vc++ 6.0也是这种情况，第一次打ctrl+z 其实都没有进入键盘缓冲区，建议用高版本的，比如vs 2012可能就不会有这个问题(我没有2012实验不了，估计2楼没出现问题估计就是用的高版本的)，linux 下的crtl+z就直接退出程序了

if(scanf("%s",s)==EOF) 这句 scanf返回成功输入的变量个数,相当于用  输入几个参数和EOF作比较,而不是输入什么和EOF做比较

应该把这句拆开， scanf("%s",s)

楼主不小心把，函数返回值，当成输入的值了

引用 3 楼 baichi4141 的回复:宏EOF代表没有接收到数据，一般定义为-1 如果你输入EOF，你输入的是三个字符数据，如果你输入-1，你输入的是一个整数数据，只有当你输入Ctrl+Z的时候，函数才会返回宏EOF或者说整数-1 楼主的问题在于没有分清函数返回值和函数输出 我就是输入的ctrl +z

引用 楼主 u011488256 的回复:// 回音程序.cpp : Defines the entry point for the console application. //  #include "stdafx.h" #include "stdio.h"  int main(int argc, char* argv[]) { 	char s[10]; 	while (1) 	{ 		if(scanf("%s",s)==EOF) 			break; 		printf("%s\n",s); 	} 	return 0; }  这段小程序 运行后 为什么每次输入EOF后 点回车不能退出循环？ 必须要再一次输出EOF点回车才能退出循环啊？  如果换成if(scanf("%d",n)==EOF)  这样的话 输入一次EOF就可以退出循环 求解！ 我就是输入的 ctrl +z 啊 为什么我这里两次 我这里VC环境

帮你程序改短了一点，功能是一样的。 哦对了，EOF的输入方式是Ctrl+Z你知道吧。  #include "stdio.h"   int main( ) {     char s[ 10 ];     while( ~scanf( "%s", s ) )         printf("%s\n",s);     return 0; }

我这边测试没有问题啊。  测试输入输出： L:\>test 123 123 ^Z  L:\>test ^Z


Question: KMP算法在二进制匹配中是否有改进的空间

引用 6 楼 SKATE11 的回复:#include <iostream.h> #include <string.h>  void get_nextval(const char *T, int next[]) { 	// 求模式串T的next函数值并存入数组 next。 	int j = 0, k = -1; 	next[0] = -1; 	while ( T[j] != '\0' ) 	{ 		 		if (k == -1 || T[j] == T[k]) 		{ 			++j; ++k; 			if (T[j]!=T[k]) 				next[j] = k; 			else 				next[j] = next[k]; 			cout<<next[j]<<"  "; 		 		} 		else 		{ 			k = next[k]; 		} 	} }  int KMP(const char *Text,const char* Pattern) //const 表示函数内部不会改变这个参数的值。 { 	if( !Text||!Pattern||  Pattern[0]=='\0'  ||  Text[0]=='\0' )// 		return -1;//空指针或空串，返回-1。 	int len=0; 	const char * c=Pattern; 	while(*c++!='\0')//移动指针比移动下标快。 	{     		++len;//字符串长度。 	} 	int *next=new int[len+1]; 	get_nextval(Pattern,next);//求Pattern的next函数值 	 	int index=0,i=0,j=0; 	while(Text[i]!='\0'  && Pattern[j]!='\0' ) 	{ 		if(Text[i]== Pattern[j]) 		{ 			++i;// 继续比较后继字符 			++j; 		} 		else 		{ 			index += j-next[j]; //已匹配数 			if(next[j]!=-1) 			{ 				j=next[j];// 模式串向右移动 			} 			else 			{ 				j=0; 				++i; 			} 		} 	}//while 	 	delete []next; 	if(Pattern[j]=='\0') 		return index;// 匹配成功 	else 		return -1;       } int main()//abCabCad { 	char* text="l love youyouyour";     char*pattern="your"; 	//getNext(pattern,n);     //get_nextval(pattern,n); 	cout<<KMP(text,pattern)<<endl; 	return 0; } 仁兄，看清帖子好么？？！ 谢谢

引用 4 楼 diplopod 的回复:你可以试下用Sunday匹配算法，比KMP要简单并且速度快。  嗯，谢谢，  其实，我这项目最适合用最大公共子串解决  只不过原来用的KMP  暂时没决定换哪种更好的解决方案呢

你可以试下用Sunday匹配算法，比KMP要简单并且速度快。

引用 2 楼 xiayuanzhong 的回复:字符串的模式匹配终究是匹配字符串，匹配条件都是求相等序列，就算是int数组也都是一个流程，感觉不能怎么优化。  要说优化的话，只能从存储方式下手，位运算效率最高，比较二进制还是应该在位作为单位的环境下存储和比较。  lz把二进制转成数组，最终还要转成二进制的吧，效率多低。 谢谢！  我的原始数据就是bit流，所以不是比较将整形数据转化为二进制之后用二进制比较的  而是取到bit流之后开始匹配  因为我想着二进制串组成就只有1和0  其实，就想问，模式串的Next数组值与组成模式串的字符种类的多少是否有关系呢


Question: Linux溢出利用代码这个句子是函数还是字符串？它有内存空间吗？

引用 2 楼 ADF1230 的回复:这是将shellcode这个地址强制转化为void func()这样的函数的入口地址，这样shellcoe中的字符串就会被当做代码来执行。  thank you,对于原理还不太懂，但大概样子明白了

实际上是： typedef void(*PFN_TYPE)(); 	(*(PFN_TYPE)shellcode)();


Question: C语言操作excel表格问题

#include<stdio.h> void main() { 	char check[100]; 	char c;  	FILE *fp; 	fp=fopen("C:\\1.csv","r");  	while((c=fgetc(fp))!=EOF) 	{ 		fscanf(fp,"%s",check); 		printf("%s\n",check); 	} 	fclose(fp); }  这样反正是可以读出来了，但是还需要做很多其他工作！

对的，cvs这个也行，但是有逗号分隔符。 我说的txt是在Excel里面Ctrl+A然后Ctrl+C然后粘贴到txt里面。 这样文件相对于cvs没有逗号，操作起来更加方便。分隔符是'\t'。  txt转成xlc只要复制粘贴就行的。

引用 1 楼 xiayuanzhong 的回复:不能直接操作的，excel是封装的二进制文件。 想直接操作需要用VBA写脚本。 简介操作就是把Excel导出到txt里面操作。 那你感觉转换为csv文件的方法可以么？

听说一种解决办法是把excel另存为csv格式，这是纯文本，然后用读文件的方式读入到数组。 各路大神认为应该怎么办啊？


Question: 编写出一个从字符串到长整形的转换函数？

str[i] - '0';  就是把字符的'0' - '9' 变成数字的0-9.  转换原理, 那就是ASCII码.

引用 2 楼 max_min_ 的回复:n = n*10 + str[i] - '0';//???什么意思  后面的减法操作是ascii码的大小操作， 前面的 *10操作是十进制进位操作 同意！！！

引用 1 楼 xiayuanzhong 的回复:不用这么麻烦。 #include <stdio.h>  int main( ) {     long result; 	char source[ 20 ]; 	 	scanf( "%s", source ); 	sscanf( source, "%ld", &result ); 	printf( "%ld\n", result ); 	 	return 0; } 这个还真没想到


Question: 内存被释放了为何也可以使用？

引用 7 楼 baichi4141 的回复:[quote=引用 5 楼 aaadddzxc 的回复:] 我只是觉得奇怪 为何内存被释放了 还可以拷贝东西过去，拷贝的东西放在哪儿？哪儿可以让他放东西了？？按照道理来说 strcpy应该崩溃才对塞 。。。 你可以在任何时候访问任何内存，只要你有内存条 你拷贝的东西在哪？当然在内存条里啊 除非你申请了，否则你的访问是非法的，后果自负 当然，操作系统和杀毒软件会阻止一些访问，但那是它们阻止了你，而不是你无法访问[/quote] 恩！!

你用一个指针（a）指向了一段内存，这个内存使用完了之后，就释放了。（释放了的意思是，这段内存又交给操作系统来管理了，别的地方申请内存的时候可以申请这篇内存了。如果申请了叫做b）但是这个指针的值你并没有改变，他依然指向以前申请的内存。 所以 就会有这样潜在的危险，以前的指针a和b都指向同一片内存，他们都更该内存数据的话， 那么这片内存的数据就混乱了。离崩溃也就不远了。

引用 5 楼 aaadddzxc 的回复:我只是觉得奇怪 为何内存被释放了 还可以拷贝东西过去，拷贝的东西放在哪儿？哪儿可以让他放东西了？？按照道理来说 strcpy应该崩溃才对塞 。。。 你可以在任何时候访问任何内存，只要你有内存条 你拷贝的东西在哪？当然在内存条里啊 除非你申请了，否则你的访问是非法的，后果自负 当然，操作系统和杀毒软件会阻止一些访问，但那是它们阻止了你，而不是你无法访问

free只是作了一个释放的标记而已，其中的内容并不会被擦除。  引用 5 楼 aaadddzxc 的回复:我只是觉得奇怪 为何内存被释放了 还可以拷贝东西过去，拷贝的东西放在哪儿？哪儿可以让他放东西了？？按照道理来说 strcpy应该崩溃才对塞 。。。

free之后意味着这块内存随时可能被其它代码段使用，由于你的代码太简单，仅仅是还未发生危险而已。  引用 楼主 aaadddzxc 的回复:  #include <stdio.h> #include <stdlib.h> #include <string.h>  void Test(void) {     char *str = (char *) malloc(100);     strcpy(str,"hello");     free(str);     if(str != NULL)     {         strcpy(str,"world");         printf("%s\n",str);     } }  int main() {     Test();      return 0; }      为何？

C语言规定不能使用没有指向有效对象的指针 你使用了 然后 程序能运行 看起来好像没出错 然后你问 为什么可以使用释放了的内存  这样帮你类比一下   交通法规定不能闯红灯 你开车闯红灯之后 没被交警察觉没被罚款 然后你问 为什么开车可以闯红灯   你可以体会一下

错误代码就是错误代码，还得非给错误代码正名么？

你开车闯红灯 没被撞死  然后你问 我为什么还没死?

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

当内存free后，只是做了一个标记，但是你的指针依然指向它的地址，依然可以使用！做那个标记的作用是意味着该内存已经释放，可以被其它进程分配，也就是其它地方申请空间时，也可能申请到该内存空间。


Question: C小程序问题

试试11楼代码能不能输入汉字。

好吧这个字符的问题还是没能够解决。那么就此结束把！

//City->cityname(这个写快了) 应该是：City[i].cityname

#include <iostream> using namespace std;  struct citys{ 	int number; 	char *cityname; }City[3]={ 	{1, "fuzhou"},  	{2, "ÏÃÃÅ"},   	{4, "ÆÎÌï"}, 	};  int f(char *city) { 	int i; 	int numcity; 	for(i = 0; i < 3; i++) 	{ 		if(strcmp(City->cityname, city) == 0) 		{ 			numcity = City[i].number; 			break; 		} 	} 	return numcity; }  int main() { 	int number; 	char city[6]; 	scanf("%s", city); 	number = f(city); 	printf("%s number is 059%d", city, number); }//修改了下，现在的问题是“无法输入汉字”这是什么原因呢。

除了楼上说的字符串比较问题之外，main里定义的char *city指向随机，直接cin >> city可能会有问题吧？至少如果在我的C-FREE5.0上编译运行会被计算机阻止的。 建议将 char *city; cin >> city; 改成 char city[4]; scanf("%s",city);

= =忘记了是字符串不能用==比较了，太久没写了。我知道用string可以，只是想用char来写写看。

再一个，char*表示的字符串，不能用"="来比较是否是相等，要用字符串比较函数。

直接用string不是挺好么，为什么非要用char*

纠正一下上面的乱码： {1, "fuzhou"},   {2, "ÏÃÃÅ"},    {4, "ÆÎÌï"},   {1, "福州"},   {2, "厦门"},    {4, "莆田"},

引用 10 楼 richyhuang 的回复:不能输入汉字是因为你工程设置没有使用unicode吧 如何设置？

仅供参考#pragma warning(disable:4786) #include <iostream> #include <string> #include <map> using namespace std; int main () {     wstring ws1,ws2;      wcin.imbue(locale("chs"));     wcout.imbue(locale("chs"));     getline(wcin,ws1);     getline(wcin,ws2);     if (ws1.size()!=ws2.size()) {         wcout<<ws1<<L" 和 "<<ws2<<L" 不对应"<<endl;         return 1;     }      map<wchar_t,wchar_t> m1,m2;     int n=ws1.size();      for (int i=0;i<n;i++) {         if (m1.find(ws1[i])==m1.end() && m2.find(ws2[i])==m2.end()) {             m1[ws1[i]]=ws2[i];             m2[ws2[i]]=ws1[i];         } else {             if (m1[ws1[i]]!=ws2[i] || m2[ws2[i]]!=ws1[i]) {                 wcout<<ws1<<L" 和 "<<ws2<<L" 不对应"<<endl;                 return 1;             }         }     }     wcout<<ws1<<L" 和 "<<ws2<<L" 对应"<<endl;     return 0; }

不能输入汉字是因为你工程设置没有使用unicode吧

运行后无法输入汉字，只能处理英文。

好像没有问题，楼主运行是什么效果？


Question: 求教，怎么用C实现对一个网站的访问，要填写那个网站上的一张表并提交，似乎跟什么HTTP-TINY有关

引用 1 楼 user-3 的回复:http://freecode.com/projects/http-tiny 感谢user-3 对回答，网站有些简介，但是上面的库下载不了。。英文不大行，找不到例子，能再帮忙看看不

经典实用！  引用 1 楼 user-3 的回复:http://freecode.com/projects/http-tiny


Question: WriteConsoleOutputCharacter的问题

引用 1 楼 xiayuanzhong 的回复:最后一个DWORD要指明。 以下代码测试通过。  #include <windows.h> #include <stdio.h> #include <conio.h> #include <string.h>  int main( void ) {     COORD pos = { 10, 10 }; 	LPCSTR str = "hello,world";     DWORD buf = 0; 	     HANDLE hOut = GetStdHandle( STD_OUTPUT_HANDLE );     WriteConsoleOutputCharacterA( hOut, str, strlen( str ), pos, &buf ); 	     getch( ); 	return 0; }   我用 LPDWORD buf=new  DWORD;  也过了。


Question: 自己写了一段小小的程序，运行结果是……偶尔随机出错

复制字符串可以用strcpy,检测字符串长度可以用strlen，你的思维挺不错的，就是写的比较乱，很多细节处理地方不尽人意。多参考下经典例子有助于你养成良好的代码写作风格

引用 4 楼 u012239887 的回复:    i--;}//i的值就减少1，意味着继续向前检查 	juzi2[i+1]='\0';     for(i; i >=0; i--)//终于遇到不是空格或者制表符的了，跳出上面的while，开始自后向前复制字符 加个语句就可以了。 同意！！

果然是第二个字符串没有加结束符'\0'的原因。新手总是懵懵懂懂，想破了头都没找到的纰漏，老将们一眼就看透其中玄机。以后还得多跟各位师父们请教。谢谢！

引用 8 楼 zhao4zhong1 的回复:仅供参考#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }   思路整齐，条理清晰，赞！

输出数组未初始化

好长看起来好乱， shuru可以用gets（）+strlen（）实现，重复造轮子， shuchu可以用你那while计算出那个长度后再加个打印语句测试下，要学会测试，谁喜欢看一大坨代码，看就烦，简洁，自我测试

#include <stdio.h> #include <string.h> #define MAX 1000 //定义字符串的最大长度  int shuru(char juzi[], int len);//定义函数，输入整个字符串  int shanchu(char juzi1[], char juzi2[], int len1);//定义函数，删除字符串后部的空格和制表符   int shuru(char juzi[], int len)//输入字符，形成字符串的函数  { 	int c,i; 	for (i = 0; i < len - 2 && (c = getchar()) != EOF && c != '\n'; ++i){  		juzi[i] = c;//依次输入，形成字符串  	} 	if (c == '\n'){//遇到回车了，说明输入结束  		juzi[i] = '\0';//在字符串的最终加入结束标志  		 	} 	return i;//返回值i，表面字符串长度  }  int shanchu(char juzi1[], char juzi2[], int len)//删除字符串后部的空格和制表符的程序，juzi1是刚才输入的，juzi2是一个空的字符串，len是juzi1的长度  { 	int i = len - 1;//开始检查是否为空格或者制表符的起始点：字符串的倒数第二位  	while(juzi1[i] == ' ' || juzi1[i] == '\t'){//开始自后向前检查，如果是空格或者制表符的话……  		i--;}//i的值就减少1，意味着继续向前检查  	for(i; i >=0; i--)//终于遇到不是空格或者制表符的了，跳出上面的while，开始自后向前复制字符  		(juzi2[i] = juzi1[i]) ;//从juzi1当中依次将字符复制到juzi2中  	return 0;//复制完成，无需返回值  }  main() { 	int len; 	char juzi[MAX]; 	char juzi2[MAX] = {0}; 	len = shuru(juzi, MAX);//利用子程序求得尾部可能含空格和制表符的字符串的长度  	printf("输入的句子是:%s, 它有%d个单词。\n", juzi, len); //打印字符串  	shanchu(juzi, juzi2, len);//利用子程序获得清理掉尾部空格和制表符的字符串  	printf("整理后的句子是:%s, 它有%d个单词\n", juzi2, strlen(juzi2)) ;//打印字符串及其长度  } 你的程序的问题是juzi2结尾没有'\0'，在利用%s输出时无法确定终点，juzi2初始化时吧每个元素都初始化为0就好了，在把juzi1中的某部分复制到2中后结尾就肯定是\0了。


Question: sha1计算文件的哈希值不正常啊

3楼的大神，请问这是对文件加密得到文件吗？

这是对文件加密得到文件吗

我发现用codeblocks时就是好的。。。

sprintf格式%02x貌似不会出现乱码，检查shaFile的返回值，可能文件打开错误直接返回，那么des就是一堆未初始化的数据...

单步调试是一个方法

char *这个类型的数据一般不能理解为字符串

仅供参考： #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "advapi32.lib") #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define KEYLENGTH  0x00800000 void HandleError(char *s); //-------------------------------------------------------------------- //  These additional #define statements are required. #define ENCRYPT_ALGORITHM CALG_RC4 #define ENCRYPT_BLOCK_SIZE 8 //   Declare the function EncryptFile. The function definition //   follows main. BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword); //-------------------------------------------------------------------- //   Begin main. void main(void) {     CHAR szSource[100];     CHAR szDestination[100];     CHAR szPassword[100];     printf("Encrypt a file. \n\n");     printf("Enter the name of the file to be encrypted: ");     scanf("%s",szSource);     printf("Enter the name of the output file: ");     scanf("%s",szDestination);     printf("Enter the password:");     scanf("%s",szPassword);     //--------------------------------------------------------------------     // Call EncryptFile to do the actual encryption.     if(EncryptFile(szSource, szDestination, szPassword)) {         printf("Encryption of the file %s was a success. \n", szSource);         printf("The encrypted data is in file %s.\n",szDestination);     } else {         HandleError("Error encrypting file!");     } } // End of main //-------------------------------------------------------------------- //   Code for the function EncryptFile called by main. static BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword) //-------------------------------------------------------------------- //   Parameters passed are: //     szSource, the name of the input, a plaintext file. //     szDestination, the name of the output, an encrypted file to be //         created. //     szPassword, the password. {     //--------------------------------------------------------------------     //   Declare and initialize local variables.     FILE *hSource;     FILE *hDestination;     HCRYPTPROV hCryptProv;     HCRYPTKEY hKey;     HCRYPTHASH hHash;     PBYTE pbBuffer;     DWORD dwBlockLen;     DWORD dwBufferLen;     DWORD dwCount;     //--------------------------------------------------------------------     // Open source file.     if(hSource = fopen(szSource,"rb")) {         printf("The source plaintext file, %s, is open. \n", szSource);     } else {         HandleError("Error opening source plaintext file!");     }     //--------------------------------------------------------------------     // Open destination file.     if(hDestination = fopen(szDestination,"wb")) {         printf("Destination file %s is open. \n", szDestination);     } else {         HandleError("Error opening destination ciphertext file!");     }     //以下获得一个CSP句柄     if(CryptAcquireContext(                 &hCryptProv,                 NULL,               //NULL表示使用默认密钥容器，默认密钥容器名                 //为用户登陆名                 NULL,                 PROV_RSA_FULL,                 0)) {         printf("A cryptographic provider has been acquired. \n");     } else {         if(CryptAcquireContext(                     &hCryptProv,                     NULL,                     NULL,                     PROV_RSA_FULL,                     CRYPT_NEWKEYSET))//创建密钥容器         {             //创建密钥容器成功，并得到CSP句柄             printf("A new key container has been created.\n");         } else {             HandleError("Could not create a new key container.\n");         }     }     //--------------------------------------------------------------------     // 创建一个会话密钥（session key）     // 会话密钥也叫对称密钥，用于对称加密算法。     // （注: 一个Session是指从调用函数CryptAcquireContext到调用函数     //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程）     //--------------------------------------------------------------------     // Create a hash object.     if(CryptCreateHash(                 hCryptProv,                 CALG_MD5,                 0,                 0,                 &hHash)) {         printf("A hash object has been created. \n");     } else {         HandleError("Error during CryptCreateHash!\n");     }     //--------------------------------------------------------------------     // 用输入的密码产生一个散列     if(CryptHashData(                 hHash,                 (BYTE *)szPassword,                 strlen(szPassword),                 0)) {         printf("The password has been added to the hash. \n");     } else {         HandleError("Error during CryptHashData. \n");     }     //--------------------------------------------------------------------     // 通过散列生成会话密钥     if(CryptDeriveKey(                 hCryptProv,                 ENCRYPT_ALGORITHM,                 hHash,                 KEYLENGTH,                 &hKey)) {         printf("An encryption key is derived from the password hash. \n");     } else {         HandleError("Error during CryptDeriveKey!\n");     }     //--------------------------------------------------------------------     // Destroy the hash object.     CryptDestroyHash(hHash);     hHash = NULL;     //--------------------------------------------------------------------     //  The session key is now ready.     //--------------------------------------------------------------------     // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的，所以被加密的     // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的     // 数据长度。     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;     //--------------------------------------------------------------------     // Determine the block size. If a block cipher is used,     // it must have room for an extra block.     if(ENCRYPT_BLOCK_SIZE > 1)         dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;     else         dwBufferLen = dwBlockLen;     //--------------------------------------------------------------------     // Allocate memory.     if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {         printf("Memory has been allocated for the buffer. \n");     } else {         HandleError("Out of memory. \n");     }     //--------------------------------------------------------------------     // In a do loop, encrypt the source file and write to the source file.     do {         //--------------------------------------------------------------------         // Read up to dwBlockLen bytes from the source file.         dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);         if(ferror(hSource)) {             HandleError("Error reading plaintext!\n");         }         //--------------------------------------------------------------------         // 加密数据         if(!CryptEncrypt(                     hKey,           //密钥                     0,              //如果数据同时进行散列和加密，这里传入一个                     //散列对象                     feof(hSource),  //如果是最后一个被加密的块，输入TRUE.如果不是输.                     //入FALSE这里通过判断是否到文件尾来决定是否为                     //最后一块。                     0,              //保留                     pbBuffer,       //输入被加密数据，输出加密后的数据                     &dwCount,       //输入被加密数据实际长度，输出加密后数据长度                     dwBufferLen))   //pbBuffer的大小。         {             HandleError("Error during CryptEncrypt. \n");         }         //--------------------------------------------------------------------         // Write data to the destination file.         fwrite(pbBuffer, 1, dwCount, hDestination);         if(ferror(hDestination)) {             HandleError("Error writing ciphertext.");         }     } while(!feof(hSource));     //--------------------------------------------------------------------     //  End the do loop when the last block of the source file has been     //  read, encrypted, and written to the destination file.     //--------------------------------------------------------------------     // Close files.     if(hSource)         fclose(hSource);     if(hDestination)         fclose(hDestination);     //--------------------------------------------------------------------     // Free memory.     if(pbBuffer)         free(pbBuffer);     //--------------------------------------------------------------------     // Destroy session key.     if(hKey)         CryptDestroyKey(hKey);     //--------------------------------------------------------------------     // Destroy hash object.     if(hHash)         CryptDestroyHash(hHash);     //--------------------------------------------------------------------     // Release provider handle.     if(hCryptProv)         CryptReleaseContext(hCryptProv, 0);     return(TRUE); } // End of Encryptfile //-------------------------------------------------------------------- //  This example uses the function HandleError, a simple error //  handling function, to print an error message to the standard error //  (stderr) file and exit the program. //  For most applications, replace this function with one //  that does more extensive error reporting. void HandleError(char *s) {     fprintf(stderr,"An error occurred in running the program. \n");     fprintf(stderr,"%s\n",s);     fprintf(stderr, "Error number %x.\n", GetLastError());     fprintf(stderr, "Program terminating. \n");     exit(1); } // End of HandleError


Question: 用C语言设计一个年历系统。。。求代码

引用 3 楼 u013682489 的回复:我不会c++的，能改成c语言吗？  改了下，变量定义没有完全按照C语言的语法规则来。 你把文件命名为*.cpp后缀的即可。不要命名成*.c的   //日历C语言版本   作者QQ 93506222 于2014.2.17 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h>  //是否闰年 #define IS_LEAP_YEAR(iYear) (((iYear) % 100 == 0) ? ((iYear) % 400 == 0) : ((iYear) % 4 == 0))  int Calendar(int iYear, int iMonth);  void main() { 	//获取今天的日期 	struct tm *today; 	time_t ltime; 	time(<ime); 	today = localtime(<ime);  //	printf("%d-%02d-%02d %02d:%02d:%02d\n星期%d 当年第%d天\n",  //		today->tm_year + 1900, today->tm_mon + 1, today->tm_mday,  //		today->tm_hour, today->tm_min, today->tm_sec, today->tm_wday, today->tm_yday);  	int iYear = today->tm_year + 1900; 	int iMonth = today->tm_mon + 1;  	do { 		system("cls");  		int ch = Calendar(iYear, iMonth); 		if (ch == 27) break;  		switch (ch) 		{ 		case 75:	//<-- 			iYear--; 			break; 		case 77:	//--> 			iYear++; 			break; 		case 80:	//下箭头 			iMonth++; 			if (iMonth > 12) 			{ 				iYear++; 				iMonth = 1; 			} 			break; 		case 72:	//上箭头 			iMonth--; 			if (iMonth < 1) 			{ 				iYear--; 				iMonth = 12; 			} 			break; 		case 71:	//Home 			iYear = today->tm_year + 1900; 			iMonth = today->tm_mon + 1; 			break; 		} 	} while (1); }  //显示给定年月的日历 //返回值为获取的用户按键, 以确定下一步的操作 int Calendar(int iYear, int iMonth) { 	int i, j, iDays;  	//初始化数组w的值为1至31 	int w[31]; 	for (i = 0; i < 31; i++) w[i] = i+1; 	 	//获取本月天数于iDays中 	switch (iMonth) 	{ 	case 1: case 3: case 5: case 7: case 8: case 10: case 12: 		iDays = 31; 		break; 	case 4: case 6: case 9: case 11: 		iDays = 30; 		break; 	case 2: 		iDays = IS_LEAP_YEAR(iYear) ? 29 : 28; 		break; 	} 	 	//显示 日历头 	printf("\n    %d年%d月 日历\n\n", iYear, iMonth); 	printf(" 日 一 二 三 四 五 六\n"); 	printf("----------------------\n"); 	  	//获取参数指定年月的第一天是周几。保存在firstday.tm_wday中 	struct tm firstday = {0}; 	firstday.tm_year = iYear - 1900; 	firstday.tm_mon = iMonth - 1; 	firstday.tm_mday = 1;  	time_t ltime; 	ltime = mktime(&firstday);  	firstday = *localtime(<ime);  	//处理1号前的留空 	j = firstday.tm_wday;	//周几 	for (i = 0; i < j; i++) 	{ 		printf("   ");	//3个空格 	} 	 	//显示日历正文 	for (i = 0; i < iDays; i++) 	{ 		printf("%3d", w[i]); 		if (++j == 7) 		{ 			printf("\n");//逢七换行 			j = 0; 		} 	} 	if (j != 0) printf("\n");   	//获取今天日期 	time(<ime); 	struct tm today = *localtime(<ime);  	//显示 日历尾 	printf("----------------------\n"); 	printf("今天是: %d年%d月%d日\n\n", today.tm_year + 1900, today.tm_mon + 1, today.tm_mday);  	printf("←: 上一年  →: 下一年\n"); 	printf("↑: 上一月  ↓: 下一月\n\n"); 	printf("Home: 今天  Esc: 退出\n");  	//获取用户按键 (不用按回车立即返回) 	fflush(stdin); 	clearerr(stdin);  	int c = getch(); 	if (c == 0xe0 || c == 0) c = getch();  	return c; }

《C语言课程设计案例精编》里有，当当网。

我需要的是c语言

下载链接： https://www.kernel.org/pub/linux/utils/util-linux/v2.18/

cal 20                                 20         January               February                 March Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa     1  2  3  4  5  6                1  2  3                   1  2  7  8  9 10 11 12 13    4  5  6  7  8  9 10    3  4  5  6  7  8  9 14 15 16 17 18 19 20   11 12 13 14 15 16 17   10 11 12 13 14 15 16 21 22 23 24 25 26 27   18 19 20 21 22 23 24   17 18 19 20 21 22 23 28 29 30 31            25 26 27 28 29         24 25 26 27 28 29 30                                               31         April                   May                   June Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa     1  2  3  4  5  6             1  2  3  4                      1  7  8  9 10 11 12 13    5  6  7  8  9 10 11    2  3  4  5  6  7  8 14 15 16 17 18 19 20   12 13 14 15 16 17 18    9 10 11 12 13 14 15 21 22 23 24 25 26 27   19 20 21 22 23 24 25   16 17 18 19 20 21 22 28 29 30               26 27 28 29 30 31      23 24 25 26 27 28 29                                               30         July                  August                September Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa     1  2  3  4  5  6                1  2  3    1  2  3  4  5  6  7  7  8  9 10 11 12 13    4  5  6  7  8  9 10    8  9 10 11 12 13 14 14 15 16 17 18 19 20   11 12 13 14 15 16 17   15 16 17 18 19 20 21 21 22 23 24 25 26 27   18 19 20 21 22 23 24   22 23 24 25 26 27 28 28 29 30 31            25 26 27 28 29 30 31   29 30         October               November               December Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa        1  2  3  4  5                   1  2    1  2  3  4  5  6  7  6  7  8  9 10 11 12    3  4  5  6  7  8  9    8  9 10 11 12 13 14 13 14 15 16 17 18 19   10 11 12 13 14 15 16   15 16 17 18 19 20 21 20 21 22 23 24 25 26   17 18 19 20 21 22 23   22 23 24 25 26 27 28 27 28 29 30 31         24 25 26 27 28 29 30   29 30 31  linux有cal这个工具的， 属于这个包util-linux-ng

我不会c++的，能改成c语言吗？

仅供参考#include <stdio.h> #include <string.h> #include <time.h> struct tm st; time_t tt; char timstr[40]; char tmpbuf[128]; char c; int t; int AP() {     if ('P'==c || 'p'==c) {st.tm_hour+=12;return 1;}     if ('A'==c || 'a'==c)                 return 1;                                           return 0; } int dtparse() {     if (7==sscanf(timstr,"%d/%d/%4d %d:%d:%d %c",&st.tm_mday,&st.tm_mon ,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec,&c)) if (AP()) goto STEP2;     if (6==sscanf(timstr,"%d/%d/%4d %d:%d%c"    ,&st.tm_mday,&st.tm_mon ,&st.tm_year,&st.tm_hour,&st.tm_min           ,&c)) if (AP()) goto STEP1;     if (6==sscanf(timstr,"%4d/%d/%d %d:%d %c"   ,&st.tm_year,&st.tm_mon ,&st.tm_mday,&st.tm_hour,&st.tm_min           ,&c)) if (AP()) goto STEP1;     if (5==sscanf(timstr,"%d.%d.%4d %d:%d"      ,&st.tm_mon ,&st.tm_mday,&st.tm_year,&st.tm_hour,&st.tm_min              ))           goto STEP1;     if (6==sscanf(timstr,"%4d-%d-%d %d:%d:%d"   ,&st.tm_year,&st.tm_mon ,&st.tm_mday,&st.tm_hour,&st.tm_min,&st.tm_sec   ))           goto STEP2; STEP1:     st.tm_sec=0; STEP2:     st.tm_year-=1900;     if (st.tm_mon>12) {t=st.tm_mon;st.tm_mon=st.tm_mday;st.tm_mday=t;}     st.tm_mon-=1;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S",localtime(&tt));         return 1;     } else {         printf("[%s] is Invalid time string!\n",timstr);         return 0;     } } int main() {     strcpy(timstr,"10.01.2012 15:43"        );if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     strcpy(timstr,"8/11/2006 11:10AM"       );if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     strcpy(timstr,"2006/10/31 04:50 PM"     );if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     strcpy(timstr,"1/6/2010 5:20:12 PM"     );if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     strcpy(timstr,"13/12/2012 11:16:17 a.m.");if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     strcpy(timstr,"2013-06-08 09:56:59"     );if (dtparse()) printf("[%s] is [%s]\n",timstr,tmpbuf);     return 0; } //[10.01.2012 15:43] is [2012-10-01 15:43:00] //[8/11/2006 11:10AM] is [2006-11-08 11:10:00] //[2006/10/31 04:50 PM] is [2006-10-31 16:50:00] //[1/6/2010 5:20:12 PM] is [2010-06-01 17:20:12] //[13/12/2012 11:16:17 a.m.] is [2012-12-13 11:16:17] //[2013-06-08 09:56:59] is [2013-06-08 09:56:59] //

这是C++版本的，将其中的C++语法改成C语言的即可。  //日历   作者QQ 93506222 于2012.9.22 #include <iostream> using namespace std;  #include <iomanip> #include <windows.h> #include <conio.h>  //是否闰年 #define IS_LEAP_YEAR(iYear) (((iYear) % 100 == 0) ? ((iYear) % 400 == 0) : ((iYear) % 4 == 0))  int Calendar(int iYear, int iMonth);  void main() { 	//获取今天的日期 	SYSTEMTIME tm; 	::GetLocalTime(&tm); 	int iYear = tm.wYear; 	int iMonth = tm.wMonth;  	do { 		system("cls");  		int ch = Calendar(iYear, iMonth); 		if (ch == 27) break;  		switch (ch) 		{ 		case 75:	//<-- 			iYear--; 			break; 		case 77:	//--> 			iYear++; 			break; 		case 80:	//下箭头 			iMonth++; 			if (iMonth > 12) 			{ 				iYear++; 				iMonth = 1; 			} 			break; 		case 72:	//上箭头 			iMonth--; 			if (iMonth < 1) 			{ 				iYear--; 				iMonth = 12; 			} 			break; 		case 71:	//Home 			iYear = tm.wYear; 			iMonth = tm.wMonth; 			break; 		} 	} while (1); }  //显示给定年月的日历 //返回值为获取的用户按键, 以确定下一步的操作 int Calendar(int iYear, int iMonth) { 	int i, j, iDays;  	//初始化数组w的值为1至31 	int w[31]; 	for (i = 0; i < 31; i++) w[i] = i+1; 	 	//获取今天的日期 	SYSTEMTIME tmToday; 	::GetLocalTime(&tmToday);  	//获取参数指定年月的第一天是周几。保存在tm1.wDayOfWeek中 	SYSTEMTIME tm1 = tmToday; 	tm1.wYear = iYear; 	tm1.wMonth = iMonth; 	tm1.wDay = 1; 	::SetLocalTime(&tm1); 	::GetLocalTime(&tm1);  	::SetLocalTime(&tmToday);  	//获取本月天数于iDays中 	switch (tm1.wMonth) 	{ 	case 1: case 3: case 5: case 7: case 8: case 10: case 12: 		iDays = 31; 		break; 	case 4: case 6: case 9: case 11: 		iDays = 30; 		break; 	case 2: 		iDays = IS_LEAP_YEAR(tm1.wYear) ? 29 : 28; 		break; 	} 	 	//显示 日历头 	cout << endl << "    " << tm1.wYear << "年" << tm1.wMonth << "月 日历" << endl << endl; 	cout << " 日 一 二 三 四 五 六" << endl; 	cout << "----------------------" << endl; 	 	//处理1号前的留空 	j = tm1.wDayOfWeek; 	for (i = 0; i < j; i++) 	{ 		cout << "   ";	//3个空格 	} 	 	//显示日历正文 	for (i = 0; i < iDays; i++) 	{ 		cout << setw(3) << w[i]; 		if (++j == 7) 		{ 			cout << endl;	//逢七换行 			j = 0; 		} 	} 	if (j != 0) cout << endl;  	//显示 日历尾 	cout << "----------------------" << endl; 	cout << "今天是: " << tmToday.wYear << "年" << tmToday.wMonth << "月" << tmToday.wDay << "日" << endl << endl ;  	cout << "←: 上一年  →: 下一年" << endl; 	cout << "↑: 上一月  ↓: 下一月" << endl << endl; 	cout << "Home: 今天  Esc: 退出" << endl;  	//获取用户按键 (不用按回车立即返回) 	fflush(stdin); 	clearerr(stdin);  	int c = getch(); 	if (c == 0xe0 || c == 0) c = getch();  	return c; }


Question: 谭浩强《c语言程序设计》P82页第一题第一问的答案（在《学习辅导》上）是不是给出的结果是错的

谢谢楼上3个老兄

引用 楼主 zhy934453950 的回复:传图太慢。。。。5张高清图。。。累死了。。。直接给百度知道的问题链接：http://zhidao.baidu.com/question/552031159438999972.html?quesup2&oldq=1 知道逻辑过程就行了，计算机一涉及到浮点数问题就大了，你们搞惯了的vc或者x86、x64体系可以完美的得出你想要的结果，换了平台还得真心掂量掂量  个人原则，非x86、x64平台 一切涉及浮点的运算用位移来计算，用多个整数类型来存放不同位置的值

引用 1 楼 user-3 的回复:1000元一次性存5年，如果利息为5.85%,那么到期后总共钱为1000+1000*0.0585*5,所以他前面 的描述是对的，但是后面那个式子应该是笔误了。  这个在银行存过钱的都知道。你应该是对的。 上面说的有理。 另外需要说的是，lz的代码上面定义的 p1 和 r 都是double，但最后输出时却是 %f ，当然，这是可以运行的，但这样不好，应该为 %lf， 不然会有警告，而在写一些很长的代码时，就有可能造成错误，所以需要注意


Question: ********求指点，Unix记录锁使用问题*********

引用 1 楼 Idle_Cloud 的回复:这个的用法你要注意了。flock文件锁是进程锁，进程内拿到锁了，可以继续随便锁，进程退出就没锁了，所以你查看自己的锁是查看不到了，但是你起另外一个进程去查看就可以查看到锁。 原来如此。


Question: 函数小问题

引用 3 楼 cai5301 的回复:这只是声明对吧，具体的定义还是要写清标识符int max(int a, int b){...}? 是的

你那句话是一个函数原型，表示一个传入2个整形数据，在函数内部进行某些操作，然后传回一个整型数据，即函数值为返回的值，调用参照楼上即可

int a = 20; int b = 10; int c;  c = max(a, b);   引用 楼主 cai5301 的回复:int max(int , int ); 这样子形式的函数要怎么调用？？


Question: c求助  如何能在一组单词中挑选出到含有某个字母的单词？

算法查找。。。 实现很简单，效率问题

1.图个方便的话用string的操作函数 2.自己动手写算法实现

/*在一组单词中挑选出到含有某个字母的单 词并且按照单词含有该字母的数量排序*/ #include<stdio.h> #include<string.h> #include<ctype.h> #define MAX 20  int main(void) { 	void copym2n(char *, char *, int, int); 	int countch(char *, char);  	char s[MAX] = {0}, ch = 0; 	char p[MAX][MAX] = {0}; 	char tem[MAX]; 	int i, j, k, l, b, e, flag = 0, count = 0;  	printf("Please input a string:"); 	gets(s); 	printf("Please input a word:"); 	scanf("%c", &ch);  	l = strlen(s);  	for(i=k=b=e=0;i<=l;i++)//将字符串中的单词存放到二维数组中 	{ 		if(i && !isalpha(s[i])) 		{ 			e = i - 1; 			flag = 1; 			copym2n(p[k++], s, b, e); 		} 		if(flag) 		{ 			b = i==0 ? 0 : i + 1; 			flag = 0; 		} 	} 	for(i=j=0;i<k;i++)//剔除不含ch的字符串 		if(countch(p[i], ch)!=0) 			strcpy(p[j++], p[i]); 	 	k = j; 	 	for(i=0;i<k;i++)//比较法排序 		for(j=i+1;j<k;j++) 			if(countch(p[i], ch)<countch(p[j], ch)) 			{ 				strcpy(tem, p[i]); 				strcpy(p[i], p[j]); 				strcpy(p[j], tem); 			} 	for(i=0;i<k;i++) 		printf("%s\n", p[i]); }  //把字符串2中s[m]到s[n]的元素复制到字符串1中 void copym2n(char *p1, char *p2, int m, int n) { 	int i; 	for(p2 +=m,i=0;i<=n-m;i++) 		*(p1 + i) = *p2++; 	*(p1 + i) = 0; }  int countch(char *s, char ch)//返回s数组中含有ch的数量 { 	int i, count = 0; 	for(i=0;i<(int)strlen(s);i++) 		if(*(s+i)==ch) 			count++; 	return count; } 随便写的，只供参考，还不知道有没有bug，如有问题，烦请更正（^_^）

linux直接用awk

查找strchr() & 比较strcmp() & 排序qsort()


Question: 问下各位，这个程序是按什么顺行执行的，我一直没弄懂。不按ctrl+c什么也打印不出来，按下ctrl+c能打印出Faild to restore SIGINT　3

在prinf后面加个 fflush(stdout);

我发现问题所在了，比如下面列出的代码#include<stdio.h> int main(){ printf("aaaaaaaaaaaaaaaaaaaaaa\n"); printf("vvvvvvvvvvvvvvvvvvv\n"); while(1); printf("1111111111111111111"); return 0; } 在VC上可以输出aaaaaaaaaaaaaaaaaaaaaa  vvvvvvvvvvvvvvvvvvv 然后进入死循环，但是在ubuntu命令行中什么也输出不了就进入死循环了，具体为什么我也不知道

程序运行后为什么main下面一行printf("000000000000000000000");都没打印出来，难道和我用的系统有关系？

man 2 sigaction

从main()函数那里开始的，一步一步的走，面向过程

按什么顺序？ 直接debug不就看到了  一步一步的


Question: 递归遍历目录中的文件（包括子文件夹里的文件）的一个问题

//增加一个参数， 可以用CStringList吗？  void dirSearch( const char * file_name，CStringList &NameList ) {    _findfirst( &handle, &file_info );    if( -1 == handle )    {        printf( "....\n" );        return 0;    }           else     {        if( strcmp( file_info.name,  "." ) && strcmp( file_info.name, ".." ) )        {            ...            dirSearch( ... )         }          // 这里就是找到了完整图片的路径，但是由于是递归遍历，所以我没想到办法        // 怎么把这些图片的路径在接口外部传出来,只能在这个接口里进行操作，        // 比如加载显示图片        // 我现在想做的就是如何能在接口外面操作文件夹里的每一张图片        else        {            NameList->AddTail(file_info.name);                 }      } }

用容器，妥妥滴，最灵活。除此之外，你可以传入一个function指针，或者一个functor，这个或许看起来貌似比较高端大气上档次~

有一个vector把结果保存起来，做为参数传出来

引用 4 楼 a130098300 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。 忘了说了，是基于Windows的...[/quote] 我说的就是windows，如果是linux，就得用ls命令而不是dir命令了。

我看楼主可以把它放到一个容器里面去吧, 就可以等这个函数结束了以后再处理

引用 1 楼 zhao4zhong1 的回复:system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。 忘了说了，是基于Windows的...


Question: Socket读取消息，一般有哪些方法可以判定读取了一个完整的消息？

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://topic.csdn.net/u/20120210/09/51109ed0-07b9-41f2-b487-a51597f2ca01.html

LZ你说的这个问题，叫做“数据链路层帧格式” 通常的方法可以分成4类: 1. 字符计数法 2. 含字节填充的分界符法 3. 含位填充的分界标志法 4. 物理层编码违例法  具体的信息你可以google一下

要么固定包长, 要么加标记? 常用的也就这些方法了.

你这个貌似没得偷懒，用2或者3的方法。个人感觉3更好，我们都是用3的方法。

我知道的就是2和3，不限socket，以消息为单位的通信都是 2通常应该是一段特定格式的数据，某个位置是后面有效数据的长度 3通常应该是消息的开头和结尾都是特定的数据

最好头里带长度，不然你就得百般小心消息内容里会不会有终结符。然后，可以吧消息的checksumm和消息一起发过去，接收端验证checksum。当然，这要消耗资源。

包头 + 消息(包头中带有消息长度)


Question: API 怎么关联图片文件

在cmd窗口中输入以下命令 assoc /? ftype /?


Question: struct指针类型的问题

引用 2 楼 steedhorse 的回复:你的struct本身是匿名的，它只有一个typedef出来的名字叫LinkNode。 既然LinkNode已经是一个类型名，为什么定义成员变量的时候还使用“struct”？  多谢，懂了。

引用 1 楼 u012210441 的回复:因为你用tyepedef定义了一个新类型，后面用到它是不用struct的  多谢，懂了。

thank all， 因为我使用的是，typedef  struct名称，所以会出现警告。多谢多谢各位。

typedef struct _LinkNode {     DataType data;     struct _LinkNode* next;   }LinkNode;  一般是这样写的，注意与你的区别。

struct LinkNode {     DataType data;     struct LinkNode* next;   };

引用 1 楼 u012210441 的回复:因为你用tyepedef定义了一个新类型，后面用到它是不用struct的  嗯，也没有用到，只是在next赋值的时候出现的警告，我把代码贴全了一些。 帮我看看，完全不知道怎么避免这个警告。

引用 2 楼 steedhorse 的回复:你的struct本身是匿名的，它只有一个typedef出来的名字叫LinkNode。 既然LinkNode已经是一个类型名，为什么定义成员变量的时候还使用“struct”？  我再贴的全一些。   ... LinkNode* tempNode = charsList;  	while(tempNode->data != '\n') 	{ 		tempNode->next = (LinkNode*) malloc (sizeof(LinkNode)); 		tempNode = tempNode->next;  		int tempData = getchar(); 		tempNode->data = tempData; 	}  	tempNode->next = NULL;   正如你所说的，我并没有在使用过程中用 struct ListNode* 来进行变量声明，但由于结构体中的 变量声明为struct ListNode*, 所以next指针赋值时会出现警告。

因为你用tyepedef定义了一个新类型，后面用到它是不用struct的


Question: 正则表达式问题

参考这个 http://blog.sbw.so/Article/index/title/C++%20%E4%BD%BF%E7%94%A8%20Boost%20%E5%BA%93%E8%BF%9B%E8%A1%8C%E6%AD%A3%E5%88%99%E5%8C%B9%E9%85%8D.html


Question: 简单的结构体程序运行出错 求助！

你的代码只是相当于int a;然后就输出a的值，肯定是不行啊

struct s1 {     char a;     int b[2];     double c; }*p; 只是定义了数据类型，没有定义内存变量，p不是变量，是类型

月经贴    .

哇，一觉醒来有这么多好心人啊，我要仔细看看，谢谢大伙！！！

#include <stdio.h> #include <stdlib.h>  struct s1 {     char a;     int b[2];     double c; } s,*p;  int main() {     p=&s;     p->a = 'c';     printf("%c", p->a);     return 0; }

p 没有初始化，用p=(s1*)malloc(sizeof(s1)); ps:老用c++，写法上可能有错误

#include <stdio.h> #include <stdlib.h>  struct s1 {     char a;     int b[2];     double c; }*p;  int main() {     p=(struct s1*)malloc(sizeof(struct s1));//要分配内存     p->a = 'c';     printf("%c", p->a);     free (p);     return 0; }

没有定义变量，还没有地址呢


Question: 问一个内存方面的问题

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 10 楼 iamkconghua 的回复:楼上正解。 建议lz看看五大内存的知识。 全局静态区的内存是由系统分配，也是由系统释放的，程序员干预不了。  我懂了，只能放到堆栈里才能做到这效果

引用 楼主 was595 的回复:假如我定义一个全局数组和静态数组，我想在不用malloc函数，对这两个数组做释放内存的功能，然后把这两个数组指针指NULL，这两个数组在内存里还会被我占用吗？ 全局数组和静态数组不需要使用malloc和free来处理，其生命周期就是你的程序的生命周期 我是这么理解的

全局数组和静态数组是存放在静态存储区的，用free肯定不能释放，只能等程序结束时被系统销毁，其他的函数或原理还没学

引用 2 楼 was595 的回复:[quote=引用 1 楼 baichi4141 的回复:] 你只能free由你malloc的内存  那像我所说的，假如我把已经定义的全局数组和静态数组，两个数组都指向NULL，那这两个数组的原本空间还会被我占用吗？[/quote]  会占用的，只有free.

要分清堆栈。

会占用  程序退出的时候被销毁

引用 3 楼 was595 的回复:[quote=引用 2 楼 was595 的回复:] 那像我所说的，假如我把已经定义的全局数组和静态数组，两个数组都指向NULL，那这两个数组的原本空间还会被我占用吗？ 有一句说错了，是两个数组的首指针都指向NULL[/quote] 把指向数组的指针指向其他地方，对数组一点影响都没有 至于“做释放内存的功能”，我只能说，请不要空想

我想在不用malloc函数，对这两个数组做释放内存的功能  不明白什么意思，只要有malloc，就必须free 如果数组不是malloc的，那free它做什么

引用 1 楼 baichi4141 的回复:你只能free由你malloc的内存 引用 2 楼 was595 的回复:[quote=引用 1 楼 baichi4141 的回复:] 你只能free由你malloc的内存  那像我所说的，假如我把已经定义的全局数组和静态数组，两个数组都指向NULL，那这两个数组的原本空间还会被我占用吗？[/quote]  有一句说错了，是两个数组的首指针都指向NULL

引用 1 楼 baichi4141 的回复:你只能free由你malloc的内存  那像我所说的，假如我把已经定义的全局数组和静态数组，两个数组都指向NULL，那这两个数组的原本空间还会被我占用吗？

你只能free由你malloc的内存


Question: C语言变量定义的问题

可能是第二种好，但是我不知道原因啊。第一种说会重复定义，但是我在C语言里试第一种不会报错。求大侠解释原因啊、。。、、。、。

看了楼上各位的解释，我自己也有一些启发

我觉得这个看个人喜欢吧。

引用 11 楼 zengyaowu1988 的回复:楼上我试过了，在头文件中定义的话不会出错，我用C语言写的。 我疑惑的是头文件里面不能赋值，这样的话不知道能不能保证flag的初始值为0.因为我可能不修改这个flag的值，直接调用底层那个接口的。 C语言不知道，C++里用extern在头文件里声明，在cpp里声明加定义，就能保证它的初始化。当然cpp里的定义必须只有一次 比如  //head.h #ifndef __HEAD__H__ #define __HEAD__H__ extern int a; #endif  //source.cpp #include "head.h" int a = 0;  这样在其他任何cpp或h文件中包含head.h，都能保证有那么一个int型变量a，并且被初始化为0. 当然head.h和source.cpp必须被加入工程中。

第二种方法，毫无疑问

引用 7 楼 buyong 的回复:我觉得第一种好。 编译问题，只要在头文件加上 #ifndef *** #define *** #endif

第一种就是错误的 如果头文件多include一次就会造成变量重复定义。

引用 9 楼 zengyaowu1988 的回复:我觉得这位大哥说得对啊。 我觉得第一种好。 编译问题，只要在头文件加上 #ifndef *** #define *** #endif 其他人都说会重定义。。。到底哪个比较好啊，求大神，， 加上header guard确实不会有重定义，如果保证C中只声明不定义相当于使用extern这条规则，那第一种和第二种没区别。但若没那条规则，即使不重复声明，也会有问题。因为两个cpp都包含同一个头文件，那么这两个cpp都会有同一个变量的2个声明，这样还是会造成重复声明，具体是直接报错，还是导致程序里出现两个同名变量，这得你自己去试，但是加了extern就能保证整个程序里就一个变量，不会有副本

提倡用第二种方法

C++提倡变量定义紧挨在使用之前。

第一种明显会造成重复定义。 最好采用第二种。  也可以这样： 在第一个.c中 定义 int flag = 0； 然后再头文件中 声明 extern int flag； 然后在第二个.c中包含头文件，直接使用flag变量 ...... 然后在第N个.c中包含头文件，使用flag变量

第一种方法会出现重复定义的吧 在编译的时候，是将.c文件中的.h文件内容拷贝到.c文件中。所以，第一种使用方法就会造成两个.c文件中定义了同名的变量，导致重复定义的问题

楼上正解。 最好别用第一种方法，变量定义在头文件中，很容易在一个文件中被包含多次，从而造成变量重定义。

第一种会重定义 在头文件声明为 extern int iflag；  再选择一个.c文件定义变量 int iflag；

这两种方法本质上是等价的，第二种更明确因此更好 在C语言中，如果你定义int变量的时候未赋值，则该定义也可以被看做一个extern声明


Question: c语言中，两个形式相同的“结构数组”可以直接相互赋值吗？

引用 9 楼 u013595256 的回复:数组名只是地址，是指针型常量，常量当然不能进行赋值很有道理，谢谢。主要是忽略了结构数组也是数组，数组的性质应该对它同样适用。而是老想着机构体这一块了。

结构体只能初始化一次，整体赋值没意义吧！

数组名只是地址，是指针型常量，常量当然不能进行赋值

引用 7 楼 baichi4141 的回复:数组除定义外不能整体操作 绝大部分使用数组名的情形，实际上使用的都是数组名隐式转化的指向数组首元素的指针，包括最常见的[]操作符 跟结构体不结构体一点关系都没有一语中的！非常感谢！

好的，心里有底了，谢谢

不可以,这是为保持C语言的纯洁性

引用 3 楼 derekrose 的回复:编译器不是标准我用的是vs2010.编译时这句boy2=boy有问题。所以我才想是不是即使两个结构数组变量形式相同，但是还是不能直接相互赋值。

编译器不是标准

引用 1 楼 user-6 的回复:为啥懒到不肯去翻自己的教材？我翻了啊，书上只说结构变量可以直接相互赋值，但是结构数组变量没有明确的说明。所以写了上面的函数编译了一下，不行。但是心里没底，所以才到这里确定一下。

为啥懒到不肯去翻自己的教材？


Question: 程序思路是不是有问题~~求指点~~

不客气 还有就是lz注意代码尽量要规范

不用那个draw变量，条件改为invest > 0 draw += 10;改为invest -= 10.0; 结果是21年

引用 4 楼 u012421456 的回复:lz你的思路不对吧，每年减去10万后总数减小，下一年的增长就变小了，若按你的思路，岂不是不变？这不对吧！ 代码应该是这样吧： # include <stdio.h>  int main(void) {     double invest = 100.0,draw = 10.0;     int i = 0; 	     while(invest > 0)     {		         invest += invest*0.08; 		invest -=draw;         i++;     }     printf("%d\n", i); 	     return 0; }  最终结果是21年谢谢~~我这一直蒙圈了~~幸亏有大侠指点啊~~

可能是浮点比较出了问题。应该了解到浮点数的表达是有误差的，比较方法也不同于整型。  invest > draw 可能应该改成： invest >= draw  最后还应该判断: invest与draw的差值，如果大于0应该将i再加1。  个人建议，仅供参考。

int deposits = 10000; unsigned int times = 0;  while(deposits > 0) {     deposits *= 108;     deposits -= 1000;     ++times; }


Question: C语言头文件

是报错还是给出警告？

LISTCS_ToPre( &Cursor ); 这句是强转一下类型试试，LISTCS_ToPre((PLISTCS)&Cursor);

符号引用无法解析，这可能这是一个link error 请帖出整个.c和.h文件。

虽然说我问题的焦点不在这个地方。。。 LISTCS_Pre和LISTCS_ToPre的意义不一样。。。 一个是吧Cursor修改，一个是获取修改后的结果。。。 所以得两个函数。。。 既然这样而且LISTCS_Pre就这么几行，我当然是用inline修饰提速了。。 而且我看的资料说只有在inline函数的代码长度较长，或者包含循环语句，复杂的开关语句等的时候才会被忽略。。。 我这里就一个函数调用。。。应该不会被忽略才对。。。

引用 4 楼 l383137093 的回复:呃?为什么呢？ 没说inline函数中不能调用函数吧。。。 inline 指示对编译器来说只是一个建议，编译器可以选择忽略  inline LISTCS LISTCS_Pre( LISTCS Cursor ) {     LISTCS_ToPre( &Cursor );     return Cursor; } //这样的调用，inline意义不大，直接调用那个LISTCS_ToPre不就可以了

呃?为什么呢？ 没说inline函数中不能调用函数吧。。。

这样调用估计已经不是inline，也没必要用inline了

呃。。。工程里面只有一份.c文件，就只有 #include "list.h" int main() {     return 0; } list.h和list.c都在改工程目录下但为被包含进该工程 然后编译。。 在list.c的这里报错，提示undefined reference to LISTCS_ToPre inline LISTCS LISTCS_Pre( LISTCS Cursor ) {     LISTCS_ToPre( &Cursor );     return Cursor; } 但是在这部分之前已经声明了void LISTCS_ToPre( PLISTCS Cursor );

直接贴代码会更好


Question: 菜鸟想知道如何正确学习汇编语言与C/C++语言，请指教。

引用 楼主 JackYau 的回复:主要是想学习C/C++语言，在学校期间只看完谭浩强的C语言程序设计最基础的书，想深入学习C/C++，运用汇编语言能制作出软件Keygen，希望老鸟们能提供学习的方向与书籍，最好能提供一个下载URL，非常感谢。  教学书藉要包括汇编语言与C/C++的教学书藉，非常感谢。  看《see mips run linux》 讨厌一来就x86汇编，对于c语言基础一般和操作系统以及计算机组成原理相关内容都没什么概念的人无疑绝大多数内容是天书，学习汇编不是让你能够写汇编程序，而是让你认识到一种cpu是如何工作的。

C语言视频教程  比较基础和系统，可以去看看。

引用 5 楼 JackYau 的回复:那请教一下学好C/C++语言有什么好的书藉可以一步一步深入呢？目前我只看了谭浩强老师的那本C语言程序设计，记得原来还有一本书比我学过的这本更深入一些，但是不知道在哪里有下载。  请各位老师多给些指点吧。。详细述说一下有哪些好的教程，以及如何学习，包括使用哪些编辑器来学习等等。谢谢。我的学习过程是谭浩强那本->c primer plus->c 陷阱与缺陷->c和指针->c专家编程，这是我看的数，真的把c学好最重要的是多练习，多看别人的代码，希望对你有帮助

主要还是自己理解，这个时候自学很重要。我就是自学的特别是最开始的一个月差一点把我逼疯了

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）

非常感谢以上老师的耐心解答,简单介绍一下自己吧，CCNA目前做网管与DataCenter管理，早期学习计算机应用，然后转为计算机网络专业，毕业后一直从事网络工作十二年，学无止境，因为工作中经常需要使用很多软件，曾经也购买过一些正版软件，但是无奈钱太少，实在买不起所有自己想要的软件，所以下载了国外的0day组织破解含有keygen的软件，感觉确实非常强大，想向逆向工程师的方向学习一些，能够在平时工作中对一些软件进行破解或者自己构造keygen，不知道难度有多大，请各位老师多多说明，谢谢。  学C是在大学里由教授教的，效果很好，但是没有深入，只学了最基础的那本，说到指针后就没深入进去了，感觉很可惜。汇编语言没系统学过。不知道再深入C语言甚至C++，要如何入手。感谢你们的意见，我会尽力学习。毕竟现在年龄大多了。

引用 5 楼 JackYau 的回复:那请教一下学好C/C++语言有什么好的书藉可以一步一步深入呢？目前我只看了谭浩强老师的那本C语言程序设计，记得原来还有一本书比我学过的这本更深入一些，但是不知道在哪里有下载。  请各位老师多给些指点吧。。详细述说一下有哪些好的教程，以及如何学习，包括使用哪些编辑器来学习等等。谢谢。 一搜一大把，http://bbs.csdn.net/topics/390090123

王爽汇编和琢石成器,学习汇编的利器

进入百度，搜索中输入：  Win32ASM Tutorial Resource Kit v1.0 site:pan.baidu.com  可得之

http://www.pediy.com/document.htm 其中那本"Win32ASM Tutorial Resource Kit v1.0"

进入百度，搜索中输入：  C语言 site:pan.baidu.com


Question: 能否告知我做的这个通讯录管理系统为什么插入联系人时程序崩溃了？

插入联系人的时候有没有地址非法使用，越界等可能性呢？

引用 4 楼 sanredfish 的回复:for(i=0;i<countperson;i++) {     if(strcmp(d,m[i].name)==0)/*找符合插入的点*/     {          for(j=countperson-1;j>=i;j++)/*从最后一个联系人开始依次后移一个位置*/          {               memcpy(&(m[j+1]),&(m[j]),sizeof(Maillist));          }     } } 你的循环条件，初始条件是最后一个联系人，循环条件是后一个联系人，限制条件是大于i，肯定溢出。应该是j-- 另外你的循环中没有退出条件，效果就是如果有两个人同名，通信录将被移两次，然后你的拷贝是定点的，导致重复人记录多一，后面的人可能会被覆盖掉。在进行一次移位之后应有退出。 其实为了保证操作目标的唯一性，最好每个号码有一个索引，这样你的程序编写也会容易些。 另外有插入的记录格式，用链表比线性数组更简便快捷，在结构体里增加一个指针就可以，增加删除插入排序都不用做结构拷贝。 楼上正解。一个通讯录里不能出现同名的人。我的建议是利用strcmp写一个比较函数，当有重名的时候调用删除联系人函数。

step by step debug

把Countperson放在函数外定义


Question: 新人求助 为什么这个求方程解的程序不好用呢？

不客气，你可以试试啊！看有没有空格有啥区别，说实话，我也不清楚，只知道在这里如果不加空格会出问题 这一点我是看郝斌老师的C语言视频时他专门点出来的，至于为啥他说以后会讲到，不好意思啊！要不再看看别人知道不知道

引用 2 楼 u012421456 的回复:感觉lz的代码不太好，这是一种写法： # include <stdio.h> # include <math.h>  int main(void) { 	double a, b, c;	 	double delta; 	double x1, x2;	 	char ch; 	 	do	 	{	 		printf("请输入一元二次方程的三个系数:\n"); 		printf("a = "); 		scanf("%lf", &a); 		 		printf("b = "); 		scanf("%lf", &b); 		 		printf("c = "); 		scanf("%lf", &c); 		 		delta = b*b - 4*a*c; 		 		if (delta > 0) 		{ 			x1 = (-b + sqrt(delta)) / (2*a); 			x2 = (-b - sqrt(delta)) / (2*a); 			printf("有两个解，x1 = %lf, x2 = %lf\n", x1, x2); 		} 		else if (0 == delta) 		{ 			x1 = x2 = (-b) / (2*a); 			printf("有唯一解，x1 = x2 = %lf\n", x1, x2); 		} 		else 		{ 			printf("无实数解!\n"); 		}  		printf("您想继续么(Y/N): "); 		scanf(" %c", &ch);  //%c前面必须得加一个空格 原因略 	} while ('y'==ch || 'Y'==ch); 	 	return 0; } 而且可以实现多个一元二次函数的求解  谢谢  不过空格是为什么啊？

引用 1 楼 u012421456 的回复:[quote=引用 楼主 u012954691 的回复:] g=b*b-4*a*c; x1=(-b+g)/2*a; x2=(-b-g)/2*a; 这里用 g 是应该是用它的平方根吧! lz你加一个sqrt() 试试[/quote]  蛋疼了 这个没想到

我也是个新手，对lz代码里的一些东西表示不懂

引用 楼主 u012954691 的回复:g=b*b-4*a*c; x1=(-b+g)/2*a; x2=(-b-g)/2*a; 这里用 g 是应该是用它的平方根吧! lz你加一个sqrt() 试试