Question: c语言问题

调试环境VS2015 如果代码是 struct { 	int len; 	char* str; } *p; int main() { 	p->str++; 	return 0;	 } 调试可通过，但是运行时报错。因为此时，p的值是0x00000000，此时p->str++的理论含义是对p->str指向的内容进行自加处理，但是此时无法读取p->str指向的内存，所以会报错。 如果把代码修改成如下 struct P{ 	int len; 	char* str; } *p; int main() { 	p = new P(); 	p->str++; 	return 0;	 } 此时，在执行p->str++;之前，p->str指向的内容是0，执行p->str++;之后，内容变为1。 所以，个人觉得这个题选D

没有程序上下文，怎么知道有没有初始化呢？

C 不对吗?

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

语法没有错误，但是会运行时错误（段错误）。

答案应该就是A才对

正确答案不一定正确。

这个语句编译的时候不存在语法问题。 只是在运行的时候，由于未初始化，p将会是一个随机指针，有可能会操作到不能访问的地址，出现段错误。  你这个题目应该不完全吧。

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


Question: QT问题：为什么不能使用QString？

哈哈，谢谢1楼

试试   QString path= QFileDialog::getOpenFileName(this,"Open","D:/","*");  //后面的判断改为： 0 == path.size()

nameS 看后面红字


Question: 大佬帮我看一下为什么不能把文件的信息传到链表里去

百度搜相关关键字。

我觉得没什么大问题

楼主的代码除了fclose和return位置错了以外，没什么大毛病，把你的问题描述的再清楚点，太模糊了。

引用 6 楼 @风轻云淡_ 的回复:[quote=引用 5 楼 自信男孩 的回复:] 应该和打开的方式没有关系，主要是楼主的文件是fwrite写进去的吗？因为fwrite/fread是一对的，用什么方式写的就用什么方式读，这个是需要注意的。  另外，有两处需要注意：    return head;     fclose(fp); 这两条语句需要交换一下顺序，即先fclose，在return；因为如果按照你的方式去执行，那么fclose永远不会执行啊。   if(fread(s,LEN,1,fp)==0)             break; 这个地方是否需要改一下呢，改成：   if(fread(s,LEN,1,fp) < LEN)             break; 因为fread返回值是LEN * 1的长度，否则要么是读取失败，要么就是读到文件末尾我又自己测试了下，确实和加不加b没有关系，只要是fwrite写进去的，不加b也能fread出来。那个fread的返回值是读取成功结构体的个数，并不是读取到的字节。读取不到返回0，我测过了，你自己试试。[/quote] 恩，可能fread的返回值是1对应的值，即 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); On  success,  fread()  and  fwrite() return the number of items read or written.  This number equals the number of bytes transferred only when size is 1.  If an error occurs, or the end of the        file is reached, the return value is a short item count (or zero).

引用 5 楼 自信男孩 的回复:应该和打开的方式没有关系，主要是楼主的文件是fwrite写进去的吗？因为fwrite/fread是一对的，用什么方式写的就用什么方式读，这个是需要注意的。  另外，有两处需要注意：    return head;     fclose(fp); 这两条语句需要交换一下顺序，即先fclose，在return；因为如果按照你的方式去执行，那么fclose永远不会执行啊。   if(fread(s,LEN,1,fp)==0)             break; 这个地方是否需要改一下呢，改成：   if(fread(s,LEN,1,fp) < LEN)             break; 因为fread返回值是LEN * 1的长度，否则要么是读取失败，要么就是读到文件末尾我又自己测试了下，确实和加不加b没有关系，只要是fwrite写进去的，不加b也能fread出来。那个fread的返回值是读取成功结构体的个数，并不是读取到的字节。读取不到返回0，我测过了，你自己试试。

你既然以这种方式读取 if(fread(s,LEN,1,fp)==0) ，那么文件打开方式要选择 "rb"  if((fp=fopen("E:\\CourseDesign.txt","rb"))==NULL)

不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

麻烦能给我一个详细的代码过程可以吗 初学文件卡在这里了


Question: 求问c语言快排实现top k问题，感觉逻辑性没问题，但总是发生溢出，求各位大神看看

会调试这些都不是问题，看下溢出时low high值就知道了 80%的递归问题都是跳出递归条件判断错误或者不充分

正好这里有一个蓝桥杯大赛题  标题：快速排序。  以下代码可以从数组a[]中找出第k小的元素。 它使用了类似快速排序中的分治算法，期望时间复杂度是O(N)的。 请仔细阅读分析源码，填写划线部分缺失的内容。  #include <stdio.h>  int quick_select(int a[], int l, int r, int k) { 	int p = rand() % (r - l + 1) + l; 	int x = a[p]; 	{int t = a[p]; a[p] = a[r]; a[r] = t;} 	int i = l, j = r; 	while(i < j) { 		while(i < j && a[i] < x) i++; 		if(i < j) { 			a[j] = a[i]; 			j--; 		} 		while(i < j && a[j] > x) j--; 		if(i < j) { 			a[i] = a[j]; 			i++; 		} 	} 	a[i] = x; 	p = i; 	if(i - l + 1 == k) return a[i]; 	if(i - l + 1 < k) return quick_select(a, i + 1, r, k - p - 1); //填空 	else return quick_select(a, l, i - 1, k); } 	 int main() { 	int a[] = {1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12}; 	printf("%d\n", quick_select(a, 0, 14, 5)); 	return 0; }

这程序会跑到宇宙之外吧~

引用 3 楼 _ZGq 的回复:你没有srand()，所以rand()的结果是1。 如果想要随机值，可以先包括<time.h>，再在main函数开头写一次 srand(time(NULL)); 。 既然是rand();那么结果为啥确定是1呢？如果能确定是1，这个函数为啥还叫随机生成数函数呢？  如果没有srand()，那么这10个数可能是一个相同的数。

溢出是因为一直在递归调用。你的递归结束条件可能永远不满足。不妨把中间调用过程打印出来仔细分析。

top k 堆排序才是原罪


Question: C语言

没有初始化，那么数组内的元素都是随机值，这样就不好判定它是否为空。要判断其是否为空，建议初始化一下数组，一般初始化都是为0.

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

VS2015 C++代码  0x007CFA6C是data的起始地址，可以看到初始值都是0xCC

无法判断，请给出你的具体使用环境。局部变量未初始化时为随机值。

data[i][j][0] == '\0'


Question: 编程问题求助，求一下程序的输出结果，并分析。

[quote=引用 2 楼 user-3 的回复:] [quote=引用 1 楼 user-3 的回复:]  程序1问题： *p3=(char*)malloc(num）改为*p3=malloc(num）是否可行？ 修改程序后编译通过并且正常显示hello,且malloc函数本身返回的就是地址，加不加（char*）都一样？  程序2问题： free（str4）；//不太懂这句，释放内存后里面的内容不会清除么？？？

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

两个程序都能正常输出结果“hello", "world".  因为str3， str4虽然初始化为NULL，但是都通过malloc申请了空间，并把新的空间存放到了str3, str4中（而已理解新的地址值覆盖了NULL)。  两个程序都有一个共同的问题，就是释放内存，malloc需要手动释放，因此需要在用完之后free掉。

引用 1 楼 user-3 的回复:程序1：GetMemory3函数能够申请内存并通过第一个参数p3返回分配的内存地址。 在Test3中，首先调用GetMemory3, 为str3指针分配100字节的内存，然后利用strcpy 向该块内存赋值字符串， strcpy会同时复制字符串结束符，所以复制结束后，str3就是 一个字符串，内容为"hello"  hello   程序2：分析请你仿照程序1的分析自己写  world    估计写出结果不难，难的是分析结果？ 抱歉是“复制字符串”，不是“赋值字符串”。 拼音输入的。


Question: 再分享一个有趣的C代码 (比上次的好)

发现赵老师身影就跟上来图个脸熟

楼主辛苦了，为挖黑历史翻了6年前的帖，依然不能解释自己发一个会让人家关机的垃圾代码的本质

引用 29 楼 赵4老师 的回复:建议楼主先从网上扒一个开源虚拟机，然后从一幅美女图中提取出事先隐写在其中的浮点数，这些浮点数转为十六进制字节序列刚好是对应虚拟机的指令，虚拟机的指令对应的功能又刚好是关机。   你还别以为没这技术，CIA90年代开发的数字水印技术就可以做到，把任意数据融合到jpeg图像或者mpeg视频流中，只能通过特定的程序还原，而且能抗二次有损压缩，绝对是牛擦的情报传递工具，把小姐姐视频嵌入到xx大宣传片中都没人知道~~~

引用 20 楼 niiiloc 的回复:有病治病，这种有啥值得分享的，我们这里不是抖音，谢谢  终于明白你为什么喜欢在论坛骂人了，原本是以为你没刷牙，现在明白了，你所谓的“意义”就是在论坛各版块骂人吧，可能生活压力大吧。不过这种减压方式不值得提倡。如果你再想骂人，我建议你找个镜子，对着镜子骂，这样就你好我好大家好了。 我们老师说过两句话：一句是，只有那些懦弱无能的人才喜欢骂人，这样就诠释了“君子”动口不动手； 另一句是：如果你和一个人关系不好，可能是那个人的问题；如果你是和一些人关系不好，那就要自己找找原因了；

引用 21 楼 那年那人 的回复:[quote=引用 20 楼 niiiloc 的回复:] 有病治病，这种有啥值得分享的，我们这里不是抖音，谢谢  你的自问自答，不是挺好的吗？既然自己有病就去看病啊。  引用楼上的一些内容： “电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……”     看似很啰嗦的一段话，其实都是一样的道理。    代码本身没啥作用，算是一个小玩笑，可以用shutdown -a取消。    分享只是觉得全字符串的shellcode有值得学习借鉴的地方，人们对知识向来都是各取所需，值得看就看，不值得看就不看。没必要冷嘲热讽，酸言酸语，话又说回来了，虽然这两段代码是我发的，但是我真的不是很明白第二段那个纯字符串的原理，是真的不完全明白，因为我刚学汇编，你能讲一下吗怎么实现的？（虚心请教）   [/quote] 有病，今天是愚人节么？人家执行了关机了你很开心么？

代码对我这样的萌新有一些启发，学习了

第一个代码只是很简单的转换，刚开始不知道vc高版本是否能通过，如果能成功运行，有30s的时间可以在cmd里执行shutdown -a取消关机，如果不会，30s内保存好需要保存的文档就可以了，不会造成数据丢失的。也可以在虚拟机里测试。  第二个代码是把机器码重新编码成了纯字母字符， 是别人帮我转的，我只知道好像是类似 base64那样重新编码的，字符串最前面应该是解码部分，由于没有源码，我不理解的是解码部分如何做到也是全字母的，有兴趣的可以逆向下那个字符串，我也好学习下。  感觉无意义的请忽略。

引用 23 楼 niiiloc 的回复:这种代码除了秀没有任何意义，学汇编也不会写这种破烂代码，公司里写这种代码直接开除，够明白了么？ 如果你的电脑被关机了，真的很不好意思。代码只是简单的一个调用数组来验证shellcode是否有效，会有30s的延时提示关机，原本我以为那个弹出的对话框大家一看就知道是shutdown执行的，都知道shutdown -a来取消呢，再加上之前楼上@_ZGq有人也发帖提示过要想知道结果最好保存项目，我以为都能看到呢。这是我的疏忽。  你说“这种代码除了秀没有任何意义”，说到意义，也是针对不同的人的，你觉得没意义，你可以秀一个让大家觉得有意义的代码，你可以不用回帖，你可以不看；我觉得有意义就可以了，你能说草书你看不懂不会写你就说它没意义？你在论坛骂人就有意义？ 我相信csdn论坛官方更喜欢发帖“秀”代码的，而不是发帖“秀”怎么骂人的。  另外谢谢你的建议，每个行业都有每个行业的规范，每个公司大多有自己的编程代码规范，公司项目大多是团队开发，便于维护和升级产品，代码规范是必须的，所以你多虑了，在公司里没人会这么写的，就好比，有几个人会把项目计划书用草书打印，跟领导开会穿拖鞋? 人们都知道做事情要分场合。其次这俩代码不是汇编是C语言，只是数组中的机器码是用汇编转换的，shellcode大多应用在漏洞安全方面，个人代码怎么方便怎么写。

有病治病，这种有啥值得分享的，我们这里不是抖音，谢谢

引用 20 楼 niiiloc 的回复:有病治病，这种有啥值得分享的，我们这里不是抖音，谢谢  你的自问自答，不是挺好的吗？既然自己有病就去看病啊。  引用楼上的一些内容： “电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……”     看似很啰嗦的一段话，其实都是一样的道理。    代码本身没啥作用，算是一个小玩笑，可以用shutdown -a取消。    分享只是觉得全字符串的shellcode有值得学习借鉴的地方，人们对知识向来都是各取所需，值得看就看，不值得看就不看。没必要冷嘲热讽，酸言酸语，话又说回来了，虽然这两段代码是我发的，但是我真的不是很明白第二段那个纯字符串的原理，是真的不完全明白，因为我刚学汇编，你能讲一下吗怎么实现的？（虚心请教）

引用 10 楼 赵4老师 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  这是最强的心法了。

引用 12 楼 早打大打打核战争 的回复:double data[]只是一个障眼法，和用char data[]在数据段嵌入指令是一回事，让你不能直接看到机器码而已~~~  这么写确实是障眼法，因为本质上还是有汇编符号的；我修改了下，写成了纯字符串的了。  #pragma comment(linker,"/section:.data,rwe") char str[]= "PYVTX10X41PZ41H4A4I1TA71TADVTZ32PZNBFZDQC02DQD0D13DJE5I16OK4C162K5D16695J1TMN3P1"             "W0P5J0D7N7Z9L9K2I1W5B1M439LLM060L0R691Z414K2Z0M8O5H3Y8M3V604N13KK3L6O0R5JKO0A9Y5"             "B7O6P0N9S3Y0B1H5K100N2Z9R3A0F61075H114S1A9PMK4L5D6P1DML0L7M0F325G0H00MLKN0P7ZMN3"             "H8M0N0G0T060G2OMNJM1I3Z0K1M065A0Q3T2Z7N5KML2E0P3P3B2D8L02OK1W2C0I0U0S0O8L667M0QK"             "K660Y2H1C1U1S3X9W2B043J67JL9Q2IKL2CMN0J5O4S8K18620S0Y64MO2C0S2D1B050Y021W8M0A1S2"             "L5G1T640Q7K5DON3H4H3X355BMMKKMM0L2IKO09KN1W7M2G607K0S1W602M2A2A2M1S0R2Z0W047N2E0"             "T097O0A0D050U1U161F02"; int main() {     return ((int(*)(void))&str)(); }

学习到了，谢谢分享

跑跑运行看看

引用 14 楼 追梦金风 的回复:为什么停顿了几秒，接着返回了3221225477？看6楼。选32位模式，再全部重新编译（F11或点那个4个白方框）。

为什么停顿了几秒，接着返回了3221225477？

为什么停顿了几秒，接着返回了3221225477？


Question: 学过c的进来看看，小弟有一个问题，帮忙看看

引用 45 楼 _ZGq 的回复:[quote=引用 44 楼 赵4老师 的回复:] [quote=引用 43 楼 _ZGq 的回复:] scanf里%s后面加&和不加&的区别我知道，只是在结果上有什么不同？在我的机器上没有不同。估计是scanf对%s后面加&和不加&都做了处理，一个对应一级指针，一个对应二级指针，两种方法都有效。是这样吗？ 只有对char[]类型的变量才有效。[/quote] 是输入char[]类型加不加&都一样吗？[/quote] 对

引用 44 楼 赵4老师 的回复:[quote=引用 43 楼 _ZGq 的回复:] scanf里%s后面加&和不加&的区别我知道，只是在结果上有什么不同？在我的机器上没有不同。估计是scanf对%s后面加&和不加&都做了处理，一个对应一级指针，一个对应二级指针，两种方法都有效。是这样吗？ 只有对char[]类型的变量才有效。[/quote] 是输入char[]类型加不加&都一样吗？

引用 43 楼 _ZGq 的回复:scanf里%s后面加&和不加&的区别我知道，只是在结果上有什么不同？在我的机器上没有不同。估计是scanf对%s后面加&和不加&都做了处理，一个对应一级指针，一个对应二级指针，两种方法都有效。是这样吗？ 只有对char[]类型的变量才有效。

加&和不加&有什么不同 &是取地址，char c  时 取地址 就是 &c char jx[2]; 时 取地址 就是 jx。 因为 数组 名 就是 数组开始的 地址 。

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

大佬，能不能帮我解决一个跟这个题目很像的题目，谢谢

写的不错。。。。

学习了。。。

除了调试用，其他情况尽量少用 gets ,scanf, puts这些乱起八糟的。

引用 34 楼 schlafenhamster 的回复:printf("真的要删除该结点吗？(y/n)"); 		scanf("%c",&jx);  jx=0x0a !!!!   void delnode(linklist head) { 	char jx[2]; 	listnode *p,*q; 	p=listfind(head); //调用查找函数 	if(p==NULL) 	{ 		printf("没有查到要删除的通讯者！\n"); 		return; 	} 	else 	{ 		printf("真的要删除该结点吗？(y/n)"); 		scanf("%s",jx); 		if(jx[0]=='y'||jx[0]=='Y') 		{ 			q=head; 			while(q!=NULL && q->next!=p) q=q->next; 			q->next=p->next;                                                          //删除结点 			free(p);           //释放被删除的结点空间 			printf("通讯者已被删除！\n"); 		} 		else 		{ 			printf("通讯者被保留！\n"); 		} 	} }   注意 scanf("%c",&jx); 与 scanf("%s",jx); 的不同 我一直就不明白%s后面加&和不加&有什么不同？虽然我知道一个是一级指针一个是二级指针，但在结果方面有什么不同？

看到评论，也能学到好多东西

引用 19 楼 赖卓成 的回复：[quote=引用 14 楼 @风轻云淡_的回复:]puts输出的时候回自带回车换行 那要怎么让他不换行呢[/quote]小老弟，你字符串输入输出还有问题啊，你都能学到这里了不清楚字符串有点难以理解

初始化真的很重要，尤其在循环里。。。。

大佬可以帮我改一下错误不?

感觉看着都头疼

引用 20 楼 听、的回复:#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct{                                                                //通讯录结点类型 char num[5];                                                                      //编号 char name[9];                                                                      //姓名 char sex[3];                                                                      //性别 char phone[13];                                                                    //电话 char addr[31];                                                                    //地址 }datatype; typedef struct node{                                                            //结点类型定义 datatype data;                                                              //结点数据域 struct node*next;                                                            //结点指针域 }listnode; typedef listnode*linklist; linklist head; listnode *p; //函数说明 int menu_select(); linklist createlist(void); void insertnode(linklist head,listnode *p); listnode *listfind(linklist head); void delnode(linklist head); void printlist(linklist head); //主函数 void main() { for( ; ; ){ switch(menu_select()) { case 1: printf("***************************\n"); printf("*    通讯录链表的建立    *\n"); printf("****************************\n"); head=createlist(); break; case 2: printf("***************************\n"); printf("*    通讯者信息的添加    *\n"); printf("******************************************\n"); printf("编号(4) 姓名(8) 性别 电话(11) 地址(31)\n"); printf("*******************************************\n"); p=(listnode *)malloc(sizeof(listnode)); scanf("%s%s%s%s%s",p->data.num,p->data.name,p->data.sex,p->data.phone,p->data.addr); insertnode(head,p); break; case 3: printf("*************************************\n"); printf("*        通讯录信息的查询          *\n"); printf("***************************************\n"); p=listfind(head); if(p!=NULL){ printf("编号 姓  名  性别  联系电话  地  址\n"); printf("----------------------------------------------------------------------------------\n"); printf("%s,%s,%s,%s,%s\n",p->data.num,p->data.name,p->data.sex,p->data.phone,p->data.addr); printf("----------------------------------------------------------------------------------\n"); } else printf("没查到要查询的通讯者！\n"); break; case 4: printf("************************************\n"); printf("*        通讯录信息的删除        *\n"); printf("*************************************\n"); delnode(head); break; case 5: printf("************************************\n"); printf("*        通讯录链表的输出          *\n"); printf("*************************************\n"); printlist(head); break; case 0: printf("\t 再    见！\n"); return; } } } /*********************/ /*菜单选择函数程序 */ /*******************/ int menu_select() { int sn; printf("      通讯录管理系统\n"); printf("============================\n"); printf("      1.通讯录链表的建立\n"); printf("      2.通讯录结点的插入\n"); printf("      3.通讯录结点的查询\n"); printf("      4.通讯录结点的删除\n"); printf("      5.通讯录链表的输出\n"); printf("      0.退出管理系统\n"); printf("============================\n"); printf("    请选择0-5:  "); for( ; ; ) { scanf("%d",&sn); if(sn<0 || sn>5) printf("\n\t输入错误，重选0-5: "); else break; } return sn; } /******************************/ /*用尾插法建立通讯录链表函数*/ /*****************************/ linklist createlist(void) {                                                      //尾插法建立带头结点通讯录链表算法 linklist head=(listnode *)malloc(sizeof(listnode)); listnode *p,*rear; int flag=0;                                                                //结束标志置0 rear=head;                                                      //尾指针初始指向头结点 while(flag==0) { p=(listnode *)malloc(sizeof(listnode));                                        //申请新结点 printf("编号(4) 姓名(8) 性别 电话(11)  地址(31)\n"); printf("----------------------------------------------------------------\n"); scanf("%s%s%s%s%s",p->data.num,p->data.name,p->data.sex,p->data.phone,p->data.addr); rear->next=p;                                                //新结点连接到尾结点之后 rear=p;                                                            //尾指针指向新结点 printf("结束建表吗？ (1/0):"); scanf("%d",&flag);                                                  //读入一个标志数据 } rear->next=NULL;                                                  //终端结点指针域置空 return head;                                                            //返回链表头指针 } void insertnode(linklist head,listnode *p) { listnode *p1,*p2; p1=head; p2=p1->next; while(p2!=NULL && strcmp(p2->data.num,p->data.num)<0) { p1=p2;                                                      //p1指向刚访问过的结点 p2=p2->next;                                                //p2指向表的下一个结点 } p1->next=p;                                                        //插入p所指向的结点 p->next=p2;                                                          //连接表中剩余部分 } listnode *listfind(linklist head) { listnode *p; char num[5]; char name[9]; int xz; printf("=====================\n"); printf("1.按编号查询        \n"); printf("2.按姓名查询        \n"); printf("=====================\n"); printf("      请选择:  "); p=head->next;                                                    //假定通讯录表带头结点 scanf("%d",&xz); if(xz==1){ printf("请输入要查找者的编号: "); scanf("%s",num); while(p && strcmp(p->data.num,num)<0) p=p->next; if(p==NULL || strcmp(p->data.num,num)>0) p=NULL;                                              //没有查到要查找的通讯者 } else if(xz==2){ printf("请输入要查找者的姓名："); scanf("%s",name); while(p && strcmp(p->data.name,name)!=0) p=p->next; } return p; } void delnode(linklist head) { char jx; listnode *p,*q; p=listfind(head);                                                            //调用查找函数 if(p==NULL){ printf("没有查到要删除的通讯者！\n"); return; } printf("真的要删除该结点吗？(y/n)"); scanf("%c",&jx); if(jx=='y'||jx=='Y'){ q=head; while(q!=NULL && q->next!=p) q=q->next; q->next=p->next;                                                          //删除结点 free(p);                                                      //释放被删除的结点空间 printf("通讯者已被删除！\n"); } } void printlist(linklist head) { listnode *p; p=head->next;                                  //因为链表带头接点，使P指向链表开始结点 printf("编号 姓  名  姓别  联系电话    地  址\n"); printf("-----------------------------------------------------------------------\n"); while(p!=NULL) { printf("%s,%s,%s,%s,%s\n",p->data.num,p->data.name,p->data.sex,p->data.phone,p->data.addr); printf("-------------------------------------------------------\n"); p=p->next; } }有没有大佬帮忙解决一下这个程序删除结点时不管输入y或n都回到选择模块无限循环显示输入有误的问题 你的缓存区里应该还有东西，最好fflush一下

不要依赖调试器输出复杂数据结构！而要将复杂数据结构的整个内容在处理它的每一步使用一小段代码按自己很容易理解的格式输出，非常有助于调试！或者可以说是“基础设施” 数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633


Question: 求助一下，用C语言求蒲丰（buffon）投针问题

除了上面说的问题之外，还有一处，Get函数里distance应该取(A+1)/2的模

你的A代表的是平行线之间的距离，distance是针的中心点到最近那条平行线的垂直距离，这个值应该是在0到A/2之间的，而你是在0到L之间随机的。。（你这里A和L的值一样）所以相当于你是用了两倍的A来计算的，所以你的结果是约等于 1/pai.

如果是两倍关系，那把结果×2不就行了吗？ 如果不是，那可以检查一下公式看有没有问题。

引用 1 楼 user-3 的回复:原因：GetP函数无法改变主函数中p的值。 修改方法：把主函数中float p=0;和GetP(n);删掉，把输出中的p换成GetP(n)。  谢谢！修改之后能输出了，但是输出的结果一直为0.3几，结果应该输出0.6几的，能找到原因吗


Question: Linux编程 知道线程id怎么获取线程信息

要么知难而退，要么知难而进。

其实linux线程是用进程模仿的，而每个pid对应一个记录状态的文件 把以下${pid}换成pid值 cat /proc/${pid}/status 查看最大线程数： cat /proc/sys/kernel/threads-max


Question: 根据多字节字符串，怎么从freetype里面获取中文字符的位图

首先，非常感谢赵4老师的热心。因为技术不够强大，加上最近比较忙，对老师提供的代码没有理解透彻。然后在网上找到了另一种方法。后面有空了，我再贴出来。先把帖子结了。

我也遇到同样问题了，请问您找的另一种方法是怎么解决的

再供参考： #include <stdio.h> #include <conio.h> const unsigned char bit[8]={128,64,32,16,8,4,2,1}; unsigned char buffer[32]; FILE *hzk; unsigned long offset; unsigned int q,w; int x,y,qw; //-------------------------------------------------------- void display(char *hz) {      qw=*((int *)hz);     q=(qw&0x00FF)-0xA1;     w=((qw>>8)&0x00FF)-0xA1;     offset=q*0x5E+w;     offset*=32;     if ((hzk=fopen("HZK16","rb"))==NULL) {         printf("Can not open file HZK16!\n");         return;     }     fseek(hzk,offset,SEEK_SET);     fread(buffer,1,32,hzk);     fclose(hzk);     for (y=0;y<16;y++) {         for (x=0;x<16;x++) {             if (buffer[y*2+x/8] & bit[x%8]) {                 printf("%s",hz);             } else {                 printf("  ");             }         }         printf("\n");     } } void main() {     display("啊");     getch(); } //                          啊 //    啊  啊啊啊啊  啊啊啊啊啊啊 //啊啊啊啊啊    啊          啊 //啊  啊  啊    啊          啊 //啊  啊  啊  啊        啊  啊 //啊  啊  啊  啊    啊啊啊啊啊 //啊  啊  啊啊      啊  啊  啊 //啊  啊  啊  啊    啊  啊  啊 //啊  啊  啊  啊    啊  啊  啊 //啊  啊  啊    啊  啊  啊  啊 //啊啊啊  啊    啊  啊啊啊  啊 //啊  啊  啊啊  啊  啊  啊  啊 //        啊  啊            啊 //        啊                啊 //        啊            啊  啊 //        啊              啊啊

仅供参考：#include <mem.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <graphics.h> const unsigned char bit[8]={128,64,32,16,8,4,2,1}; //-------------------------------------------------------- void dis(xoff,code) 	unsigned int xoff,code; { 	unsigned char *buffer; 	FILE *hzk; 	unsigned long offset; 	unsigned int q,w; 	int	x,y,width;  	buffer=calloc(32,1); 	if ((code&0xFF00)!=0) { 		w=(code&0x00FF)-0xA1; 		q=((code>>8)&0x00FF)-0xA1; 		offset=q*0x5E+w; 		offset*=32; 		if ((hzk=fopen("HZK16","rb"))==NULL) { 			closegraph(); 			printf("Can not open HZK16\r\n"); 			exit(1); 		} 		fseek(hzk,offset,SEEK_SET); 		fread(buffer,1,32,hzk); 		fclose(hzk); 		width=2; 	} 	else { 		if ((hzk=fopen("ASC16","rb"))==NULL) { 			closegraph(); 			printf("Can not open ASC16\r\n"); 			exit(1); 		} 		offset=code*16; 		fseek(hzk,offset,SEEK_SET); 		fread(buffer,1,16,hzk); 		fclose(hzk); 		width=1; 	} 	for	(y=0;y<16;y++) for (x=0;x<8*width;x++) { 		if (buffer[y*width+x/8]&bit[x%8]) putpixel(xoff+x,y,15); 	} 	free(buffer); } //-------------------------------------------------------- void display(p) 	unsigned char *p; {    int i;   unsigned int qw;    i=0;   while (1) { 	if (p[i]==0x0D||p[i]==0x1A)	break; 	if (p[i]>0xA0) { 		qw=((unsigned int)p[i]<<8)|((unsigned int)p[i+1]&0x00FF); 		dis(8*i,qw); 		i+=2; 	} 	else { 		qw=(unsigned int)p[i]&0x00FF; 		dis(8*i,qw); 		i++; 	}   }  } //-------------------------------------------------------- void main() { 	int gdriver = DETECT, gmode, errorcode; 	long fl; 	FILE *hz; 	unsigned char *p;  	initgraph(&gdriver, &gmode, "c:\\borlandc\\bgi"); 	errorcode = graphresult(); 	if (errorcode != grOk) { 	   printf("Graphics error: %s\n", grapherrormsg(errorcode)); 	   exit(1); 	} 	hz=fopen("hz","rb"); 	fseek(hz,0,SEEK_END); 	fl=ftell(hz); 	p=calloc((int)fl,sizeof(unsigned char)); 	rewind(hz); 	fread(p,1,(int)fl,hz); 	fclose(hz); 	display(p); 	free(p); 	getch(); 	closegraph(); }  Win-TC里面有HZK16


Question: source insight宏定义函数名显示问题

source insight没这个本事。建议不要玩弄这样的宏技巧。

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。

Source Insigh目录，其中有一个C.tom文件。修改该文件，在其中增加一行： FUNC_DECL 试试


Question: 在vc++6.0到底能不能自定义函数调用main函数?

仅供参考：#include <iostream> using namespace std; struct MyStruct {     int Nodedata;     MyStruct *pLeft;     MyStruct *pRight; } s1,s2,s3,s4,s5,s6,s7,s8; void ashow(MyStruct * p) {     if (p != nullptr) {         ashow(p->pLeft);         ashow(p->pRight);         cout << p->Nodedata << endl;         if (p->Nodedata == 4) {             throw 1;//退出递归.直接返回.         }     } } int main() {     MyStruct *pRoot;//根      pRoot = &s1;     s1.Nodedata = 1;     s2.Nodedata = 2;     s3.Nodedata = 3;     s4.Nodedata = 4;     s5.Nodedata = 5;     s6.Nodedata = 6;     s7.Nodedata = 7;     s8.Nodedata = 8;      s1.pLeft = &s2;     s1.pRight = &s3;      s2.pLeft = &s4;     s2.pRight = &s5;      s3.pLeft = &s6;     s3.pRight = &s7;     try {         ashow(pRoot);     } catch (int err) {         cout<<"catch err "<<err<<endl;     }     return 0; } //4 //catch err 1 //

那样就循环了

实践是检验真理的唯一标准！

除非你想递归调用？

引用 1 楼 user-6 的回复:请问子函数调用主函数有啥意义？最终不就是栈溢出和递归类似的做一个出口就不会了

可以 没必要

请问子函数调用主函数有啥意义？最终不就是栈溢出


Question: 数据结构C语言版，求大神帮忙解答！

这是作业贴吧，还是自己先写出来，有问题把代码贴出来吧

你发错版块了， 让版主帮你转到 C语言版块去吧

感觉你放在这还不如自己百度来得快。论坛的意义就是碰到自己解决不了的，贴出来，仁者见仁智者见智，讨论之后选出最佳方案，最终解决自己的问题，从而印象深刻，下次碰到类似的问题可以自己解决。你这把作业题直接贴上来，代码一个子没有，这种习惯最好改改。


Question: C语言删除文件中记录的问题-救命！！

贴出自己的代码吧，这样描述没有代码具体

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

建议你换一个思路：普通的增删改查不要以文件为媒介，可以在内存中创建一个保存数据的结构（一般以链表居多）。然后程序启动之前，将数据全部读出，增删改查进行完之后，程序退出之前将结构中数据保存到文本文件。读取保存方式要一致，建议直接以二进制方式写入，以二进制方式读出。


Question: 第二次删除文件记录失败，为什么？

全部数据记录在一个文件？这个文件的内容介绍下，对文件操作的代码贴下，你这样描述，很多人其实不知道你在说什么，

我写的就是课程信息管理系统，我写的没有错误

引用 2 楼 weixin_40078613 的回复:[quote=引用 1 楼 qq_21563855 的回复:] 不可能吧，我也是用你的方法做的，没有错误 和同学都是这样，我写的学生信息管理系统（有显示学生记录，删除学生记录等）。运行程序，如果第一个操作就是删除学生信息，就能成功删除指定学号的记录，但是再回到主菜单，继续执行删除学生记录，就不行了，没有提示。但写将不删除的记录写入备份文件stubak.dat成功，再删除原文件remove("student.dat")，在文件夹里也看到删除成功，再改名rename("stubak.dat","student.dat")也成功。可就是回到主菜单，显示学生记录，只删除了前一次操作的记录，第二次执行删除操作的记录还在里面。函数执行完都fclose()了，也测试过，关闭成功了。真是纠结。如果我运行程序，第一次是执行的显示学生记录的操作showInfomation()，再执行删除记录操作delRecord()，一样删不掉。各位大神，救命！！[/quote] 源码发出来，或者发我邮箱 klxs1996@163.com

引用 1 楼 qq_21563855 的回复:不可能吧，我也是用你的方法做的，没有错误 和同学都是这样，我写的学生信息管理系统（有显示学生记录，删除学生记录等）。运行程序，如果第一个操作就是删除学生信息，就能成功删除指定学号的记录，但是再回到主菜单，继续执行删除学生记录，就不行了，没有提示。但写将不删除的记录写入备份文件stubak.dat成功，再删除原文件remove("student.dat")，在文件夹里也看到删除成功，再改名rename("stubak.dat","student.dat")也成功。可就是回到主菜单，显示学生记录，只删除了前一次操作的记录，第二次执行删除操作的记录还在里面。函数执行完都fclose()了，也测试过，关闭成功了。真是纠结。如果我运行程序，第一次是执行的显示学生记录的操作showInfomation()，再执行删除记录操作delRecord()，一样删不掉。各位大神，救命！！

不可能吧，我也是用你的方法做的，没有错误


Question: 进程状态从阻塞状态到就绪状态是怎么改变的？

唤醒原语

这么说吧，曾经看嵌入式系统启动过程，有一个内核进程不会阻塞，由它负责改变其他进程的状态标记，并且把阻塞进程放入相应的阻塞队列，把就绪的进程放入对应的就绪队列中。

程序的状态有操作系统管理

《30天自制操作系统》

取决于操作系统的调度机制

这部分功能由内核的任务调度模块完成


Question: 连续调用一个函数，返回指针类型数据，为什么得到的结果、地址都一样？

引用 11 楼 自信男孩 的回复:[quote=引用 3 楼 zzlu_88888 的回复:]    [quote=引用 1 楼 自信男孩 的回复:] 注意看一下，你的Get_String函数里有free操作，既然已经释放了，那么这部分空间是可以继续被申请和使用的。所以，出现地址一样是可能的。但是有一个问题，使用已经free的内存空间会有风险，因为以释放了，可能会被别的程序使用，那么放在这里的数据就不安全了。 可是malloc要与free配对使用啊，申请了多少个，就要释放多少个。如果不及时释放，很可能发生内存泄漏。 [/quote] 那你也得使用完之后再释放嘛，只要保存好malloc的首地址，在哪里释放，什么时候释放都没关系，只要在不需要的时候手动释放就好了。[/quote]      【只要保存住首地址，用完后在哪释放都可以】这样就懂了，谢谢！

引用 3 楼 zzlu_88888 的回复:[quote=引用 1 楼 自信男孩 的回复:] 注意看一下，你的Get_String函数里有free操作，既然已经释放了，那么这部分空间是可以继续被申请和使用的。所以，出现地址一样是可能的。但是有一个问题，使用已经free的内存空间会有风险，因为以释放了，可能会被别的程序使用，那么放在这里的数据就不安全了。 可是malloc要与free配对使用啊，申请了多少个，就要释放多少个。如果不及时释放，很可能发生内存泄漏。 [/quote] 那你也得使用完之后再释放嘛，只要保存好malloc的首地址，在哪里释放，什么时候释放都没关系，只要在不需要的时候手动释放就好了。

正如上面几位朋友说的，在Get_String()函数中已经调用free()释放了malloc()分配的内存，所以再次调用Get_String()函数时，会再次用到这个地址（因为这个地址已经被释放了）。 而你后面修改的代码就可以了，不要在Get_String()函数中调用free()释放内存，该函数的返回值就是分配的内存空间，可以在函数外部调用free()来释放内存。

1、malloc应该由调用者使用的释放。 2、释放后的指针要等于NULL。 3、malloc出来的空间，只是在虚拟内存中是连续的。而从实际的物理空间不一定是连续的。

释放了还用这个指针，这不是野指针么？ 你既然要作为出参，就不应该释放，应由外部调用者释放

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<stdbool.h>  #define STR_LEN (100)  int main(void) {    char ch;    int i = 0, j;    int postion = 0;    bool first_word_same = false;    char * str_buf1 = NULL;//[STR_LEN] = {0};    char * str_buf2 = NULL;// = {0};     str_buf1 = (char *)malloc(STR_LEN);       memset(str_buf1, 0, STR_LEN);    str_buf2 = (char *)malloc(STR_LEN);    memset(str_buf2, 0, STR_LEN);       if ((str_buf1 == NULL) ||(str_buf2 == NULL))     {          printf("malloc fail\n");          exit(-1);          return -1;     } 	     printf("please input string1: \n");     ch = getchar(); 	     while ((ch != '\n') && (i < STR_LEN))     {        str_buf1[i] = ch;        ch = getchar();        i++;     }      i = 0;     setbuf(stdin, NULL);  //清空输入缓冲区内容      printf("\n please input string2: \n");     ch = getchar();      while ((ch != '\n') && i < STR_LEN)     {        str_buf2[i] = ch;        ch = getchar();        i++;     }     printf("\n 2 str_buf1 add:%#X, str_buf1=%s\n",str_buf1, str_buf1);    printf("\n 3 str_buf2 add:%#X, str_buf2=%s\n",str_buf2, str_buf2);            for (i = 0; i < STR_LEN; i++)        {             if (str_buf1[i] == str_buf2[0])  //在第一个字符串中，找到与第二个字符串的首个字符相同的字符             {                 first_word_same = true;                 postion = i + 1;                  //记录此字符在第一个字符串中的位置                 printf("\n the location is : %dth \n\n", postion);             }  	    for (j = 1; first_word_same && (str_buf2[j] != '\0') ; i++, j++) //上面程序里，漏了i++ 	   {                 if(str_buf1[i+1]  != str_buf2[j]) //后续字符不同，退出第二个字符串查找，返回外面第一个字符串，继续查找                 {                     first_word_same = false;                     break;                 }                 else //上面漏加这种情况                {                     first_word_same = true;                } 	    }              if (first_word_same && (str_buf2[j] == '\0'))  //对比完第二个字符串最后一个字符后，若符合条件，则打印位置，并结束程序            {                 printf("\n The string2 location is %dth \n", postion);                   i = STR_LEN;// 让程序退出所有for循环            }			     }          free(str_buf1);         free(str_buf2);         str_buf1 = NULL;         str_buf2 = NULL;      return 0; }    经过以上修改，可以得到预期结果：  ************************************************* [root@localhost testfile]# gcc test09.c  [root@localhost testfile]# ./a.out  please input string1:  How are you?   please input string2:  are   2 str_buf1 add:0X9B88008, str_buf1=How are you?   3 str_buf2 add:0X9B88070, str_buf2=are   the location is : 5th     The string2 location is 5th  [root@localhost testfile]#  *************************************************

Get_String函数内，p已经free了，str=p，自然str的空间也不能用了

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

顺便问下， char * p = NULL; p = (char *)malloc(100); memset(p, 0, 100); 假如成功分配到首地址是 0x1000的连续100个内存单元，实际使用了50个连续的内存单元，也就是0x1000~0x1050被使用 此时执行free(p);  这时，释放的是0x1051～0x1100之间的空间是吗？  之后 ，假如执行： char * p2 = NULL; p2 = (char *)malloc(100); memset(p2, 0, 100); 此时可从0x1100开始分配连续100个内存单元使用。  这样理解，对么？

引用 1 楼 自信男孩 的回复:注意看一下，你的Get_String函数里有free操作，既然已经释放了，那么这部分空间是可以继续被申请和使用的。所以，出现地址一样是可能的。但是有一个问题，使用已经free的内存空间会有风险，因为以释放了，可能会被别的程序使用，那么放在这里的数据就不安全了。 可是malloc要与free配对使用啊，申请了多少个，就要释放多少个。如果不及时释放，很可能发生内存泄漏。

去掉free，再看看会不会地址一样


学会使用数据断点： #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }


Question: 传入指针参数的问题

如果指针和整形不用转换的话。 举个例子 struct ms{}; void func(ms* sss) {} 你直接传一个int给那么 那么 ms* m = (ms*)malloc(sizeof(ms)*10); func(m+1); 相当于把m当成一个数组，把第二个数组元素地址给了func 如果你直接给整形， 比如 m的地址值 0x123; func(0x123+1) 给了函数，它无法计算具体的数据，会引起混乱。

这个应该是编译器实现的问题吧，不支持参数的隐式转换吧！

楼主的头像和我的电脑壁纸是同一个猫。

void MezM (int  *fp){     printf ("传入的地址为： ox%0x\n", fp); }  这样就可以了

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

如果不需要强制转换，那么也就是说，整形=指针。 这样合理吗？

我知道是打印里面的数据，只是用来做验证的。问题是在传参的地方，为什么不强制转换传入的立即数地址值，编译器会报错呢

printf ("传入的地址为： %d \n", *fp);打印的不是fp的地址，而是那个地址里面的数据

这样的调用 MezM (0x22ff1c); 这个0x22ff1c是整型的数值，而函数的申明 void MezM (int  *fp) 明确要求入参是一个指向int类型的指针；所以直接传入整型的0x22ff1c是不行的，因为编译器会认为“入参类型不匹配”，因为报错。 这样 MezM ((int*)0x22ff1c); 强制转换就不会报错了。  在嵌入式开发中，经常有这样的用法，比如BASE_ADDR = 0x12345678; typedef struct _user_data_t {     int id;     char data[16]; }user_data_t  ; 要取出BASE_ADDR地址中存的id值，可以这样访问 ((user_data_t  *)BASE_ADDR )->id  注意，这里都是先要将整型的地址值强制转换为需要的类型指针，再通过指针的形式访问数据。


Question: c调用动态链接库(*.dll)文件

LoadLibrary动态调用.dll

个人觉得1楼的建议好些（系统环境变量path中添加相应的路径），虽然放到system32或syswow64目录下也行，但自己的程序终究放到自己运行的目录下好些

动态调用dll

在64位Windows下： 64位exe和dll在目录c:\windows\system32目录下； 32位exe和dll在目录c:\windows\syswow64目录下；

环境变量或者绝对路径dllopen

在Windows上，如果是小应用，最好还是放在应用程序同一目录，没必要污染系统环境变量，减少对系统设置依赖性。

dllopen()或dllmopen()函数

楼上是一种解决办法，还有一种解决办法是将报错dll丢到C:\Windows\System32或者C:\Windows\SysWOW64下面，不过不建议这样做，可以采用楼上的方法，将dll所在路径增加至系统环境变量path。

系统环境变量path中包括dll路径即可


Question: 求助：杭电oj,1002，高精度加法，我是用数组做，但没结果，请问哪里错？

找到错误了，谢谢大家。少了让进位归0. #include<stdio.h> #include<string.h> #define MAX 10000 int main() { 	int n,u; 	scanf("%d",&n);  	if(n>=0&&n<=20) 	{ 	for(u=1;u<=n;u++) 	{ 		char a[MAX]; 		char b[MAX]; 		int j,lena,lenb,k; 		scanf("%s",a); 		scanf("%s",b); 		lena=strlen(a); 		lenb=strlen(b); 		int c[MAX],d[MAX]; 		memset(c,0,sizeof(c)); 		memset(d,0,sizeof(d)); 		for(j=0,k=lena-1;k>=0;k--) 		{ 			c[j++]=a[k]-'0'; 		} 		for(j=0,k=lenb-1;k>=0;k--) 		{ 			d[j++]=b[k]-'0'; 		} 		int m; 		int jinwei=0; 		int result[MAX]; 		int local; 		if(lena>=lenb) 		{ 			local=lena; 		} 		else 		{ 			local=lenb; 		} 		memset(result,0,sizeof(result)); 		for(m=0;m<=local;m++) 		{ 			result[m]=c[m]+d[m]+jinwei; 			if(result[m]>=10) 			{ 				jinwei=result[m]/10; 				result[m]=result[m]%10; 			} 			else 				jinwei=0; 		} 		if(result[local]==0) 		{ 			local--; 		} 		printf("Case %d:\n",u); 		printf("%s + %s = ",a,b); 		for(m=local;m>=0;m--) 		{ 			printf("%d",result[m]); 		} 		if(u==n) 		{ 			printf("\n"); 		} 		else 		{ 			printf("\n\n"); 		} 	} 	} 	return 0; }

引用 5 楼 qq_42767647 的回复:我把程序改成下面这个，自己测试出来的答案是对的，但是怎么在杭电上一直wrong answer？？  #include<stdio.h> #include<string.h> #define MAX 1001 int main() { 	int n,u; 	scanf("%d",&n);  	if(n>=0&&n<=20) 	{ 	for(u=1;u<=n;u++) 	{ 		char a[MAX]; 		char b[MAX]; 		int j,lena,lenb,k; 		scanf("%s",a); 		scanf("%s",b); 		lena=strlen(a); 		lenb=strlen(b); 		int c[MAX],d[MAX]; 		memset(c,0,sizeof(c)); 		memset(d,0,sizeof(d)); 		for(j=0,k=lena-1;k>=0;k--) 		{ 			c[j++]=a[k]-'0'; 		} 		for(j=0,k=lenb-1;k>=0;k--) 		{ 			d[j++]=b[k]-'0'; 		} 		int m; 		int jinwei=0; 		int result[MAX]; 		int local; 		if(lena>=lenb) 		{ 			local=lena; 		} 		else 		{ 			local=lenb; 		} 		int spot=0; 		memset(result,0,sizeof(result)); 		for(m=0;m<=local;m++) 		{ 			result[m]=c[m]+d[m]+jinwei; 			if(result[m]>=10) 			{ 				jinwei=result[m]/10; 				result[m]=result[m]%10; 			} 			if(result[m]) 				spot=m;  		} 		if(result[local]==0) 		{ 			local--; 		} 		printf("Case %d:\n",u); 		printf("%s + %s = ",a,b); 		for(m=local;m>=0;m--) 		{ 			printf("%d",result[m]); 		} 		if(u==n) 		{ 			printf("\n"); 		} 		else 		{ 			printf("\n\n"); 		} 	} 	} 	return 0; } 你贴出来你的测试用例。 你用123456 + 123456的结果是不是对的。还有1+123456789，看一下结果是不是对的。 可能你的测试用例不够普遍性

你这个程序他根本跑不起来

仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110

#include<stdio.h> #include<string.h>  //#define MAX 10000 #define MAX     1024  int main() {     int n;     scanf("%d",&n);     while(n--)     {         char a[MAX];         char b[MAX];         int j,lena,lenb,k;         //lena=strlen(a);         //lenb=strlen(b);         scanf("%s",a);         scanf("%s",b);          lena=strlen(a);         lenb=strlen(b);          int c[MAX],d[MAX];         memset(c,0,sizeof(c));         memset(d,0,sizeof(d));         for(j=0,k=lena-1;k>=0;k--)         {             c[j++]=a[k]-'0';         }         for(j=0,k=lenb-1;k>=0;k--)         {             d[j++]=b[k]-'0';         }         int m;         int jinwei=0;         int result[MAX];         int local;         if(lena>=lenb)         {             local = lena;         }         else         {             local = lenb;         }         int spot=0;         memset(result,0,sizeof(result));         for(m=0;m<local+1;m++)         {             result[m]=c[m]+d[m]+jinwei;             if(result[m]>=10)             {                 jinwei=result[m]/10;                 result[m]=result[m]%10;             } else  {                 jinwei = 0;   //注意不是每次都进位的             }             if(result[m])                 spot=m;         }         printf("Case %d:\n",n);         printf("%s+%s=",a,b);         for(m=local;m>=0;m--)         {             printf("%d",result[m]);         }         printf("\n");     }     return 0; }  参考一下吧

看了几行就看不下去了。  char a[MAX]; char b[MAX]; int j,lena,lenb,k; lena=strlen(a); lenb=strlen(b);  a, b数组还没有内容，你取字符串长度结果肯定不对。后面代码自己好好读读有没有类似错误。


Question: 请问这段C代码是否有逻辑漏洞，如果有，那么这个逻辑漏洞是否可以被利用？

引用 13 楼 汪大宇Y的回复:我想知道下那个main函数里的一串字符是什么呀，新手刚入学，请指教 main函数的参数，假装看不见

增加处理输入字符串或特殊符号产生的死循环

我想知道下那个main函数里的一串字符是什么呀，新手刚入学，请指教

个人觉得有以下问题： 1 number没有定义； 2 没有对输入是否是数字进行检测； 修改的代码如下 	int number;//定义number 	for (;;) { 		printf("输入number: "); 		//------------以下代码判断输入的是否是数字----------------- 		char buffer[81]; 		int i, ch; 		for(i = 0; (i < 80) && ((ch = getchar()) != EOF) && (ch != '\n'); ++i)  		{  			if(ch<'0' || ch>'9')  			{ 				printf("输入的不是数字.\n"); 				break; 			}  			buffer[i] = (char)ch;  		} 		rewind(stdin);//清空输入缓冲区 		number = atoi(buffer);//将字符串转换为int 		if (number == 0) { 			break; 		}  		if (number > 10) { 			if (number == 11) { 				printf("number = 11.\n"); 			} 		} 	} 代码运行效果如图所示  对于getchar()函数和在控制台中判断输入是否是数字的相关知识，请参考 《C++中getchar()的使用方法》 《C++控制台程序判断输入的数字》 希望能够帮到你

这个程序好像死循环了

无非是程序健壮性不行呗，一般通用异常输入的处理就是让用户重新输入，并增加计数器，如果短时间内多次异常输入程序告警退出 引用 6 楼 yyxgs 的回复:回复楼上各位，这段代码是手写的，当时确实忘了定义number，请忽略掉这一点。 提这个问题是因为我写了一个程序，处理 list *命令。 而list *命令的逻辑判断下，比如有list available，list banned的处理，而输入一个list 123，程序没有这个判断，所以直接再次循环，提示输入命令，我就想这是否属于逻辑漏洞，可否被利用。

代码本身来说没有漏洞，个人之见。

算了，可能是我描述不清楚。大家的关注点都在number没有定义和输入非数字字符上，结贴。

这段代码有什么逻辑性可言吗？

#include <stdio.h>   int main(int argc, char* argv[]) {     for (;;) {         printf("输入number: ");         ret = scanf("%d", &number);         if (ret != 1)               continue;         //getchar();                   if (number == 0) {             break;         }                   if (number > 10) {             if (number == 11) {                 printf("number = 11");             }         }     }           return 0; } 去掉getchar();判断scanf的返回值

引用 2 楼 冷风1023 的回复:1、number没有定义 2、输入不是整型的处理 3、输入到下一次没有刷新  第3点能否解释一下是什么意思？

都跑不起来的

你这个编译都是问题，跑都跑不跑起来。理论上来说是没有漏洞的，因为你都没跑起来，更别说漏洞了，哈哈。

编都编不过还谈什么逻辑漏洞

1、number没有定义 2、输入不是整型的处理 3、输入到下一次没有刷新

楼主这个代码编译不过吧，number的类型呢？ 如果输入number的时候，不输入数字，比如输入一串字母？


Question: 关于fopen()函数的一些疑问

对于疑问2：看一下维基百科的说明 https://zh.wikipedia.org/wiki/%E4%BB%A3%E7%A0%81%E9%A1%B5

先说疑问1吧：当使用单字节字符串时，fopen使用ANSI代码页解释文件名字符串，但是可以用Windows API SetFileApisToOEM函数将其更改为使用OEM解释文件名字符串。

字符编码主要有两个钟形式utf8和GB2312


Question: 求教c语言数据结构底层问题

理解和讨论之前请先学会如何观察！  http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素


Question: c语言 为什么不能随便在程序中，任意加{}，组成代码块？

引用 9 楼 自信男孩 的回复:[quote=引用 8 楼 lin5161678 的回复:] [quote=引用 6 楼 自信男孩 的回复:] [quote=引用 1 楼 lin5161678 的回复:] if(exp)     D0(); else      Statement 这样写会找出语法错误 else 没有匹配的if  用D1 就不会 没看出来会有语法错误。宏定义就是替换 if(exp)     D0(a, b); else      Statement 就是替换为如下：  if(exp) {     a++；     a+b; } else      Statement [/quote]注意分号 if(exp) {     a++；     a+b; }; else      Statement [/quote] 没看到;，去掉;号就可以了。  另外，这样D1也是[/quote] D0去掉分号的确可以  但是这要求使用你的宏的人  用那个宏就不加分号 用这个宏就加分号 增加多余的记忆负担  D1 不能去掉分号 do-while 结尾的 分号是语法格式的要求是必须写的

第二种能保证在几乎各种“合法”代码里都有正确结果。遇见的奇怪代码多了，你自然就会明白的。 效率，在开启优化编译的情况下，正常的编译器都应该得到相同的结果。

理解和讨论之前请先学会如何观察！  VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898

关于宏定义引发的使用时带不带；一直争论不休，仁者见仁智者见智。。。。第一种方法对于习惯宏定义后面加；的人来说是个错误，但是第二种方法对于不习惯宏定义加；的人来说也是个错误。没有绝对的对与错，理解就好。

引用 8 楼 lin5161678 的回复:[quote=引用 6 楼 自信男孩 的回复:] [quote=引用 1 楼 lin5161678 的回复:] if(exp)     D0(); else      Statement 这样写会找出语法错误 else 没有匹配的if  用D1 就不会 没看出来会有语法错误。宏定义就是替换 if(exp)     D0(a, b); else      Statement 就是替换为如下：  if(exp) {     a++；     a+b; } else      Statement [/quote]注意分号 if(exp) {     a++；     a+b; }; else      Statement [/quote] 没看到;，去掉;号就可以了。  另外，这样D1也是

引用 6 楼 自信男孩 的回复:[quote=引用 1 楼 lin5161678 的回复:] if(exp)     D0(); else      Statement 这样写会找出语法错误 else 没有匹配的if  用D1 就不会 没看出来会有语法错误。宏定义就是替换 if(exp)     D0(a, b); else      Statement 就是替换为如下：  if(exp) {     a++；     a+b; } else      Statement [/quote]注意分号 if(exp) {     a++；     a+b; }; else      Statement

引用 6 楼 自信男孩 的回复:[quote=引用 1 楼 lin5161678 的回复:] if(exp)     D0(); else      Statement 这样写会找出语法错误 else 没有匹配的if  用D1 就不会 没看出来会有语法错误。宏定义就是替换 if(exp)     D0(a, b); else      Statement 就是替换为如下：  if(exp) {     a++；     a+b; } else      Statement [/quote]就是替换为如下： if(exp) {     a++；     a+b; }; else      Statement

引用 1 楼 lin5161678 的回复:if(exp)     D0(); else      Statement 这样写会找出语法错误 else 没有匹配的if  用D1 就不会 没看出来会有语法错误。宏定义就是替换 if(exp)     D0(a, b); else      Statement 就是替换为如下：  if(exp) {     a++；     a+b; } else      Statement

一般使用第二种，应为更简明，不过效率相比前者较低

2更通用点，但效率稍微低一点点 如果是大项目，很多人开发，建议用2，小项目无所谓

我觉得第一种没问题

do {} whil(0) 在编译器做优化时，已经相当于没有了，联系楼主可以参考下 Linux内核的宏设计，学习下 《从小小的宏定义窥探Linux内核的精妙设计》, 一起来围观吧 https://blog.csdn.net/szullc/article/details/84779352


Question: 求问这题的oj原题或源码

百度搜相关关键字。


Question: 求问这题的oj原题或源码

谢谢了，问题已解决

百度搜相关关键字。


Question: 求求会C语言的大牛救场，判断卡壳了

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

怎么可能卡在这个函数，一定是你定位方向错了

有个人想在一条河上造桥，但是不太会造，就想尽各种办法造了一座。怎么造的呢，在河的同一侧建了四个桥墩，用石头拱起来，但是发现达不到渡河的目的，就各种求助，想找人从旁协助一下，让它正常使用，但是，你真的具备设计桥的知识储备吗？你能造好最关键的四个桥墩吗？你想让别人帮你铺桥，你得先自己造好四个桥墩！不然桥造好了，也只是别人的成果，你不会的还是不会。谁也不是天生就会造桥，只是希望那些不会造的人多观摩一下别人的桥，好好学学怎么造桥墩。

for(i=0;i<999;i++)     {         printf("请输入信息\n");         printf("订单编号:");         scanf("%d",&i);         student.num=i;         printf("名字:");         scanf("%s",student.name);         printf("套餐:");         scanf("%s",student.style);         printf("数量:");         scanf("%d",&student.sl);         printf("订单时间:");         scanf("%s",student.time);         printf("地址:");         scanf("%s",student.add);         printf("\n录入成功\n");         printf("是否继续创建数据(继续创建按1/返回菜单按0):");         scanf("%d", &or);         if (or==0)         {             break;         }     } 真个程序有一个普遍的问题，那就是student是数组名，能直接student.add这样用吗？  void all()   //显示所有订单 {     int i;     printf("编号    名字    套餐    数量   订单时间     地址\n");     for(i=0;((student[i].sl)!=0);i++)     {         //printf("%-8d%-9s%-7s%-7d%-13s%s\n",student.num,student.name,student.style,student.sl,student.time,student.add);         printf("%-8d%-9s%-7s%-7d%-13s%s\n",student[i].num,student[i].name,student[i].style,student[i].sl,student[i].time,student[i].add);     } } 这是我的一个修改；  我估计楼主的代码是无法编译不过去的。  void sum() {     int i=0;     //if (student[0].style='c')     if (student[0].style=='c')         i++; } 当然也有真个问题，但是真个sum有什么作用呢？计算的i给谁？定义的是void类型的返回值。  建议先看一下数组的使用，真个是最大的问题。

i变量只能用于sum函数中，函数没有任何输出，就算这个函数统计了订单你也看不到啊

设断点，单步调试下，应该很清楚的

这样也不行啊


Question: c语言程序流程图

判断平闰年后面 year%400==0; 应该这样的吧

先把程序看懂吧，不要为了应付，多对自己负责吧

引用 1 楼 一念通慧的回复:代码都写出来了，流程图怎么还画不出来了呢？ 程序是老师给的 让我们画流程图

用visio画很简单的

代码都写出来了，流程图怎么还画不出来了呢？


Question: 如何用autoflowchart生成流程图

https://www.cnblogs.com/aademeng/articles/6905351.html EA可以生成关系图


Question: 求一本中英文（双语）的C语言教程，谢谢各位大侠。

引用 楼主 weixin_41794845 的回复:求一本中英文（双语）的C语言教程，谢谢各位大侠。 最好是近几年的，适合大学本科生初学者使用的。 如果有PPT，课本例题源码，习题源码一起的话，就在这里跪谢了。 C语言程序设计 现代方法 非常棒的书籍，要是没有记错，已经是第二版了

估计是没有这种的，又不是英汉读物。不过你可以同时用中文版加英文原版的（或者pdf）。

可以考虑英文和中文版本各买一本。不过，如果但从学习技术方面上好像没必要


Question: 关于数组结束符的问题

基本语法就不对 stu.s_r_BACK_CAT_CODE[101].arr[stu.s_r_BACK_CAT_CODE[101].len]='\0' 不应该是stu.s_r_BACK_CAT_CODE[101][len] = '\0'么 为啥多了个莫名其妙的arr

先初始化成\0，然后再赋值就行了

对的，就是这一句话编译不过去 不是varchar的值，读出来要补一个结束符嘛 arr 不是varchar类型的内容属性嘛

stu.s_r_BACK_CAT_CODE[101].arr[stu.s_r_BACK_CAT_CODE[101].len]='\0' 这句编译不过去吧 s_r_BACK_CAT_CODE和arr是什么关系？从数据结构上看不出什么关系

什么意思？ 没明白


Question: sprintf打印成字符串，首位0如何打出来？

其实就是格式问题，%08d,%-08d，%d等的区别。

其实是输出格式的问题，scanf/printf/fprintf是格式化输入输出，可以通过不同的格式符输出不同的数据格式。%8x改成%08x即可。 还可以通过x的大小写来输出16进制a~f的大小写。

引用 1 楼 leehh 的回复:sprintf((char *)buf,"%08x%08x%08x",ID[0],ID[1],ID[2])； +1

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。


Question: 求助关于PTA1009求和运算的问题

建议贴出更多信息，比如你的输入信息，输出结果等等；      for(i=0;i<number;i++)         scanf("%ld%c%ld",&son[i],&c,&mother[i]); 这个地方很可能是你的输入有问题，因为这里有%c，很可能出现你的输入和你的想要的输入不一致。

表示看你的代码真不如看题目来的直接，虽然不明白你想干嘛。 scanf("%ld",&number); for(i=0;i<number;i++)//这里是不是漏了大括号了，为什么没有大括号会有缩进     scanf("%ld%c%ld",&son[i],&c,&mother[i]);     for(i=0;i<number;i++)

既然你题目都不说了 那我就问题也不答了 来呀 互相伤害呀 斜眼.jpg

自己顶下


Question: 在Windows下，C 关于写入文件的时候遇到的一个问题

引用 3 楼 user-2 的回复:[quote=引用 2 楼 会瞬移的猪 的回复:] [quote=引用 1 楼 user-2 的回复:] 首先 你写的2段代码 属于未定义行为 不要这样做了  然后 你的两个问题其实都是一个问题 并且和C没什么关系  notpad这个软件本身是通过对文件数据分析 猜测文件编码  出现乱码就只是猜错了  顺便 代码2 前面不是2个空格 是2个NUL 只是notpad无法表示NUL而已 你用notpad++打开就能看到2个NUL了   谢谢。 但是是哪一句代码是未定义行为呢？如果是fseek()函数的话，microsoft visual studio上的开发文档说可以在文件结尾外放置指针，并清除文件结尾指示器。你说的意思是这个功能是微软自己添加上去的，而c标准定义该函数的时候是没有定义这个行为的吗？还是？[/quote]的确是fseek 这个函数的用法属于未定义行为 但不是 因为越过 文件结尾  是因为你的文件打开方式  文本模式 fseek 用SEEK_SET 之外的模式都属于 未定义行为的  [/quote]  谢谢。

不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

引用 2 楼 会瞬移的猪 的回复:[quote=引用 1 楼 user-2 的回复:] 首先 你写的2段代码 属于未定义行为 不要这样做了  然后 你的两个问题其实都是一个问题 并且和C没什么关系  notpad这个软件本身是通过对文件数据分析 猜测文件编码  出现乱码就只是猜错了  顺便 代码2 前面不是2个空格 是2个NUL 只是notpad无法表示NUL而已 你用notpad++打开就能看到2个NUL了   谢谢。 但是是哪一句代码是未定义行为呢？如果是fseek()函数的话，microsoft visual studio上的开发文档说可以在文件结尾外放置指针，并清除文件结尾指示器。你说的意思是这个功能是微软自己添加上去的，而c标准定义该函数的时候是没有定义这个行为的吗？还是？[/quote]的确是fseek 这个函数的用法属于未定义行为 但不是 因为越过 文件结尾  是因为你的文件打开方式  文本模式 fseek 用SEEK_SET 之外的模式都属于 未定义行为的

引用 1 楼 user-2 的回复:首先 你写的2段代码 属于未定义行为 不要这样做了  然后 你的两个问题其实都是一个问题 并且和C没什么关系  notpad这个软件本身是通过对文件数据分析 猜测文件编码  出现乱码就只是猜错了  顺便 代码2 前面不是2个空格 是2个NUL 只是notpad无法表示NUL而已 你用notpad++打开就能看到2个NUL了   谢谢。 但是是哪一句代码是未定义行为呢？如果是fseek()函数的话，microsoft visual studio上的开发文档说可以在文件结尾外放置指针，并清除文件结尾指示器。你说的意思是这个功能是微软自己添加上去的，而c标准定义该函数的时候是没有定义这个行为的吗？还是？


Question: 给出程序，求各式结果并分析!!

谢谢各位的解答！

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

引用 3 楼 自信男孩 的回复:第一个sizeof是考察结构体对齐的知识点，在32位系统里是按照4字节对齐的，不足4字节的编译器会补齐4字节。因此：short int data; char ha;  data加上ha的长度是3个字节，因此会补一个字节。short ba[5];长度是10字节，因此后面也会补2个字节。所以长度是28；  c. p+0x200=? d. (unsigned long)p+0x200=? 这两个是考察指针类型与偏移值的关系。p是info_t因此p + 1即p向后偏移sizeof(info_t)即，偏移28个字节，所以p + 0x200 = (char *)p + 0x200 * 28;同理(unsigned long)p + 0x200 = (char *)p + 0x200 * sizeof(usigned long); 我的回复有一个问题：d. (unsigned long)p+0x200=?这个我看成(unsigned long *)p + 0x200;所以，不是(char *)p + 0x200 * sizeof(long);  而是相当于0x10000000 + 0x200;因为p为0x10000000;

引用 2 楼 user-4 的回复:[quote=引用 1 楼 user-4 的回复:] a. 28 b. 4 c . 0x10003800 d   0x10000800 e  0x10000200 a. 首先对成员变量进行对齐运算，然后看结构体自己是否对齐到4字节：  typedef struct{ long num;       // 4 bytes char *name;    // 4 bytes; short int data;    //2 bytes char ha;             // 1 bytes //因为short需要从2的倍数开始，所以这里空余 1byte short ba[5];       //10 bytes //因为int需要从4的整数倍开始，所以这里空余 2bytes int crc;               // 4bytes }info_t; info_t *p;  合计: 28bytes.  b. 因为是32位机器，所有指针都是4个字节  c.  p+0x2000， 移动地地址由p指针指向的类型决定。28字节为0x1c, 结果是0x200乘以0x1c, 再加上其实地址 d.  unsigned long长度为4字节，结果为4*0x200 , 再加上起始地址 e. char*指向长度为1字节，所以结果是起始地址加上0x200[/quote]   疑问？？ 如果问题e由（char*）p+0x200改为（char）p+0x200  ，我的理解是这样的，char长度为1字节，结果为1*0x200，再加上起始地址，所以是0x10000200，加*和不加*结果一样？

struct结构内存对齐

引用 4 楼 半根烟浪江湖 的回复:[quote=引用 2 楼 user-4 的回复:] [quote=引用 1 楼 user-4 的回复:] a. 28 b. 4 c . 0x10003800 d   0x10000800 e  0x10000200 a. 首先对成员变量进行对齐运算，然后看结构体自己是否对齐到4字节：  typedef struct{ long num;       // 4 bytes char *name;    // 4 bytes; short int data;    //2 bytes char ha;             // 1 bytes //因为short需要从2的倍数开始，所以这里空余 1byte short ba[5];       //10 bytes //因为int需要从4的整数倍开始，所以这里空余 2bytes int crc;               // 4bytes }info_t; info_t *p;  合计: 28bytes.  b. 因为是32位机器，所有指针都是4个字节  c.  p+0x2000， 移动地地址由p指针指向的类型决定。28字节为0x1c, 结果是0x200乘以0x1c, 再加上其实地址 d.  unsigned long长度为4字节，结果为4*0x200 , 再加上起始地址 e. char*指向长度为1字节，所以结果是起始地址加上0x200[/quote]   疑问？？ 如果问题e由（char*）p+0x200改为（char）p+0x200  ，我的理解是这样的，char长度为1字节，结果为1*0x200，再加上起始地址，所以是0x10000200，加*和不加*结果一样？[/quote] 抱歉看错了。d是“(unsigned long)p+0x200”的话，结果是0x10000200.相当于无符号整数相加。  e如果修改为(char)p+0x200, 也相当于两个整数相加，结果也是0x10000200. (char*)p + 0x200, 是地址增加，结果也是0x10000200. 结果没变。

引用 1 楼 user-4 的回复:a. 28 b. 4 c . 0x10003800 d   0x10000800 e  0x10000200 a. 首先对成员变量进行对齐运算，然后看结构体自己是否对齐到4字节：  typedef struct{ long num;       // 4 bytes char *name;    // 4 bytes; short int data;    //2 bytes char ha;             // 1 bytes //因为short需要从2的倍数开始，所以这里空余 1byte short ba[5];       //10 bytes //因为int需要从4的整数倍开始，所以这里空余 2bytes int crc;               // 4bytes }info_t; info_t *p;  合计: 28bytes.  b. 因为是32位机器，所有指针都是4个字节  c.  p+0x2000， 移动地地址由p指针指向的类型决定。28字节为0x1c, 结果是0x200乘以0x1c, 再加上其实地址 d.  unsigned long长度为4字节，结果为4*0x200 , 再加上起始地址 e. char*指向长度为1字节，所以结果是起始地址加上0x200


Question: C语言Switch语句

仅供参考：#include <stdio.h> #include <string.h> char s[80]; int i; char c; int main() {     while (1) {         printf("Input a integer:");fflush(stdout);         rewind(stdin);         fgets(s,80,stdin); 		if (strlen(s)>10) { 			printf("Input too long(>9)!\n"); 			continue; 		}         if (2==sscanf(s,"%d%c",&i,&c)) {             if ('\n'==c) {                 printf("%d is a integer.\n",i);                 break;             }         }         if ('\n'==s[strlen(s)-1]) s[strlen(s)-1]=0;         printf("\"%s\" is NOT a integer!\n",s);     }     return 0; }

scanf有问题，只能输入整形

建议楼主在使用系统接口时，先熟知其定义及返回值；如scanf的函数原型为： int scanf(const char * restrict format,...); 它的返回值定义如下： scanf函数返回成功读入的数据项数，读入数据时遇到了“文件结束”则返回EOF；当返回0时，表示实际没有成功读入对应数据。  回到楼主的测试代码，我稍微修改了，一下子就能发现问题了：注意有2个问题，一是a未初始化，而是未判断scanf的返回值；#include <stdio.h>  void main(void) {     int a; //这里定义a是未初始化的，理论上它的值是随机的 	int ret; 	 	printf("1=====a=%d\n", a);     printf("请输入: ");     ret= scanf("%d",&a); //注意判断scanf的返回值 	printf("2=====a=%d， scanf ret=%d\n", a, ret); 	     switch(a)     {         case 1:            printf("输入了1。\r\n");            break;         case 0:            printf("输入了0。\r\n");            break;         default :            printf("输入错误!\r\n");            break; 	} }  修正后的测试代码如下： void main(void) {     int a = -1; //这里定义a时初始化为-1 	int ret; 	 	printf("1=====a=%d\n", a);     printf("请输入: ");     ret= scanf("%d",&a); //注意判断scanf的返回值 	printf("2=====a=%d， scanf ret=%d\n", a, ret); 	 	if (ret != 1) { //判断scanf的返回值，当ret不为1时(读入1个整数)，表示输入错误 		printf("输入错误!\r\n"); 		return; 	} 	     switch(a)     {         case 1:            printf("输入了1。\r\n");            break;         case 0:            printf("输入了0。\r\n");            break;         default :            printf("输入错误!\r\n");            break; 	} }  测试记录如下： root@liluchang-ubuntu:/share/llc/test_scanf# ./test_scanf  1=====a=-1 请输入: 777777777 2=====a=777777777， scanf ret=1 输入错误!  root@liluchang-ubuntu:/share/llc/test_scanf# ./test_scanf  1=====a=-1 请输入: 1 2=====a=1， scanf ret=1 输入了1。  root@liluchang-ubuntu:/share/llc/test_scanf# ./test_scanf  1=====a=-1 请输入: 0 2=====a=0， scanf ret=1 输入了0。  root@liluchang-ubuntu:/share/llc/test_scanf# ./test_scanf  1=====a=-1 请输入: gggggg 2=====a=-1， scanf ret=0 输入错误!  测试案例输入很大的整数、字符串、数字1和输0，均能得到预期效果。

只定义了a为int型，如果a为字符就不能执行了

引用 15 楼 Hello.Word 的回复:[quote=引用 14 楼 Hello.Word的回复:]代码没问题呀，非0即为真 case '1':printf（"输入了1"）；把1加单引号试试[/quote] 那你就要输入49才会回答“输入了1”。a是int类型也是%d输入的，应该用整数来运算。

把a初始化不就行了？

引用 14 楼 Hello.Word的回复:代码没问题呀，非0即为真 case '1':printf（"输入了1"）；把1加单引号试试

代码没问题呀，非0即为真

我在我的编译器上跑了一下代码，并没有出现楼主所说的问题。但是以防万一，最好还是把a初始化。

应该就是int 和char类型不匹配，使scanf错误

变量改成char 类型吧      类型不匹配出问题是很正常的  （C语言中， 用int 定义变量，采用scanf("%d")函数进行数据输入时，如果按下了非数字键，则scanf()函数会返回错误。）

输入的有问题吧

加一句这个试试？ default：        fflush(stdin);        printf。。。。

代码没有问题，应该是编译器的问题

定义变量最好都初始化，好的习惯

引用 2 楼 qq_33462307 的回复:[quote=引用 1 楼 自信男孩 的回复:] 输入非数字之外的，那么scanf执行会出现问题，即并没有把输入的内容放到a中，建议你这样操作时，先在scanf后面加上一条打印语句： printf("a = %d\n", a);你看一下a是什么值。 我猜是0 哈哈[/quote] 从结果来看是a的值是0。这个值应该是定义并初始化了0,（未初始化的局部变量是随机值，0也是可能的）

执行switch 0，只是因为你编译器正好让a的默认值为0了而已。

scanf要求输入的字符类型为整型，如果输入了字符，应该是读取失败，本行语句没有对a进行操作。 可以把a设置一个初始值，如99，然后加上打印语句，运行后输入字符，发现a的值仍然是99。

引用 1 楼 自信男孩 的回复:输入非数字之外的，那么scanf执行会出现问题，即并没有把输入的内容放到a中，建议你这样操作时，先在scanf后面加上一条打印语句： printf("a = %d\n", a);你看一下a是什么值。 我猜是0 哈哈


Question: [C语言] 关于函数指针的疑惑

可以类比数组名和数组地址吧，比如int a[10]中，a这个变量同时也是这个数组的首地址，而&a同样是这个值，但是意义不同

函数名隐式类型转换 指向这个函数的指针  对函数指针执行 * 操作 得到一个函数  然后 这个函数又会重新隐式类型转换成 指向这个函数的指针  无限递归  你甚至可以 (**************************************************aTest)(3,5) 这样来调用 aTest函数 虽然没什么意义就是了

这和数组名差不多吧。数组名是数组的首地址，本身就是地址。而函数名也是地址，是函数的首地址（使用入口地址更确切）；

同样一个语法元素要在上下文中才能确定其具体语义，这一点编程语言和我们平时说的语义是一样的。 说白了就是同一种符号，在不同的语句中表达的含义不同，这是语法规则决定的。拿你这个例子来说，就是&p p *p三个东西来，在当p是一个普通变量时、当p是一个普通变量一级指针时、当p是一个普通变量二级指针时、当p是一个函数指针时......这些场景下的三个东西代表的含义是不一样的，具体是什么含义就是你所看到的。 再举一个简单的例子，“abcd”是同样的，但在printf("abcd")和sizeof("abcd")两句话中的类型是完全不同的。 总之有些语义可以通过语法来推测，而有一些则不能“推广”，这本身也是语法的一部分。


Question: 求书求书啊大佬们

搜C基础或者C++基础。随表一本都差不多，结构就是定义，真正用到了才是纠结的时候

数据结构与算法（C语言版）

《数据结构与算法分析》

记得学校发的数就可以的。如果想边学边实践（有例子的），可以考虑看一下《C programming  plus》


Question: MS-DOS下运行程序卡死怎么退出的问题

Ctrl+C 即可中断

引用 1 楼 super_admi 的回复:进入MS-DOS，狂按Ctrl+C应该也可以，直接中断。  话说，你这不是调试MS-DOS程序的状态啊，好歹配置下Config.sys或者在Autoexec.bat中写个分支。  对，这个绝对可以的

MS-DOS，中断应该是 Ctrl+C  难道现在还有在这上面开发程序？

CTRL+BREAK

Ctrl+C

分的高分段分的高分段

多刷新几次，不行再关机重启试试

什么年代了，还用free dos

多多钻研，，，，

简述：非蓝牙模式，普简述：非蓝牙模式，普通音箱和普通耳机连接电脑，声音没有延迟。蓝牙模式连接蓝牙音箱，则蓝牙音箱的声音出现明显的延迟5-6秒。通音箱和普通耳机连接电脑，声音没有延迟。蓝牙模式连接蓝牙音箱，则蓝牙音箱的声音出现明显的延迟5-6秒。

引用 4 楼 ooolinux 的回复:[quote=引用 2 楼 zhoup20 的回复:] [quote=引用 1 楼 ooolinux 的回复:] MS-DOS什么版本？纯DOS是16位的，老的Turbo C或Turbo Pascal等写的程序才可以运行。Win9x带的DOS是32位的。 纯MS-DOS系统下的，版本好像是5点几，程序是我用Turbo C编译后用U盘拷进去的，拷贝的时候有点问题，现在系统一直运行那个程序，我不知道怎么退出来[/quote]  用DOSBox试试。  C与C++程序设计学习与实验系统 2013.3 可以不用建立项目（单文件），简单的试验代码甚至不用保存为文件，直接编译运行观察结果，比较方便。 只有几十M大小。自带GCC编译器、VC 6.0编译器和TC编译器（选项可设置），自带DOSBox运行TC生成的exe程序。  TC（Turbo C）老代码（比如小游戏）最好看懂了以后，理解了算法和过程，用VC改写成Windows平台的。 [/quote]谢谢，主要是这系统运行在PC104里

引用 3 楼 user-13 的回复:开机后  多次F5 可以跳过config.sys 和 autoexec.bat, 或者F8  选择性启动恩恩，好的，我明天试试，感谢感谢

引用 2 楼 zhoup20 的回复:[quote=引用 1 楼 ooolinux 的回复:] MS-DOS什么版本？纯DOS是16位的，老的Turbo C或Turbo Pascal等写的程序才可以运行。Win9x带的DOS是32位的。 纯MS-DOS系统下的，版本好像是5点几，程序是我用Turbo C编译后用U盘拷进去的，拷贝的时候有点问题，现在系统一直运行那个程序，我不知道怎么退出来[/quote]  用DOSBox试试。  C与C++程序设计学习与实验系统 2013.3 可以不用建立项目（单文件），简单的试验代码甚至不用保存为文件，直接编译运行观察结果，比较方便。 只有几十M大小。自带GCC编译器、VC 6.0编译器和TC编译器（选项可设置），自带DOSBox运行TC生成的exe程序。  TC（Turbo C）老代码（比如小游戏）最好看懂了以后，理解了算法和过程，用VC改写成Windows平台的。

引用 1 楼 ooolinux 的回复:MS-DOS什么版本？纯DOS是16位的，老的Turbo C或Turbo Pascal等写的程序才可以运行。Win9x带的DOS是32位的。 纯MS-DOS系统下的，版本好像是5点几，程序是我用Turbo C编译后用U盘拷进去的，拷贝的时候有点问题，现在系统一直运行那个程序，我不知道怎么退出来


Question: C语言菜鸟，两个横线填什么

int fun(int(*a)[N]) { 	int  i, j, m1, m2, row, colum; m1 = m2 = 0; 	for (i = 0; i<N; i++)//计算主对角线和反对角线的和 	{ 		j = N - i - 1;  		m1 += a[i][i]; //主对角线的和 		m2 += a[i][j];//反对角线的和 	} 	if (m1 != m2) 	{ 		return  0; 	} 	//计算每行和每列的和 	for (i = 0; i<N; i++) 	{ 		row = 0;//每次行的和要清零 		colum = 0;//每次列的和要清零，注意列的英语是column 		for (j = 0; j<N; j++) 		{ 			row += a[i][j];   			colum += a[j][i]; 		} 		if ((row != colum)||(row != m1)) 			//如果每行的和不等于每列的和 			//或者虽然每行的和与每列的和相等，但是它们与主对角线的和不相等 			return 0; 	} 	return 1; }

在外部循环内，求每行每列的和。很简单，求和前对row, column清零0    for(i=0; i<N; i++) {row=0;      colomun=0;      for(j=0; j<N; j++)      {  row+=a[i][j];  colum+=a[j][i];  }         if( (row!=colum) ||   (row!=m1) )  return 0;


Question: 编程问题求助，以下程序输出结果是什么 求分析

1楼和8楼都给出了详尽的回答，确实代码语法问题挺多，最重要的是传入指针给函数内部执行malloc是无法将malloc的地址传递出去的，需要传入二级指针，像8楼的那样，运行没有问题。

首先上修改后的代码 #include<stdio.h> #include <stdlib.h> #include <string.h> using namespace std;  void GetMemory1(char **p1) { 	*p1 = (char*)malloc(100);        //malloc(100):开辟100个字节的临时分配域，函数值为其第1个字节的地址  }   void Test1(void) { 	char *str1 = NULL; 	GetMemory1(&str1); 	strcpy(str1, "hello world"); 	printf(str1); 	printf("\n");         free(str1); }  int main() { 	Test1(); 	system("pause"); 	return 0; }  VS2015+Windows10运行的效果如下  主要存在问题： 1 Test1()函数要在main()函数之外定义，且要先声明（定义）GetMemory1，在定义Test1()函； 2 要包含string.h头文件，该头文件中包含了strcpy()函数的声明； 3 在Test1()函数中要用free()函数释放动态分配的空间，以免引起内存泄漏； 4 GetMemory1()函数的参数应该是指针的指针，这样在Test1()函数中才能正确获取分配空间的地址； 关于函数参数是指针的指针类型的相关知识，请参考《C++中函数参数类型为指针的指针》 希望能够帮到你

谢谢各位的解答！

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

看上去像是面试改错题

这个问题，笔试和面试都问烂了吧，随便搜一下到处都是答案，比这里的回答可以详细多了

结果是运行会出现段错误；因为str1是指向NULL，即不可读写的位置。strcpy就是对其写，因此会出现段错误；  可能会说给其分配空间了，只是分配的空间的首地址并没有存在str1中，即分配空间的函数并没有修改str1的值，对str1没有影响，另外还导致内存泄漏，因为GetMemory1函数执行之后，申请的空间找不到了，无法手动释放它了。

我先说结果哈, 结果就是没输出, 啥也没有, 就算有, 也是直接崩溃这么一个结果.  首先, 我先说这代码写的有很多语法错误: 1. void GetMemory1(char *p1) 这个函数没有函数声明. 2. 用 strcpy() 需要 #include <string.h> 3. printf 输出字符串应该为 printf ("%s", str1);  (你的写法是 puts() 的用法)  4 !!!!!!!! 最重要的一点 !!!!!!!!  c 语言不能在函数里面定义函数啊啊啊啊啊啊, 即使是主函数也不可以 !!!!!!!!!!  上面的如果都更改之后! ( 我尽量猜测一下你想干嘛..) 就变成了下面这样:   #include <stdio.h> #include <stdlib.h> #include <string.h>  void GetMemory1(char *p1); void Test1(void);  int main(){     Test1();     return 0; }  void Test1(void){      char *str1=NULL;      GetMemory1(str1);      strcpy(str1,"hello world");      printf("%c", str1[0]);     printf("\n"); }  void GetMemory1(char *p1){     p1=(char*)malloc(100);        //malloc(100):开辟100个字节的临时分配域，函数值为其第1个字节的地址 }   这样依然会报错, malloc虽然会在堆中开辟空间, 也将地址赋值给了p1,   但由于 p1 只是形参, 即使给他赋值了, 他也更改不了,   返回主调函数, 他原来是啥现在就依然还是啥, (这一点可能你对指针理解有点问题, 仔细看看书好好理解一下指针做函数参数是怎么回事)  正因如此, test1() 调用的 GetMemory(), 所以 str1 的值还是 NULL .  str1 就只是一个指针, 并没有为他分配空间, 在给他 strcpy() 时, 会报指针越界的错误.  所以!!!! 真的没有输出 !!!!!   ps: 头一回发评论, 不知道说的全不全, 大佬看到我说的如果有错误, 千万要指正..跪谢..


Question: C语言

应该说多维数组是一维数组的数组（的数组。。）

strcpy(data[0][0], "xxx");  注意数组越界问题。  字符串赋值除了初始化可以直接赋值，其他情况建议借助字符串处理函数

多维数组的最后一维是一个一维数组，比如三维数组char data[3][5][20]，data[0][0]就是一维数组了，也是该一维数组的首地址，等于&data[0][0][0]。给这个地址strcpy就可以了。 谭浩强的那本书讲多维数组还是蛮清楚的，可以参考一下。

引用 7 楼 qq_41771408 的回复:为什么不能直接data[0][0]="数据已删除!";呢data[0][0]是一个数组 类型是 char[20] 数组都不能赋值不是常识么

“变量赋值”和“变量初始化”不是一回事！ “变量赋值”发生在运行期，其写法遵循赋值语法规定。 “变量初始化”发生在编译期或运行期，其写法遵循初始化列表语法规定。

strcpy(),不能直接初始化

1、strcpy/strcpy_s 2、sprintf/sprintf_s 3、memcpy/memcpy_s

1. 使用strcpy() 2. 可以循环拷贝。

strcpy() 在 string.h 中 如下:  #include <stdio.h> #include <string.h>  int main(){     char data[2][6][20];     strcpy(data[0][0], "数据已删除!");     puts(data[0][0]);     return 0; }

定义的时候直接用字符串赋值  注意：不能先定义再给它赋值  可以利用strcpy


Question: 【C语言】多级指针如何确定类型？

这个问题需要通过具体的应用去分析

建议结合例子分析指针类型可能会更好一些，可以找一些例子分析一下，同时通过调试打印验证自己猜测或者别人的结论。

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

char*是用来指向char的，char**用来指向char*，char***用来指向char**......这样下去，每一级都是有类型限制的，最终的结果就是像你说的一样。 建议你把char**也看做一种特定的类型，它char在语法上是同等地位的，而不是某种用来“过渡”的东西。

char **p 是一个指向char*型变量地址的指针，而char*型变量指向一个char型变量的指针。


Question: 指向指针的指针, 获取数据为何是 *((key_type**)

引用 1 楼 老马何以识途 的回复:default_configs[0]即&csr_stereo_default_config，它是一個config_type指針，即一個config_type結構的首地址，這個地址同時也是其第一個元素battery_config的地址，，也就是説如果對它進行*運算，得到的當然就是battery_config的内容了。battery_config的内容是什麽呢？就是一個key_type*，其地址當然是key_type**，所以爲了類型正確，先做一個key_type **轉換。  爲了理解“一個config_type結構的首地址，這個地址同時也是其第一個元素battery_config的地址”這句話，我們舉一個簡單例子：   struct example {         int age;         int num; } a*;   這個a所指向的地址見下圖：    age的地址怎麽表示呢？其實首地址依然是a，這時候我們只要强制轉換：   int * b = (int *)a;   就可以得到它了。 感谢谢谢谢谢, 关键在于引用battery_config的内容是什麽呢？就是一個key_type*，其地址當然是key_type** 此句, 此前没有想到.赞!

《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！


Question: 有没有人还在用pro c 的，有一个连接问题

参考：  Pro *C/C++学习笔记（一）

pro*c是效率最高的访问oracle的方式，也许除了oci？ oracle_id里可以使用 用户/密码@数据库地址/数据库名 这样的格式 或者在tnsname.ora里设置，就可以直接使用  用户/密码@配置好的连接名

Oracle是用tns listener連接的，你需要到Oracle客戶端中配置這個東西。


Question: 一道数据结构题目

整理一下，不知道分析正不正确，忘高手和大神指教：   1）设D(i)为第i个节点的比较次数，等于 大于等于其深度的最小整数；对于具有N个节点的树： C（成功查找）= [D(1) + ... + D(N) ] / N； 而不成功查找的节点最后一次比较必然在树的叶子节点上，可以认为与每个叶子节点比较的概率相等，故不成功查找的平均比较次数为 大于等于平均高度的最小整数； 2）对于完全二叉查找树，深度为d的层的节点数为 Nd = 2^d，则深度为k的完全二叉查找树的总节点数为：N = 2^(k+1) - 1, 设每个节点的被查找的次数相等， a.则成功查找的平均比较次数为： Avg（成功查找）= （1 * 2^0 + 2*2^1 + 3*2^2+...+(k+1)*2^k）/ N; 又因为 S(n) = 1 + 2*2 + 3*2^2 +...+(n+1)*2^n=n*2^(n+1) + 1，（k=0,1,2,...,n）; 故   Avg（成功查找）= [k*2^(k+1) + 1] / [2^(k+1) - 1] = k + (k + 1) / [2^(k+1) - 1];  k <= Avg <= k + 1, k = log (N + 1) - 1,  -->  log(N+1) -1 <= avg <= log(N + 1),即平均查找次数为 大于等于logN的最小整数； b.若不成功查找，每次比较的次数都等于其 （树高 + 1 = 大于等于logN的最小整数）；

对于完全二叉查找树，深度为d的层的节点数为 Nd = 2^d，则深度为k的完全二叉查找树的总节点数为：N = 2^(k+1) - 1, 设每个节点的被查找的次数相等， 1）则成功查找的平均比较次数为： Avg（成功查找）= （1 * 2^0 + 2*2^1 + 3*2^2+...+(k+1)*2^k）/ N; 又因为 S(n) = 1 + 2*2 + 3*2^2 +...+(n+1)*2^n=n*2^(n+1) + 1，（k=0,1,2,...,n）; 故   Avg（成功查找）= [k*2^(k+1) + 1] / [2^(k+1) - 1] = k + (k + 1) / [2^(k+1) - 1];  k <= Avg <= k + 1, k = log (N + 1) - 1,  -->  log(N+1) -1 <= avg <= log(N + 1),即平均查找次数为 大于等于logN的最小整数； 2）若不成功查找，每次比较的次数都等于其 （树高 + 1 = 大于等于logN的最小整数）；


Question: 数据结构 顺序表 结构体

建议贴出数据结构

理解和讨论之前请先学会如何观察！  //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]   不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

data.[i].key 这个是啥意思？

data  是咋个申明和定义的


Question: warning C4090  不同的“const”限定符

问题自己解决了，计算机不骗人，函数的参数类型和传入的类型之前写的有区别，查了一点。

NTSTATUS s; s=File_GetFIleStandardInfo...

中间变量 中转

添加一个中间变量即可，如一楼所示。

FltObjects是PostCreate函數帶進來的，試一下在File_GetFileStandardInfo函數中對該參數用和PostCreate相同的限定符_In_如何？


Question: while多条件循环问题

不要用逻辑与&&，而是要用逻辑或||，当这两个条件之一成立时（暴力输入或者输入负数时），就要重新输入。 对于scanf()函数的用法，请参考 《C++中scanf和printf系列函数简介》 希望能够帮到你

(scanf("%f",&one.count)!=1&&one.count>0) 能不能先解释下你的目的？

看了好几遍才看懂楼主想表达的意思 按照正常的理解应该用||逻辑才对 两个只要有一个不满足就打印重新输入

上面说错了，应该改成while (scanf("%f",&one.count)!=1 || one.count<=0){..} 这样，因为上面两个条件只要有一个不满足就不通过

while (scanf("%f",&one.count)!=1&&one.count>0) 这和用不用别的变量没关系，注意看他的条件，&& one.count>0    &&是and的意思，你的意思是让他输入大于0的时候重新输入吗，应该是小于0的时候重新输入吧。应该改成while (scanf("%f",&one.count)!=1&&one.count<=0)

scanf("%f",&one.count)!=1成立的条件是你输入的不是一个float数，比如字符串； 那么你要同时满足上述条件和count>0，那到底什么条件是满足的，你举个例子； 我想你要写的是scanf("%f",&one.count)==1吧

用别一个变量呗 int input; while (scanf("%f",&input)!=1&&input<0)             {                 printf("\n输入不规范，请重新输入");                 fflush(stdin);                 printf("\n请输入购买该种水果的数量：");             } one.count = input


Question: [小白]用c写了个css自动格式化的工具，遇到一些问题。。

仅供参考：//有字符串 //1_22_333,,4444__55555,_666666 //需要解析为 //1 //22 //333 //_ //4444 //55555 //666666 #include <stdio.h> char s[]="1_22_333,,4444__55555,_666666"; char c,*p,*p1; int st; void main() {     st=0;     p=s;     while (1) {         c=*p;         if (0==c) {             switch (st) {             case 1:printf("_\n");    break;             case 2:printf("%s\n",p1);break;             }             break;//         }         switch (st) {         case 0:                  if ('_'==c) {                            st=0;}             else if (','==c) {                            st=1;}             else             {p1=p;                       st=2;}         break;         case 1:                  if ('_'==c) {                            st=1;}             else if (','==c) {printf("_\n");              st=1;}             else             {p1=p;                       st=2;}         break;         case 2:                  if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}             else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}             else             {                            st=2;}         break;         }         p++;     } } //1 //22 //333 //_ //4444 //55555 //666666

抱歉才看见，之前的问题解决了，我研究一下您的代码，晚上结帖哈哈哈，感谢大佬~~~

目前可以将上图这种被压缩过没有空格换行的min.css文件转换为下图这模样。。但是我不想要 tag 名和 hover，focus等等之间的空格啊啊啊。。 心态崩了。。

源码如下： #include <stdio.h> #include <string.h>  int main(int argc, char const *argv[]) {     FILE *srcfile, *aimfile;     char srcpath[100] = "tmp/";     char aimpath[100] = "res/";     char srcfilename[] = "bootstrap-reboot.min.css";     char aimfilename[] = "bootstrap-reboot.css";     char prechar, curchar, sufchar;     int brace = 0;              // '{' counts. For computing indent.     int isAnnotation = 0;     int iscolon = 0;            // to make a ':' is a line; solve something like 'font-family: SFMono-Regular, "Liberation Mono", "Courier New", monospace;'      strcat(srcpath, srcfilename);     strcat(aimpath, aimfilename);      srcfile = fopen(srcpath, "r");     aimfile = fopen(aimpath, "w");      curchar = fgetc(srcfile);     prechar = curchar;     do {         sufchar = fgetc(srcfile);         fputc(curchar, aimfile);    // only put curchar into new file          // ignore annotation         if (curchar == '*' && sufchar == '/') {             isAnnotation = 0;         }         if (prechar != '*' && curchar == '/' && sufchar == '*') {             isAnnotation = 1;         }         if (isAnnotation) {             curchar = sufchar;             continue;         }         // put an enter between '*/' and classname         if (prechar == '*' && curchar == '/') {             fputc('\n', aimfile);         }            if (sufchar == '{') {  // put a space between classname and '{'             fputc(' ', aimfile);         } else if (sufchar == '}') {             if (curchar != '}' && curchar != ';') { // avoid unnecessary line break                 fputc('\n', aimfile);             }             brace--;        // a '{}' is over, indent will reduce             for (int i = 0; i < brace; i++) {                 fputc('\t', aimfile);             }         }            if (curchar == '{' || curchar == ';') {             if (curchar == '{'){                 brace++;        // one '{' makes its items one more indent             }             if (curchar == ';') {                 iscolon = 0;    // the ':' is over.             }             fputc('\n', aimfile);             for (int i = 0; i < brace; i++) {                 fputc('\t', aimfile);             }         } else if (curchar == '}') {             iscolon = 0;    // the ':' is over.             fputc('\n', aimfile);             if (curchar == '}') {                 for (int i = 0; i < brace; i++) {                     fputc('\t', aimfile);                 }             }         } else if (curchar == ',') {             if (iscolon) {                 fputc(' ', aimfile);             }             else {                 fputc('\n', aimfile);             }         } else if (curchar == ':' && prechar != ':' && sufchar != ':') {             fputc(' ', aimfile);    // put a space behind ':', except something like '::after'             iscolon = 1;            // ':' is begin         }           prechar = curchar;         curchar = sufchar;     } while (curchar != EOF);          fclose(srcfile);     fclose(aimfile);     return 0; }


Question: 新手求解，实在是搞不懂怎么判断有向图无向图邻接矩阵邻接表的边数度数什么的

《算法精解（C语言描述）》


Question: 编程小白求助。遇到两个小编程算法不会

堆排序了解下

参考： https://blog.csdn.net/kisslalaa/article/details/74278852

谢谢。可是第二题我在网上只搜到快排最坏情况下时间复杂度为O(n^2)的算法，最坏情况下复杂度为O(nlogn)的我还是没找到

1.  while (n) {   n = n & (n - 1);   count++; }

这两个题都是很常见的测试题，网上一搜就有很多，第一道图题的第二问楼上已给 下面这个搜快速排序算法就行了


Question: metlab求教

所见不一定是所得。 可能原因1：两者类型不严格一致。 可能原因2：浮点数计算机表达误差。 参考： 浮点数格式 http://bbs.csdn.net/topics/390676437


Question: 为什么这个程序输出结果是a=16,b=9,c=7？求大神指点，代码如下

【变量作用域的问题: 当一个代码段有与全局变量同名的变量时，该代码段以局部变量为生效；反之，则以全局变量为生效】  c=func(&a,b); 执行过程： int func(int *p,int a)  { 	a++; //a=3+1=4 	*p=a+b; //*p=4+0=4 //b是全局的，默认初始化为0 	b++; //b=0+1=1 	return(*p+a); //return (4+4) = 8 } 之后a=4，c=8，全局的b=1，局部的b=3  b=func(&c,a); 执行过程： int func(int *p,int a)  { 	a++; //a=4+1=5 	*p=a+b; //*p=5+1=6 //b是全局的，此时值为1 	b++; //b=1+1=2 	return(*p+a); //return (6+5) = 11 } 之后a=4，c=6，局部的b=8，全局的b=2，  a=func(&b,c); 执行过程： int func(int *p,int a)  { 	a++; //a=6+1=7 	*p=a+b; //*p=7+2=9 //b是全局的，此时值为2 	b++; //b=2+1=3 	return(*p+a); //return (9+7) = 16 } 之后a=16，c=6，局部的b=9，全局的b=3，  打印输出结果：printf("a=%d,b=%d,c=%d",a,b,c); 都是输出局部的a/b/c，所以答案是 16,9,6 ; 而不是 16,9,7

多多养成单步调试和设断点调试的习惯。通过自己调试解决问题，比他人帮你找出原因，受益是完全不一样的

每一步执行完以后就加个打印 printf("a=%d,b=%d,c=%d",a,b,c); 这实际就是指针传递和值传递问题，传指针的时候如果用*p=这样的解应用就改变了原来的值，值传递不改变值。

c=func(&a,b); printf("a=%d,b=%d,c=%d",a,b,c); b=func(&c,a); printf("a=%d,b=%d,c=%d",a,b,c); a=func(&b,c); printf("a=%d,b=%d,c=%d",a,b,c);  自己动手，丰衣足食

a的值由a = func(&b, c);决定，因为这个是最后修改a的表达式；同样b而是；c由b  = func(&c, a);这个表达式之后就能确定c的值。注意由于main中重新定义了b,所以全局变量b就会被屏蔽，main中输出的是局部变量b。但在func函数里是有效的。  先看第一个: c=func(&a,b);这条语句执行之后，a = 4（*p = 4 + 0); b = 1（全局），b = 3(局部), c = 8;  b = func(&c, a); 这条语句执行之后：a = 4, b = 2（全局）, b = 11(局部), c = 6； a=func(&b,c);这条语句执行之后: a = 16, b = 9, c = 6;

主函数中定义的b不是把全局变量中的b给覆盖了吗？

上边定义int *a int p为什么下边就成int *p int a了？？

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

怎么会有这么乱的代码，完全就是中国式考题，你就按照步骤一步步算下去就行了，主要是这个函数int func(int *p,int a)的定义 p是一个指针，改变p的内容会改变传入的变量的值，而改变a不会改变传入的变量值，然后注意一下返回值就行了

如果把函数中的int *p改成int p 然后在函数内部写*p=a+b;就会是另一个结果

因为你func（&a,b）,对应的函数是(int *p,int b) 所以说*p=&a; 由于是把a的地址赋给了指针，所以返回的return （*p+b）中的*p取得值就是2


Question: 为什么最大值在0行0列时输出结果不是在零行零列，哪里写错了吗？

引用 2 楼 user-3 的回复:2楼给的结果也不对吧 我试着从打从1-16的数组 16在第四行四列，但是运行之后显示的结果中是第三行第三列。 数组下表是从0开始的

4*4的数组最大的就是第三行第三列啊

#include<stdio.h>  void input(int *p,int r,int l); void max(int *p,int r,int l);  void print(int (*arr)[4], int row, int col); //void main() int main() {     int a[4][4];     printf("input a[4][4]\n");     input(a[0],4,4);     print(a, 4, 4);     max(*a,4,4); } void input(int *p,int r,int l) {     int *q,*q_end=p+r*l;     for(q=p;q<q_end;q++)         scanf("%d",q); } void max(int *p,int r,int l) {     int i,j,m = 0, n = 0,mx=*p;     for(i=0;i<r;i++)         for(j=0;j<l;j++,p++)             if(mx<*p)             {                 mx=*p;m=i;n=j;             }     printf("max=%d,第%d行第%d列\n",mx,m,n); }  void print(int (*arr)[4], int row, int col) {     int i, j;      for (i = 0; i < row; i++) {         for (j = 0; j < col; j++)             printf("%d ", arr[i][j]);         putchar(10);     }     putchar(10); } m和n没有初始化，当最零值在第一行第零列时，n和m是随机值


Question: 请教下老师这

第五题： 思路：a[i]=a[i-1]+a[i-2] #include<iostream> using namespace std; int a[1001],x; int main(void) { 	cin>>x; 	a[1]=1; 	a[2]=1;//初始化前两项  	for(int i=3;i<=x;i++) 	{ 		a[i]=a[i-1]+a[i-2];//递推求解  	} 	cout<<a[x];//输出  	return 0; } 第六题： 本题可以直接使用字符串模拟int #include<iostream> using namespace std; string s; int siz; int main(void) { 	cin>>s;//Input 	siz=s.size;//size 	cout<<s<<" "; 	for(int i=0;i<siz;i++) 	{ 		cout<<s[i]<<" ";//按位输出  	} 	return 0; }

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

写程序？还是有不懂的地方？


Question: 求助while循环问题

8楼正解！清晰易懂

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

continue好像用的很少吧，break用的比较多，多用break

没有i++，只在i＝31循环

int main（void）{ int i； i=31； while（i <=40）{ i++； if（i %3==0）{ continue； } printf（"%d"，i）； } return 0； }

注意 while 不是 for 没有 增量 语句 ， i++ 要自己写

int main（void）{ int i； i=31； while（i <=40）{ if（i %3==0）{ i++； continue； } printf（"%d"，i）； i++； } return 0； }

也就break有用，continue完全可以用代码结构替换掉

尽量不要用continue，没什么用，也没必要

压根没必要用continue，影响代码结构。  while（i <=40）{ if（i %3<>0）{ printf（"%d"，i）； } i++； } return 0； }

很6的死循环，，，，

[code=c][/codewhile（i <=40）{ if（i %3==0）{ i++; continue； } printf（"%d"，i）； i++； }

引用 4 楼 qq_33462307 的回复：引用 3 楼 weixin_40377939 的回复:[quote=引用 1 楼 qq_33462307 的回复：]continue之后没有执行i++，I恒等于33那是在Continue后面加上i++解决吗？ 前面...[/quote]哦哦懂了谢谢dalao

引用 3 楼 weixin_40377939 的回复:引用 1 楼 qq_33462307 的回复：continue之后没有执行i++，I恒等于33那是在Continue后面加上i++解决吗？ 前面...

引用 1 楼 qq_33462307 的回复:continue之后没有执行i++，I恒等于33 +1


Question: 请问，为什么用C11的泛型测试结果数组名是指针型？

引用 2 楼 自信男孩 的回复:数组名可以认为是指针常量（不能做左值）。 可数组名是数组类型啊，只有在运算时才转换为常量指针类型

隐式类型转换了 参见 引用6.3.2 Other operands 6.3.2.1 Lvalues, arrays, and function designators  3 Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.

数组名可以认为是指针常量（不能做左值）。


Question: 结构体指针初始化问题

还是要看下楼主的调用代码， 但是通过5楼这种方式是可取的， 即往里面传递一个二级指针，对这个二级指针的内容，即一级指针进行操作； 由于malloc和free的操作不在同一个代码片段，注意在使用完malloc的空间后，要调用free释放内存，否则就有可能发生内存泄漏。

其实就是作用域的区别，实参和形参的区别

还是基础不扎实，传值 传引用 区分清楚

形参与实参虚实结合，为形参分配空间，随着函数调用结束，为形参分配的内存空间也会被释放掉，然而对实参并没有是什么影响，要改变指针的值，要用二级指针或者指针的引用

应该Memset *A_INFO_

typedef struct  {  u8 length;  u8 timeout;  u8 state;  u8 buff[200];  }A_INFO;    void Test(A_INFO **A_INFO_)  {  *A_INFO_ = (A_INFO *)malloc(sizeof(A_INFO));  memset(*A_INFO_,0x0,sizeof(*A_INFO_));  } 给点分吧，下资料没有C贝，呵呵

自定义的函数作用域有限，在函数中申请内存，进行初始化为0。 A_INFO_ = (A_INFO *)malloc(sizeof(A_INFO)); memset(A_INFO_,0x0,sizeof(*A_INFO_)); 这个语句执行后，就会被释放。 而且在自定义函数内进行赋值是不会被传出去的。

你这个明显是有问题的，函数传参是通过值传递的。 void Test(A_INFO *A_INFO_)，形参的值是通过将实参的拷贝一份得来的，给形参分配地址以后，两个指针指向的就不是同一个位置，你给形参分配内存，和实参有个毛线的关系。 在函数里面给形参分配内存以后，函数结束之前还没有进行释放，这又造成了内存泄露。。。  这种问题有两个解决办法：1.把实参的地址穿进去，通过间接操作实参，给实参分配地址。2、函数的返回值返回一个分配好的地址，用指针在外面进行接收。。

void Test(A_INFO **A_INFO_) { *A_INFO_ = (A_INFO *)malloc(sizeof(A_INFO)); memset(*A_INFO_,0x0,sizeof(A_INFO)); } 用传入传出参数，就可以把申请后的空间已经初始化之后的内容获取。  如果是malloc/memset，建议用calloc。两个一起做了。

哦，函数没有问题。 应该是声明结构体指针的时候去申请内存空间，不要在这个函数里面申请。

2楼一语中的，是正解

在函数里申请空间是没有问题的，malloc是在堆里分配内存空间，又不是在栈上。看看你执行报什么错误或警告。

//存在问题： //主函数中定义变量并将变量的内存首地址赋给了初始化函数void Test(A_INFO *A_INFO_)中的结构体指针，此时结构体指针正指向主函数中结构体变量的内存地址； //初始化函数void Test(A_INFO *A_INFO_)申请新内存并清空，此时，内存地址改变，但函数返回前并没有及时修正主函数中变量的内存地址，造成内存泄露 //所以应该使用二级指针，其实就是传址与传值的区别 #include "stdio.h" #include "string.h" #include "stdlib.h"  typedef struct { 	int length; 	int timeout; 	int state; 	int buff[200]; }A_INFO;  void Test(A_INFO **A_INFO_) { 	*A_INFO_ = (A_INFO *)malloc(sizeof(A_INFO)); 	memset(*A_INFO_,0x0,sizeof(**A_INFO_));  }  int main() { 	int i = 0; 	A_INFO *test;	//主函数定义A_INFO变量  	Test(&test); 	for (i = 0; i<200; i++) 		printf("test->buff[i] = %d\n",test->buff[i]) ; 	 }


Question: 为什么不能在头文件里定义全局变量以及指针

引用 5 楼 xiaoqiang521 的回复:[quote=引用 4 楼 lin5161678 的回复:] 了解2个知识点  1. 编译器以文件为单位 对代码进行编译 2. #include的作用是 把文件的全部内容插入#include这个位置  你在文件1里面include了头文件 文件1里面就有一句 int cc = 0； 编译编译文件1 会在符号表里面 记录 文件1有一个变量名字叫做cc  你在文件2里面include了头文件 文件2里面就有一句 int cc = 0； 编译编译文件2 会在符号表里面 记录 文件2有一个变量名字叫做cc  所以就出问题了  顺便单纯按照你的描述是不会出问题的 只是有隐患  目测你在哪里include了头文件 然后忘记了 确实如你所言，但是只要把head.h 文件名改成head.c，然后主文件包含head.c,立即出错[/quote] 编译器不会编译 .h 文件  你把 .h 改成 .c 这个文件会编译一次  include的文件 会再编译一次  所以出错

引用 6 楼 @风轻云淡_ 的回复:#ifndef _MY_HEAD__ #define_MY_HEAD__ int cc = 0; #endif这个做法只能实现在同一个文件不会重复包含 不同文件重复包含没作用的

头文件会被多个文件包含，然后就会重定义了，可以在cpp中定义，然后使用extern关键字引用到头文件中

引用 4 楼 lin5161678 的回复:了解2个知识点  1. 编译器以文件为单位 对代码进行编译 2. #include的作用是 把文件的全部内容插入#include这个位置  你在文件1里面include了头文件 文件1里面就有一句 int cc = 0； 编译编译文件1 会在符号表里面 记录 文件1有一个变量名字叫做cc  你在文件2里面include了头文件 文件2里面就有一句 int cc = 0； 编译编译文件2 会在符号表里面 记录 文件2有一个变量名字叫做cc  所以就出问题了  顺便单纯按照你的描述是不会出问题的 只是有隐患  目测你在哪里include了头文件 然后忘记了 确实如你所言，但是只要把head.h 文件名改成head.c，然后主文件包含head.c,立即出错

引用 1 楼 lin5161678 的回复:所以你的问题是啥  因为会重定义 所以不能在头文件定义全局变量呗  没了 为什么会造成重定义？？

补充一句，如果是main.c 包含同样的head文件就可以通过编译，这是为什么？

所以你的问题是啥  因为会重定义 所以不能在头文件定义全局变量呗  没了


Question: 抢答器

得先找到规律，行号和打印的字符，能有公式表示出来，就可以用程序写出来。

求各位大佬各位看看这个用C语言怎么打印 oooooooop oooooooppp ooooooppppp ooooop           p ooooppp       ppp ooopppp     ppppp oop           p            p oppp      ppp        ppp ppppp  ppppp   ppppp

多綫程，變量做互斥訪問。


Question: Aquila 0.1.0 发布，多媒体应用框架

这个不是对ffmpeg 的一个封装吗？


Question: 初学C语言，运行提示我未说明标示符，有点不理解，大伙帮我看看

scanf("d%",&x);,格式符

getchar给谁了？

写代码，还是要仔细啊

%d 而不是d%

看着好深奥啊 进来学习下

多注意细节问题，

厉害厉害

引用 11 楼 @风轻云淡_ 的回复：3个问题： 1是“d%”----“%d” 2是  x>=o ----  x >= 0 3是getchar() 需要在return的前面+1

同意三楼的解答

看见if（）{  }else{  }不加大括号就难受

引用 楼主 piuoooxiu的回复:#include<stdio.h> int main(){ 	int x,y; 	printf("输入一个角度值：\n"); 	scanf("d%",&x); 	if(x>=o&&x<=180) 		y=180-x; 	else if(x>180&&x<360) 		y=360-(x-180); 	printf("y=%d\n",y); 	return 0; 	getchar(); } 第五行应该是scanf("%d",&x)；

一定要区分开o和0哦

可能是你在码的时候不小心了，反正就是1不要切换输入法2在借鉴别人的代码的时候先理解，否则很难复查

#include<stdio.h> int main(){ int x,y; printf("输入一个角度值：\n"); scanf("%d",&x); if(x>=o&&x<=180) y=180-x; else if(x>180&&x<360) y=360-(x-180); printf("y=%d\n",y); return 0; getchar(); }

很好很好，得到了帮助

同意三楼的解答

#include<stdio.h> int main(){ int x,y; printf("输入一个角度值：\n"); scanf("%d",&x); if(x>=0&&x<=180) y=180-x; else if(x>180&&x<360) y=360-(x-180); printf("y=%d\n",y); return 0; getchar(); }

两个地方的问题，一个是d%, 一个是0和o的问题。 上面的朋友也指出来了。

第一个if哪儿是0不是o吧


Question: 求助，用C语言求将一根棒子任意折成三段，求它们可以构成三角形的概率

引用 5 楼 weixin_43251091 的回复:[quote=引用 3 楼 user-1 的回复:] [quote=引用 2 楼 user-1 的回复:]  #include <stdlib.h> #include <stdio.h> #include <time.h>  // 初始长度 int nInitLength = 1000;  // 获取边长 void GetEdgeLength(int &a, int &b, int &c) {     int point1 = 1+ rand() % (nInitLength - 1);     int point2 = 2 + rand() % (nInitLength - 2);      if (point2 == point1)         point2 = 1;      if (point2 < point1)     {         int tmp = point2;         point2 = point1;         point1 = tmp;     }      a = point1;     b = point2 - point1;     c = nInitLength - point2; }   bool IsTriangle(int a, int b, int c) {     if (a + b > c && a + c > b && b + c > a)         return true;      return false; }  int main() {     srand(time(NULL));      int a, b, c;     int nSucceedCount = 0;     int nTestCount = 1;     for (int n = 1; n <= 7; ++n)     {         nTestCount *= 10;         nSucceedCount = 0;         for (int idx = 0; idx  < nTestCount; ++idx)         {             GetEdgeLength(a, b, c);             if (IsTriangle(a, b, c))             {                 ++nSucceedCount;             }         }          printf("测试次数%10d, 组成三角形次数%10d, 组成三角形概率%.2f%%\n", nTestCount, nSucceedCount, (nSucceedCount * 1.0f / nTestCount * 100));     }      return 0; }  我只是尝试写了一下，结果发现随着试验次数增多，居然趋近于25%，会不会是一个新的发现？ 测试次数        10, 组成三角形次数         3, 组成三角形概率30.00% 测试次数       100, 组成三角形次数        25, 组成三角形概率25.00% 测试次数      1000, 组成三角形次数       232, 组成三角形概率23.20% 测试次数     10000, 组成三角形次数      2559, 组成三角形概率25.59% 测试次数    100000, 组成三角形次数     25061, 组成三角形概率25.06% 测试次数   1000000, 组成三角形次数    251188, 组成三角形概率25.12% 测试次数  10000000, 组成三角形次数   2509202, 组成三角形概率25.09% 测试次数 100000000, 组成三角形次数  25099636, 组成三角形概率25.10%[/quote] 你好我想问一下你这是给棒子定下了初始长度，再随机两个断点，从而形成随机的三段吧，那能给棒子随机取初始长度吗[/quote]  可以啊，那就再随机一个棒子长度呗

引用 3 楼 user-1 的回复:[quote=引用 2 楼 user-1 的回复:]  #include <stdlib.h> #include <stdio.h> #include <time.h>  // 初始长度 int nInitLength = 1000;  // 获取边长 void GetEdgeLength(int &a, int &b, int &c) {     int point1 = 1+ rand() % (nInitLength - 1);     int point2 = 2 + rand() % (nInitLength - 2);      if (point2 == point1)         point2 = 1;      if (point2 < point1)     {         int tmp = point2;         point2 = point1;         point1 = tmp;     }      a = point1;     b = point2 - point1;     c = nInitLength - point2; }   bool IsTriangle(int a, int b, int c) {     if (a + b > c && a + c > b && b + c > a)         return true;      return false; }  int main() {     srand(time(NULL));      int a, b, c;     int nSucceedCount = 0;     int nTestCount = 1;     for (int n = 1; n <= 7; ++n)     {         nTestCount *= 10;         nSucceedCount = 0;         for (int idx = 0; idx  < nTestCount; ++idx)         {             GetEdgeLength(a, b, c);             if (IsTriangle(a, b, c))             {                 ++nSucceedCount;             }         }          printf("测试次数%10d, 组成三角形次数%10d, 组成三角形概率%.2f%%\n", nTestCount, nSucceedCount, (nSucceedCount * 1.0f / nTestCount * 100));     }      return 0; }  我只是尝试写了一下，结果发现随着试验次数增多，居然趋近于25%，会不会是一个新的发现？ 测试次数        10, 组成三角形次数         3, 组成三角形概率30.00% 测试次数       100, 组成三角形次数        25, 组成三角形概率25.00% 测试次数      1000, 组成三角形次数       232, 组成三角形概率23.20% 测试次数     10000, 组成三角形次数      2559, 组成三角形概率25.59% 测试次数    100000, 组成三角形次数     25061, 组成三角形概率25.06% 测试次数   1000000, 组成三角形次数    251188, 组成三角形概率25.12% 测试次数  10000000, 组成三角形次数   2509202, 组成三角形概率25.09% 测试次数 100000000, 组成三角形次数  25099636, 组成三角形概率25.10%[/quote] 你好我想问一下你这是给棒子定下了初始长度，再随机两个断点，从而形成随机的三段吧，那能给棒子随机取初始长度吗

引用 3 楼 user-1 的回复:[quote=引用 2 楼 user-1 的回复:]  #include <stdlib.h> #include <stdio.h> #include <time.h>  // 初始长度 int nInitLength = 1000;  // 获取边长 void GetEdgeLength(int &a, int &b, int &c) {     int point1 = 1+ rand() % (nInitLength - 1);     int point2 = 2 + rand() % (nInitLength - 2);      if (point2 == point1)         point2 = 1;      if (point2 < point1)     {         int tmp = point2;         point2 = point1;         point1 = tmp;     }      a = point1;     b = point2 - point1;     c = nInitLength - point2; }   bool IsTriangle(int a, int b, int c) {     if (a + b > c && a + c > b && b + c > a)         return true;      return false; }  int main() {     srand(time(NULL));      int a, b, c;     int nSucceedCount = 0;     int nTestCount = 1;     for (int n = 1; n <= 7; ++n)     {         nTestCount *= 10;         nSucceedCount = 0;         for (int idx = 0; idx  < nTestCount; ++idx)         {             GetEdgeLength(a, b, c);             if (IsTriangle(a, b, c))             {                 ++nSucceedCount;             }         }          printf("测试次数%10d, 组成三角形次数%10d, 组成三角形概率%.2f%%\n", nTestCount, nSucceedCount, (nSucceedCount * 1.0f / nTestCount * 100));     }      return 0; }  我只是尝试写了一下，结果发现随着试验次数增多，居然趋近于25%，会不会是一个新的发现？ 测试次数        10, 组成三角形次数         3, 组成三角形概率30.00% 测试次数       100, 组成三角形次数        25, 组成三角形概率25.00% 测试次数      1000, 组成三角形次数       232, 组成三角形概率23.20% 测试次数     10000, 组成三角形次数      2559, 组成三角形概率25.59% 测试次数    100000, 组成三角形次数     25061, 组成三角形概率25.06% 测试次数   1000000, 组成三角形次数    251188, 组成三角形概率25.12% 测试次数  10000000, 组成三角形次数   2509202, 组成三角形概率25.09% 测试次数 100000000, 组成三角形次数  25099636, 组成三角形概率25.10%[/quote] 是啊 通过笔算的计算是可以得到它的概率大概是25%的。谢谢！

引用 2 楼 user-1 的回复: #include <stdlib.h> #include <stdio.h> #include <time.h>  // 初始长度 int nInitLength = 1000;  // 获取边长 void GetEdgeLength(int &a, int &b, int &c) {     int point1 = 1+ rand() % (nInitLength - 1);     int point2 = 2 + rand() % (nInitLength - 2);      if (point2 == point1)         point2 = 1;      if (point2 < point1)     {         int tmp = point2;         point2 = point1;         point1 = tmp;     }      a = point1;     b = point2 - point1;     c = nInitLength - point2; }   bool IsTriangle(int a, int b, int c) {     if (a + b > c && a + c > b && b + c > a)         return true;      return false; }  int main() {     srand(time(NULL));      int a, b, c;     int nSucceedCount = 0;     int nTestCount = 1;     for (int n = 1; n <= 7; ++n)     {         nTestCount *= 10;         nSucceedCount = 0;         for (int idx = 0; idx  < nTestCount; ++idx)         {             GetEdgeLength(a, b, c);             if (IsTriangle(a, b, c))             {                 ++nSucceedCount;             }         }          printf("测试次数%10d, 组成三角形次数%10d, 组成三角形概率%.2f%%\n", nTestCount, nSucceedCount, (nSucceedCount * 1.0f / nTestCount * 100));     }      return 0; }  我只是尝试写了一下，结果发现随着试验次数增多，居然趋近于25%，会不会是一个新的发现？ 测试次数        10, 组成三角形次数         3, 组成三角形概率30.00% 测试次数       100, 组成三角形次数        25, 组成三角形概率25.00% 测试次数      1000, 组成三角形次数       232, 组成三角形概率23.20% 测试次数     10000, 组成三角形次数      2559, 组成三角形概率25.59% 测试次数    100000, 组成三角形次数     25061, 组成三角形概率25.06% 测试次数   1000000, 组成三角形次数    251188, 组成三角形概率25.12% 测试次数  10000000, 组成三角形次数   2509202, 组成三角形概率25.09% 测试次数 100000000, 组成三角形次数  25099636, 组成三角形概率25.10%

核心就是一条线段随机两个点，可以考虑使用random函数 然后就是判断组成三角形的条件，两边之和大于第三边 判断之后记录判断次数和组成三角形的次数  核心代码，随机分三段和循环统计次数，最后计算概率


Question: 为什么无法正常运行函数,选择功能1录入信息后,再选择功能2,就无法运行排序,运行print后无法跳回MainMenu

无非是循环后有些变量没还原到原始位置


Question: 运行程序遇到的编译器问题

楼主真是菜，说的那么清楚了还看不懂

else里，先ans[row][col] = '\0', 然后再row++, col=0;  因为这样才能在row行最后一个字符赋值'\0'，否则row++, col = 0;再赋值'\0'，那不是新的一行新的一列赋值'\0'吗？

你的问题在于每一行对应的字符串没有'\0'，printf打印字符串可能出现越界。 还有为啥先row++再赋值'\0'，不应该是每一行结束添加个'\0'么


Question: 对于一个长度为count的int数组，求按序号取出来k个数有多少种方法  取出来的要求:每次取出来的数，要比已经取出来的任何数都要大

按序号取出来k个数？这不是没得选了么~~~

能大概说一下算法思路吗？ 能有代码最好

按序号取出N个数还能理解，比如取3个数，那就是取下标未： 1,2,3或者 2,3,4， 或者3，4,5或者 5,6,7 。。。。 :每次取出来的数，要比已经取出来的任何数都要大 后面这个要求就不太明白了，需要排序么？或者已经排序了？


Question: cin 输入的问题

使用回车试试

引用 4 楼 自信男孩 的回复:a,b,c的长度都是1，输入"123"等已经导致其越界了。 这个长度是指字符数组的长度，因为初始化时，只赋值了一个'\0'

a,b,c的长度都是1，输入"123"等已经导致其越界了。

改成这样就好了： char a[10]=""; char b[10]=""; char c[10]="";  申明不带长度的char数组导致越界，你的代码是c越界覆盖了a、b，因此才打印成这样的。

乍看起来c++的cin、cout、ifstream、ofstream、istringstream、ostringstream在输入、输出上比c的scanf、printf、fscanf、fprintf、fread、fwrite、sscanf、sprintf简单，不用格式控制符！ 但是不用格式控制符，输入输出恰好是你期望的格式的时候好说；等到输入输出不是你期望的格式的时候，你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout、ifstream、ofstream、istringstream、ostringstream！ 使用scanf、printf、fscanf、fprintf、fread、fwrite、sscanf、sprintf。  #include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }

用回车也一样，出这个错误的结果

你试试字符串用回车来分隔


Question: 这个作业让我头疼    C语言读取txt文件中的小数的问题

请判断scanf函数的返回值。 //NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %31[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8

可以参考一下#include <fstream> #include <sstream>  using namespace std;  struct Score { 	int num; 	float score_one; 	float score_two; 	float score_thr; 	float score_max; 	float score_min; 	float score_avg; };  void scoreCalculate(Score& mscore) { 	float min = mscore.score_one<mscore.score_two?mscore.score_one:mscore.score_two; 	mscore.score_min = min<mscore.score_thr?min:mscore.score_thr;  	float max = mscore.score_one>mscore.score_two?mscore.score_one:mscore.score_two; 	mscore.score_max = max>mscore.score_thr?max:mscore.score_thr;  	mscore.score_avg = (mscore.score_one+mscore.score_two+mscore.score_thr)/3; }  int main() { 	fstream read_ptr("/root/123.txt",ios_base::binary|ios_base::in); 	string one_row; 	stringstream ss; 	Score score; 	bool has_head = true;//用于跳过数据头 	while(getline(read_ptr,one_row)) 	{ 		if(has_head) 		{ 			has_head = false; 			continue; 		} 		sscanf(one_row.c_str(),"%d%f%f%f",&score.num,&score.score_one,&score.score_two,&score.score_thr); 		scoreCalculate(score); 		ss << score.score_max << " " << score.score_min << " " << score.score_avg << endl; 	} 	read_ptr.close(); 	read_ptr.open("/root/1234.txt",ios_base::binary|ios_base::out); 	read_ptr << ss.str().c_str(); 	read_ptr.close();  	return 0; }

getLine 一次取一行，sscanf进行格式化输入，然后求你想求的值。

文件读取直接用呀，百度一下看看就懂啦

直接%lf读取，有什么困难吗

fgets(buf, 16, fp);  //first line fscanf(fp, "%d %lf %lf\n", &no, &f1, &f2, &f3);     建议使用结构体数组存放no, f1, f2, f3

readline split(' ')

格式化输入fscanf， 空格会作为分隔符处理。


Question: C语言指针问题，请教

ok，谢谢大哥们的解答。

char* pos = strtok(s, " ");  这个函数调用有问题。因为你的A声明的方式，导致A这个字符串是只读的。但是strtok需要在处理中填充0。所以不行。 可以这样修改；   char A[]= "this apple is sweet";

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

第二个程序和第一个程序的愿意你是一样的。改成数组就没问题。

char* pos = strtok(s, " "); 需要了解这个strtok的处理逻辑，strtok是遇到第二个参数后，在s的" "出赋值'\0'，然后将s的首地址返给pos。既然是在源串上修改。但是main中，A指向的字符串是只读的，不能写。这就和strtok的处理逻辑相矛盾，如果程序运行应该是提示你段错误。 改成数组就可以了。


Question: C语言请问char *s:gets(s):puts(s）;

字符数组能存是因为人家有内存空间，指针变量有吗？当然有，但是这个空间是来存它指向空间地址的，gets(s)函数不是把输入的字符串存到s变量里, 而是存到s指向的空间里，你的代码明显没有让s指向一块有效的空间，所以输入的东西存到哪呢？

char *s;这里的s是指针变量，并且是一个野指针，所谓野指针，即指针变量里存放的地址是一个随机数，若这个地址值是指向不可读写的位置，那么gets(s)或fgets(s，xx, xx);就会出现段错误；  而用char s[16], gets(s), fgets(s, 16, xx);就没问题，是因为数组的长度16是有效内存空间，可以读写。  char *s = malloc(sizeof(char) * 16); 这样可以把s看成s[16]了，但是注意malloc是在堆上申请空间，需要手动释放free(s);

最好能贴一下你的代码进一步诊断。  字符指针和字符数组某些情况下可以认为是一样的。 例如:  char sarray[128] = {'1','2','3','4',0}; const char *s  = "1234"； printf("%s",s); printf("%s",sarray);  这种情况下s和sarray可以认为是一样的变量，它们代表的都仅仅是一个指针。 以上两个printf都能打印出“1234”；  你提到的s不可以，而数组可以，我猜测可能是你的s没有开辟内存空间，而数组是系统自动帮你开辟了的。 所以，你最好是这样写： char *s = (char *)malloc(1024); 然后再使用gets等函数。

指针需要分配内存才能使用. char* s = new char[64];

str野指针 不能作为gets 和 puts的参数 顺便gets这个函数已经被废弃 别再用了

确定下你的字符指针初始化了没

不管是指针，还是数组，指针必须指向有效的且可写的内存空间。 char *s; // 没初始化，所以地址是随机的，野指针！ gets(s); // 错误！指针指向的随机区域不一定属于你的进程空间，就算是也不一定可写。 puts(s); // 不算错误，也不正确！读取可能不属于自己进程空间的内容数据，大多情况是乱码！// 严格来讲，这样写是不正确的，应该是 const char *s 才对： char *s = "abc"; // 初始化，指向常量区的 "abc" 字符串； gets(s); // 错误！指针指向的的是常量区，属于你的进程空间，但是只读不可写。 puts(s); // 正确！输出字符串！char buffer[128] = { 0 }; // 初始化 128 个字节为空； char *s = buffer; // 初始化，指向 buffer 可以读写。 gets(s); // 正确！也可以直接用 buffer 传参。数组名传递到参数则退化为指针，即和 char *s 相同意义。 puts(s); // 正确！也可以直接用 buffer 传参。数组名传递到参数则退化为指针，即和 char *s 相同意义。char *s = calloc(128, sizeof(char)); // 初始化 s 为新申请的 128 字节内存空间。 gets(s); // 正确！ puts(s); // 正确！ free(s);