Question: 关于二维数组指针的疑惑

引用 2 楼 bob76012 的回复:都指向同一块地址 只是写法不同 缩减版不是同一块地址 写法不同意义也不同

都指向同一块地址 只是写法不同 缩减版

本想回答一下,但看了@zhao4zhong1但看了的问答,觉得楼主应该已经懂了.

*a和a[0]一样，因为规定数组名可以作为首地址的指针用，所以*a就是对应a[0]的值 因为是二维数组，所以a[0]又是一个数组名，所以可以推出后面几个也是一样的

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

引用 7 楼 zhao4zhong1 的回复:A[B] *(A+B) *(B+A) B[A] //以上四行等价  "abc"[1] *("abc"+1) *(1+"abc") 1["abc"] //以上四行等价

肯定都是一样的啊，其实真正并没有什么二维数组，所有的都可以看作一维数组，二维数组只是相当于一维数组中每个元素都是一个数组而已。a代表了数组，既有数组首地址的属性，也有这个数组的大小的属性（从sizeof(a)求出大小就可以看出a并不是单纯的数组首地址）。对于&a是数组的首地址，但是步进值就不一样了，只是&a的值与a一样而已，比如a+1与&a+1是不一样的，&a表示对整个数组求地址，你可以+1试试看值一不一样。a[0]表示第一个元素，也就是一维数组里的第一个一维数组地址，其他的同理了。你只要记住，并没有所谓的多维数组。


Question: 谁有http协议调试源码，功能类似于httpdebug.exe工具

引用 1 楼 fengxuxing 的回复:如果是单机就用  Fiddler 如果用火狐  Firebug 不懂，是用代码实现吗

有人有源码吗？或者该怎么写啊

如果是单机就用  Fiddler 如果用火狐  Firebug

用libcurl

如果只是发送HTTP协议获取结果，那就是简单的TCP socket啊， 可以参考一下我的代码http://www.cnblogs.com/user-3/p/Linux-Http-DownLoad.html 例子是linux的，你要是会winsock改写很容易，不会就参考这个帖子http://bbs.csdn.net/topics/391068694


Question: c语言如何读取mysql储存的一万多字节的text类型数据

引用 1楼羽飞 的回复:报错是什么？根据错误找原因是0xc0000005

引用 1楼羽飞 的回复:报错是什么？根据错误找原因mysql没有报错。我用的mysql 提供的c语言接口，传回的res不为空，row也不为空，但是输出row中相应的内容时发生错误，iis应用程序日志提供的异常代码是0xc000005，应该是内存方面的问题

报错是什么？根据错误找原因


Question: 我有一个结构体数组，如何删除数组中的一组？

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

数组长度是变不了的，要是想改变数组的长度，你直接创建一个新的数组替换原来的

后面的覆盖前面的，空的或是结尾的置空

只能覆盖重写文件


Question: C指针的指针

引用 14 楼 sholber 的回复:[quote=引用 13 楼 cfjtaishan 的回复:] char *array[10];数组array可以看成一个二维数组，即10行（10个指针变量元素），列数未知；列数即指针指向的字符串；目前没初始化，这10个指针都是野指针；ptr指向该数组，那么ptr+1即指向下一个指针地址；  列数是指针指向的东西……彻底颠覆了数组的定义……好大胆。[/quote] 提出列数的概念，是为了更好地理解。因为这10个指针指向的字符串是未知的，因为没有给这10个指针赋值，所以还不能确定列数的个数即长度。10个指针，指向的内容，不可以理解为列数吗？

char *array[10}; char **ptr=array;  char *array[10};指针数组 char **ptr=array; 指向指针数组的指针 ptr指向的是指针数组的首个指针的地址，ptr++指向指针数组中第二个元素的地址。 这和指针指向数组，指针+1后指针会指向下一个数组元素一样。  至于为什么，是因为数组都是分配连续的内存空间，指针+1实际会进行地址偏移sizeof(char *) ，所以实际指向了下一个元素

引用 13 楼 cfjtaishan 的回复:char *array[10];数组array可以看成一个二维数组，即10行（10个指针变量元素），列数未知；列数即指针指向的字符串；目前没初始化，这10个指针都是野指针；ptr指向该数组，那么ptr+1即指向下一个指针地址；  列数是指针指向的东西……彻底颠覆了数组的定义……好大胆。

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

指针数组，char **ptr=array;其实是将array数组第一个数的首地址赋值给了ptr，当你ptr+1，其实就是在首地址上加1，自然跳转到了数组的第二个数的首地址上。

完全不懂

引用 1 楼 user-13的回复:指针变量+1，是会根据变量类型计算步长，因此ptr+1 = ptr(实际变量地址) + sizeof(char *) 正解

Pointer Arithmetic Additive operations involving a pointer and an integer give meaningful results only if the pointer operand addresses an array member and the integer value produces an offset within the bounds of the same array. When the integer value is converted to an address offset, the compiler assumes that only memory positions of the same size lie between the original address and the address plus the offset.  This assumption is valid for array members. By definition, an array is a series of values of the same type; its elements reside in contiguous memory locations. However, storage for any types except array elements is not guaranteed to be filled by the same type of identifiers. That is, blanks can appear between memory positions, even positions of the same type. Therefore, the results of adding to or subtracting from the addresses of any values but array elements are undefined.  Similarly, when two pointer values are subtracted, the conversion assumes that only values of the same type, with no blanks, lie between the addresses given by the operands.

把char *换成char来看,不就清楚了

首先要搞清楚两者表示的是什么。 第一个char*array[10]指针数组  有十个原因素  也就存着10个指针，其中array[0]是一个指针..... 第二个char** ptr是一个二级指针，指向一个地址，这个地址存着一个指针 这样就好说了，让ptr=array， 也就是让二级指针ptr指向array[0]这个指针的地址， 而二级指针ptr+1则是移动多少单位，这个单位是根据它指向的类型char*来确定的， 也就是sizeof(char*)，而一个sizeof(char*)也就是array[0]，array[1],......这些指针的大小， 所以二级指针ptr+1就是移动到下一个数组的元素。

直接指针名加1的话，对应的数组就是指向数组的下一个元素。而你那里直接ptr=array，就是**ptr的值会等于*array[0]的值，也就是ptr跟array在同一个地址上。

char * array [10};          //array是数组，元素类型是char *  char * * ptr = array;     //左边：char * *；右边，array是数组，被转换为指向其首元素的指针。因元素为char *，故转换后为char * *

ptr+1==array+1==&array[1]就是array数组第2个元素的地址

引用 楼主 binrow 的回复:char *array[10}; char **ptr=array; ptr加上一，为什么是指向了ARRAY的下一个元素？求大神解答  第一行定义了10个指针，第二行定义了一个指针的指针，指向array的开头（第一个指针），ptr+1当然就是第二个指针了


Question: C语言倒酒次数最少难题，

用一个字节表示状态, 4升用3位,3长用2位,1升1位, 记录一下访问的状态去重就可以了,最少次数应该用广搜吧

可以改写 波松瓦酒。 改一下循环条件， 加一下次数， 找最小并记录就行了。


Question: linux 的动态库的蛋疼问题

引用 8 楼 caddor9100 的回复:[quote=引用 7 楼 jiqiang01234 的回复:] 不想导出的就不写到头文件中，有什么问题吗？这个原则无论什么系统都成立   你的意思是，导出否，和在头文件里有关系？ [/quote] 我的意思是：对于动态库接口的头文件，只写出需要导出的函数。就算其他的函数出现在导出符号表中，但是没有头文件来说明参数类型，也没什么太大意义(破解除外)

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

引用 12 楼 mymtom 的回复:[quote=引用 楼主 caddor9100 的回复:]    windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！ 导出根本就是多余，写在DLL里的函数，如果不能被调用，有毛用啊！[/quote]  假设一个so里有100个函数，  现在阅读这个so。  阅读人一看便头昏，  它不知道 接口在哪里？  哪个是需要关注的。   比如， 你只导出某几个函数，  人家的注意就会关注导出的哪几个，  其他根本不会关注。  这就是好处。   顺便请教个问题：   linux 下是否可导出 变量？

引用 楼主 caddor9100 的回复:windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！ 导出根本就是多余，写在DLL里的函数，如果不能被调用，有毛用啊！

按照C的标准, 函数就是可以被模块调用的，除非用static进行隐藏。 Windows的dll实用export做法才是比较蛋疼的

都开源时代了，楼主还在纠结哪些函数该导出，哪些函数不该导出？

linux  api 去哪里查询资料？ http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm

引用 7 楼 jiqiang01234 的回复:不想导出的就不写到头文件中，有什么问题吗？这个原则无论什么系统都成立   你的意思是，导出否，和在头文件里有关系？

不想导出的就不写到头文件中，有什么问题吗？这个原则无论什么系统都成立

引用 5 楼 cjqpker 的回复:[quote=引用 4 楼 caddor9100 的回复:] [quote=引用 2 楼 cjqpker 的回复:] [quote=引用 楼主 caddor9100 的回复:]    windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！  你说对了，编译时带着头文件，链接时指明需要链接的so文件，就可以了。[/quote]   假设有个so库有3个:  a.h b.h c.h a.c b.c c.c  要导出的函数在 c.h c.c中，请问如何写？  不能把a.h /a.c  b.h/b.c也导出啊  [/quote]  3楼说的对，你可以按照这种方法，选择性的导出。 如果担心麻烦，那你发布这个so的时候，把c.h 发布出去就可以了，a.h、b.h不发布。[/quote]  pthread_mutex_init   问个问题：  linux  api 去哪里查询资料？  man 这个用法我知道，我需要的是 函数索引，目录，  可以看到很多函数的分类，名字，  而不是知道一个函数的名字，然后去man  function_name

引用 4 楼 caddor9100 的回复:[quote=引用 2 楼 cjqpker 的回复:] [quote=引用 楼主 caddor9100 的回复:]    windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！  你说对了，编译时带着头文件，链接时指明需要链接的so文件，就可以了。[/quote]   假设有个so库有3个:  a.h b.h c.h a.c b.c c.c  要导出的函数在 c.h c.c中，请问如何写？  不能把a.h /a.c  b.h/b.c也导出啊  [/quote]  3楼说的对，你可以按照这种方法，选择性的导出。 如果担心麻烦，那你发布这个so的时候，把c.h 发布出去就可以了，a.h、b.h不发布。

引用 2 楼 cjqpker 的回复:[quote=引用 楼主 caddor9100 的回复:]    windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！  你说对了，编译时带着头文件，链接时指明需要链接的so文件，就可以了。[/quote]   假设有个so库有3个:  a.h b.h c.h a.c b.c c.c  要导出的函数在 c.h c.c中，请问如何写？  不能把a.h /a.c  b.h/b.c也导出啊

gcc 默认是所有都导出  如果不想导出就加 编译时 -fvisibility=hidden  要导出的函数加 __attribute ((visibility("default")))修饰   (跟vc 的 dll 导出修饰符一样用)   linux  默认是不会加载当前目录的 so 库. 只会查找  ldconfig 所配置的

引用 楼主 caddor9100 的回复:windows下dll有关键字导出，可linux 没有，  问题来了:   是不是意味着so文件里的任何一个函数都可以被调用者使用？   windows 下是不行的，必须导出！！！！  你说对了，编译时带着头文件，链接时指明需要链接的so文件，就可以了。

objdump楼主会用吗？


Question: 关于PAT上一道树的问题

不过谁能详细解释下

总算通过了，问题出在那个fflush(stdin);本来是为了去除scanf();用后的回车。现在改成在scanf();下加一条getchar(); 原来是用vs2010写的，在vs2010上没有任何问题，后来在linux下试试，发现输入到一半老是有什么段错误，核心已转存。


Question: 最简单的方法

各位大神，希望有更短的代码，！！

仅供参考 #include<stdio.h> #include<stdbool.h> int main() { 	bool have_c[256]={false}; 	size_t outstrlen=0; 	char c,outstr[256]={0}; 	while((c=getchar())!='\n') 		if(!have_c[c]) 		{ 			have_c[c]=true; 			outstr[outstrlen++]=c; 		} 	puts(outstr); 	return 0; }

这样试试     char a[N];     scanf("%s",a);     int s=0,d=0;     for(;a[s];s++) if(a[s]!=a[d]) a[++d] =a[s];     if(a[d]) a[++d]=0;     puts(a);


Question: 写一个点赞代码

不懂什么意思


过度优化？？

vc6.0确实存在这个问题。楼主怎么解决的

学会调试每句C对应的汇编指令，是楼主的当务之急！   计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

debug 版会把变量的内存空间初始化为0xcc，release版不会

VS2008鉴定完毕, 一样

在VC6.0中运行，debug和release的输出结果一比较就会看到，记得是VC6.0啊！

结果哪里不同？明确指出来


Question: C新手求解

我测试下效果，打扰了

因为循环还没推出，根据你设定的循环条件，在Linux下需要键盘输入ctrl+d，windows下应该是输入ctrl+z

最后回车也是一个字符。

#include<stdio.h> int main(){     long nc=0;     while(getchar()!=EOF){         ++nc;         printf("%ld\n",nc);     }     return 0; }  这样的话我输入的时候是有统计的，而且输出是一个个输出的而且最后还会多出一个。改良以后是这样的。 #include<stdio.h> int main(){     long nc=0;     while(getchar()!=EOF){         ++nc;     }     printf("%ld\n",nc);     return 0; }  但是按Ctrl+C之后一闪就没了，难以看见，所以最好还是改一下循环条件吧。

Linux:Ctrl+D Windows:Enter,Ctrl+Z,Enter

你需要输入一个终止符号，一般Ctrl+c刘可以了


Question: 新手请教C语言问题

使用WinIO.sys


Question: 请问sscanf的参数格式可以可以如下

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  //if (p && 1==sscanf(p,"op:%1023[^,]",MDL) //如上面这个sscanf的正则匹配格式，假设上面这个语句是在一个函数里面的， //现在我想把那个前置符op:和[^,]里面的逗号作为一个字符指针来传入行么？ #include <stdio.h> char *split(char *src,char *symbol,char *gap) {     static char res[1024];     char format[1024];     res[0]=0;      sprintf(format,"%s%%1023[^%s]",symbol,gap);     sscanf(src,format,res);     return res; } int main() {     printf("[%s]\n",split("op:abc def,123 456","op:",","));     printf("[%s]\n",split("OP:abc def;123 456","OP:",";"));     return 0; } //[abc def] //[abc def] //

你先弄个字符串，再传呗

@user-2  什么叫正则字符串？我把要分割的字符串可以传进来，"op:%1023[^,]"这里怎么改写啊？就是不知道，因为我是想把op:和，作为两个参数传进来的

你得把所谓正则字符串先转换为一个确定得字符串 比如 “%d”，“%f”什么的

@user-2 那比如说在一大串字符串中，我想说截取其中op:后面几个非逗号，的字符串，op：是一个参数，逗号，是一个参数，那这里该怎么写？怎么放两个字串变量？

可以，sscanf(p,"op:%1023[^,]",MDL) 红色的部位你可以使用一个符合要求的字串变量，字串内容要符合要求


Question: 字符串尾部多了个字符 （x11）

呃，谢谢各位。

同学，char *这么简单的东西，干嘛用LPCTSTR, CString 自己找虐啊  bool fun(char *pIP, ...) char strIP[INET6_ADDRSTRLE + 1]; fun(strIP,...) UseIP(strIP);  把简单的事情搞复杂，受罪的是自己。

bool fun(char *pIP, ...) 看着个函数的定义，她是填充到 pIP 的内存空间，此时需要呼叫者，定义足够的缓存。 你的 CString 需要先开辟足够的空间。

Setting a Breakpoint When the Value at a Specified Memory Address Changes To break when the value at a specified memory address changes  1.	From the Edit menu, click Breakpoints. 2.	Click the Data tab of the Breakpoints dialog box. 3.	In the Expression text box, type the memory address for the byte.  For a word or doubleword memory address, enclose the address in parentheses, and precede it with a cast operator. For example, WO(21406036) for the word at memory location 21406036. Use the cast operator BY for a byte (optional), WO for a word, or DW for a doubleword. (The debugger interprets all integer constants as decimal unless they begin with zero (0) for octal or zero and x (0x) for hexadecimal.) 4.	In the Number Of Elements text box, type the number of bytes, words, or doublewords to monitor. If you used the BY operator in the Expression field, specify the number of bytes. If you used WO, specify the number of words. If you used DW, specify the number of doublewords.  5.	Click OK to set the breakpoint.

我原来遇到过一次类似问题， 文件的结尾莫名其妙的有的被加了一个字节，有的被删了一个字节（程序解析文件的地方） 我那次是电脑中毒了,lpk.dll 还是 usp.dll  还是其他（忘了，好几年了）


Question: 用指针给结构体中字符数组赋值问题

strcpy(str, "World!");  // 正确但不安全 strncpy(str,"World!",9);str[9]=0;//完全正确

要向结构体的 name 赋值，也应该是 p->name 而不是 p->name[20]。首先赋值方式不对，应该是 strcpy，其次 p->name[20] 本身已经越界了，而且类型也不对，把一个字符赋值给一个字符！看看这种写法： char str[10] = "Hello!"; str[0] = 'h';           // 正确 str[10] = 'H';          // 越界但语法正确 str[10] = "World!";     // 越界且语法不正确，类型不匹配 strcpy(str, "World!");  // 正确对于结构体成员，写法是一样的，只是前面多了一个 "p." 或 "p->" 而已。如果你连这段代码都会犯错误，只能说明基础不扎实。

引用 1 楼 lgbxyz 的回复:数组不能这么赋值得用memcpy汗 字符串有专用的 strcpy 或 strncpy 用什么memcpy  自造麻烦?

// 字符指针和字符数组的初始化： char *ps      = "Hello!"; char str[256] = "Hello!"; // 运行时刻重新赋值： // 对于指针而言，只是改变了指针指向 ps = "World!"; // 对于数组而言，改写内存区域的内容 strcpy(str, "World!"); // 结构体同理： // 结构体字符指针和字符数组成员的初始化： typedef struct { const char *p; } STRUCT_A; typedef struct { char str[256]; } STRUCT_B; // 指针和数组初始化方式相同： STRUCT_A st_a = { "Hello!" }; STRUCT_B st_b = { "Hello!" }; // 运行时刻重新赋值(同上)： st_a.p = "World!"; strcpy(st_b.str, "World!");

字符数组可不支持这种直接字符串赋值的，你应该通过内存copy等方式来实现，或者通过字符串指针给数组直接赋值

引用 2 楼 gcx100 的回复:[quote=引用 1 楼 lgbxyz 的回复:]  数组不能这么赋值得用memcpy 如果是定义的时候可以直接赋值是吧，比如 char str[20] = "ggggggg"[/quote] 你得分清 初始化和赋值

定义的时候是可以的，但是中间的赋值需要memcpy, 如果你想直接赋值就用MFC中的CString吧。

引用 1 楼 lgbxyz 的回复:数组不能这么赋值得用memcpy 如果是定义的时候可以直接赋值是吧，比如 char str[20] = "ggggggg"

数组不能这么赋值得用memcpy


Question: malloc后free不对吗？为什么调试时说遇到断点

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

int *p = (int *)malloc(sizeof(int)); 你是要打算至分配一个int长度(4个字节)的内存吗？

void Mergesort(int a[], int n) {     int *p = (int *)malloc(sizeof(int));//分配空间不够，n * sizeof(int)       mergesort(a, 0, n, p);       free(p);  // 调试显示这里触发一个断点,其原因可能是堆被损坏，搞不明白什么原因，malloc后free不对吗？     p = NULL; }


Question: 用C实现去掉字符串中的相同字母

仅供参考：#include <stdio.h> #include <string.h> char s1[]="delete"; char s2[]="select"; unsigned char n[256]={0}; char r[257]; int i,L,o=0; void main() {     L=strlen(s1); for (i=0;i<L;i++) if (!n[(unsigned int)s1[i]]) n[(unsigned int)s1[i]]=++o;     L=strlen(s2); for (i=0;i<L;i++) if (!n[(unsigned int)s2[i]]) n[(unsigned int)s2[i]]=++o;     L=0;     for (o=1;o<=256;o++) {         for (i=0;i<256;i++) {             if (o==n[i]) {                 r[L++]=i;                 break;             }         }         if (i>=256) break;     }     r[L]=0;     printf("[%s]\n",r); } //[deltsc]

引用 6 楼 weixin_29041015 的回复:你这只是判断是否与前一个字符相同。逻辑有问题你弄错了  你这个解决的是 删除连续相同字符 题目 不连续的相同字符也要删掉的撒

你这只是判断是否与前一个字符相同。逻辑有问题

上面的解答说的很清楚了。判断字符是否出现过有问题。

void printString(char str[], int count) {     char *Output = (char*)malloc(sizeof(char) * (count + 1)); 	int OutputCount = 1; 	Output[0] = str[0];     for (int i = 1; i < count; i++) 	{ 		bool Exist = false; 		for(int j = 0; j < OutputCount; j++) 		{ 			if(str[i] == Output[j] && str[i] != ' ') 			{ 				Exist = true; 				break; 			} 		} 		if(Exist == false) 			Output[OutputCount++] = str[i];     } 	Output[OutputCount] = '\0';     printf("delete the same character result:");     for (int i = 0; i < OutputCount; i++)         printf("%c", Output[i]); }  void main(int argc, char* argv[]) { 	printString("gggggoogoooood", 14); 	printf("\n"); 	system("PAUSE"); }

你的程序作用是删除连续的字符，因为判断重复部分只与上一个字符比较，改成用已得出的所有字符进行比对即可

你只有判别temp上一个字符 只要字符是交错的话那肯定都是错答案 你可以把出现过的记录下来做后续比对

我这个程序实现的后输出为gogod


Question: 闲着没事，写了个根据指定时间计算星期几的函数，各位看官，看后给个评价～～

公式真好。。

用这么复杂？  int  today,week； char  day[30];          strcpy(day,"2015.09.03");         today=rstrjul(day);//since 1899.12.31,days         week=today%7;         printf("day=%s,week=%d\n",day,week);

const char *weekdays[] = {     "星期天",     "星期一",     "星期二",     "星期三",     "星期四",     "星期五",     "星期六", };  void output_weekday() {     if (total_day < 7) {         printf("%d年%d月%d日是%s\n",year,mon,day,weekdays[total_day]);     } }

看到大家的评论，楼楼欣喜不已，以对科学尤其是数学致敬的态度重写代码，如下： #include <stdio.h> int GetWeekDay(int year,int mon,int day) { 	int weekend; 	if((1==mon) || (2==mon)) 	{ 		mon+=12; 		year-=1; 	} 	weekend=(day+2*mon+3*(mon+1)/5+year+year/4-year/100+year/400)%7; 	printf("%d\n",weekend); 	return weekend; }  int main() { 	int year=0; 	int mon=0; 	int day=0; 	while(1){ 	scanf("%d",&year); 	if(year==99)	//退出标志 		break; 	getchar(); 	scanf("%d",&mon); 	getchar(); 	scanf("%d",&day); 	getchar(); 	int week=GetWeekDay(year,mon,day); 	switch(week) 	{ 	case 0: 		printf("%d-%d-%d is  Monday\n",year,mon,day);  		break; 	case 1: 		printf("%d-%d-%d is Tuesday\n",year,mon,day); 		break; 	case 2: 		printf("%d-%d-%d is Wednesday\n",year,mon,day); 		break; 	case 3: 		printf("%d-%d-%d is Thursday\n",year,mon,day); 		break; 	case 4: 		printf("%d-%d-%d is Friday\n",year,mon,day); 		break; 	case 5: 		printf("%d-%d-%d is Saturday\n",year,mon,day); 		break; 	case 6: 		printf("%d-%d-%d is Sunday\n",year,mon,day); 		break; 	default: 		break; 	} 	} 	getchar(); 	return 0; }

@2楼@4楼 这么好的公式，很不错，很不错，多谢了

楼主闲着没事，还是学学怎么使用COleDateTime吧。 The COleDateTime class handles dates from 1 January 100 – 31 December 9999. COleDateTime Class Members Construction  COleDateTime Constructs a COleDateTime object.  GetCurrentTime Creates a COleDateTime object that represents the current time (static member function).    Attributes  GetStatus Gets the status (validity) of this COleDateTime object.  SetStatus Sets the status (validity) of this COleDateTime object.  GetAsSystemTime Converts the time in the COleDateTime object to be represented as aSYSTEMTIME data structure.  GetYear Returns the year this COleDateTime object represents.  GetMonth Returns the month this COleDateTime object represents (1 – 12).  GetDay Returns the day this COleDateTime object represents (1 – 31).  GetHour Returns the hour this COleDateTime object represents (0 – 23).  GetMinute Returns the minute this COleDateTime object represents (0 – 59).  GetSecond Returns the second this COleDateTime object represents (0 – 59).  GetDayOfWeek Returns the day of the week this COleDateTime object represents (Sunday = 1).  GetDayOfYear Returns the day of the year this COleDateTime object represents (Jan 1 = 1).    Operations  SetDateTime Sets the value of this COleDateTime object to the specified date/time value.  SetDate Sets the value of this COleDateTime object to the specified date-only value.  SetTime Sets the value of this COleDateTime object to the specified time-only value.  Format Generates a formatted string representation of a COleDateTime object.  ParseDateTime Reads a date/time value from a string and sets the value of COleDateTime.    Operators  operator DATE Converts a ColeDateTime value into a DATE.  operator DATE* Converts a ColeDateTime value into a DATE*.  operator = Copies a COleDateTime value.  operator +, - Add and subtract ColeDateTime values.  operator +=, -= Add and subtract a ColeDateTime value from this COleDateTime object.  operator ==, <, <=, etc. Compare two ColeDateTime values.    Data Members  m_dt Contains the underlying DATE for this COleDateTime object.  m_status Contains the status of this COleDateTime object.    Archive/Dump  operator << Outputs a COleDateTime value to Carchive or CDumpContext.  operator >> Inputs a ColeDateTime object from CArchive.    COleDateTime Overview |  Hierarchy Chart COleDateTime::GetDayOfWeek int GetDayOfWeek( ) const;  Return Value  The day of the week represented by the value of this COleDateTime object.  Remarks  Call this member function to get the day of the week represented by this date/time value.  Valid return values range between 1 and 7, where 1=Sunday, 2=Monday, and so on. If the status of this COleDateTime object is not valid, the return value is AFX_OLE_DATETIME_ERROR.  For information on other member functions that query the value of this COleDateTime object, see the following member functions:   GetDay   GetMonth   GetYear   GetHour   GetMinute   GetSecond   GetDayOfYear  COleDateTime Overview |  Class Members |  Hierarchy Chart  See Also   COleDateTime::COleDateTime, COleDateTime::SetDateTime, COleDateTime::operator =, COleDateTime::GetStatus

/****************************************************************************/ /* Function Name    :    getWeekdayFromGrogoryDate                          */ /* Description      :    通过格里高利日期获取星期                               */ /*--------------------------------------------------------------------------*/ /* Parameter        :    1) year        :    年(阳历)                        */ /*                       2) month       :    月(阳历)                        */ /*                       3) day         :    日(阳历)                        */ /*--------------------------------------------------------------------------*/ /* Return            :    星期几(0~6)[0为星期天,1~6 为星期一至星期六]            */ /* Remark            :    使用 基姆拉尔森计算公式                               */ /*                        W = (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1) mod 7   */ /*                        把1月和2月看成是上一年的13月和14月                     */ /****************************************************************************/ int getWeekdayFromGrogoryDate(int year, int month, int day) {     if ((1 == month) || (2 == month))     {         month += 12;    /* 13/14月 */         year -= 1;        /* 上一年 */     }          return (day + 2 * month + 3 * (month + 1)/5 + year + year/4 - year/100 + year/400 + 1) % 7; }

其实是有公式可计算的。 S=x-1+[(x-1)/4]-[(x-1)/100]+[(x-1)/400]+t  其中x表示公元的年号，中括号内的分数计算时，只取商的整数部分即可。 t表示从这一年的元旦开始算到要求的这一天为止的天数

没有用到这个方面的，看着很复杂，楼主辛苦了。


Question: scanf的连续输入

讨论千句道听途说的标准、想法、…… 不如调通一句自己编写的代码！

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。  Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

引用 4 楼 qq_25987103 的回复:那么输入 3   4    +     敲一个回车 怎么写break的if条件呢？scanf最后还会读取‘\n’?我发现敲了一个回车之后还要求继续输入？为什么？ 输入回车并不是输入“EOF”啊，满足循环的条件那可不继续执行吗。

用%s接收数据时，是不接收空格的，你输入4  5 + ，这三个字符之间有空格，第一次循环接收4 这个字符，然后接收数据结束，满足条件，输出一个a，紧接着第二次循环，由于输入缓冲区中（这里涉及到键盘缓冲区的问题）还有5这个字符等待输入，所以直接把5读进去，依然不读空格，在输出一个a，“+”这个字符也是这样的。

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。  #include <stdio.h> #include <string.h> int main() {     char tmp[30];     int a,b;     char s[2],op,c;     while (1) {         printf("Input # # op(example:4 5 +):");fflush(stdout);         rewind(stdin);         fgets(tmp,30,stdin);         if (tmp[0]=='\n') break;         if (4==sscanf(tmp,"%d%d%1s%c",&a,&b,s,&c)) {             if (c=='\n') {                 op=s[0];                 if (op=='+'                  || op=='-'                  || op=='*'                  || op=='/') {                     if (op!='/' || (op=='/' && b!=0)) {                         printf("You input is %d %d %c\n",a,b,op);                     }                 }             }         }     }     return 0; } //Input # # op(example:4 5 +):4 5 + //You input is 4 5 + //Input # # op(example:4 5 +):1 2 - //You input is 1 2 - //Input # # op(example:4 5 +):3 4 * //You input is 3 4 * //Input # # op(example:4 5 +):5 6 / //You input is 5 6 / //Input # # op(example:4 5 +):7 0 / //Input # # op(example:4 5 +):4 5 +! //Input # # op(example:4 5 +): //

另外我再补充一下，你可以这样实现你的功能while(（tmp[i++]=getchar()） != EOF&&i<10 )

scanf返回的是非0值，所以你的程序不管输入什么一直在while循环中，你输入几个数就输出几个a


Question: 结构体赋值调试问题

不要依赖调试器输出复杂数据结构！ 而要将复杂数据结构的整个内容在处理它的每一步使用一小段代码按自己很容易理解的格式输出，非常有助于调试！或者可以说是“基础设施”： 十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495


Question: c语言错误

建议楼主以后先将所有英文提示信息放在百度翻译里面翻译为中文后自己还是看不懂再在此发帖提问。

文件最后一行 空行

文件末尾加回车，我编单片机程序时有这个警告，你也是编单片机程序吗

文件最后加个回车


Question: 纵横字谜的答案

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


Question: 用vs写c控制台程序为什么能显示中文而写windows应用程序就不能

VS IDE中，在不明白的符号_T上点鼠标右键，选转到定义。

纯粹宽字符是wchar_t类型， wchar_t wStr[] = L"中文";  我自己也学习了。

MessageBox  的定义： #ifdef UNICODE #define MessageBox  MessageBoxW #else #define MessageBox  MessageBoxA #endif // !UNICODE  UNICODE是否定义： Project—Properties—Configuration Properties—General—Character Set 被设置为：Use Unicode Character Set ANSI是否定义： Project—Properties—Configuration Properties—General—Character Set 设置为：Not Set 或者 Use Multi-byte Character Set  MessageBox  函数和参数字符串匹配应该就可以，或者都是UNICODE，或者都是ANSI。代码未验证。 TCHAR d[] = _T("中文")比较好，会自动适配UNICODE或者ANSI。我也是初学者一起学习。

如果你的.c源文件采用ansi格式编码，好像中文是可以 直接显示的。编码到char d[]中的码流是按你的源文件本身的编码格式编译进去的，其实就是看编译器的实现，没有必要纠结，  可以直接将d开始的内存打印一下，看一下编码内容就知道了。

MessageBoxA(NULL, d, d, MB_OKCANCEL);


Question: cgdb调试的时，发现源文件乱码了，没法解决。

up 起来，等高手解答


Question: 想问问下面这段数据文件怎么用正则表达式匹配出结果？（用C语言写）

Linux版本更新一下， Windows版本在你另一个帖子上http://bbs.csdn.net/topics/391073876  /* on linux using posix regex */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include <regex.h>  #define MAX_MATCH_NUM (5) /* all,date,op,bytes,cliID */  void main(void) {     regex_t reg;     regmatch_t match[MAX_MATCH_NUM];     char pattern[] = "(^[^,]+).+bytes: ([^,]+).+op: ([^,]+).+cliID: DFSClient_attempt([^,]+)_m";     char result[256] = {0};     int errcode = 0;     /* compile pattern */     errcode = regcomp(®, pattern, REG_EXTENDED);     if (errcode != 0)     {/* print human readable error prompt */         char errbuff[64];         regerror(errcode, ®, errbuff, sizeof(errbuff));         printf("regcomp failed,%s\n", errbuff);         exit(EXIT_FAILURE);     }      /* do match */     errcode = regexec(®, string, MAX_MATCH_NUM, match, 0);     if (0 == errcode)     {         /* op */         strncat(result, string + match[3].rm_so, \             match[3].rm_eo - match[3].rm_so);         strcat(result, "|");          /* date */         strncat(result, string + match[1].rm_so, \             match[1].rm_eo - match[1].rm_so);         strcat(result, "|");          /* application */         strcat(result, "application");         strncat(result, string + match[4].rm_so, \                 match[4].rm_eo - match[4].rm_so);         strcat(result, "|");          /* bytes */         strncat(result, string + match[2].rm_so, \             match[2].rm_eo - match[2].rm_so);          printf("result = %s\n", result);     }      else if (REG_NOMATCH == errcode)     {         printf("no match\n");     }     else     {/* print human readable error prompt */         char errbuff[64];         regerror(errcode, ®, errbuff, sizeof(errbuff));         printf("regcomp failed,%s\n", errbuff);         regfree(®);         exit(EXIT_FAILURE);     }      /* free regex */     regfree(®);     exit(EXIT_SUCCESS); }

正则表达式不是万能的； 有限状态自动机是万能的。

想问下大家，如何把这些截取字段和分割符是写在配置文件中，打算从程序中读取配置文件，然后传入程序进行匹配截取，这样的话，程序感觉匹配难度会加大很多，求赐教思路

@ lgbxyz #include <regex.h> 这个头文件Linux下才能用，Windows下无法包含呢

把64行放到50行上面

/* on linux using posix regex */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include <regex.h>  #define MAX_MATCH_NUM (5) /* all,date,op,bytes,cliID */  void main(void) { 	regex_t reg; 	regmatch_t match[MAX_MATCH_NUM]; 	 	char string[] = "2015-07-07 15:42:52,666 INFO org.apache.hadoop.hdfs.server.datanode.DataNode.clienttrace: src: /10.215.145.89:9003, dest: /10.196.139.31:38385, bytes: 17660496, op: HDFS_READ, cliID: DFSClient_attempt_1435652218972_8928036_m_000228_0_1283375306_1, offset: 0, srvID: DS-885471072-10.215.145.89-9003-1416312428093, blockid: BP-1531210715-10.215.135.49-1416303685693:blk_1256393234_183414267, duration: 32839633797"; 	char pattern[] = "(^[^,]+).+(bytes: [^,]+).+(op: [^,]+).+(cliID: [^,]+_m)"; 	char result[256] = {0};   	int errcode = 0; 	    /* compile pattern */     errcode = regcomp(®, pattern, REG_EXTENDED);     if (errcode != 0)     {/* print human readable error prompt */         char errbuff[64];         regerror(errcode, ®, errbuff, sizeof(errbuff));         printf("regcomp failed,%s\n", errbuff);         exit(EXIT_FAILURE);     }     	 	/* do match */     errcode = regexec(®, string, MAX_MATCH_NUM, match, 0);     if (0 == errcode)     { 		/* op */ 		strncat(result, string + match[3].rm_so + strlen("op: "), \ 			match[3].rm_eo - match[3].rm_so - strlen("op: ")); 		strcat(result, "|"); 		/* date */ 		strncat(result, string + match[1].rm_so, \ 			match[1].rm_eo - match[1].rm_so); 		strcat(result, "|"); 		/* application */ 		strcat(result, "application"); 		strncat(result, string + match[4].rm_so + strlen("cliID: DFSClient_attempt"), \ 				match[4].rm_eo - match[4].rm_so- strlen("cliID: DFSClient_attempt") - strlen("_m")); 		strcat(result, "|"); 		/* bytes */ 		strncat(result, string + match[2].rm_so + strlen("bytes: "), \ 			match[2].rm_eo - match[2].rm_so - strlen("bytes: "));		     }     else if (REG_NOMATCH == errcode)     {         printf("no match\n");     }     else     {/* print human readable error prompt */         char errbuff[64];         regerror(errcode, ®, errbuff, sizeof(errbuff));         printf("regcomp failed,%s\n", errbuff);         regfree(®);         exit(EXIT_FAILURE);     } 	 	printf("result = %s\n", result);      /* free regex */     regfree(®);     exit(EXIT_SUCCESS); }

感觉一个正则表达式无法匹配出这么多的字符串


Question: 哪位大神帮忙用crypto库实现一个RSA签名的算法，密钥文件一直有了，填充方式是RSA_PKCS1_PADDING

仅供参考：#pragma comment(lib, "crypt32.lib") #pragma comment(lib, "advapi32.lib") #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include <wincrypt.h> #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 destination 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

顶！！！！！！

def sha1Sign(key, data = None):    if data == None:       return None    privateKey=RSA.importKey(open(key,'r').read())	    h=SHA.new(data)     signer = pk.new(privateKey)     signn=signer.sign(h)     return base64.b64encode(signn)

顶！！！！！！


Question: c在vs2013里怎样打印字符呢？

因为你scanf_s用错误了, 最后少一个max buf size, 或者你用scanf别用scanf_s

看代码真的一点问题都没有…………

引用 3 楼 gzwgyfgpf 的回复:是你的scanf_s函数的问题，你可以看一下这个帖子http://bbs.csdn.net/topics/320083123 看了一下，c在vs2013里面打印字符，在scanf_s()加上第三个参数1就可以了，如下：  scanf_s("%c",ch,1);


Question: 指针变量必须要定义吗？书本上这个例子怎么没有定义？

引用 12 楼 u011573693 的回复:指针也是个变量，不同于基本类型变量，指针存储的是一个地址，该地址指向的内存位置才是真正存储数据内容的，而普通变量存储的就是实际数据内容。  指针因为存储的是一个地址，比如访问一个字符串或者数组，因为大多数情况先字符串或者数组都是按顺序存储的，所以指针在大多数情况下也是只带字符串或者数组的首地址，然后你可以通过 （指针+ number）的模式来访问指定的数组元素，你贴上的图就是使用这种方式来访问数组中的元素的。 这种方式访问要number的表示值，int和char下表示是不一样的  你说的都很有道理，多谢~ 就是意思“*”只是一个指示符号？单纯的指针只是一个地址，所以不需要定义，而只有指针变量需要定义？

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

引用 8 楼 gzwgyfgpf 的回复:你这个程序还没涉及二维及多维数组与指针的问题，只是单纯的指针与字符数组的关系，看不明白的话多写几个程序验证一下就好懂一些了，你可以看一下这个程序 #include<stdio.h>  int main() { 	char a[]="i am a boy",b[20]; 	char c[][20]={"yes i do","no way"}; 	char *c0=a,*c1=b; 	int i=0; 	while((*c1++=*c0++)!='\0'); 	printf("string a is %s\n",a);  	printf("string b is\n"); 	for(i=0;*(b+i)!='\0';i++) 		printf("%c",*(b+i)); 	putchar('\n');  	printf("%c",*(*(c+1)+1));//输出的是o }  你这个里面的*c0  什么的，是不是没有加[]符号~

*(a +i)就是a[i] *a就是a[0]，两边取地址： a就是&a[0]就是a[0]地址就是数字a的首地址

建议楼主再看一下关于指针和数组之间的关系

意思*是个取值符号，对任何指针都有用？ 前提还是针对指针啊，既然是指针，不得声明么

引用 3 楼 u013409439 的回复:[quote=引用 2 楼 user-6 的回复:] a是变量,  *(a +i), 指取 a向后移 i 个 char字节 时的值  *这个符号可以随便用吗？[/quote] ...取值, 可以对任何有效指针使用

引用 2 楼 user-6 的回复:a是变量,  *(a +i), 指取 a向后移 i 个 char字节 时的值  *这个符号可以随便用吗？

a是变量,  *(a +i), 指取 a向后移 i 个 char字节 时的值

图中的*（a+i）不是指针变量吗？


Question: 结果和所给结果一样，就是ACM不通过，弄了快一下午了，求大神指教下

如果输入最后一行没有换行符了?

更新下代码： #include "stdio.h" int main(){ 	char c; 	int sum=0,i=0,j=0; 	while(scanf("%c",&c)!=EOF){    		    switch(c){ 			case 'A': sum+=4;i++;break; 			case 'B': sum+=3;i++;break; 			case 'C': sum+=2;i++;break; 			case 'D': sum+=1;i++;break; 			case 'F': sum+=0;i++;break; 			default: if((c<'A'||c>'F'||c=='E')&&c!=' '&&c!='\n') 						 j++; 				     if(c!='\n') break; 			} 		if(c=='\n'){ 			if(j!=0) {printf("Unknown\n");j=0;} 			else {printf("%.2f\n",sum/(1.0*(i))); i=0;  j=0;  sum=0;} 			i=0;sum=0; 		} 	} 	return 0; }


Question: 《c语言的科学和艺术》里的inchtocm.c在vc6里面老是提示出错啊！求大神

引用 2 楼 GKatHere的回复:写一个  double GetReal() {  double db; cin >> db; return db; }   谢谢，我再试试您的方法

引用 1 楼 我就_看看的回复:GetReal 函数的库没找到, 没看过这本书,这个函数也不是标准函数,你仔细找找是哪个库里的, 库的路径加到项目里,或者代码里包含一下#pragma comment(lib, "xxx") 谢谢，终于在论坛里找到资源了，已经解决


Question: 一个scanf的问题

引用 13 楼 lgbxyz 的回复:[quote=引用 12 楼 zzzrrr1989 的回复:] 恩，这个是对的~~  你明白为什么加一个getchar() 就OK了?[/quote] -------------------------------------------------------------- 如果是%s的话，可以不用getchar()；但是%[^\n]的话，\n会一直留在输入缓冲区，然后一直循环~~或者像另一位写的，在%[^\n]前面加上空格，使其不匹配单个\n。

引用 13 楼 lgbxyz 的回复:[quote=引用 12 楼 zzzrrr1989 的回复:] 恩，这个是对的~~  你明白为什么加一个getchar() 就OK了?[/quote] ------------------------------------------------------- 把缓冲区最后一个字符取走...

引用 12 楼 zzzrrr1989 的回复:恩，这个是对的~~  你明白为什么加一个getchar() 就OK了?

引用 8 楼 lgbxyz 的回复:终于明白你的意思了  #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>  #define TRUE 1 #define FALSE 0   char const CHARACTER_TABLE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";   int prepare_key(char *key);  int main( int argc, char *argv[] ){ 	char input_letter[27]; 	char *buf; 	 	do { 		memset(input_letter, 0x00, 27); 		printf("Please input a letter: ");         scanf("%[^\n]", input_letter);         getchar(); //get '\n' 	}while ( prepare_key(input_letter)==FALSE );  	printf("The input letter is %s\n", input_letter);  	return EXIT_SUCCESS; }   /*  * if input letter is empty or contains un-alpha characters, or its length surpasses 26, just return FALSE  * */ int prepare_key(char *key){ 	if ( strlen(key)>26 || strlen(key)==0 ){ 		return FALSE; 	} else { 		while ( *key!='\0' ){ 			if ( !isalpha(*key) ){ 				return FALSE; 			} 			key++; 		} 		return TRUE; 	} }   ---------------------------------------------------------------------------------------------------- 恩，这个是对的~~

引用 7 楼 dooX8086 的回复:rewind(stdin); 应该可以吧！！！！不行的话就这样 格式控制符前加多个空格在前面 scanf(" %[^\n]", input_eletter);   "这里加个空格%[^\n]"  其实它就是  gets(input_eletter) ------------------------------------------------------------------ rewind(stdin); 这个确实没用；加空格有用。

引用 7 楼 dooX8086 的回复:rewind(stdin); 应该可以吧！！！！不行的话就这样 格式控制符前加多个空格在前面 scanf(" %[^\n]", input_eletter);   "这里加个空格%[^\n]"  其实它就是  gets(input_eletter) ------------------------------------------------------------------------ 我知道gets或者fgets可以实现，我主要是疑惑为什么这里用scanf会有为题~~我再试试。

Please input a letter: hel lo Please input a letter: hello The input letter is hello 请按任意键继续. . .  ------------------------------------ 这样是否是想要的结果

引用 5 楼 lgbxyz 的回复:反正hel lo好用 ------------------------------------------------ 你输入"hel  lo"正确应该输出的是“Please input a letter: ”，就是让你重新输，而不是printf("The input letter is %s\n", input_letter);

反正hel lo好用

引用 1 楼 user-3 的回复:rewind(stdin); scanf("%[^\n]", input_letter);  清除一下输入缓冲区，每次scanf 遇\n  读取前面内容，一直没有清\n, 每次到scanf就自动判断读取结束 ----------------------------------------------------------------------- 没有诶，fflush(stdin)这个也没用~~你可以跑下我代码试试？

引用 2 楼 lgbxyz 的回复: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>  #define TRUE 1 #define FALSE 0   char const CHARACTER_TABLE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";   int prepare_key(char *key);  int main(int argc, char *argv[]) { 	char input_letter[27] = {0}; 	 	do  	{ 		printf("Please input a letter: "); 		scanf("%[^\n]", input_letter); 	} 	while (prepare_key(input_letter)==TRUE);  	printf("The input letter is %s\n", input_letter);  	exit(EXIT_SUCCESS); }   /*  * if input letter is empty or contains un-alpha characters, or its length surpasses 26, just return FALSE  * */ int prepare_key(char *key) { 	if ( strlen(key)>26 || strlen(key)==0 ) 	{ 		return FALSE; 	}   	while ( *key!='\0' ) 	{ 		if ( !isalpha(*key) ) 		{ 			return FALSE; 		} 		key++; 	} 	return TRUE; }    --------------------------------------------------------------------------------------------- 请问你试过了么？


Question: 请将如下创建单链表的代码改为二级指针用参数带出头结点

问题算是被你回答了，但这是一种投机取巧的方法，内部实现还是一级指针，看我的代码： //C语言二级指针创建链表 #if 0 #include <stdio.h>   #include <stdlib.h>      typedef int ElemType;      typedef struct Node{       ElemType elem;       struct Node *next;   }Node, *LinkedList;      //void init_linkedlist(LinkedList *list) //{   //    *list = (LinkedList)malloc(sizeof(Node));   //    (*list)->next = NULL;   //}   //   //void insert(LinkedList list, ElemType elem) //{   //    Node *p, *q;   //    q = list;   //    p = (Node *)malloc(sizeof(Node));   //    p->elem = elem;   //    p->next = NULL;   //    while(q->next != NULL) q = q->next;   //    q->next = p;   //} void CreateList(LinkedList *p1, LinkedList *p2, LinkedList *head) { 	*p1 = *p2 = (LinkedList)malloc(sizeof(Node));  	while (scanf_s("%d", &(*p1)->elem)) 	{ 		if(NULL == *head) 		{ 			*head = *p1; 			(*head)->next = NULL; 		} 		else 		{ 			(*p2)->next = *p1; 			*p2 = *p1; 		} 		*p1 = (LinkedList)malloc(sizeof(Node)); 	} 	free(*p1); 	*p1 = NULL; 	(*p2)->next = NULL; }    void main() {   	/*LinkedList list, p;   	init_linkedlist(&list);   	insert(list, 3);   	insert(list, 4);   	insert(list, 5);   	p = list->next;   	while(p != NULL) {   		printf("%4d", p->elem);   		p = p->next;   	}   	printf("\n");  */  	LinkedList p1 = NULL, p2 = NULL, p = NULL, head = NULL; 	CreateList(&p1, &p2, &head); 	p = head;   	while(p != NULL) {   		printf("%4d", p->elem);   		p = p->next;   	}    }   #endif  看看这代码，能否有更好的答案呢？

有区别吗？ 不都是声明一级指针，然后取地址得到2级指针。

#include <stdio.h> #include <malloc.h>  //定义链表结点结构体 typedef struct _Node { 	int data; 	struct _Node* next;  }List;  void CreateList(List** ppHead) { 	List *head = NULL, *p1, *p2; 	 	if (NULL == ppHead) 	{ 		return; 	} 	 	p1 = p2 = (List*)malloc(sizeof(List));  	while (scanf("%d", &p1->data)) 	{ 		if(NULL == head) 		{ 			head = p1; 			head->next = NULL; 		} 		else 		{ 			p2->next = p1; 			p2 = p1; 		} 		 		p1 = (List*)malloc(sizeof(List)); 	} 	 	free(p1); 	*ppHead = head; }  int main(void) { 	List* pHead; 	CreateList(&pHead); 	 	if (NULL == pHead) 	{ 		return -1; 	} 	 	//operation 	 	//free list 	 	return 0; }


Question: 谁能给我一个w8可以安装的vs2010 .我是新手菜鸟。

win8可以用 使用VS社区版 免费的

学C语言用vc6.0不就行了    没必要用vs10吧

百度  MSDN我告诉你，找一个win8系统，重装。或者掉VS2010，装VS2013或者装vs2015


Question: 大一C语言课程设计通讯录管理系统，程序中有错误，求助高手

i也没赋值，你这怎么搞。

你那个edit()里的a变量没有赋值

for循环的边界值都错了 for(a=0; a < i; a++)


Question: C 实现输入字符串，存储到文件里面，然后打印出来

引用 9 楼 xdhyqd 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] #pragma warning(disable:4996) ... 除非专门说明，本ID一律使用VC6和VB6 赵老师，请问关于这个内存的分配呢？怎么分配到最优呢[/quote] 我的代码已经是分配到最优了。只是你没看出来而已。

引用 8 楼 zhao4zhong1 的回复:#pragma warning(disable:4996) ... 除非专门说明，本ID一律使用VC6和VB6 赵老师，请问关于这个内存的分配呢？怎么分配到最优呢

scanf  就是回车做结束符的， 把里面的内容（字符串）保存下来就行。 char buf[256]; scanf(“%s",buf);

引用 5 楼 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; }  This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.。 赵老师，你用的是什么版本呢

各位有误解哈，假如我要读入一个流，但是怎么分配内存才是最优的呢？试过一个一个读，然后在remalloc，感觉有点笨笨的，可有什么好想法

那你就用getchar(), 一个一个的读,如果超过之前malloc的长度就realloc. 还可以用setvbuf控制.

循环读取字符 /**************************************  *FILE    :D:\c\main.c  *PROJECT :NULL  *AUTHOR  :707wk  *CREATED :2015/7/10 13:33:43  *TEXT    :NULL  *EMAIL   :gtsoft_wk@foxmail.com  *CODE    :https://github.com/707wk  *LOGO    :                #########                                      ############                                    #############                                  ##  ###########                                ###  ###### #####                               ### #######   ####                             ###  ########## ####                           ####  ########### ####                        #####   ###########  #####                     ######   ### ########   #####                   #####   ###   ########   ######                ######   ###  ###########   ######             ######   #### ##############  ######           #######  ##################### #######          #######  ##############################        #######  ###### ################# #######       #######  ###### ###### #########   ######       #######    ##  ######   ######     ######       #######        ######    #####     #####         ######        #####     #####     ####           #####        ####      #####     ###             #####      ;###        ###      #                 ##       ####        ####                ***************************************/  #include <stdio.h>  int main() { 	char ch; 	FILE* fpout; 	FILE* fpin;  	fpout=fopen("data.txt","w"); 	for(;ch=getchar();) 	{ 		if(ch=='\n')break; 		fputc(ch,fpout); 	} 	fclose(fpout);  	fpin=fopen("data.txt","rb"); 	for(;!feof(fpin);) 	{ 		printf("%c",fgetc(fpin)); 	} 	fclose(fpin); 	 	return 0; }

是要确切的知道一共录入了多少个字符吗？如果是就把字符串读出来，直到读到\0，记录读取次数


Question: 第一次试着写linux的.so，总是有个错误，不知道哪里出了问题

编译的时候把库链接放在最后

编译 so gcc test.c -o libtest.so  -shared -fpic 会成生  libtest.so  编译main.c gcc -o test main.c  -L. -ltest  -Wl,-rpath,./  ------------------------------------------- gcc 时依赖要放在后面 linux 默认情况是不会在当前目去找 so  如果你的环竟 ld_libaray_path 也没指向当前目录  (可以用 ldconfig 来查看 ...)  所以要添加   -Wl,-rpath,./    (注：这个参中间不能有空格)

引用 6 楼 user-3 的回复:[quote=引用 5 楼 C_Java_php_python 的回复:] [quote=引用 3 楼 user-3 的回复:] 尝试一下改变gcc的选项顺序，比如gcc -L -ltest -o main.c gcc main.c -ltest -L. -o test 这个顺序可以，可是为什么？[/quote]这个或许跟gcc的版本有关系。。[/quote] 好吧

引用 5 楼 C_Java_php_python 的回复:[quote=引用 3 楼 user-3 的回复:] 尝试一下改变gcc的选项顺序，比如gcc -L -ltest -o main.c gcc main.c -ltest -L. -o test 这个顺序可以，可是为什么？[/quote]这个或许跟gcc的版本有关系。。

引用 3 楼 user-3 的回复:尝试一下改变gcc的选项顺序，比如gcc -L -ltest -o main.c gcc main.c -ltest -L. -o test 这个顺序可以，可是为什么？

引用 3 楼 user-3 的回复:尝试一下改变gcc的选项顺序，比如gcc -L -ltest -o main.c 也不行。。

引用 1 楼 user-3 的回复:暂时没看出问题来，能用nm 查看一下so的符号表么   这个吗？

暂时没看出问题来，能用nm 查看一下so的符号表么


Question: 古尺问题 回溯法解题

有点像八皇后？

要一次测量,就是只能用刻度之间, 每选一个刻度, 计数一下看是不是能够包含所有的值 int ruler[37],ans[10]; bool solve(int d){     if(d==9){         for(int i=1;i<36;i++) if(!ruler[i]) return false;         for(int i=1;i<=8;i++) printf("%d ",ans[i]);         return true;     }     for(int i=ans[d-1]+1;i<=27+d;i++){         ++ruler[36-i];         for(int d1=d-1;d1>=0;d1--) ++ruler[i-ans[d1]];         ans[d]=i;         if(solve(d+1)) return true;         for(int d1=d-1;d1>=0;d1--) --ruler[i-ans[d1]];         --ruler[36-i];     }     return 0; }  int main() {     solve(1);     return 0; }


Question: 发现csdn新增加的重要功能，顺便问一个makefile问题

1#楼用法没错，只是第四行少了一个右括号。     val=$(shell echo $(PWD)  $(shell ...) 跟 $(if ... ) ,$(filter ...)等一样，都是make的内建函数，可以用在makefile的任何地方。

引用 5 楼 chouxiaoya8100 的回复:[quote=引用 4 楼 hnwyllmm 的回复:] Makefile一般还有这个写法： .PHONY: clean clean:     -rm *.o $(TARGET) *.d core*  这里也没有放到rm下面 还有这个： $(DEPEND):%.d:%.c     $(CC) $(INCLUDE_PATHS) -MM $< > $@; \     echo "\t$(CC) $(CFLAG) $(INCLUDE_PATHS) $(MACRO_DEFS) $< -o $(@:.d=.o)" >> $@   为啥说一定要放在all下面呢   不管放哪里，为什么必须放在某个目标下才能调用shell呢？   这给我带来很大的麻烦。   还有，我想打印某个变量的值， 直接报错。  my_root = $(shell echo $${PWD%%xyz*}) val=3 ifeq ($(shell echo $(my_root)), $(shell echo $(PWD)))     val=$(shell echo $(PWD)     $(warning $(val))     $(warning $(my_root))    $(error dddddddddddd-------------) else      SRCROOT = $(my_root)xyz endif   就拿这个语法来说， echo $val 肯定报错。  不信自己试试。  [/quote]    o你试试我这个吧。就知道我为什么问你了

GNU make 查这个manual

不是的，这里有个例子，是可以在外面调的： obj-m=map_drv.o mod = map_drv KERNELDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd)  module-objs = map_drv.o  default:     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  clean:     rm -f *.o *.ko *.mod.c modules.order Module.symvers  install:     modprobe $(mod).ko

引用 4 楼 hnwyllmm 的回复:Makefile一般还有这个写法： .PHONY: clean clean:     -rm *.o $(TARGET) *.d core*  这里也没有放到rm下面 还有这个： $(DEPEND):%.d:%.c     $(CC) $(INCLUDE_PATHS) -MM $< > $@; \     echo "\t$(CC) $(CFLAG) $(INCLUDE_PATHS) $(MACRO_DEFS) $< -o $(@:.d=.o)" >> $@   为啥说一定要放在all下面呢   不管放哪里，为什么必须放在某个目标下才能调用shell呢？   这给我带来很大的麻烦。   还有，我想打印某个变量的值， 直接报错。  my_root = $(shell echo $${PWD%%xyz*}) val=3 ifeq ($(shell echo $(my_root)), $(shell echo $(PWD)))     val=$(shell echo $(PWD)     $(warning $(val))     $(warning $(my_root))    $(error dddddddddddd-------------) else      SRCROOT = $(my_root)xyz endif   就拿这个语法来说， echo $val 肯定报错。  不信自己试试。

引用 2 楼 hnwyllmm 的回复:ifeq后面为啥加个逗号？ 第二句那个就是调用shell语句 放在目标里是什么意思？ 引用 1 楼 jerry_dqh 的回复:使用echo 打印   就是说  all:    rm   cp   echo    all 就是makefile的一个目标，   echo , rm cp这些shell 命令，必须放在al里，不放在里面，  报语法错误。  但是你想， 只把shell 放在all中，不现实。

使用echo 打印


Question: 两个队列实现一个栈  下面代码是入栈的实现，编译通过，但是运行错误

void push_queue(Linkqueue **q1, Linkqueue **q2, int element) {     if((*q1)->front != (*q1)->rear)         Enqueue(q1, element);     else         Enqueue(q2, element); }   int main(int argc, char *argv[]) {     Linkqueue *q1 = NULL;     Linkqueue *q2 = NULL;               push_queue(&q1, &q2, 5);           return 0; }  木有变红呢？这句会崩吧？空指针怎么可能有数据？？

void push_queue(Linkqueue **q1, Linkqueue **q2, int element) {     if((*q1)->front != (*q1)->rear)         Enqueue(q1, element);     else         Enqueue(q2, element); }   int main(int argc, char *argv[]) {     Linkqueue *q1 = NULL;     Linkqueue *q2 = NULL;               push_queue(&q1, &q2, 5);           return 0; } 这句会崩吧？空指针怎么可能有数据？？

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


Question: 求助：windows服务程序实现局域网截屏功能

使用服务方式应该需要穿透Session 0隔离 http://www.cnblogs.com/therock/articles/2261371.html 这一篇是基于c#的，使用c进行系统调用更方便些

网上有人说用这个方法： 先DuplicateToken,SetTokenInformation把token的sessionid改成登录的用户的sessionid 然后用CreateProcessAsUser创建进程，在startupinfo中指定desktop为WinSta0\Default 这个子进程再调用你的抓取桌面的函数  没看的懂~你去试试，可以的话告诉我吧。急需

同样的问题，不知道楼主是怎么解决的？各种方法都用了 ，虚拟桌面什么的

引用 10 楼 zhao4zhong1 的回复:搜“Windows服务（Windows Service，system权限）程序显示界面与用户交互（xp，win7通用）”  我用的下面的方法 http://blog.csdn.net/harrymeinan/article/details/8440057   LaunchAppIntoDifferentSession((LPTSTR)bitmap->BitBltPicture()); 后 还是没有穿透session0，图片截取还是全黑。。。 函数BitBltPicture 是截图函数。

引用 7 楼 fly_dragon_fly 的回复:img.fromHBITMAP(m_hbmp); img.save(...) 试试 CImage没有成员fromHBITMAP

引用 6 楼 zhao4zhong1 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 设置服务属性、登录、允许服务与桌面交互 然后重启服务。[/quote] 还是不行。。我觉得是程序有问题。

引用 2 楼 zhao4zhong1 的回复:设置服务属性、登录、允许服务与桌面交互 然后重启服务。

引用 2 楼 zhao4zhong1 的回复:设置服务属性、登录、允许服务与桌面交互 图片大小特别小，只有10多K，是不是少了像素 位图大小设置的问题。

引用 1 楼 fly_dragon_fly 的回复:有没在本机上测试过能不能截 本机上也不可以，局域网内其他机器 也是全黑的图片。

引用 2 楼 zhao4zhong1 的回复:设置服务属性、登录、允许服务与桌面交互 允许了，还是那样。代码没问题吗？

设置服务属性、登录、允许服务与桌面交互

有没在本机上测试过能不能截


Question: 求一个用C语言实现的关于文件和链表的程序

ft -> b = (char *)malloc(ft ->f1)

[quote=引用 3 楼 zhao4zhong1 的回复:]  编译的时候这一行：ft -> b = malloc(ft ->f1)这行一个错误提示：“=”cannot convert from 'void *'to 'char *'但是不知道怎么改。还有赵老师能不能把这个程序功能说具体点，我是初学者看着很不理解。谢谢您了！

引用 2 楼 lgbxyz 的回复:智商不够用了,没看懂到底要干什么我们也是听的很迷糊，但是老师说让我们自己去想。让我们自己去完善这个问题。那意思好像就是：你们搞出来啥样是啥样！

引用 1 楼 user-3 的回复:文件目录是TREE吧：目录文件自己定义，什么类型都可以。

仅供参考：//将c:\\tmp文件夹下的所有文件的内容全部放到用malloc分配的内存中 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> struct FB {     char fn[256];     size_t fl;     char *b;     struct FB *next;     struct FB *prev; } *fh,*fb,*ft; char ln[256]; char fpn[256]; FILE *af; FILE *f; int L,n; int main() {     system("dir /b /a-d c:\\tmp\\*.* >c:\\allfn.txt");     af=fopen("c:\\allfn.txt","r");     if (NULL==af) {         printf("Can not open file c:\\allfn.txt!\n");         return 1;     }     fh=NULL;     fb=NULL;     n=0;     while (1) {         if (NULL==fgets(ln,256,af)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) ln[L-1]=0;         printf("read %s\n",ln);         strcpy(fpn,"c:\\tmp\\");         strcat(fpn,ln);         ft=(struct FB *)malloc(sizeof(struct FB));         if (NULL==ft) {             printf("Can not malloc ft!\n");             fclose(af);             return 2;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]==%p\n",n,ft);         strcpy(ft->fn,fpn);         f=fopen(fpn,"rb");         if (NULL==f) {             printf("Can not open file %s!\n",fpn);             fclose(af);             return 3;//之前的malloc在main退出后由操作系统自动free         }         ft->fl=_filelength(fileno(f));         ft->b=malloc(ft->fl);         if (NULL==ft->b) {             printf("Can not malloc ft->b!\n");             fclose(f);             fclose(af);             return 4;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]->b==%p\n",n,ft->b);         if (ft->fl!=fread(ft->b,1,ft->fl,f)) {             printf("fread error!\n");             fclose(f);             fclose(af);             return 5;//之前的malloc在main退出后由操作系统自动free         }         fclose(f);         ft->next=NULL;          if (NULL==fh) {             ft->prev=NULL;             fh=ft;         } else {             fb->next=ft;             ft->prev=fb;         }         fb=ft;         n++;     }     fclose(af);     printf("-----list-----\n");     for (ft=fh;NULL!=ft;ft=ft->next) {         printf("%8d %s\n",ft->fl,ft->fn);         if (NULL!=ft) fb=ft;     }     printf("-----free-----\n");     n--;     if (NULL!=fh) {         for (ft=fb->prev;NULL!=ft;ft=ft->prev) {             if (NULL!=ft->next->b) {                 printf("ft[%d]->b==%p\n",n,ft->next->b);                 free(ft->next->b);             }             if (NULL!=ft->next) {                 printf("ft[%d]==%p\n",n,ft->next);                 free(ft->next);             }             n--;         }         if (NULL!=fh->b) {             printf("ft[0]->b==%p\n",fh->b);             free(fh->b);         }         printf("ft[0]==%p\n",fh);         free(fh);     }     return 0; } //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //找不到文件 // //C:\tmp\tmp\Debug>tmp //找不到文件 //-----list----- //-----free----- // //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //2011-06-30  18:04            44,840 my_c.rar //2011-06-30  17:18             1,036 err.frm //2011-06-30  14:32            14,243 出租.txt //2011-06-28  12:08            23,681 MSDN98书签.txt //             4 个文件         83,800 字节 //             0 个目录 17,041,870,848 可用字节 // //C:\tmp\tmp\Debug>tmp //read my_c.rar //ft[0]==00421800 //ft[0]->b==00520068 //read err.frm //ft[1]==00421670 //ft[1]->b==0052AFC0 //read 出租.txt //ft[2]==00421530 //ft[2]->b==00378F28 //read MSDN98书签.txt //ft[3]==004213F0 //ft[3]->b==0052B3F8 //-----list----- // 44840 c:\tmp\my_c.rar //  1036 c:\tmp\err.frm // 14243 c:\tmp\出租.txt // 23681 c:\tmp\MSDN98书签.txt //-----free----- //ft[3]->b==0052B3F8 //ft[3]==004213F0 //ft[2]->b==00378F28 //ft[2]==00421530 //ft[1]->b==0052AFC0 //ft[1]==00421670 //ft[0]->b==00520068 //ft[0]==00421800 // //C:\tmp\tmp\Debug>

智商不够用了,没看懂到底要干什么

文件目录是TREE吧


Question: 怎么转化成C++程序？

请问博主，您的这个程序最后转换过来了吗

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


Question: 学习C语言的网站


Question: 递归与栈

更正：       x=   f(10)； //n=10  函数调用      f(n) ---->f(n-1)+f(n-2)                                        f(9) +f(8)

x=   f(10) //n=10  函数调用      f(n) ---->f(n-1)+f(n-1)                                        f(9) +f(8) 如此反复   调用树如下                        f(10)                     /          \                    f(9)    +     f(8)               /    \            /        \           f(8) + f(7)    f(7)  +  f(6)          /       ...............................................     /    \            f(2) +f(1)       /      \        \  f(1)+f(0)    1 1    + 1     当每一分支都到了，可以直接得到结果的时候，就返回上一步计算了  由于编译 和程序运行，是两个不同的步骤 而解析表达式，是在编译期间进行的 得到表达式结果，通常是在运行期间进行的。 所以  + 加法 可以确定的说，一定会在 f(n-1),f(n-2) 都计算出来后进行，除非出错 f(n-1) 和 f(n-2) 哪个先计算，则看编译器的安排了。 和程序里的顺序，并无必然联系。

f（n -1） + f（n - 2） 这个表达式解析  会 先解析两个函数递归调用 假设 n=10 , 即类似 x = f(10) 这种调用，那么 n-1=9,n-2 =8   f（n -1） + f（n - 2）这个表达式就会变成 f(9) +f(8) 的计算 f(9) 会变成 f(8)+f(7) ,,,,,直到 计算出最内层的 例如 f(2) +f(1) 这一步， f(2) 会继续递归 为 f(1)+f(0) ,  f(1) 则是直接得到结果 1 f(0) 同样是 接得到结果 1 这样的到结果的调用递归结束，返回上一步继续计算 直到 f(9) ,f(8) 的结果都计算出来了 把 f(9)+f(8) 这个表达式（加法） 计算出来 ，整个递归结束。 递归调用必须能够终止，无休止的递归调用是个灾难 。。。。。。。 另外，计算 .斐波那契数列， 不是好的递归应用场景，递归很快就会耗尽堆栈，从而得不到结果，并且很可能会出错退出，甚至引发其他灾难性的错误。

新人还是不怎么懂  函数执行到 f（n -1） + f（n - 2）这句时，执行到f（n-1）就又返回递归了，那 + f（n-2）是啥时候执行的，等f（n-1）得到结果在执行+f（n-2）吗。。。真是搞懵掉了

用递归求，就不需要栈了吧

int f(int a, int b)   // 递归 {    //    假设局部变量需要cSize空间   //        那么每调用一次需要:     //         压栈 f 地址, (4字节) (esp -4)     //          压栈 b, a, (4*2字节)(esp -4 *4)     //          分配栈内空间:  cSize字节 (esp -cSize)     //           所以递归一次需要4 + 4*2 +cSize栈空间    //           返回反之, esp + cSize + 4*2 +4      }

你写一个上述的程序，再单步调试一下不就清楚了

函数的每一次调用，都要给函数的参数准备空间。 所以函数定义本身，并没有为参数分配内存（寄存器），函数调用才是参数分配内存（寄存器）的时候。 函数局部（非静态）变量，也是在函数调用的时候分配内存（寄存器）的。

程序在调用函数的地方压栈，函数退出的时候出栈，无参函数主要处理 函数调用和返回。 有参数的函数，还要压栈函数参数，出栈要清理函数参数。  循环处可能也需要， 压栈出栈。 表达式的计算。 也需要压栈出栈---函数调用也是表达式， 所以函数返回值压栈出栈，不属于函数调用本身，而是属于表达式计算的过程。 本质上，函数递归调用，和函数调用没啥两样。  递归函数和非递归函数，唯一不同之处是函数有没有，直接间接调用自己。  递归函数，要求函数必须能够终止递归调用，不能无休止的递归下去。

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

我就是想问用递归实现斐波那契数列，程序是怎么走的，压栈，出栈是怎么一个过程


Question: 请各位高手帮忙看一下，把n=strlen（p）但是这个n不能用于for循环的条件

按照你说的功能写的  char p[] = "wqasdflj"; 	int n = strlen(p); 	for (int i = 0; i < n / 2; i++) 	{ 		char ch = p[i]; 		p[i] = p[n - 1 - i]; 		p[n - 1 - i] = ch; 	}

i=0时      p[n-i]  = p[n]   = '\0' swap(p[0],p[n-i]),此时    p[0] ='\0' 这时候 按cha*读字符串  应该是空字符串吧

n=strlen(p); ===> n=strlen(p) - 1;

可以呀，同四楼

对了、用n=strlen(p);的时候最后用puts（p）则只是空白的一行


Question: 二叉树遍历运行出错unhandled exception in XXx.exe 0xC0000005;Access Violation

刚刚注册，还不是很会用······ 不过 ，楼主在这里很谢谢大家的回答，问题答案在第二天和老师谈论过了。在这里也和大家分享一下，以便以后遇到同样问题的小伙伴少跑路。 楼主没有把全部的程序放出来，就像 logiciel说的，要全部程序的话，需要加上头文件，这里就不多说了。  楼主刚写完时，是用vc6.0来编译运行的，但更致命的是还是汉化版。和老师讨论了一下，汉化版的vc6.0会出现很多莫名其妙的错误，这是没办法纠正的。所以如果小伙伴的程序也出现这种错误时，在再三检查编译错误无错时，可以视为无错。然后看看运行会不会输出想要的结果，如果输出了，就不要太在意断这个问题了。如果没有出现想要的结果时，那么肯定就是自己的编译有问题了，再仔细查找一下，一定有答案。  再说回二叉树这个程，虽然运行出错，断开，但能输出结果。然后楼主把所有任务都单调试一遍，除了运行时都会出现错误（也就是错误相同），其他都对。之后楼主做了菜单可以选择任务，再进行运行时，就没有出现错误了。所以楼主建议出现这种错误的小伙伴不要着急，只要有输出结果，忽略就好了······ 以上纯属楼主个人意见，楼主是个初学者，有疑问还请指教。

在楼主代码前加了以下4行： #include <stdio.h> #include <stdlib.h> #define OVERFLOW 0 #define OK 1  运行输入以下例子没有出错： 请输入您要建立的二叉树 123##4##56##7## 该二叉树的先序遍历为： 1234567 该二叉树的中续遍历为： 3241657 该二叉树的后续遍历为： 3426751  “中续”要改为“中序”。“后续”要改为“后序”。

仅供参考：#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G


Question: #include“socket.c"我在C语言开源代码中看到的

谢谢楼上各位啦

可以这样做，就想当于复制了一份代码到这里。

可以的，c++语言也一样

C语言可以包含任何后缀名的文件, 当然前提是文件中的内容得是C语言语句. #include "xxx" 只是在预处理时将xxx文件的内容完全展开,后缀名什么的根本不重要.

#include"socket.c" 头文件还可以包含.c文件吗


Question: 一个编程题，大家探讨下

话说文曲星上有个类似的游戏好像

貌似算法入门经典中有这道题

没什么特别好的办法,直接用dfs或者bfs去搜, 只有二种状态考虑二进制位表示每一格.

不像是编程题，倒像是逻辑推理题了，看起来有点意思，怎么没有人回复了，顶一下！


Question: c语言，U盘识别

windows的不了解。 linux下的如上面前辈们说的，需要文件系统支持，其实也就是加载对应的驱动（默认fat32支持，ntfs的可能需要单独加载驱动）。 linux下视版本，一般可监控系统文件/proc/bus/input/devices（有的是/proc/bus/usb/devices）获取到usb设备信息（设备号，厂商号等），再根据设备号，厂商号自行创建设备节点（/dev目录下sda，sdb这样的），再把对应的节点挂载到某个路径下，就可访问了。 另外hotplug可以看看，libusb也可以了解下（缺点是，插入多个usb设备无法区分，可能需要用户根据u盘里的标识文件来自行判断）

这个要OS了，不光C语言了。

用netlink,  监听热插拔事件， 就可以了。代码不多

WM_DEVICECHANGE 其中lParam是PDEV_BROADCAST_HDR类型 话说上MSDN找不会更快吗

搜索 hotplug

我觉得应该上驱动了，挂钩文件系统，每当有磁盘接入或移除的时候，都会产生一个请求包，拦截这个请求包就可以得到要变动的磁盘信息。 如果不上驱动的话，我觉得只能不断检查A盘到Z盘是否存在来判断了。

这个恐怕不是只学会c语言就可以搞定的，我这个菜鸟也只能帮你顶一下了

去看USB协议


Question: 函数中变量实时取值请大家给一个解决办法。

引用 17 楼 zhao4zhong1 的回复:

引用 13 楼 lm_whales 的回复:例如共享内存策略，其中内存映射文件，是现代操作系统提供的一种数据共享方式 其他，如写到文件中，通过 有名无名管道通讯， 通过 网络接口通讯 单机版，可以通过 测试地址127.0.0.1 实现两个进程通讯 。 这个地址，是不用联网就可以使用的网络地址  我现在就正在写进程间通讯。谢谢你啦。

引用 11 楼 zhao4zhong1 的回复:问我啊！ 哈哈，那真是太好了!

引用 10 楼 fly_dragon_fly 的回复:放在全局或者static不行吗 对  就是这样。刚才脑子短路了

外部接收？网？串口？其它程序，如dos命令行，unix,linux ,shell 命令？ 那就需要同步一下了 可能涉及进程间通讯问题， 进程通讯的话，一般都是不同操作系统，方法不同， 但也都更多的是同步问题。 至于如何处理，接收到的数据，只是个策略问题。

引用 7 楼 leee7338 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 学习时间的长短有时不重要。 是否带着问题去学有时很重要。 学的时候有没有师傅带，师傅的水平够不够高，有时很重要。  我是带着问题学习，遇见问题自己想办法，实在解决不了的就来这问大家，可我感觉这样太耽误时间了， 领导让我有问题问旁边的同事，可我每次问他如果很简单的就会给我说的很细，唠唠叨叨的我又不好打断，如果难的就会讲一通然后糊弄过去，我现在都不问他了，因为我怕他会误导我。领导整天忙，我想去问又不好打扰。哎！其他人都是做java的。 [/quote] 问我啊！

放在全局或者static不行吗

引用 16 楼 leee7338 的回复:[quote=引用 13 楼 lm_whales 的回复:] 例如共享内存策略，其中内存映射文件，是现代操作系统提供的一种数据共享方式 其他，如写到文件中，通过 有名无名管道通讯， 通过 网络接口通讯 单机版，可以通过 测试地址127.0.0.1 实现两个进程通讯 。 这个地址，是不用联网就可以使用的网络地址  我现在就正在写进程间通讯。谢谢你啦。[/quote]

引用 8 楼 zhangxiangDavaid 的回复:又见 fflush(stdout); rewind(stdin);

又见 fflush(stdout); rewind(stdin);

引用 5 楼 zhao4zhong1 的回复:学习时间的长短有时不重要。 是否带着问题去学有时很重要。 学的时候有没有师傅带，师傅的水平够不够高，有时很重要。  我是带着问题学习，遇见问题自己想办法，实在解决不了的就来这问大家，可我感觉这样太耽误时间了， 领导让我有问题问旁边的同事，可我每次问他如果很简单的就会给我说的很细，唠唠叨叨的我又不好打断，如果难的就会讲一通然后糊弄过去，我现在都不问他了，因为我怕他会误导我。领导整天忙，我想去问又不好打扰。哎！其他人都是做java的。

《Windows核心编程》

引用 4 楼 leee7338 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] //一个程序，包括两个函数func1();func2();和一个main(); //main函数中根据flag来选择调用这两个函数中的其中一个， //调用func1函数时可以接收一个字符串保存在buff数组中， //而调用func2函数时需要用到这个字符串， //请问该怎么做  能在调用func2的时候能得到上一次func1接收的字符串？ #include <stdio.h> #include <string.h> char buff[256]; void func1() {     rewind(stdin);     fgets(buff,256,stdin);     if ('\n'==buff[strlen(buff)-1]) buff[strlen(buff)-1]=0; } void func2() {     printf("buff:[%s]\n",buff); } int main() {     int flag=1;      while (1) {         printf("flag:");fflush(stdout);         rewind(stdin);scanf("%d",&flag);         switch (flag) {             case 1:func1();break;             case 2:func2();break;             case 0:return 0;         }     }     return 0; } //flag:2 //buff:[] //flag:1 //Hello, world! //flag:2 //buff:[Hello, world!] //flag:0 //  不是一次执行，是如果执行两次改怎么获得。。。。、 不过现在想通了  惭愧啊！麻烦赵四老师了。   顺便问大家一个问题：我每天从9点开始上班，5点半下班。晚上8点学习到11点半回去睡觉， 照这样下去  我多久才能成为一个合格的C程序员？ [/quote] 学习时间的长短有时不重要。 是否带着问题去学有时很重要。 学的时候有没有师傅带，师傅的水平够不够高，有时很重要。

引用 2 楼 zhao4zhong1 的回复://一个程序，包括两个函数func1();func2();和一个main(); //main函数中根据flag来选择调用这两个函数中的其中一个， //调用func1函数时可以接收一个字符串保存在buff数组中， //而调用func2函数时需要用到这个字符串， //请问该怎么做  能在调用func2的时候能得到上一次func1接收的字符串？ #include <stdio.h> #include <string.h> char buff[256]; void func1() {     rewind(stdin);     fgets(buff,256,stdin);     if ('\n'==buff[strlen(buff)-1]) buff[strlen(buff)-1]=0; } void func2() {     printf("buff:[%s]\n",buff); } int main() {     int flag=1;      while (1) {         printf("flag:");fflush(stdout);         rewind(stdin);scanf("%d",&flag);         switch (flag) {             case 1:func1();break;             case 2:func2();break;             case 0:return 0;         }     }     return 0; } //flag:2 //buff:[] //flag:1 //Hello, world! //flag:2 //buff:[Hello, world!] //flag:0 //  不是一次执行，是如果执行两次改怎么获得。。。。、 不过现在想通了  惭愧啊！麻烦赵四老师了。   顺便问大家一个问题：我每天从9点开始上班，5点半下班。晚上8点学习到11点半回去睡觉， 照这样下去  我多久才能成为一个合格的C程序员？

引用 1 楼 lm_whales 的回复:函数参数传递，是最简单的方法，C 可以用全局变量，C++ 只要定义一个类，方法在类内定义 并在main函数内部，定义一个 对象，就可以了。 可能是我说的有问题。让你理解错了。 这个程序是从外面接收一个命令，main函数由这条命令来判断要调用哪个函数， 如果前两次运行行先调用了两次func1，接收了两次字符串， /*写到这里的时候我突然明白过来了，还是写完吧。就是怕大家笑话我，因为我写的程序是一直在运行的，不停的接收和发送*/ 若第三次main要调用func2来发送最近一次func1接收的字符串，改怎么办？除了建立文件。 还是谢谢你。


Question: 如何利用动态数组实现多选一，求助大神！

为什么要动态数组，我这只是举列100道题，因为题是可以随意增加减少。十个人每人最多可选择10道题（1~10）.用C++实现

c++的话可以用std::set

首先你得知道什么是动态数组! 你是想用C++的vector吧

仅供参考：#include <stdio.h> #include <stdlib.h> #include <time.h> int d[6]; int i,n,a,b,t; int c,j; void main() {     srand(time(NULL));     printf("shuffle 0..n-1 demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=0;i<n;i++) d[i]=i;/* 填写0～n-1 */             for (i=n;i>0;i--) {/* 打乱0～n-1 */                 a=i-1;b=rand()%i;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=0;i<n;i++) printf("%d",d[i]);             printf("\n");         }     }     printf("shuffle 1..n demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=1;i<=n;i++) d[i]=i;/* 填写1～n */             for (i=n;i>1;i--) {/* 打乱1～n */                 a=i;b=rand()%i+1;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=1;i<=n;i++) printf("%d",d[i]);             printf("\n");         }     } }

这种事情明显用普通的数组更好啊   为毛要用什么动态数组........  每个课程都设一个属性：是否被选  没有被选 就能被人选 被选了  就不能被人选

it looks good.

少了一行代码。   typedef struct problem{     bool isSelected;     char *text;     int  id; }PRM;  typedef struct student{     char *name;     int  prmNum;     int  prmList[10]; }STU;  PRM prmList[100] = {/*BLABLA*/}; STU stuList[10] = {/*BLABLA*/};  void select(PRM prmList[100], STU *stu){     for(int i = 0;i<100 && stu->prmNum < 10;i++){         //判断该题目是否已被选走         if(prmList[i].isSelected == true)             continue;         else         {             //如果选择该题目，则修改学生对应的已选题目数量和已选题目列表             stu->prmNum++;             stu->prmList[stu->prmNum] = prmList[i].id;         }     } }  for(int i = 0; i < 10;i++){     select(prm[100],stuList[i]); }

首先，你既然已经固定了100道题目，为什么还要动态数组？ 是想要被选中的题目删除掉？ 那直接定义一个结构体设置一个FLAG isSelected 不就好了么？  大致写了一段代码如下（没有编译，当做伪代码看好了）  typedef struct problem{     bool isSelected;     char *text;     int  id; }PRM;  typedef struct student{     char *name;     int  prmNum;     int  prmList[10]; }STU;  PRM prmList[100] = {/*BLABLA*/}; STU stuList[10] = {/*BLABLA*/};  void select(PRM prmList[100], STU *stu){     for(int i = 0;i<100;i++){         if(prmList[i].isSelected == true)             continue;         else         {             stu->prmNum++;             stu->prmList[stu->prmNum] = prmList[i].id;         }     } } for(int i = 0; i < 10;i++){     select(prm[100],stuList[i]); }

bool selected[101] , 作为全局可好


Question: 汇编转C语言

将StatusReg的值装入寄存器SR中。


Question: 大家帮忙看看

先翻译成算术表达式：  #include <stdio.h> #include <string.h> char *NUMBERS_UP_TO_10[] = { 	"zero", "one", "two", "three", "four", 	"five", "six", "seven", "eight", "nine", }; int get_num(char *word) { 	int i = 0; 	while (i < 10) 	{ 		if (0 == strcmp(word, NUMBERS_UP_TO_10[i])) return i; 		i++; 	} 	return -1;   //word错误 } char *word_to_num(char *s) { 	int i, j, k; 	i = j = k = 0; 	char word[10]; 	while(1) 	{ 		if ('=' == s[k]) break; 		else if ('+' == s[k] || '-' == s[k] || '*' == s[k] || '/' == s[k] || '%' == s[k]) 		{ 			s[i++] = ' '; 			s[i++] = s[k]; 			s[i++] = ' '; 			k += 2; 			j = k; 		} 		else 		{ 			while ('=' != s[k] && ' ' != s[k]) k++; 			if ('=' != s[k]) 			{ 				strncpy(word, s + j, k - j); 				word[k - j] = 0; 				s[i++] = get_num(word) + '0'; 				j = ++k; 			} 		} 	} 	s[i++] = ' '; 	s[i++] = '='; 	s[i] = 0; 	return s; } int main(void) { 	char s[100]; 	while (1 == scanf("%100[^\n]s", s)) 	{ 		rewind(stdin); 		printf("%s\n", word_to_num(s)); 	} 	return 0; } //one + two = //0 + 1 = //three four + five six = //34 + 56 = //zero seven + eight nine = //07 + 89 = //zero + zero = //0 + 0 =

仅供参考：#pragma warning(disable:4996) #include <stdio.h> char *NUMBERS_UP_TO_20[] ={     "zero"   ,"one"    ,"two"     ,"three"   ,"four"    ,     "five"   ,"six"    ,"seven"   ,"eight"   ,"nine"    ,     "ten"    ,"eleven" ,"twelve"  ,"thirteen","fourteen",     "fifteen","sixteen","sventeen","eighteen","nineteen", }; char *NUMBERS_MULTIPLE_OF_10[] ={     "twenty", "thirty" , "fourty", "fifty" ,     "sixty" , "seventy", "eighty", "ninety", }; char *NumberToString(long long int nNum,char *p) {     char *q;     int n;     long long int nCrntNumber;      q=p;     if (nNum<0) return "";     if (nNum<20) return NUMBERS_UP_TO_20[nNum];      nCrntNumber=nNum/1000000000;     if (nCrntNumber>0) {         n=sprintf(p,"%s billion ",NumberToString(nCrntNumber,p));         p+=n;         nNum%=1000000000;     }      nCrntNumber=nNum/1000000;     if (nCrntNumber>0) {         n=sprintf(p,"%s million ",NumberToString(nCrntNumber,p));         p+=n;         nNum%=1000000;     }      nCrntNumber=nNum/1000;     if (nCrntNumber>0) {         n=sprintf(p,"%s thousand ",NumberToString(nCrntNumber,p));         p+=n;         nNum%=1000;     }      nCrntNumber=nNum/100;     if (nCrntNumber>0) {         n=sprintf(p,"%s hundred ",NumberToString(nCrntNumber,p));         p+=n;         nNum%=100;     }      if (0<nNum && nNum<20) {         n=sprintf(p,"%s ",NumberToString(nNum,p));         p+=n;     } else {         nCrntNumber=nNum/10;         if (nCrntNumber>0) {             n=sprintf(p,"%s ",NUMBERS_MULTIPLE_OF_10[nCrntNumber-2]);             p+=n;             nNum%=10;         }          nCrntNumber=nNum;         if (nCrntNumber>0) {             n=sprintf(p,"%s ",NumberToString(nCrntNumber,p));             p+=n;         }     }      if (p[-1]==' ') p[-1]=0;      return q; } int main() {     char sRes[256];     long long int d;      d=                  0  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                  1  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                  9  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                 19  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                 20  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                 21  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                 90  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=                100  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=               2000  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=            3000000  ;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=         4000000000ll;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=1000000000000000002ll;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=1234567890123456789ll;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));     d=9223372036854775807ll;printf("%19lld is [%s]\n",d,NumberToString(d,sRes));//2^63-1     return 0; } //                  0 is [zero] //                  1 is [one] //                  9 is [nine] //                 19 is [nineteen] //                 20 is [twenty] //                 21 is [twenty one] //                 90 is [ninety] //                100 is [one hundred] //               2000 is [two thousand] //            3000000 is [three million] //         4000000000 is [four billion] //1000000000000000002 is [one billion billion two] //1234567890123456789 is [one billion two hundred thirty four million five hundred sixty seven thousand eight hundred ninety billion one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine] //9223372036854775807 is [nine billion two hundred twenty three million three hundred seventy two thousand thirty six billion eight hundred fifty four million seven hundred seventy five thousand eight hundred seven] //

参考     http://blog.csdn.net/cyg0810/article/details/8011972


Question: MFC鼠标移动画线并获取坐标

请问这是什么？

MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl MSDN98\SAMPLES\VC98\MFC\TUTORIAL\SCRIBBLE\STEP1～7\*.*


Question: 错误求解释

引用 1 楼 chengye_xin 的回复:你连代码都没贴叫人怎么看？ 不好意思…不过问题已经解决了。刚在函数的左花括号后面加了个右花括号没注意到，]任然谢谢你。

你连代码都没贴叫人怎么看？


Question: TCP网络通信缓存不够，如何接收全部数据？

引用 7 楼 zxh707wk 的回复:分多次发送呗   分发目前是不行的，我客户端是一个调测软件，服务端是被动接收客户端发送来的数据，等后面要写客户端的话才能分多次发送

引用 6 楼 xian_wwq 的回复:缓存够不够都需要循环判断接收， 否则就有可能接收不全   缓存是足够了，我自己写了个简单的客户端程序，发送3300多字节的数据，服务端有的时候接受全了，有的时候也只接收了2000多字节的数据；  大神能不能给段代码，如何进行循环接收？

引用 8 楼 qq_27115241 的回复:[quote=引用 6 楼 xian_wwq 的回复:] 缓存够不够都需要循环判断接收， 否则就有可能接收不全   缓存是足够了，我自己写了个简单的客户端程序，发送3300多字节的数据，服务端有的时候接受全了，有的时候也只接收了2000多字节的数据；  大神能不能给段代码，如何进行循环接收？[/quote] //接收数据后，解析包头得到需要接收的数据长度 int nSendLen = GetPacketLen(); int nRecLen = 0;  //接收计数 //循环接收 while(true) {      //累计每次接收的长度      nRecLen += RecData();      if( nRecLen >= nSendLen)      {          //如果已经收够           break;      }     //如果没有收全，则继续 } //对接收数据根据长度“分包”及进行后续处理     ParseData(...)

缓存够不够都需要循环判断接收， 否则就有可能接收不全

分多次发送呗

TCP传输的数据可以看作是字节流。就好比两个进程通过管道传输文件，管道里面只能容纳512字节的数据，但是文件却有1MB‘，那怎么办呢？很简单啊，发送者不停的读文件到内存，然后发送到管道中；接收者不停的从管道中读取数据，再写到文件中。至于接收者如何判断文件发送结束了，要么双方指定一个协议，这样接收者能够明确的知道文件发送完成；要么发送者发完文件后关闭管道，接收者read返回0就代表文件发送完成。

每次接收到数据后缓存到自定义的队列中，最后集中处理

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

TCP协议有滑动窗口的，一次发不完，会分多次发送的。

http协议里面有个thunked方式下载数据，楼主感兴趣的话，可以参考下


Question: 如何用C程序自动获取局域网可用IP（不是DHCP）

引用 1 楼 user-3 的回复:自己随便设一个，然后ping这个地址，没回应就用呗 因为要用C实现，随便设一个网段不知道，跨网段也不一定可以ping通，如果上百台机器，ping过去会不会效率很低

要想在局域网内通信就必须有个IP地址呀， 你们说的都是在电脑上，电脑是本身有DHCP获取了可用ip的， 所以可以ping啊，或者发送arp包呀这些可以与其他主机交互，然后去发现局域网里有哪些可用ip， 现在不用DHCP，就是想给小盒子（用来测试网络的）分配一个可用的IP地址怎么办（当然DHCP和手动分配可以，但很多企业不开启DHCP服务，手动设置IP要询问管理员，所以想问有没有什么自动发现可用IP的方法）

引用 4 楼 zh_kun 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 仅供参考：#include <windows.h> #include <stdio.h> #include <string.h> char YN(int k) {     FILE *f;     char fn[40];     char ln[80];     char yn;     int n;      yn='N';     sprintf(fn,"d:\\ping%d.txt",k);     f=fopen(fn,"r");     if (NULL!=f) {         n=0;         while (1) {             if (NULL==fgets(ln,80,f)) break;//             if (strstr(ln,"ms ")) {                 yn='Y';                 break;//             }             n++;             if (n>=4) break;//         }         fclose(f);     }     return yn; } void main(int argc,char **argv) {     char cmdstr[256];     int i;     int IP[3];     char c;      if (argc<2) {     USAGE:         printf("Usage example:\n    %s 192.168.60.\nto test 192.168.60.1-254\n",argv[0]);         return;     }     if (4==sscanf(argv[1],"%d.%d.%d%c",&IP[0],&IP[1],&IP[2],&c)) {         if (0<=IP[0] && IP[0]<=255          && 0<=IP[1] && IP[1]<=255          && 0<=IP[2] && IP[2]<=255          && '.'==c) {             for (i=1;i<255;i++) {                 sprintf(cmdstr,"cmd /c ping %s%d -n 1 -w 1000 >d:\\ping%d.txt",argv[1],i,i);                 WinExec(cmdstr,SW_HIDE);             }             Sleep(3000);             for (i=1;i<255;i++) {                 printf("%c %s%d\n",YN(i),argv[1],i);             }             Sleep(3000);             WinExec("cmd /c del /q d:\\ping*.txt",SW_HIDE);         } else goto USAGE;     } else goto USAGE; }  你好感谢你的回答，因为是用的linux系统，没有办法测试，我看你也是用的ping吧，是知道网络地址（一般都是C类192.168.*.*吧），是从主机地址为0.0的挨个ping吗？而且跨网段好像ping不通，那我要想ping是不是要先在程序中设一个ip，因为是个小盒子没有界面，我也不知道该怎么办啦！主要没有思路（麻烦您了）...[/quote]  你不会加个手动输入网段的代码吗……………………

引用 3 楼 zhao4zhong1 的回复:仅供参考：#include <windows.h> #include <stdio.h> #include <string.h> char YN(int k) {     FILE *f;     char fn[40];     char ln[80];     char yn;     int n;      yn='N';     sprintf(fn,"d:\\ping%d.txt",k);     f=fopen(fn,"r");     if (NULL!=f) {         n=0;         while (1) {             if (NULL==fgets(ln,80,f)) break;//             if (strstr(ln,"ms ")) {                 yn='Y';                 break;//             }             n++;             if (n>=4) break;//         }         fclose(f);     }     return yn; } void main(int argc,char **argv) {     char cmdstr[256];     int i;     int IP[3];     char c;      if (argc<2) {     USAGE:         printf("Usage example:\n    %s 192.168.60.\nto test 192.168.60.1-254\n",argv[0]);         return;     }     if (4==sscanf(argv[1],"%d.%d.%d%c",&IP[0],&IP[1],&IP[2],&c)) {         if (0<=IP[0] && IP[0]<=255          && 0<=IP[1] && IP[1]<=255          && 0<=IP[2] && IP[2]<=255          && '.'==c) {             for (i=1;i<255;i++) {                 sprintf(cmdstr,"cmd /c ping %s%d -n 1 -w 1000 >d:\\ping%d.txt",argv[1],i,i);                 WinExec(cmdstr,SW_HIDE);             }             Sleep(3000);             for (i=1;i<255;i++) {                 printf("%c %s%d\n",YN(i),argv[1],i);             }             Sleep(3000);             WinExec("cmd /c del /q d:\\ping*.txt",SW_HIDE);         } else goto USAGE;     } else goto USAGE; }  你好感谢你的回答，因为是用的linux系统，没有办法测试，我看你也是用的ping吧，是知道网络地址（一般都是C类192.168.*.*吧），是从主机地址为0.0的挨个ping吗？而且跨网段好像ping不通，那我要想ping是不是要先在程序中设一个ip，因为是个小盒子没有界面，我也不知道该怎么办啦！主要没有思路（麻烦您了）...

自己随便设一个，然后ping这个地址，没回应就用呗


Question: 求助大神，帮我找出错误并改正

一共就是这些函数么，是不是有什么地方用不同的类型重定义了？

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

可以具体用英文写吗？这实在看不懂，谢谢

在你声明sear_开头的这些函数的.h文件加上  #ifndef  XX_H_ #define XX_H_  #endif //假如是menu.h的话可以用  #ifndef _MENU_H_ #define _MENU_H_ //这里填你原本的文件内容 #endif

是做一个财务系统 #include "stdio.h" #include "stdlib.h"          //常用子程序 #include "string.h" #include "dos.h"             //Ms-dos和8086调用的一些常量和函数 #include "windows.h"  #define LEN sizeof(Node) #include "mytypedef.h"//加载自定义结构 #include "menu.h"//加载菜单   int menu_select();//声明函数  int main(int argc,char *argv[])  { 	link l; 	l=(Node *)malloc(LEN); 	l->next=NULL; 	show_menu(); 	while(1) 	{ 		switch(menu_select())  //调用菜单函数 		{ 		case  1:  			luru(l);    			break;  	    case  2:    			save(l);     			break;  		case  3:    			load(l);   			break;  		case  4:    			xianshi(l);     			break;  		case  5:    			add(l);   			break;  		case  6:   			sear(l);   			break;  	    case  7:    			del(l);  			break;  		case  8:   			printf("您选择的是8");   			break;  		case  9:    			exit(0); 		} 	} }

main函数在哪？

移动上去，又出现main.obj : error LNK2001: unresolved external symbol _xianshi main.obj : error LNK2001: unresolved external symbol _luru Debug/GJP.exe : fatal error LNK1120: 2 unresolved externals 执行 link.exe 时出错.

你把下面那几个sear_开头的函数都移动到sear函数前面去。这是由于还没实现函数就用了的原因。英文提示是重定义函数，说明你在mytypedef.h里定义了这些函数。


Question: 【求助】网址字符串翻转

我写的大体思路             a = "www.baidu.com"            sscanf(a, "%s.%s.%s", b, c, d);  // "3[a-z].3[a-z].3[a-z]"  这个也行吧 你试试           b-> www           c->baidu           d->com           sprintf(f, "%s.%s.%s", d, c b);            f -> com.baidu.www

#include <stdio.h> #include <stdlib.h> #include <string.h>  int main(void) { 	char url[] = "www.baidu.com.cn"; 	char reverse_url[32] = {0}; 	char* pdot = url;  	pdot = strrchr(url, '.'); 	while(pdot != NULL)  	{ 		*pdot = '\0'; 		strcat(reverse_url, pdot + 1); 		strcat(reverse_url, "."); 		pdot = strrchr(url, '.'); 	} 	strcat(reverse_url, url);  	printf("%s\n", reverse_url); 	return 0; }

//www.baidu.com反转成com.baidu.www #include <stdio.h> #include <string.h> int main() {     char *s="www.baidu.com";     char a[20],b[20],*p[10],*q;     int i,n,L;      strncpy(a,s,19);a[19]=0;     i=0;     p[i]=strtok(a,".");     while (1) {         if (p[i]==NULL) break;         i++;         if (i>=10) break;         p[i]=strtok(NULL,".");     }     n=i;     L=0;     q=b;     for (i=n-1;i>=0;i--) {         if (i==0) {             L=sprintf(q,"%s",p[i]);         } else {             L=sprintf(q,"%s.",p[i]);         }         q+=L;     }     printf("[%s]\n",b);     return 0; } //[com.baidu.www] //

a.join(".")

ruby的方法是


Question: wireshark 抓SMTP包，邮件正文的还原

最好还是翻翻协议吧 标准的协议包括 smtp,imap,pop3 还有个eml文件的格式

通读SMTP协议？


Question: 有a，b两个等量数组，需要将a数组中的数依次取出分别与b数组中的数挨个相加得到新的数组再输出新数组的和

#include <stdio.h>  int main(void) {     int i = 0; //for loop     int sum_b = 0;     int sum_c = 0;     int count = 0;     int a[] = {1, 2, 3, 4, 5};      int b[] = {1, 2, 3, 4, 5};       count = sizeof(b) / sizeof(b[0]);     for (i = 0; i < count; i++)     {            sum_b += b[i];     }         for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)     {            sum_c = sum_b + a[i] * count;         printf("c[%d] = %d\n", i, sum_c);      }         return 0; }

//先将数组b中的数字全部加起来得到一个和值，然后将数组a中的每个数乘以5加上那个和值，也得到你想要的数啦 #include<iostream> using namespace std; void main() { 	int a[]={1,2,3,4,5}; 	int b[]={1,2,3,4,5}; 	int lena=sizeof(a)/sizeof(int); 	int lenb=sizeof(b)/sizeof(int); 	int cursum=0; 	for(int i=0;i<lenb;i++) 	{ 		cursum+=b[i]; 	} 	cout<<cursum<<endl; 	for(int j=0;j<lena;j++) 	{ 		int sum=0; 		sum=cursum+a[j]*5; 		cout<<sum<<endl; 	} }

凑个热闹：  2.2.1 :006 > a = (1..5).to_a  => [1, 2, 3, 4, 5]  2.2.1 :007 > b = (1..5).to_a  => [1, 2, 3, 4, 5]  2.2.1 :008 > a.each do |x| 2.2.1 :009 >     c = b.map {|y|y+x} 2.2.1 :010?>   total = c.inject {|s,i|s+i} 2.2.1 :011?>   puts "#{c.join(" + ")} = #{total}" 2.2.1 :012?>   end 2 + 3 + 4 + 5 + 6 = 20 3 + 4 + 5 + 6 + 7 = 25 4 + 5 + 6 + 7 + 8 = 30 5 + 6 + 7 + 8 + 9 = 35 6 + 7 + 8 + 9 + 10 = 40

int a[]={1,2,3,4,5,},b[]={1,2,3,4,5}; int size_a = sizeof(a)/sizeod(int),size_b =  sizeof(b)/sizeod(int); int total_b =0; for(int i=0;i<size_b;++i) {   total_b+=b[i]; } for(int j=0;j<size_a;++j) { printf("%d ",a[j]*size_b+total_b); }

int a[]={1,2,3,4,5},b[ ]={1,2,3,4,5};     for(int ib: b){         int s=0;         for(int ia: a){             if(s) cout<<'+';             cout<<ia+ib;             s +=ia+ib;         }         cout<<'='<<s<<endl;     }

矩阵相加