Question: 大家给看下POJ的1006，哪里还有问题

for(;d<365&&d>=0&&p<365&&p>=0&&e<365&&e>=0&&i<365&&i>=0;s++) 改为 for(s=0;;s++) 可AC

生理周期   Time Limit: 1000MS  Memory Limit: 10000K  Total Submissions: 128692  Accepted: 40855   Description  人生来就有三个生理周期，分别为体力、感情和智力周期，它们的周期长度为23天、28天和33天。每一个周期中有一天是高峰。在高峰这天，人会在相应的方面表现出色。例如，智力周期的高峰，人会思维敏捷，精力容易高度集中。因为三个周期的周长不同，所以通常三个周期的高峰不会落在同一天。对于每个人，我们想知道何时三个高峰落在同一天。对于每个周期，我们会给出从当前年份的第一天开始，到出现高峰的天数（不一定是第一次高峰出现的时间）。你的任务是给定一个从当年第一天开始数的天数，输出从给定时间开始（不包括给定时间）下一次三个高峰落在同一天的时间（距给定时间的天数）。例如：给定时间为10，下次出现三个高峰同天的时间是12，则输出2（注意这里不是3）。  Input  输入四个整数：p, e, i和d。 p, e, i分别表示体力、情感和智力高峰出现的时间（时间从当年的第一天开始计算）。d 是给定的时间，可能小于p, e, 或 i。 所有给定时间是非负的并且小于365, 所求的时间小于21252。   当p = e = i = d = -1时，输入数据结束。  Output  从给定时间起，下一次三个高峰同天的时间（距离给定时间的天数）。   采用以下格式：  Case 1: the next triple peak occurs in 1234 days.   注意：即使结果是1天，也使用复数形式“days”。  Sample Input 0 0 0 0 0 0 0 100 5 20 34 325 4 5 6 7 283 102 23 320 203 301 203 40 -1 -1 -1 -1  Sample Output Case 1: the next triple peak occurs in 21252 days. Case 2: the next triple peak occurs in 21152 days. Case 3: the next triple peak occurs in 19575 days. Case 4: the next triple peak occurs in 16994 days. Case 5: the next triple peak occurs in 8910 days. Case 6: the next triple peak occurs in 10789 days.


Question: 求奇数的乘积

C99动态数组，不是先定义一个不明确的大小 而是要定义一个明确的大小 定义以后，数组的大小，就是固定的了 我举的这个例子里，n 就是每次输入的n 值，如果不是再循环里面 数组的大小是不会随着变化的 例如 C99动态数组中 scanf("%d",n); int a[n]; //这里数组的元素个数，就是刚才输入的n 的值 ....... scanf("%d",n);//这个新n值，跟数组的元素个数无关，数组保持上次的大小   while(scanf("%d",&n))     { ///这里进入新的语句组作用域           int a[n]; ///C99中，这个数组是每次循环，会重新初始化的，数组元素个数，跟新输入的n 保持一致、           /// demo(n);//为了清晰起见，代码都移到函数中了，直接写在这里也可以          n=10;///这里修改了n ，但是数组的元素个数，保持不变     } 你的代码中，n没有初始化，因此这个数组的元素个数，是不能确定的，也许很大，也许很小 很大的话。就会占用很大内存空间，很小的话，可能数组空间，就不够用了

这样子也可以哦

引用 9 楼 lm_whales 的回复:还有 n 必须先有一个值， 也就是你这里  scanf  要在数组定义前面。  #include<stdio.h> int main() {      int s,i,n; 	int a[n];     while(scanf("%d",&n))     {         for(s=1,i=0;i<n;i++)         {             scanf("%d",&a[i]);             if(a[i] % 2 != 0)             s = s * a[i];         }         printf("%d\n",s);     }     return 0; }

还有 n 必须先有一个值， 也就是你这里  scanf  要在数组定义前面。

引用 6 楼 qq423399099 的回复:你这代码改成这样是要输出啥？ 我是用你教的动态申请空间的方法放在另外一道题目上

引用 4 楼 lm_whales 的回复:如果用了C99 ;n 同样必须初始化 另外，输入的时候，每次只是输入a[0] 其他数据并没有输入，却在应用 #include<stdio.h>  void demo(int n){         int n,s,i;         int a[n];//C99 用 变量定义数组（变量作为数组的大小）         for(s=1,i=0;i<n;i++)         {             /// scanf("%d",a); //只是输入a[0] 而已，当 i!=0 时候，并没有输入a[i]              scanf("%d",a+i); //改成 a+i 或者 &a[i] 表示要输入a[i];                                        //scanf 的实参，需要对象（数据）的地址，而非一个（整型，浮点型，字符型）值。             if(a[i] % 2 != 0)                    s = s * a[i];      //这里一直在使用a[i] ，不改的话，除了a[0] 都没有初始化。         }         printf("%d\n",s); }  int main() {     int n;       while(scanf("%d",&n))     {             demo(n);//为了清晰起见，代码都移到函数中了，直接写在这里也可以     } return 0; }  所以是说可以用c99直接用变量定义数组，只需要把scanf("%d",a); 改成 scanf("%d",&a[i]);就可以了吗？ 但是我改完之后总是会出现错误：id return 1 exit status

你这代码改成这样是要输出啥？

#include<stdio.h> #include<stdlib.h>  int main() { 	int a,b,c,n,i; 	n<100; 	while(scanf("%d",&n)) 	{ 		int *p; 		p = (int *)malloc(sizeof(int) * n); 		for(i=0;i<n;i++) 		{ 			a = b = c = 0; 			scanf("%d",&p[i]); 			if(p[i] < 0) 				a ++; 			else if(p[i] == 0) 				b ++; 			else 				c ++; 		} 		printf("%d %d %d\n",a,b,c); 	} }  用这个代码统计给定的n个数（n<100）中，负数、零和正数的个数。 比如说输入：6 0 1 2 3 -1 0             输出：1 2 3  但是这个代码不能输出正确结果

引用 2楼我是你的主体 的回复:int *a = (int *)malloc(sizeof(int) * n);  这行代码的意思是：让指针a指向了一块能存放n个int的内存地址，可以理解为动态创建了数组a[n]?

嗯嗯 明白了 谢谢

两处错误： 1.int a[n];你的n都没有附上值，怎么能这样申请数组的空间？ 改成用malloc动态申请 2.scanf("%d",a);要改成scanf("%d",&a[i]);  #include<stdio.h> #include<stdlib.h> int main() { 	int n,s,i; 	 	while(scanf("%d",&n)) 	{ 		int *a = (int *)malloc(sizeof(int) * n); 		for(s=1,i=0;i<n;i++) 		{ 			scanf("%d",&a[i]); 			if(a[i] % 2 != 0) 			s = s * a[i]; 		} 		printf("%d\n",s); 		free(a); 	} }


Question: 求解！《C语言入门经典》案例12.1原封不动输入到cfree 5.0中，提示无法打开文件用于写入数据

引用 2楼我是你的主体 的回复: 真是不好意思，我还以为是编译器设置问题呢。原来 是自己精心大意，见笑了！看来编译前最好自己检查下，不能完全相信程序。 谢谢！解决了记得结帖

你的if (!(pfile = fopen(filename, "w")));最后多了一个分号 下面的if (!(pfile = fopen(filename, "r")));这句也是


Question: 变量用float与用double类型最后的结果不一样，但是数字还很小啊，没有超范围，求解。

谢谢各位啦，的确是输入的时候控制字符串错误了，换成%f之后的确是对的。谢谢诶这么仔细的看我的代码，问题也很好地一针见血地指出，万分感谢！

所以，%f 输出 double 这个设计，真的会误导人 %f--->float 输入输出 %lf --->double 输入输出，各负其责多好，不知道C,C++标准为何 要合并 float 和double 的输出格式。 难道仅仅因为 输出float ,double 的时候，其实只是在输出 double? 并没有输出float 过?

你用%lf读入到float当然不对了（可能丢失了4个字节的数据）

float时应该用scanf("%f")


Question: 一个关于c语言的问题，新人求解答

再简洁只能查表了.

引用 1 楼 user-3 的回复:n.month == 1 || n.month == 3 || .....  谢谢解答！ 有没有简洁点的写法，如果后面集合太大怎么解决阿

遍历你的集合，然后一个个判断。。

谢谢解答！ 有没有简洁点的写法，如果后面集合太大怎么解决阿

n.month == 1 || n.month == 3 || .....


Question: C语言数组特定元素赋值

5楼正解，请使用兼容C99的编译器编译，比如gcc

这个毫无疑问是C99的新特性，因为微软对C++的执着，MSVC编译器对C语言的标准只支持到C90。具体写法：  EXAMPLE 11 Designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood: struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 }; EXAMPLE 12 Space can be ‘‘allocated’’ from both ends of an array by using a single designator: int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };

这个应该不是C89标准，可能在C99或者更高版本的C标准里面才有吧，或者这是某家编译器自身定义的扩展，并不是C语言标准，并不是所有编译器都支持的。像gcc自身就支持很多新特性，但是并不在C语言标准里面，vs并不支持这些特性。

struct A b[] =  []内要有个数，编译器需要知道有几个元素的

少个{。。。

换个编译器比如vs的


Question: Windows编程 RegisterClass 窗口注册意义

引用 1 楼 user-1 的回复:///主窗口 wndclass.lpszClassName = szAppName;///这个用于区分不同窗口类 wndclass.lpfnWndProc = WndProc; ///这个用于必要时，调用窗口过程函数  ///子窗口 wndclass.lpszClassName = szChildClass; wndclass.lpfnWndProc = ChildWndProc;  主窗口是 WinMain 中 CreateWindow 直接创建的 子窗体 在主窗体的 WndProc 函数响应  WM_CREATE 时候，调用CreateWindow 创建 创建主窗体，第一个参数 szAppName 和 RegisterClass 时候，wndclass.lpszClassName 是相同的 hwnd = CreateWindow(szAppName, TEXT("Checker3 Mouse Hit-Test Demo"),         WS_OVERLAPPEDWINDOW,         CW_USEDEFAULT, CW_USEDEFAULT,         CW_USEDEFAULT, CW_USEDEFAULT,         NULL, NULL, hInstance, NULL);   hwndChild[x][y] = CreateWindow(szChildClass, NULL,。。。。。。 子窗体的 第一个参数，和注册子窗体时候 wndclass.lpszClassName 是相同的 操作系统，通过 这个参数，查找这个记录下来的窗体类 按照注册信息，创建窗体 按照注册的 wndclass.lpfnWndProc  参数，调用窗口过程函数   就是这么回事 注册就是记录下来 创建的时候去查找 调用函数的时候，也去查找 原来是这样啊，太感谢了


Question: 有个关于fread函数的问题请教下论坛的高手

引用 6 楼 lm_whales 的回复:链表从文件里读取，很容易啊，读到一个数据，插入链表 很多书中，创建链表就是这么创建的。 链表里面的数据写入数据，也很简单直接写入就是了 唯一比较麻烦的就是链表对数据的管理不方便，需要循环查找 数组就比较方便，可以随机查找  如果真的需要在文件里创建链表， 那就自己做个分配文件位置的函数（包括回收） 可以模拟内存释放和回收 这样就可以内存链表 的数据，写入文件链表了 不过这个要麻烦点 嗯，确实是，链表找个数据还要从头找，数组可以直接指定位置，那我再多练练数组的操作，谢谢了，鲸鱼哥。

引用 5 楼 qq423399099 的回复:你的if后面貌似多了个分号？ 哈哈，瞧我这眼神，分号输习惯了，确实问题是出在分号上，输了分号，if语句就断开了，我说怎么加了if总是要触发if语句，谢谢舞版。

不是if的问题，这里fread返回值为读取字节数，应该没有问题

struct student {     long num;                    struct student *next;    } ;  fwrite (&p->num,sizeof(p->num),1,fp); 这样就可以写入了

你的if后面貌似多了个分号？

引用 1 楼 lm_whales 的回复:链表读写，只需要读写数据就行了， 指针， 就不要读写了 因为从磁盘上读取的指针，并不是此刻创建的，而是存储时候链表中的指针 你好，鲸鱼哥。我存盘数据的时候是直接存放有效数据吗？那fwrite的sizeof应该怎么写呢？我试过用数组，数组用起来没什么问题，但是数组之间应该怎样联系起来呢？用链表可以用一个开辟一个内存空间的，数组好像是定义了多大就占多大，是这样吗？

引用 2 楼 qq423399099 的回复:你这个是将next指针的地址也存到文件里了？ 这种虚拟地址程序每次运行都可能不同，存下地址是没用的。 你好小灸舞，我这个练习主要想实现这个功能，从文件读取数据，然后进行插入，删除操作，操作后将修改的数据又存起来。我看fwrite函数是按照结构体的大小来存放数据的，如果只存数据，那么读取的时候我应该按怎样的数据大小来读取数据呢？是直接读取的num成员吗？还有就是对fread进行判断的if函数，为什么用了if函数fread返回值就变了呢？直接用fread函数返回值却又是正常的，这点实在不明白为什么。


Question: 关于栈的初始化和SqStack *&s

引用 10 楼 SXJIAKE 的回复:// C++ 引用方式： void InitStack(SqStack *&refps) { 	refps = (SqStack *)malloc(sizeof(SqStack)); 	refps->top =- 1; } // 调用方式： SqStack *ps; InitStack(ps);   // C 二级指针方式： void InitStack(SqStack **lpps) { 	if (lpps != NULL) 	{ 		(*lpps) = (SqStack *)malloc(sizeof(SqStack)); 		(*lpps)->top =- 1; 	} } // 调用方式： SqStack *ps; InitStack(&ps);   // C 一级指针方式： SqStack *InitStack(void) { 	SqStack *ps = (SqStack *)malloc(sizeof(SqStack)); 	if (ps != NULL) 	{ 		ps->top = -1; 	} 	return ps; } // 调用方式： SqStack *ps; ps = InitStack();   refps = (SqStack *)malloc(sizeof(SqStack));这里的代表着什么意思

引用 10 楼 SXJIAKE 的回复:// C++ 引用方式： void InitStack(SqStack *&refps) { 	refps = (SqStack *)malloc(sizeof(SqStack)); 	refps->top =- 1; } // 调用方式： SqStack *ps; InitStack(ps);   // C 二级指针方式： void InitStack(SqStack **lpps) { 	if (lpps != NULL) 	{ 		(*lpps) = (SqStack *)malloc(sizeof(SqStack)); 		(*lpps)->top =- 1; 	} } // 调用方式： SqStack *ps; InitStack(&ps);   // C 一级指针方式： SqStack *InitStack(void) { 	SqStack *ps = (SqStack *)malloc(sizeof(SqStack)); 	if (ps != NULL) 	{ 		ps->top = -1; 	} 	return ps; } // 调用方式： SqStack *ps; ps = InitStack();谢谢，已经搞懂了

C++ 引用方式： void InitStack(SqStack *&refps) { 	refps = (SqStack *)malloc(sizeof(SqStack)); 	refps->top =- 1; }  C 二级指针方式： void InitStack(SqStack **lpps) { 	if (lpps != NULL) 	{ 		(*lpps) = (SqStack *)malloc(sizeof(SqStack)); 		(*lpps)->top =- 1; 	} }  C 一级指针方式： SqStack *InitStack(void) { 	SqStack *ps = (SqStack *)malloc(sizeof(SqStack)); 	if (ps != NULL) 	{ 		ps->top = -1; 	} 	return ps; }就是不能用你的那种方式，因为你没法返回你申请的内存。

不用引用的话只是你函数中的参数指向了申请的内存，而这个参数只是一个复制后的指针，而不是你调用的那个

引用 6 楼 qq423399099 的回复:你不用二级指针的话，可以通过带返回值的InitStack函数（在InitStack函数里return malloc出来的指针），这样的话一级指针足矣。 引用 5 楼 yj7758423 的回复:[quote=引用 2 楼 yangyijk 的回复:] void InitStack(SqStack *&s) {     s=(SqStack *)malloc(sizeof(SqStack));     s->top=-1; }  这个是C++的feature吧，C语言考虑使用二级指针 void InitStack(SqStack **s) {     *s=(SqStack *)malloc(sizeof(SqStack));     (*s)->top=-1; } 那么我想要用C初始化一个顺序栈，必须用二级指针吗？[/quote] 如@qq423399099所说也可以，那样就不用传递参数。又或者全局指针也可以。

引用 2 楼 yangyijk 的回复:void InitStack(SqStack *&s) {     s=(SqStack *)malloc(sizeof(SqStack));     s->top=-1; }  这个是C++的feature吧，C语言考虑使用二级指针 void InitStack(SqStack **s) {     *s=(SqStack *)malloc(sizeof(SqStack));     (*s)->top=-1; } 那么我想要用C初始化一个顺序栈，必须用二级指针吗？

引用 1 楼 qq423399099 的回复:void InitStack(SqStack *&s)里的&是引用传参，不是取址 如果是void InitStack(SqStack *s)，那么久不能通过InitStack函数修改实参的指向 要在函数里修改指针的指向，必须传一级指针的引用或者二级指针才行 仅仅传一级指针只能修改指针所指向的区域的值（因为实参和形参是两个不同的指针，他们仅仅只是指向了同一块内存而已） 我觉得其实没必要弄个指针的引用吧，接口只一个指针void InitStack(SqStack *s)或者只一个引用void InitStack(Sqstack &s)都行，这里的SqStack只是一个收纳箱，里面的top和base指针才有可能要改实参的指向吧。 这几天我也在啃数据结构，严蔚敏的书上就是只用引用的。。

SqStack *&s 传入的是一个指针的引用，也就是函数中的参数用的是调用时的参数，而SqStack *s函数中的参数只是一个复制品，你修改不会影响到调用的参数


Question: 为什么从配置文件中读取的参数严重拖慢程序速度？

推荐楼主使用软件filemon

关闭杀毒软件的实时防护功能。

引用 11 楼 zscdzh 的回复:[quote=引用 10 楼 lm_whales 的回复:] 编码错误，  if (1==sscanf(buf,"x1=%f",&x1)) break; 读到一个正确的数据，你就退出了 这个代码，不打算正常工作啊，这是 是不是手误啊 改成   if (1!=sscanf(buf,"x1=%f",&x1)) break; 世事  哦，这个是我debug的时候弄的，因为我发现只要从配置文件中读一个参数，程序就慢三倍了，效果立竿见影...所以其他参数都是写在代码里面的，目前只读一个参数debug[/quote] 参数这么少，直接一次读出。 需要的时候，写到文件里。 如果，参数多了，直接开数据库 这种读法，效率不会高 但是60秒这个真不知道咋回事 写文件，读文件不会这么慢的

引用 4 楼 u011609112 的回复:[quote=引用 3 楼 paschen 的回复:] 先用性能工具分析下代码，看下执行哪些语句耗时多，然后再下结论和找原因  推荐一下一般的性能工具，还没用过，简单实用的[/quote]  VS就自带有，百度搜一下怎么用

引用 10 楼 lm_whales 的回复:编码错误，  if (1==sscanf(buf,"x1=%f",&x1)) break; 读到一个正确的数据，你就退出了 这个代码，不打算正常工作啊，这是 是不是手误啊 改成   if (1!=sscanf(buf,"x1=%f",&x1)) break; 世事  哦，这个是我debug的时候弄的，因为我发现只要从配置文件中读一个参数，程序就慢三倍了，效果立竿见影...所以其他参数都是写在代码里面的，目前只读一个参数debug

引用 8 楼 lm_whales 的回复:这样啊，文件读取应该比手动输入快得多才对 同样输出到文件，比输出到屏幕要快得多 你这不是读写文件的问题 一个较大的可能是，存储文件的磁道有问题 正常读写文件。不会消耗多少时间的 秒级读写，已经是很慢很慢的了 几十个参数的话，是毫秒级的，甚至更快 不清楚你这是什么情况 不会是电脑中了病毒了吧  应该不是吧，中病毒应该没这效果...其他计算程序都是没问题的 所以我才纳闷啊，我把从参数文件里面读取的值在后面又赋值一遍，速度还是慢，这样看起来是读取参数语句的问题，但是我把读取参数的语句保存，读取一个在后面用不上的参数，速度又正常了！ 我真是....

引用 6 楼 lm_whales 的回复:小文件，直接全部读到内存，就可以了 大文件，要么分段处理，要么采用别的工具处理（数据库，注册表，.ini ） 这么读来读去的不是个事情。  谢谢！ 参数文件不大，就十几个参数，问题在于我读取参数后，程序主循环变慢了好多，当然读取参数不在主循环里面，所以我很难理解，从键盘中scanf得到的参数不会对计算速度造成任何影响，一旦从配置文件中读取哪怕一个参数，就会导致程序慢三倍...

可以Windows 用API函数读取配置文件 当然手工读取也是可以的 关键问题是，查找比较耗时吧（文件中查找，要反复来回读取，这太折腾了） 读取不费什么时间 也许可以用内存映射文件方式读写

引用 3 楼 paschen 的回复:先用性能工具分析下代码，看下执行哪些语句耗时多，然后再下结论和找原因  推荐一下一般的性能工具，还没用过，简单实用的

多谢各位！ 问题差不多解决了，导致速度慢的情况只会出现在x1和dx这两个参数上，这两个参数是我用来划分计算网格的，虽然还不知道为什么会这样，但是对我的程序已经影响不大了，有空再仔细分析一下，谢谢各位！

感觉从文件里读出来的参数有毒...... 我新建了一个变量，从txt中读出，然后把它赋值给真正用上的变量，结果还是变慢了....

引用 14 楼 zhao4zhong1 的回复:关闭杀毒软件的实时防护功能。  试了一下，关掉了windows defends实时防护，还是那样 而且这也解释不了为什么我读一个用不上的数据，可以读而且对速度没有影响，一旦我读入一个参数，哪怕后面对参数在程序内再次赋值，也会造成程序变慢 这个程序变慢应该是每一步计算都变慢了，因为我有实时计算结果的二维显示图像 感觉像是这个读取让我的参数结构变化了，精度扩大了好多位，然后计算就慢了，但是这个读取的不是float么...

先用性能工具分析下代码，看下执行哪些语句耗时多，然后再下结论和找原因

我需要的是从文件中读取参数啊，从配置文件中读取每一个需要的参数，你这个是打印吧？ 无论如何，多谢回复！

要不试试我的？ http://blog.csdn.net/u010370871/article/details/50508859


Question: 关于位域和字节序的问题

位域涉及 位序，和字节序这两个东西，都是不确定的，由实现决定 所以没啥可讨论的。  如果 有字节序问题，可以校正（网络传播都会处理好的） 位序问题，也是一样。 如果位域存到文件里，最好标注字节序，和位序 这样读取的时候，就可以按照不同的位序，字节序处理了 位序测定，直接用一个字节的位段检测 字节序检测，直接用int (例如和 char 数组的union） 检测 字节序，intel x86系列CPU,和motorola 68XXX系列CPU  作为字节序类型的两个代表，一个为小端的话，另一个就是大端。  另外，我看到过字节序的两种，大小端的说法， 一种说intel 是小端， 一种说是大端，不知道为什么 PS: 一般程序都不关心位序，因为不同位序的程序，编译好以后，一般不影响使用 除非存为文件，供别的程序使用 字节序，往往也是存为文件，或者网上传播，才会有问题

引用前后两个变量哪个表示低位，哪个表示高位。  这个东西是 implementation-defined ，意味着不同的实现可能不同 ...


Question: 为什么scanf输入的值会发生变化呢？

浮点数格式 http://bbs.csdn.net/topics/390676437

在输出字符之前最好调用一下这个 fflush(stdin); 把这个放在scanf的前面，可以清除之输入的缓存区。

如果你用BCD码存储浮点数，那结果就是精确的，因为他是按十进制方式来存储的

保存和运算的方式不一样  比如下面这个： 在带有 数值型 数据类型的字段中，小数部分的长度在创建该字段的设计时就被确定了。小数部分的长度是总长度的一部分。例如，如果指定了数值型字段的长度是 6，而小数设置为 4，则该字段可以存储的最大值是 9.9999。

引用 5 楼 liups 的回复:[quote=引用 2 楼 Atom2004 的回复:] 哦，原来如此。  顺便问一下，为什么想C#和MATLAB这种语言就不会有这样的问题呢？  我把同样的这几个数值放到C#里面，打印出来的值都是准确的。 有些语言支持原样保存[/quote]  什么是原样保存啊？那难道他进行计算的时候不会产生误差吗？

引用 2 楼 Atom2004 的回复:哦，原来如此。  顺便问一下，为什么想C#和MATLAB这种语言就不会有这样的问题呢？  我把同样的这几个数值放到C#里面，打印出来的值都是准确的。 有些语言支持原样保存

float：最多能有7位有效数字，但绝对能保证的为6位，也即float的精度为6~7位有效数字； double：同理，double的精度为15~16位。 也可以看看这篇：http://www.cnblogs.com/jiahu-Blog/p/4502990.html

引用 1 楼 qq423399099 的回复:大部分浮点数在内存无法精确存储，仅仅只是存储一个近似值。 所以我们比较浮点数的时候，需要设置一个误差值，如果两者相减小于误差值，我们就认为这两个数相等。 http://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html  再请教一下，那一般float和double，这个误差值设置多少合理呢？


Question: 去除字符串内的空格无法正常运行

引用 6 楼 qq423399099 的回复:那是因为你的head指针的next是指向NULL的 你没法使得(*list)->next == tmp 完美解决了，非常感谢

引用 3 楼 qq423399099 的回复:你原来链表连接newNode的两句左值和右值反了  void add2head(linkedlist * list, int data) { 	linkedlist tmp = *list; 	linkedlist newNode = (linkedlist)malloc(sizeof(node)); 	(*list)->prior = newNode; //第一处！！！！ 	newNode->next = *list; 	newNode->data = data; 	while ((*list)->next != tmp) { 		*list = (*list)->next; 	} 	newNode->prior = *list; 	(*list)->next = newNode;//第二处！！！ 	*list = newNode; }   刚刚测试了一下还是不行，内存访问冲突  这是全部代码  #include <stdio.h> #include <stdlib.h>  typedef struct node{ 	int data; 	struct node * next; 	struct node * prior; }node;  typedef struct node * linkedlist;  linkedlist init(int data) { 	linkedlist  newNode = (linkedlist)malloc(sizeof(node)); 	newNode->data = data; 	newNode->next = NULL; 	newNode->prior = NULL; 	return newNode; }  void add2head(linkedlist * list, int data) { 	linkedlist tmp = *list; 	linkedlist newNode = (linkedlist)malloc(sizeof(node)); 	newNode->next = *list; 	(*list)->prior = newNode; 	newNode->data = data; 	while ((*list)->next != tmp) { 		*list = (*list)->next; 	} 	newNode->prior = *list; 	(*list)->next = newNode; 	*list = newNode; }   int main(void) { 	linkedlist head = init(123); 	add2head(&head, 7); 	add2head(&head, 9); 	system("pause"); 	return 0; }

引用 3 楼 qq423399099 的回复:你原来链表连接newNode的两句左值和右值反了  void add2head(linkedlist * list, int data) { 	linkedlist tmp = *list; 	linkedlist newNode = (linkedlist)malloc(sizeof(node)); 	(*list)->prior = newNode; //第一处！！！！ 	newNode->next = *list; 	newNode->data = data; 	while ((*list)->next != tmp) { 		*list = (*list)->next; 	} 	newNode->prior = *list; 	(*list)->next = newNode;//第二处！！！ 	*list = newNode; }   刚测试了

引用 1 楼 qq423399099 的回复:你需要先记录res的首地址，否则return回去的是已经指向字符串末尾的位置，所以打印出来的是空白  static char * rmSpace(const char * str) { 	int spaceCnt = 0; 	const char * head = str; 	while ((*str) != '\0') { 		if (isspace(*str)) 			spaceCnt++; 		str++; 	} 	str = head; 	int resLen = strlen(str) - spaceCnt + 1; 	char * res = (char *)malloc(sizeof(char)* resLen); 	char *res_head = res; 	memset(res, 0, resLen); 	while (*str != '\0') { 		if (*str != ' ') { 			*res = *str; 			res++; 		} 		str++; 	} 	return res_head; }  大神又是你 那我顺便再问一个关于双向链表的问题  void add2head(linkedlist * list, int data) { 	linkedlist tmp = *list; 	linkedlist newNode = (linkedlist)malloc(sizeof(node)); 	newNode = (*list)->prior; 	newNode->next = *list; 	newNode->data = data; 	while ((*list)->next != tmp) { 		*list = (*list)->next; 	} 	newNode->prior = *list; 	newNode = (*list)->next; 	*list = newNode; }  我的思路是创建一个新节点，然后这个新节点next指向已有链表的第一个节点，这个新节点的prior指向已有节点的最后一个，但是为什么还是无法运行


Question: C语言：for嵌套实现4*5矩阵

引用 9楼我是你的主体 的回复:[quote=引用 8 楼 小灸舞的回复:]C89规定，在任何执行语句之前，在块的开头声明所有局部变量。 在C99以及C++中则没有这个限制，即在首次使用之前，可在块的任何位置都可以声明变量。 而你用的VC6实在是太老了，如果不是一定要用VC6建议换一个IDE 噢，Soga。原来如此，谢谢大神哈[/quote]解决了记得结帖

C语言要求变量在语句前先要声明，而C++则无限制

因为你是.c的 文件，变量的定义都要放在代码前面

补充:j/i还有j+=i是因为矩阵是这样的 (-^〇^-)

/*打印输出4*5矩阵 1 2 3  4  5 2 4 6  8  10 3 6 9  12 15 4 8 12 16 20 */ #include <stdio.h> #include <math.h> int main() { 	//int a[4][5]; 	int i,j; 	for(i=1;i<5;i++) 	{ 		for(j=1;j<6;j++) 			printf("%d\t",i*j); 		printf("\n"); 	} 	return 0; }

引用 8 楼 小灸舞的回复:C89规定，在任何执行语句之前，在块的开头声明所有局部变量。 在C99以及C++中则没有这个限制，即在首次使用之前，可在块的任何位置都可以声明变量。 而你用的VC6实在是太老了，如果不是一定要用VC6建议换一个IDE 噢，Soga。原来如此，谢谢大神哈

引用 4 楼 user-4的回复:for(int j=1;j<=5;j++)  // 这样清楚一点   printf("%d\t",i*j); printf("\n"); 嗯嗯，那样改可以。不过不懂为什么我那样写会报错

引用 4 楼 user-4的回复:for(int j=1;j<=5;j++)  // 这样清楚一点   printf("%d\t",i*j); printf("\n"); 试了一下，这里没问题，还是会报错呢。

引用 3 楼 小灸舞的回复:因为你是.c的 文件，变量的定义都要放在代码前面 不太懂呢，定义是在使用前，第一个for定义的i在第二个for里面也是有效的呀。


Question: 继续新人求救命，free之后求链表长度

这个改法是把NULL赋给头指针吗？ 虽然可以……但是函数的声明是给定的……不然早就改了 从getlength入手跳过读取头指针似乎也不太可能吧…… 啊啊啊啊啊

那就void LinkTable_free(Link_t oLink)改成有返回值的函数： Link_t LinkTable_free(Link_t oLink)

没错啊，就是这个问题，按理说用二重指针可以解决，但是boss不让用……

你在LinkTable_free中最后oLink = NULL; 并没有修改到主函数中的head_point参数，而只是将临时参数对象设置为NULL而已  所以你之后在主函数中再调用LinkTable_getLength(head_point)时，head_point的值并不是NULL，你只是把指针指向的内存释放了，但指针仍指向那块内存

用变量？指的是在主函数里吗？

引用 6楼我是你的主体 的回复:其实我一开始用的就是带头节点，后来说没要求就撤掉了……不过当时free函数是连着头结点一起删的。 这个似乎可以啊……我去商量一下 但总之如果不改要求的话这个错误就没法纠正的吧？ 或者你拿变量纪录节点个数

或者你应该设计成带头结点的链表（头结点不要放数据） LinkTable_free函数里仅仅需要把有数据的结点都free掉，头结点等到程序结束前在主函数free


Question: 编写一个打印的宏

C++11可以  http://en.cppreference.com/w/cpp/preprocessor/replace 里面的(3)

VC++是可以的。

这样试试看  #if defined(COMBINED_DEBUG) #    define XX_PRINTF printf #else #    define XX_PRINTF  // #endif

引用 11 楼 mLee79 的回复:远古时期大家都是下面这样,  移植性最好,  C99 后可以 像9楼...  #if defined(COMBINED_DEBUG) #    define XX_PRINTF(expression)   printf  expression #else #    define XX_PRINTF(expression) #endif  唯一不好的就是使用的时候要多打一对括号,   XX_PRINTF(("Hello %d\n", 100));++

引用 9 楼 lm_whales 的回复:1）还可以这样定义，不知老板的编译器支持不支持 #include <stdio.h>  #if defined(COMBINED_DEBUG) #define Print printf #else #define Print(...) #endif // COMBINED_DEBUG  2）或者： #ifdef NDEBUG #define Print printf #else #define Print(...) ((int)(0)) #endif // COMBINED_DEBUG  1）没有警告，但不知道早期板本支持不支持 2）有警告，但是更符合  printf 函数输出的情况，因为 printf 又返回值  这两种VC 6.0都无法通过。

。。\。。。\main.cpp|57|warning: left operand of comma operator has no effect [-Wunused-value]| 可能会有警告 另外，逗号表达式可单独出现，加上分号，变成表达式语句的，加不加小括号都可以。 有时候，用逗号表达式，或者， 单个变量名的表达式 用来消除，（形参）变量定义了，但是没有使用的警告。

引用 5 楼 u010165006 的回复:[quote=引用 4 楼 lm_whales 的回复:] 这么做的,看看行不？ #if defined(COMBINED_DEBUG) #    define XX_PRINTF printf #else #    define XX_PRINTF #endif  XX_PRINTF("%d",i); 变成 ("%d",i); // 编译能过吗？[/quote]  试了一下没问题

能啊，这是逗号表达式外加括号  引用 5 楼 u010165006 的回复:[quote=引用 4 楼 lm_whales 的回复:] 这么做的,看看行不？ #if defined(COMBINED_DEBUG) #    define XX_PRINTF printf #else #    define XX_PRINTF #endif  XX_PRINTF("%d",i); 变成 ("%d",i); // 编译能过吗？[/quote]

引用 4 楼 lm_whales 的回复:这么做的,看看行不？ #if defined(COMBINED_DEBUG) #    define XX_PRINTF printf #else #    define XX_PRINTF #endif  XX_PRINTF("%d",i); 变成 ("%d",i); // 编译能过吗？

如果调试输出的不多，也可以每次： #ifdef _DEBUG printf(.........) #endif


Question: 数据结构：树的每个节点都有随机数个子节点，节点结构体如何定义？

struct Node {  int n;  struct Node **children; } root;

一个节点的第一个子节点作为它的child，其它兄弟节点作为child节点的next节点。


Question: 求帮助，邮槽通信问题【C语言】

你的意思是用共享内存吗？这个我今天也刚刚自己打了，也是那个问题。你有例子吗，可以发给我看下吗

要么改成内存映射文件好了，这个网上例子多。


Question: C语言，c primer plus 5，第七章求“ei"的次数

int count (const char *str) { 	int ret = 0 ; 	int state = 0 ; 	for (int i = 0 ; str[i] != '#' ; i++) { 		if (state == 0 && str[i] == 'e') { 			state = 1 ; 		} else if (state == 1 && str[i] == 'i') { 			ret++ ; 			state = 0 ; 		} else { 			state = 0 ; 		} 	} 	return ret ; }  int main () { 	printf ("%d\n" ,count ("eiieiieiss#")) ; 	return 0 ; }

=是赋值运算符 ==才是比较运算符


Question: 请问在VS2015上写的C程序给别人用都会提示缺少运行库，除了让别人提前安装运行库外，还有没有其他的方法？

如果是小工程，就用低版本的vs 如果是大工程，就直接把所有需要的动态库一起拷贝过去

项目菜单 -> 属性 ， 在对话框中 选择配置属性-->常规， 然后在配置类型中改。

引用 4 楼 yyxgs 的回复:[quote=引用 2 楼 liups的回复:][quote=引用 1 楼 liups 的回复:] 你把运行库都拷上 或者静态编译[/quote] 静态编译？怎么操作呢？[/quote]  工程属性之类的地方找设置

引用 3 楼 小灸舞的回复:用依赖库查看软件，比如procexp 将需要用到的DLL都一起拷贝过去就行了 除了这个，还有其他的方法吗？

引用 2 楼 liups的回复:[quote=引用 1 楼 liups 的回复:] 你把运行库都拷上 或者静态编译[/quote] 静态编译？怎么操作呢？

用依赖库查看软件，比如procexp 将需要用到的DLL都一起拷贝过去就行了

引用 1 楼 liups 的回复:你把运行库都拷上 或者静态编译

你把运行库都拷上


Question: c语言函数调用

引用 14 楼 qaz_7 的回复:但是这样做运行结果什么都没有诶  我预想的运行结果是2 4 6 8 10 得到这种结果很容易，关键是不知道你的思路

#include<stdio.h> void fun(int n) { 	while (1) 	{ 		printf("%d ", n); 		n = n + 2; 		if (n == 12) 			return; 	} }  int main() { 	int n; 	printf("结果是:"); 	fun(2); 	 }

但是这样做运行结果什么都没有诶  我预想的运行结果是2 4 6 8 10

fun(2); 替换成 n=fun(2);

引用 11 楼 qaz_7 的回复:[quote=引用 9 楼 liups 的回复:] [quote=引用 7 楼 u010165006 的回复:] main函数也没有调用fun函数，楼主是不是写错了。  但是人家调用了printf[/quote]  #include<stdio.h> int fun(int n) { 	while(n%2==0) 	{ 		n=n+2; 	} 	if(n==10) 		return 0; 	else     	return n; }  int main()  { 	int n; 	fun(2); 	printf("结果是：%d",n); }[/quote]  调用了fun，但是丢弃了fun的返回值！

引用 9 楼 liups 的回复:[quote=引用 7 楼 u010165006 的回复:] main函数也没有调用fun函数，楼主是不是写错了。  但是人家调用了printf[/quote]  #include<stdio.h> int fun(int n) { 	while(n%2==0) 	{ 		n=n+2; 	} 	if(n==10) 		return 0; 	else     	return n; }  int main()  { 	int n; 	fun(2); 	printf("结果是：%d",n); }

路过

引用 7 楼 u010165006 的回复:main函数也没有调用fun函数，楼主是不是写错了。  但是人家调用了printf

main函数也没有调用fun函数，楼主是不是写错了。

编译器给你分配的虚拟地址。

你用十六进制打印，就看起来正常一点！

为什么n的地址是2293324？

打印n的运算结果

printf("结果是：%d",&n); 这里多了一个&

楼主想干嘛？ 你这个打印的是n的地址。。。


Question: 编写程序希望实现两个链表合成一个新链表，编译没报错但是实现不了，希望大神给看看~

好像没啥问题。 1.你那两句malloc最好强转一下：List pnew = (List)malloc(sizeof(pnew)); 2.List ptemp = malloc(sizeof(ptemp));也不需要malloc（你这样直接造成内存泄漏），直接让它指向phead就行了  List addback(List phead, int data)//利用返回值实现尾插  { 	List pnew = (List)malloc(sizeof(pnew)); 	pnew->pNext = NULL; 	pnew->data = data;  	if (phead == NULL) 	{ 		phead = pnew; 	} 	else 	{ 		List ptemp = phead; 		while (ptemp->pNext != NULL) 		{ 			ptemp = ptemp->pNext; 		} 		ptemp->pNext = pnew; 	}  	return phead; }


Question: 求一个算法的思想和实现的方式

引用 1 楼 cyfcsd 的回复:没看懂楼主的思路。。。  求给个思路 怎么实现赛马程序 上面这代码 你无视他就好！（因为我自己也看不明白了）

没看懂楼主的思路。。。


Question: c/c++ 结构体分配内存问题 1C

strlen(t->fname)+1错了，strlen函数本身已经包含结束符了，你又加1，结果内存溢出了。

memcpy(p_rrq->req, t->fname, strlen(t->fname)+1);   memcpy(p_rrq->req + strlen(t->fname) + 1, t->mode,  strlen(t->mode)+1);  这样行吗？

引用 5 楼 cyfcsd 的回复:[quote=引用 4 楼 dcy_xm 的回复:] 完整代码有点多 还需要自己的函数接口 没法给你 那是什么问题啊，编译通不过，还是运行时程序崩溃啊[/quote]  指针问题吧 结构体中的指针分配内存的时候是不是有问题。然后不能给其赋值？

运行时 内存问题。程序崩溃。

引用 4 楼 dcy_xm 的回复:完整代码有点多 还需要自己的函数接口 没法给你 那是什么问题啊，编译通不过，还是运行时程序崩溃啊

完整代码有点多 还需要自己的函数接口 没法给你

引用 2 楼 dcy_xm 的回复:VS2010 不是这个环境，是完整的代码的意思

请给出可运行的代码环境，这样太不好调试了


Question: 怎样改变指针数组指向的字符串的值？

引用 8 楼 qq423399099 的回复:[quote=引用 7楼qq_16774199 的回复:][quote=引用 6 楼 qq423399099 的回复:] 你要改的话直接让指针指向另一个常量字符串"222"是可以的  #include<stdio.h> int main() { 	char *aaa[] = { "111" }; 	aaa[0] = "222"; 	printf("%s\n", aaa[0]); }  请教，指针变量不是只能用来储存地址吗？为什么能储存字符串了？[/quote]它存储的是常量字符串"111"的首地址[/quote]  那么这个常量字符串只能用指针读取，没办法用正常的字符类似数组变量读取？

跟前面一样的看法，你定义了字符指针数组，但初始化后，就不能改变其大小 char *p="111" ,p指向的内容是在常量区，无法改变 如果，你想要定义一个可以改变大小的数组，可以用C++的vector模板 http://blog.csdn.net/zycxnanwang/article/details/51934397

改变不了，"111"存放在常量区，无法修改。

引用 7楼qq_16774199 的回复:[quote=引用 6 楼 qq423399099 的回复:] 你要改的话直接让指针指向另一个常量字符串"222"是可以的  #include<stdio.h> int main() { 	char *aaa[] = { "111" }; 	aaa[0] = "222"; 	printf("%s\n", aaa[0]); }   请教，指针变量不是只能用来储存地址吗？为什么能储存字符串了？[/quote]它存储的是常量字符串"111"的首地址

引用 6 楼 qq423399099 的回复:你要改的话直接让指针指向另一个常量字符串"222"是可以的  #include<stdio.h> int main() { 	char *aaa[] = { "111" }; 	aaa[0] = "222"; 	printf("%s\n", aaa[0]); }   请教，指针变量不是只能用来储存地址吗？为什么能储存字符串了？

char *p1 = "111"; 	char *p2 = "222";  	char *aaa[] = { p1, p2, "333" };

引用 9 楼 qq_16774199 的回复:[quote=引用 8 楼 qq423399099 的回复:] [quote=引用 7楼qq_16774199 的回复:][quote=引用 6 楼 qq423399099 的回复:] 你要改的话直接让指针指向另一个常量字符串"222"是可以的  #include<stdio.h> int main() { 	char *aaa[] = { "111" }; 	aaa[0] = "222"; 	printf("%s\n", aaa[0]); }  请教，指针变量不是只能用来储存地址吗？为什么能储存字符串了？[/quote]它存储的是常量字符串"111"的首地址[/quote]  那么这个常量字符串只能用指针读取，没办法用正常的字符类似数组变量读取？[/quote] 这样？  #include<stdio.h> int main() { 	char *aaa[] = { "111" }; 	aaa[0] = "242"; 	printf("%c\n", aaa[0][1]); }

引用 1 楼 q932104843 的回复:*aaa[0]="222"; 你这里初始化都定义了数组大小了，貌似不能再添加了，貌似也不能删除吧  error C2440: '=' : cannot convert from 'const char [4]' to 'char'


Question: C语言初学者提问 IF语句

建议你看一下 C语言的 运算符优先级

关键在于 k=i*j==6; 先  进行i*j 之后表达式就成了 k=6==6; 6==6 成立 故 k=1; 所以就是1了

运算符优先级  参看：http://en.cppreference.com/w/cpp/language/operator_precedence

运算符优先级

if在哪里？ 并且：C语言没有IF，只有if，大小写严格区分！

运算符优先级的问题：逻辑运算符大于赋值运算符 k=i*j==6; 这个先算逻辑运算符：i*j=6，即k=6==6; k=6==6又是关系运算符(==)优先级高，6==6恒等，所以k=1(判断)

这里三个运算符*最大，最先运算。然后是==，最后是=

==的优先级高于=的优先级 http://www.jb51.net/article/37282.htm

1为真，0为假


Question: 恶心的strtok函数，太不人性化了。

引用 12 楼 cfjtaishan 的回复:建议不用strtok而改用strtok_r；在多线程中,建议使用strtok_r,而不要使用strtok； strtok_r可以不会很晦涩；使用方法稍微查一下；  strtok_r是linux平台下的strtok函数的线程安全版。windows的string.h中并不包含它。 但是我发现这句话，而我用windows学习。

从来不用这个函数，这个的实现太简单，修改了原始内容。 自己去写一个比这个好用的，直接传常量字符串都行。

引用 6 楼 qq_16774199 的回复:[quote=引用 3 楼 paschen 的回复:] 也没你说那么难用,自己写一个函数封装strtok不就行了 请问自己写的函数，运行速度会不会比自带的慢些？ 我还没到关心速度的层次，只是想了解一下自制函数的速度是不是比自带的慢。[/quote]  效率影响不会太大  可以简单封装这个函数，也可以完全自己去实现这个功能

http://www.jb51.net/article/55954.htm  另外MFC的CString也自己封装了分割字符串的方法

也没你说那么难用,自己写一个函数封装strtok不就行了

自己写，很快的啊

根据需求自己写一个就行了，逻辑不是很复杂

这个函数非线程安全，慎用

这个函数修改了源数据，确实是非常糟糕的设计。

引用 3 楼 paschen 的回复:也没你说那么难用,自己写一个函数封装strtok不就行了 请问自己写的函数，运行速度会不会比自带的慢些？ 我还没到关心速度的层次，只是想了解一下自制函数的速度是不是比自带的慢。

引用 楼主 qq_16774199 的回复:函数非常晦涩，理解了也很容易搞错。欲分割的字符串，第二次调用居然要设置为NULL。总之不好用。  请问c有没有什么人性化的函数，第三方的也行，用#include方式加进去也好？  这个函数设计的确实非常恶心，自己写函数分割吧。

不会用不用就是了啊, 像C这么自由的语言, 这是个事么...


Question: c语言异常为题求助

点击中断 结合调用堆栈调试

你的num成员变量应该用%d打印吧？


Question: 重新复习C语言遇到的一个神奇的问题

3L说得很对啊, 有溢出的.是该复习一下了.

strlen是字符串的大小（字符串大小，C中字符串是以\0结尾）  sizeof是字符数组的大小（数组大小）

楼主还没有明白sizeof和strlen的区别吧 sizeof是用来计算某个类型的变量的长度的，它一定是对应一种类型的，你这里的类型就是char[15]，虽然C语言里没把这个东西看做一种类型，但理解上可以这么理解，即st是一个类型为char[15]的变量，所占的内存空间大小就是15个字节，以后你遇到sizeof直接去找对应的类型就可以了 strlen是一个函数，是专门用来求字符数组（只能是字符数组）长度的，它的原理也很简单，就是遇到'\0'，就会停止计数（不包括'\0'），它不会管你是什么类型的，它只知道去找\0' 你的输入显然是超出了预先分配的空间大小，发生了缓冲器溢出错误，但并没有造成严重后果，你可以试试再多输入一些，肯定是有问题的，这也是gets这类函数的最大缺点

引用定义的字符数组st是15长度的，但实际输入的字符串明显超过了15 未定义行为  未定义行为可能产生任何结果，包括但不限于：产生期望的结果，产生未期望的结果，产生随机的结果，产生无法解释的结果，运行错误，随机的运行时错误，编译错误，等等

strlen只能用char*做参数，且必须是以''\0''结尾的，strlen的结果要在运行的时候才能计算出来字符串的长度。   大部分编译程序 在编译的时候就把sizeof计算过了 是类型或是变量的长度这就是sizeof(x)可以用来计算字符数组长度的原因  有的编译器把内存的大小放在了数组首地址前的空间里。


Question: 一个C语言的语法问题求解释

我觉的内存没有释放。

1）如果 udp_new是调用 malloc.calloc,realloc,new 分配的 得看这三个函数如何处理 upcb udp_bind udp_echoserver_receive_callback  udp_recv 如果没释放，可能会有内存泄漏  2）如果不是， 要看是不是 调用 alloca 分配的 alloca 分配的不用释放 。。。 具体情况，具体分析，不一定就会有内存泄露 3）其他，。。。还是看看 udp_new的实现吧

要看 udp_new 怎么写的， 如果是分配在栈内， 函数结束后就没有了， 如果是在堆上 需要单独释放


Question: 初学者求助

楼上正解。但是不知道原作者为什么加*呢？是出于什么考虑，是有这个语法么？

去掉%s中间的* printf里面的*的用法C89二十多年前就规定好了. ===================    A field width or precision, or both, may be indicated by an asterisk * instead of a digit string.  In this case, an int argument supplies the field width or precision.  The arguments specifying field width or precision, or both, shall appear (in that order) before the argument (if any) to be converted.  A negative field width argument is taken as a - flag followed by a positive field width.  A negative precision argument is taken as if it were missing. ===================  #include<stdio.h>  int main(void) { 	char name[40], name1[40]; 	printf("Please tell me your name,\n"); 	scanf("%s %s", name, name1); 	printf("Oh!You are \"%s %s\"\n", name, name1); 	getchar(); getchar(); 	return(0); }

%*s什么意思啊……


引用 2 楼 赵4老师的回复:https://www.baidu.com/s?wd=stc89s52%20源代码  什么意思，我没有看到，直接给我源代码可以吗？

有人吗在吗帮帮忙求求你们了


Question: 关于一个指针的小问题

strstr

引用 5 楼 baidu_35631329 的回复:[quote=引用 4 楼 cyfcsd 的回复:] 你的s4是在my_replace函数的栈上分配的内存，函数返回时栈内存被回收，所以结果是不正确的 要想正确返回有两个方法： 1）定义一个全局栈数组，这样函数返回以后数组内存不会被释放，但定义全局数组不是什么好方法 2）在主函数里定义一个数组，这样从my_replace函数返回以后还可以在主函数里使用 以上两种方法因为不能提前知道数组长度，所以只能分配大数组 3）用malloc在堆上分配内存，这样可以先用strlen确定一下s1的长度，因为s4的长度肯定不好超过s1 最后这种方法可以在main函数里分配，也可以在my_replace里分配，无论在哪儿分配，一定要记得释放，为了保持一致性，最好是在main函数里分配 如果只是一个小例子，上面的方法都能实现，如果是真的系统开发，还是建议第3种方法 那我假如在main中为s4申请了内存，可我函数的输入只有三个常量字符串，咋在里面使用他呢？ 还有就是假如我位s4malloc了100位char的大小，那他和s4[100]有区别吗？ [/quote] 如果函数的参数和返回值都定了，那就只能在my_replace函数里malloc内存了，因为外面的内存地址没法传递到函数里面去了，malloc内存和s4[100]的区别就是malloc的内存是分配在堆上的，它不会以为函数结束而被系统回收，还可以继续用

引用 4 楼 cyfcsd 的回复:你的s4是在my_replace函数的栈上分配的内存，函数返回时栈内存被回收，所以结果是不正确的 要想正确返回有两个方法： 1）定义一个全局栈数组，这样函数返回以后数组内存不会被释放，但定义全局数组不是什么好方法 2）在主函数里定义一个数组，这样从my_replace函数返回以后还可以在主函数里使用 以上两种方法因为不能提前知道数组长度，所以只能分配大数组 3）用malloc在堆上分配内存，这样可以先用strlen确定一下s1的长度，因为s4的长度肯定不好超过s1 最后这种方法可以在main函数里分配，也可以在my_replace里分配，无论在哪儿分配，一定要记得释放，为了保持一致性，最好是在main函数里分配 如果只是一个小例子，上面的方法都能实现，如果是真的系统开发，还是建议第3种方法 还有就是题目里要求返回一个*s，那么是不是2）的方法就不能用了？ 感谢大神！求解答

引用 4 楼 cyfcsd 的回复:你的s4是在my_replace函数的栈上分配的内存，函数返回时栈内存被回收，所以结果是不正确的 要想正确返回有两个方法： 1）定义一个全局栈数组，这样函数返回以后数组内存不会被释放，但定义全局数组不是什么好方法 2）在主函数里定义一个数组，这样从my_replace函数返回以后还可以在主函数里使用 以上两种方法因为不能提前知道数组长度，所以只能分配大数组 3）用malloc在堆上分配内存，这样可以先用strlen确定一下s1的长度，因为s4的长度肯定不好超过s1 最后这种方法可以在main函数里分配，也可以在my_replace里分配，无论在哪儿分配，一定要记得释放，为了保持一致性，最好是在main函数里分配 如果只是一个小例子，上面的方法都能实现，如果是真的系统开发，还是建议第3种方法 那我假如在main中为s4申请了内存，可我函数的输入只有三个常量字符串，咋在里面使用他呢？ 还有就是假如我位s4malloc了100位char的大小，那他和s4[100]有区别吗？

1.使用malloc在堆上分配内存 2.可以考虑把字符串长度作为参数传进函数，或者换一门语言比如C++并使用vector 3.如果有关于2.)的更好的解决方案能提醒我感激不尽

#include <stdio.h> #include <stdlib.h> #include <stdbool.h>  struct node{ 	int data; 	struct node * next; };   struct node *  init(int data){ 	struct node * head = (struct node *)malloc(sizeof(struct node *)); 	struct node *  n = (struct node *)malloc(sizeof(struct node)); 	n->data = data; 	n->next = NULL; 	head = n; 	return head; }  void add2tail(struct node *  list, int data){ 	struct node *  n = list; 	while (n->next != NULL){ 		n = n->next; 	} 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	n->next = newnode; 	newnode->data = data; 	newnode->next = NULL; 	return; }  void print(struct node *  list){ 	struct node *  n = list; 	while (n != NULL){ 		printf("%d ", n->data); 		n = n->next; 	} 	printf("\n"); 	return; }  int main(void){ 	struct node *  head = init(123); 	print(head); 	add2tail(head, 7); 	print(head); 	system("pause"); 	return 0; }


Question: 求助关于一个简单的链表实现

引用 10 楼 qq423399099 的回复:[quote=引用 9楼我是你的主体 的回复:][quote=引用 8 楼 qq423399099 的回复:] [quote=引用 7楼我是你的主体 的回复:][quote=引用 5 楼 user-2 的回复:] #include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }[/quote]你要在add2head函数里改变list的指向，必须传二级指针或者一级指针的引用才行[/quote] ....感觉白看了c primer plus，话说为什么要传二级指针或者一级的引用，有没有这方面的资料免得麻烦您了，我一直就以为指针可以任意改变指向，实在不懂为什么还要二级指针才能改变参数的指向[/quote]那是因为你的实参和形参并不是同一个指针，他们只是指向了同一块内存[/quote] 明白了，感谢。

引用 9楼我是你的主体 的回复:[quote=引用 8 楼 qq423399099 的回复:] [quote=引用 7楼我是你的主体 的回复:][quote=引用 5 楼 user-2 的回复:] #include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }[/quote]你要在add2head函数里改变list的指向，必须传二级指针或者一级指针的引用才行[/quote] ....感觉白看了c primer plus，话说为什么要传二级指针或者一级的引用，有没有这方面的资料免得麻烦您了，我一直就以为指针可以任意改变指向，实在不懂为什么还要二级指针才能改变参数的指向[/quote]那是因为你的实参和形参并不是同一个指针，他们只是指向了同一块内存

引用 8 楼 qq423399099 的回复:[quote=引用 7楼我是你的主体 的回复:][quote=引用 5 楼 user-2 的回复:] #include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }[/quote]你要在add2head函数里改变list的指向，必须传二级指针或者一级指针的引用才行[/quote] ....感觉白看了c primer plus，话说为什么要传二级指针或者一级的引用，有没有这方面的资料免得麻烦您了，我一直就以为指针可以任意改变指向，实在不懂为什么还要二级指针才能改变参数的指向

引用 7楼我是你的主体 的回复:[quote=引用 5 楼 user-2 的回复:] #include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }[/quote]你要在add2head函数里改变list的指向，必须传二级指针或者一级指针的引用才行

引用 5 楼 user-2 的回复:#include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }

引用 4 楼 qq423399099 的回复:你这句其实会造成内存泄漏struct node * head = (struct node *)malloc(sizeof(struct node *)); 你这个链表根本就是不带头结点的链表，你为head指针malloc了4个字节的空间，之后马上让它指向了n 之前malloc的4个字节的地址你已经丢失了，struct node * head = (struct node *)malloc(sizeof(struct node *));这句完全可以去掉。  但是如果去掉，head就变成了auto变量，它会在函数调用结束后回收吧？

引用 11楼我是你的主体 的回复:[quote=引用 10 楼 qq423399099 的回复:] [quote=引用 9楼我是你的主体 的回复:][quote=引用 8 楼 qq423399099 的回复:] [quote=引用 7楼我是你的主体 的回复:][quote=引用 5 楼 user-2 的回复:] #include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; } 我想写的头插是直接在头部的上一个插入比如原来1->5->7头插一个9就变成了9->1->5->7 但是我这样写为什么不对 void add2head(struct node * list, int data){ 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	newnode->data = data; 	newnode->next = list; 	list = newnode; 	return; }[/quote]你要在add2head函数里改变list的指向，必须传二级指针或者一级指针的引用才行[/quote] ....感觉白看了c primer plus，话说为什么要传二级指针或者一级的引用，有没有这方面的资料免得麻烦您了，我一直就以为指针可以任意改变指向，实在不懂为什么还要二级指针才能改变参数的指向[/quote]那是因为你的实参和形参并不是同一个指针，他们只是指向了同一块内存[/quote] 明白了，感谢。[/quote]解决了记得结帖

引用 2 楼 qq423399099 的回复:因为你的add2tail根本没有将新结点连接上。 1.add2tail函数里while (n != NULL)改成while (n->next != NULL) 2.n= newnode;改成n->next = newnode;  #include <stdio.h> #include <stdlib.h> #include <stdbool.h>  struct node{ 	int data; 	struct node * next; };   struct node *  init(int data){ 	struct node * head = (struct node *)malloc(sizeof(struct node *)); 	struct node *  n = (struct node *)malloc(sizeof(struct node)); 	n->data = data; 	n->next = NULL; 	head = n; 	return head; }  void add2tail(struct node *  list, int data){ 	struct node *  n = list; 	while (n->next != NULL){ 		n = n->next; 	} 	struct node *  newnode = (struct node *)malloc(sizeof(struct node)); 	n->next = newnode; 	newnode->data = data; 	newnode->next = NULL; 	return; }  void print(struct node *  list){ 	struct node *  n = list; 	while (n != NULL){ 		printf("%d ", n->data); 		n = n->next; 	} 	printf("\n"); 	return; }  int main(void){ 	struct node *  head = init(123); 	print(head); 	add2tail(head, 7); 	print(head); 	system("pause"); 	return 0; }  感谢您，我尝试了一下的确可以，我等下再想想原因 另外还有一个问题想麻烦您一下，我突然觉得struct node * head = (struct node *)malloc(sizeof(struct node *));会不会有点多余或者有点错误，malloc根据我的理解是为指针所指向的内容分配内存，这里指向的是一个节点却只分配了sizeof(struct node *)的大小会不会有点问题，求教正确的该这么改

在线急求


Question: 小车发生反转，该左转往右转

小车发生反转，该左转

什么小车，什么程序？

楼主，你这问题描述的太笼统了，看不懂啊。。。

这是个什么问题，能说的清楚鞋吗？？


Question: 为什么不能获取非本地的文件大小

在哪位高手知道吗，烦表指点一下，急。


Question: 这个正则表达是怎么匹配？

[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}


Question: c重定向

比如在cmd下输入 > 可以将输出重定向到某个文件

重定向不是C语言的功能，而是操作系统的功能，windows,Linux操作系统都支持重定向

百度一下重定向就可以了，比如在控制台输入echo hello >c:\test.txt并回车，会把hello写到c盘根目录下的test.txt文件下


Question: 一个简单链表的改错，改了之后依然错，请指正

谢谢，我调试了很多次，我看到p的值为要删除的值了，p=p->next，我以为连接上后面的结点了。原来是没有连接上。。

用一个pre指针记录当前结点的前一个结点的地址，然后找到要删除的结点后，让pre->pNext指向p的后一个结点就行了（这里要考虑如果删除的是第一个结点，需要执行的应该是p_gHead = p->pNext）  #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> typedef int DATA; struct SNode { 	DATA data;//数据 	SNode*pNext;//指针区域 }; SNode*p_gHead = NULL; void AddHead(DATA data)//头曾 { 	SNode*p = (SNode*)malloc(sizeof(SNode)); 	p->data = data; 	p->pNext = p_gHead; 	p_gHead = p; } void Print()//大印 { 	SNode* p = p_gHead; 	while (p) 	{ 		printf("%d ", p->data); 		p = p->pNext; 	} } void AddList(DATA data)//尾曾 { 	SNode *p = p_gHead; 	while (p->pNext != NULL) 		p = p->pNext; 	SNode*pNew = (SNode*)malloc(sizeof(SNode));  	pNew->data = data; 	pNew->pNext = NULL; 	p->pNext = pNew; } void modif(DATA data, DATA dat)//链表修改 { 	SNode*p = p_gHead; 	while (p) 	{  		if (p->data == data) 		{ 			p->data = dat; 			break; 		} 		p = p->pNext;  	} } /*---------------------------------------------------------------------------------------*/ int  Delete(DATA data)//需要改错的地方 { 	SNode *p = p_gHead, *deltemp, *pre = p_gHead; 	while (p) 	{ 		if (p->data == data) 		{ 			deltemp = p; 			if (deltemp == p_gHead)//删除的是第一个结点 				p_gHead = p->pNext; 			else 				pre->pNext = p->pNext; 			free(deltemp); 			return 1; 		} 		pre = p; 		p = p->pNext; 	} 	return 0; } /*------------------------------------------------------------------------------------------------*/ int main() { 	AddHead(3); 	AddHead(2); 	AddHead(1); 	Print(); 	printf("\n"); 	modif(2, -888); 	Print(); 	printf("\n"); 	int i = Delete(-888); 	Print(); 	return 0; }


Question: C程序打包为DLL在C#调用出错（含完整源代码）

引用 7 楼 weiran2009 的回复:[quote=引用 5 楼 CharlesSimonyi 的回复:] DllExport void cvCanny(string str)  这里也有问题，c++中的string和c#中的string是不一样的，应该使用const char *或const wchar_t * DLL导出函数尽量以简单C类型为参数  您好，我按照网上这个帖子的方法： http://blog.csdn.net/shilogic/article/details/7027360   //头文件： #define DllExport __declspec(dllexport)  namespace OpenCV2UnityStudy0715 { 	//Return a + b 	extern "C" DllExport int plgAdd(int x, int y);  	//Return a * b 	extern "C" DllExport int plgMultiply(int x, int y);  	//	extern "C" DllExport const char *__stdcall  cvCanny(char *s); 	extern "C" DllExport void cvCanny(char *str); 	extern "C" DllExport const char* __stdcall ProcessString(char* str); 	//test string  	//extern "C" DllExport string plgString(); }   //cpp文件： namespace OpenCV2UnityStudy0715 { …… 	const char* __stdcall ProcessString(char* str) 	{  		//str 是 c# 创建的 StringBuilder，长度是255 		strcpy_s(str,sizeof(str), "I come from C++ PS class!!!"); 		//strcpy_s() 		return str; 	} …… }    C#代码：   using UnityEngine; using System.Collections; using OpenCvSharp.CPlusPlus; using OpenCvSharp; using System.Runtime.InteropServices;  using System;//IntPtr ... using System.Text;//StringBuilder str  public class testOpenCV0714 : MonoBehaviour {     [DllImport("OpenCV2UnityDLLTest0714")]     private static extern int plgCGetRandom();   //    [DllImport("OpenCV2UnityDLLw0715c", EntryPoint = "cvCanny", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] //    public static extern IntPtr cvCanny(StringBuilder str); //    [DllImport("OpenCV2UnityDLLw0718", EntryPoint = "cvCanny", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] //    private static extern void cvCanny(StringBuilder str);     [DllImport("OpenCV2UnityDLLw0718")]     private static extern void cvCanny(string str);     [DllImport("OpenCV2UnityDLLw0715c")]     private static extern int plgAdd(int a, int b);     [DllImport("OpenCV2UnityDLLw0715c")]     private static extern int plgMultiply(int a, int b);     [DllImport("VC.dll", EntryPoint = "ProcessString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]     public static extern void ProcessString(StringBuilder str);  	void Start () {          StringBuilder sSetPath = new StringBuilder(255);         StringBuilder str = new StringBuilder(255); //255 是 capacity         ProcessString(str);         print(str.ToString()); }   其它方法都能运行（简单加减乘除），但只要运行到 ProcessString(str);函数有关还是上面的问题，请问这是如何解决呢？[/quote]   不懂，但是可以推测是字符串参数没有正确传递

检查调用约定

引用 5 楼 CharlesSimonyi 的回复:DllExport void cvCanny(string str)  这里也有问题，c++中的string和c#中的string是不一样的，应该使用const char *或const wchar_t * DLL导出函数尽量以简单C类型为参数  您好，我按照网上这个帖子的方法： http://blog.csdn.net/shilogic/article/details/7027360   //头文件： #define DllExport __declspec(dllexport)  namespace OpenCV2UnityStudy0715 { 	//Return a + b 	extern "C" DllExport int plgAdd(int x, int y);  	//Return a * b 	extern "C" DllExport int plgMultiply(int x, int y);  	//	extern "C" DllExport const char *__stdcall  cvCanny(char *s); 	extern "C" DllExport void cvCanny(char *str); 	extern "C" DllExport const char* __stdcall ProcessString(char* str); 	//test string  	//extern "C" DllExport string plgString(); }   //cpp文件： namespace OpenCV2UnityStudy0715 { …… 	const char* __stdcall ProcessString(char* str) 	{  		//str 是 c# 创建的 StringBuilder，长度是255 		strcpy_s(str,sizeof(str), "I come from C++ PS class!!!"); 		//strcpy_s() 		return str; 	} …… }    C#代码：   using UnityEngine; using System.Collections; using OpenCvSharp.CPlusPlus; using OpenCvSharp; using System.Runtime.InteropServices;  using System;//IntPtr ... using System.Text;//StringBuilder str  public class testOpenCV0714 : MonoBehaviour {     [DllImport("OpenCV2UnityDLLTest0714")]     private static extern int plgCGetRandom();   //    [DllImport("OpenCV2UnityDLLw0715c", EntryPoint = "cvCanny", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] //    public static extern IntPtr cvCanny(StringBuilder str); //    [DllImport("OpenCV2UnityDLLw0718", EntryPoint = "cvCanny", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] //    private static extern void cvCanny(StringBuilder str);     [DllImport("OpenCV2UnityDLLw0718")]     private static extern void cvCanny(string str);     [DllImport("OpenCV2UnityDLLw0715c")]     private static extern int plgAdd(int a, int b);     [DllImport("OpenCV2UnityDLLw0715c")]     private static extern int plgMultiply(int a, int b);     [DllImport("VC.dll", EntryPoint = "ProcessString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]     public static extern void ProcessString(StringBuilder str);  	void Start () {          StringBuilder sSetPath = new StringBuilder(255);         StringBuilder str = new StringBuilder(255); //255 是 capacity         ProcessString(str);         print(str.ToString()); }   其它方法都能运行（简单加减乘除），但只要运行到 ProcessString(str);函数有关还是上面的问题，请问这是如何解决呢？

引用 5 楼 CharlesSimonyi 的回复:DllExport void cvCanny(string str)  这里也有问题，c++中的string和c#中的string是不一样的，应该使用const char *或const wchar_t * DLL导出函数尽量以简单C类型为参数  以本人猜测，这个可能较大。也就是文件名没有正确传递过去

引用 2 楼 liups 的回复:用Emgu CV吧 嘿！终于看到一位搞OpenCV的小伙伴了~ 不过据我所知，现在主要有2种方案解决：  1、使用OpenCvSharp 2、使用OpenCVForUnity  2好像收费，主要是 Texture2D与Mat 的转换问题， 我现在就想，直接从OpenCV里面生成dll在Unity里面调用，不过看起来比较复杂，更谈不上在Android里面Unity调用了……

引用 1 楼 user-4 的回复:c的动态库只需要头文件和dll文件，不需要源文件。 头文件中，不要出现c++的数据类型，只能使用c的数据类型  建议楼主仔细学习一下如何生成一个c语言兼容的dll   我这个代码好像就是C的，我要重新在C++板块发一个？ 感觉比较复杂，请问有专门的书籍介绍如何跨平台dll打包的吗？

用Emgu CV吧


Question: 关于宏定义的非常重要的问题。。。

用的宏定义,已经解决问题了，下面作为保留。  #define DEF_ADD_ZERO(ID,VALUE) memset (ID, 0x30, sizeof(ID) - 1 );ID[sizeof(ID) - 1] = 0x00; strncpy(ID + sizeof(ID) - strlen(VALUE) - 1, VALUE, strlen(VALUE));  调用时： 	char a2[8]; 	char a3[9];  	DEF_ADD_ZERO(a2,"1234"); 	DEF_ADD_ZERO(a3,"14");  结果：a2="0001234" , a3="00000014"

std::snprintf需要传递缓存长度, std::sprintf不用，所以我才说是“不安全”的嘛

引用 5 楼 dustpg 的回复:[quote=引用 4 楼 adusuccessfully 的回复:] [quote=引用 3 楼 dustpg 的回复:] #include <iostream>  template<size_t T, class U> void def_add_zero(int d, U call) {     char buffer[T+1];     std::snprintf(buffer, T + 1, "%0*d", int(T), d);     call(buffer); }   int main() {     def_add_zero<5>(2, [](const char* buf) {         std::printf(buf);     });     return 0; }  请教下：你的程序我在VC上是会提示snprintf不是std的成员[/quote]  换编译器或者用稍微不安全的std::sprintf[/quote]  会报另一个错误：错误	1	error C2664: “sprintf”: 不能将参数 2 从“const size_t”转换为“const char *”

引用 4 楼 adusuccessfully 的回复:[quote=引用 3 楼 dustpg 的回复:] #include <iostream>  template<size_t T, class U> void def_add_zero(int d, U call) {     char buffer[T+1];     std::snprintf(buffer, T + 1, "%0*d", int(T), d);     call(buffer); }   int main() {     def_add_zero<5>(2, [](const char* buf) {         std::printf(buf);     });     return 0; }  请教下：你的程序我在VC上是会提示snprintf不是std的成员[/quote]  换编译器或者用稍微不安全的std::sprintf

引用 3 楼 dustpg 的回复:#include <iostream>  template<size_t T, class U> void def_add_zero(int d, U call) {     char buffer[T+1];     std::snprintf(buffer, T + 1, "%0*d", int(T), d);     call(buffer); }   int main() {     def_add_zero<5>(2, [](const char* buf) {         std::printf(buf);     });     return 0; }  请教下：你的程序我在VC上是会提示snprintf不是std的成员

这个长度和 sizeof 有什么关系？

c++自从出现了匿名表达式, 这些涉及到临时数组的东西简直易如反掌了.....


Question: fprintf运行问题

scanf_s在读取%c和%s的时候必须多指定一个参数用来指定读取的长度，否则必定无法读取成功

scanf_s函数的用法不对，应该加一个长度scanf_s("%d%s%lf", &account, name, 30, &balance);


Question: C语言返回地址的问题

看了楼上的回答， 我总结下自己的看法不知道对不对 1、返回局部变量的指针（除静态变量），一般会出错，因为它在栈中，函数结束后空间会被回收利用。 2、返回动态内存指针（比如malloc），可正常使用。 因为它在堆中，不会因函数结束而回收。 3、返回常数及静态指针，比如楼主这里的字串常量。可正常使用。因为它在静态存储区。

return_2中的"2222"是个常量字符串，这个字符串被当作常量而且被放置在此程序的内存静态区，不会因为return_2调用结束就被销毁  而你的return_1返回的是局部变量的地址，所以发生什么都不要觉得奇怪。


Question: 谁能解释下多级指针（有点蒙了）！

非得用三级指针这种东西吗，一般二级就够用了。 http://sysuor.blog.163.com/blog/static/8620131200832051039568/

三]====>三

所谓的级，其实就是间接引用的次数。 二级 整型指针，不能直接指向 整型对象。 三]级 整型指针，不能直接指向一级 整型指针。 只有一级 整型指针可以直接指向 整型对象。

这个可以先从数组来理解，然后在改为动态分配的内存  int a[2][3][4]={ {{1,2,3,4},{5,6,7,8},{9,10,11,12}}, {{13,14,15,16},{17,18,19,20},{21,22,23,24}}, };  int *p =&a[0][0][0];//一级整型指针，直接指向整型对象 a[0][0][0];这样 *p 就是 a[0][0][0]; int **pp=&p;//二级整型指针，直接指向整型指针p, *pp就是 p; **pp 就是  a[0][0][0]; int ***ppp =&p;//三级指针指向二级指针pp， *ppp就是 pp,**ppp 就是p,***ppp 就是 a[0][0][0];  再看动态分配 int ***ppp= (int ***) malloc(sizeof(int **)* 2);//3级指针，分配一个二级指针数组，储存 2个二级指针 for(int i=0;i<2;i++){           *(ppp+i) = (int **) malloc(sizeof(int *)*3); //每个二级指针，分配3个一级指针，储存 3个一级指针 }  for(int i=0;i<2;i++){          for(int j=0;j<4;j++)         {                 *( *(ppp+i)+j) = (int **) malloc(sizeof(int)*4);//每个一级指针，分配4个整形对象，储存 4个整型数据。         }  }  ***ppp 就是 *(*(*ppp))) 也就是ppp指向 *ppp ,*ppp 指向 **ppp ,**ppp 指向***ppp; 通过三次间接引用，才能找到对应的整型对象 读取 ***ppp 要先读取 **ppp 读取 **ppp 又要 先读取 *ppp 这样 才能去去读 ***ppp 这个 对象。

指针也是一种变量，只是其中保存的是地址。  如果x是指针，则*x表示该地址中的内容。  所谓二级、三级指针，只是这个内容本身还是地址而已

引用 1 楼 user-3 的回复:除了***ppp外，p,*p,**p都是指针 这我知道  我不明白的是对于一个三级指针 **ppp 和*ppp 分别是什么意思  ，

除了***ppp外，p,*p,**p都是指针


Question: 新手看不懂书，为什么最小的整数是0，为什么整数没有下溢？

单说整数是可笑的，需要区分有符号和无符号

讲一大堆没有用的  其实简单介绍以后，给一个完整的表格就完了

引用 5 楼 lm_whales 的回复:类似的，浮点数溢出的定义为 非0 相乘，相除，结果为0 下溢（太小，精度丢失） 结果为正负 无穷， 上溢。（太大无法表示）； 参与运算的数，不是nan,inf 结果变成只能用inf 表示 相加减，结果为正负 无穷 ，上溢（太大无法表示）；参与运算的数，不是nan,inf 结果变成只能用inf 表示  浮点数，可以表示  无穷大（正负无穷大+inf,-inf），Nan 不是一个数（应该不止一个编码） 0 以及一定范围内的非0实数（其实是有理数）  PS： 用最大最小数值，定义溢出，就没有办法定义浮点数下溢了 ，，，，，，， 当然，用绝对值定义溢出，也没有法子表示无符号数之差为负数的情况。

谭书或类似的书！最可恨了  自己胡乱总结或定义概念，关健还很多不对

类似的，浮点数溢出的定义为 非0 相乘，相除，结果为0 下溢（太小，精度丢失） 结果为正负 无穷 上溢。（太大无法表示） 相加减，结果为正负 无穷 上溢（太大无法表示）

这里说的应该是绝对值的溢出。 因此整数没有下溢。 不是数据类型的溢出。 小于绝对值最大的负数和大于最大值正数都为 上溢

对整数，溢出指代数值：小于最小值为下溢，大于最大值为上溢 上溢：超出所能表示的最大正数 下溢：超出所能表示的最小负数 如16位整数范围为：-32768 ~ +32767，则当32767再加1时，发生上溢；当-32768再减1时，发生下溢。  对浮点数，溢出指绝对值：绝对值小于浮点数所能表示的最小值，为下溢，当作 0；绝对值大于浮点数所能表示的最大范围，为上溢，当作 INF。 根据具体符号的不同，又分为：正上溢、正下溢、负上溢、负下溢  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

这里说的没有错吧,  0 是最小的,所以没有下溢. 要是float 你要想用来表示0.0000000000000000000000000000000000000000000000001,那是表示了的,那就下溢,因为达不到那个精度.

楼主这是什么书啊，可以扔了，我还没听过有最小的整数一说呢，计算机中的整数和浮点数表示的范围都是有限的，都会产生上溢和下溢，还有下面一段说的int表示范围较小，然后整数上溢在小型计算机中很常见，这也是扯淡，溢出是会发生，也应该注意，但真的在编程过程中溢出的情况肯定比得癌症的几率还低，哪儿有那么多大的数字要处理啊


Question: 学习C语言准备、执行过程、变量的定义与使用、常量的定义与使用、枚举的定义与使用、数组的定义与使用

引用 1 楼 zhanghow 的回复：没人看，自己的日记我看我看

日记写在博客里

没人看，自己的日记


Question: PAT的段错误和格式错误问题   求救QAQ

好像跟这个没关系，我把10改成100，还是这两个错误。。。而且如果是因为长度不够的话 应该是答案错误把。。。

struct jie {     char  ch[10]; }T[50000];  如果一个单词大于10个字节呢？


Question: apache如何截获post数据


Question: HDU 5655 DZY loves playing balls 求答疑

好的，谢谢！

按照LZ的思路，需如下修改可AC： #include<stdio.h> #include<algorithm>  using namespace std;  int main() {   int t;   int a[1000];   scanf("%d",&t);   while(t>0)   {     int n,i;     scanf("%d",&n);     for(i=0;i<n;i++)     {       scanf("%d",&a[i]);     }     sort(a,a+n);     double k=0,d=0;     double p,q;     for(i=1;i<n;i++) //改 for(i=n-1;i>=1;i--)     {       if(a[i]>a[i-1])       {         p= static_cast<double>(i);         q= static_cast<double>(n);         d=p/(q*(q-1));       }       /*       当i为n-1时，a[i+1]超界，因此不能用a[i]==a[i+1]，要改为if(a[i]==a[i-1])。       但此时不能是d=d+d，而是沿用上次d的值。因此要删除以下代码       if(a[i]==a[i+1])       {         d=d+d;       }*/       k=k+d;     }     t--;     printf("%.6f\n",k);   }   return 0; }

有人没？顶一下


Question: windows程序设计 [菜单-困扰很久的问题]

已解决，多谢您的关注~！

菜单用着用着就没了， 一般可能是什么原因？

没有鼠标的响应事件，只是关于菜单的一个程序

在你的程序中是否存在对鼠标事件的响应？


Question: 条件关系符的问题

用scanf_s读%c和%s的时候，必须多传一个参数用来指定需要读入的长度  #include<stdio.h> #include<math.h> void main() { 	char ch; 	scanf_s("%c", &ch, 1); 	ch = (ch >= 'A'&& ch <= 'Z') ? (ch + 32) : ch; 	printf("%c\n", ch); }

不会用_s函数就用原版的函数，这里_s函数需要在传递一个参数  既然用VS2015不看提示么:  1>c:\users\dust\documents\visual studio 2015\projects\project2\test\main.c(5): warning C4473: “scanf_s”: 没有为格式字符串传递足够的参数 1>  c:\users\dust\documents\visual studio 2015\projects\project2\test\main.c(5): note: 占位符和其参数预计 2 可变参数，但提供的却是 1 参数 1>  c:\users\dust\documents\visual studio 2015\projects\project2\test\main.c(5): note: 缺失的可变参数 2 为格式字符串“%c”所需 1>  c:\users\dust\documents\visual studio 2015\projects\project2\test\main.c(5): note: 此参数用作缓冲区大小

int main(void) { 	char ch; 	ch = getchar(); 	ch = ((ch >= 'A') && (ch <= 'Z')) ? (ch - 'A' + 'a' ) : ch; 	printf("%c\n", ch); 	return 0; }


Question: 请问调用函数时，实参类型可以不和形参类型一样吗？

看一下数据类型隐式转化规则你就知道能不能转换了。

指针的话，最好一致 注意 const形参通常可以用非const 反之一般不可以

如果可以隐式转化，那就是可以，int和long是可以隐式转换的，但int*和long*是不可以的，所以编译器会报错 如果机器上int和long占的内存大小相同（一般是相同的），那可以采用类型转换（int*）来完成


Question: 关于vc++6.0连接多个文件问题？

问题已经解决，我觉得@user-1讲解的挺好，是的注意

怎么没人看啊！！！！！

Delete_Node 再修改下，   void Delete_Node(Node **head) {   Node *t, *p;    if(head)   {     t = *head;     while( t !=NULL)     {       p = t->next;       free(t);       t = p;     }     *head = 0;   } }

我在XP VC6 下测试的正常， 可能是 VC6 与操作系统的兼容性问题？  按你的测试用例没有问题， 但是有即点可能要注意下   1 变量和指针尽量初始化， 这样不会导致Release 和 Debug的条件差异 2 如果 Input_Node  输入空元素的话， 可能会有访问冲突， Input_Node(0, 0, 0) 3 释放链表完了 指针应该清零， 避免 被再次使用到时误认为是有效的   //Node *pa = 0, *pb = 0;  // pa = Input_Node(0, a, 5); //初始化 // pa = Input_Node(pa, b, 6); //追加  //追加元素  Node * Input_Node(Node *head, DataType *a, int n) {   Node *p, *t;   int i;    p = head;   while(p && p->next) p = p->next; //找到尾端    //追加节点   for(i=0; a && i < n; i++)   {     t = (Node *)malloc(sizeof(Node));      t->data = a[i];     t->next = 0;     if(p)       p->next = t;     else       head = t; //head     p = t;   }    return head; }  //Delete_Node(&pa); void Delete_Node(Node **head) {   Node *t = *head, *p;    if(head)   {     t = *head;     while( t !=NULL)     {       p = t->next;       free(t);       t = p;     }     *head = 0;   } }

再次通过使用dev c++编译器把<Node.h>这类包含改成"Node"，能完美运行的，但是VC++6.0还是不行的，问题是没有运行Node.cpp类的函数，不知道哪位大神解释下出现这种情况的原因！！！！！不要沉下去啊！！！！！！

我测试的结果是，链表已经生成好的，但是在调用Print_Node()函数时，不管在函数里加入什么输出，没反应，感觉好像主函数没运行到似的，但是为什么运行了Input_Node()函数，，并且在主函数重写个Print_Node_2()函数,复制一样的代码，是能显示的，还有后面的Delete_Node()函数，会出现运行错误。放在主函数没问题。这就让人匪夷所思了？


Question: 关于c语言的一段累加效验的程序

求教各位大神，感谢！


Question: C语言课程设计：学生成绩系统

/*    return 0  :    return 1  : repeat    return -1 : illeage address */ int IfRepeat(struct Student *head,struct Student *stu) {                 int iFlag=0;        if( NULL==head ) 		return -1;        if( NULL==stu ) 		return -1;        for( ; (NULL!=head)&&( 1!=iFlag ); head=head->next )     	{                   if(head->num==stu->num)                   {                       iFlag=1;                  }         }                  return iFlag; }

int flag=0; 		while(head!=null) 		{ 			if(head->num==stu->num) 			{ 				flag=1; 				break; 			} 			else 			{ 				head=head->next; 			} 		} 		if (flag==0)  		{ 			printf("the num is unique!"); 		} 		else if (flag==1)  		{ 			printf("sorry,num is repeat") 		}


Question: C语言 字符读取问题

用select或者polling或者epoll，检查stdin的可读缓存

或者并行计算，可以实现吗

导致我的letime（）函数就不会输出当前剩余时间。

把 c = getch()移动到另一个线程中去  具体办法： 1 写一个线程函数，开辟一个全局变量用于存放输入的字符 2 主线程中检查线程是否输入了字符

windows系统下，怎么处理呢


Question: free修改过的malloc指针会怎么样？

引用 6 楼 max_min_ 的回复:可以写一个简单程序测试一下的 malloc出来的地址是要比你填进去的size要大，里面有一些需要管理的标志位 其一就是你说的free结束的标志位。 你好，我理解你的意思，用户让calloc分配40，暗地里它分配更多，多出的空间储存着大小等信息，free从中得知空间大小。 请问什么代码可获取calloc真正分配了多少内存？sizeof（指针）没用。

引用 5 楼 yang004 的回复:直接会死机 *** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000023af014 ***  从free()的源代码看，ptr只能指向可用空间的首地址，不然，减去结构体大小之后一定不是指向管理信息空间的首地 址。所以，要确保指针指向可用空间的首地址！  你好，我理解你的意思，让calloc分配40字节，其实它分配得更多，多出来的空间储存着大小等信息，free则从中得知空间大小。 但是以上代码在我pellesC没出错，不知为什么。

据说 是放在返回给你 的 地址 之前 的 4个字节,但这是由系统决定的不同系统可能不一佯 转一个别人的文章 http://blog.csdn.net/a10615/article/details/41063063

你敢随便释放malloc的返回的位置。 明确告诉你，结果是未知的。

void free(void *ptr) {    struct mem_control_block *free;              free = ptr - sizeof(struct mem_control_block);         free->is_available = 1;         return;     } 请参考源码

free释放malloc内存必须整体释放。

引用 7 楼 c_s_d_n_l_a_m 的回复:请问free()的源代码从哪里来的？我还想看看其它库函数的源代码。 c 语言手册中好像有函数源码

请问free()的源代码从哪里来的？我还想看看其它库函数的源代码。

p1只移动4个字节，是因为它是int * malloc实际占用的空间一定是大于你申请的字节数，因为在申请的空间周围需要存放内存管理信息以及调试信息 如果只有申请的空间，那么编译器free时又怎么可能知道该释放多少字节呢？

这也引出我另一个疑问。malloc返回是指针只能说明malloc开始位置，malloc多大指针并不知道。free一个指针，C语言如何保证刚刚好把malloc的内存块释放？


Question: c语言编程求解

参考楼上版主

你这个问题好多： 1.输入a以后之所以输入b有错误，是因为输入缓冲区中有残留的回车符，所以getchar会直接读走，所以要在get_option开头加一句：fflush(stdin); 2.main函数里你遍历head,也不能直接操作head,否则你遍历打印完以后，head已经是NULL了，之后再进行别的操作就会因为访问空指针而报错，所以需要用个临时变量temp去遍历就行了。 3.你的check函数里，for循环内q = q->next;这句应该放到if后面，而不是前面，否则也会出现空指针而报错 PS：还有别的问题，楼主自己单步调试看看，单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  #include<string.h> #include<stdio.h> #include<stdlib.h> #include "ctype.h"//字符处理函数 #define LEN sizeof(struct list)  struct list *head; static unsigned int count;  char get_option(void); int check(char arr[], unsigned int count, struct list *head); struct list *createlist(void); struct list *sortlist(struct list *head);    /*************选择，接受用户选项*********************/ char get_option(void) { 	fflush(stdin); 	char ch; 	puts("请输入a,b,c或者d."); 	while ((ch = getchar())<'a' || ch>'d') 	{ 		while ((ch = getchar()) != '\n'); 		puts("输入错误，请输入a,b,c或者d."); 	} 	return ch; }   struct list { 	char data[15]; 	struct list *next; }; /************创建链表**********/  struct list *createlist(void) { 	unsigned int i = 0; 	struct list *head, *q, *s; 	char a[15]; 	head = (struct list*)malloc(LEN); 	q = head; 	puts("开始创建字典1"); 	puts("请输入单词（每行一个，END结束输入）"); 	while (scanf("%s", a) == 1) 	{ 		if (check(a, i, head)) 			continue; 		if (strncmp(a, "END", 3) == 0) 		{ 			count = i; 			break; 		} 		else 		{ 			s = (struct list *)malloc(LEN); 			strcpy(s->data, a); 			q->next = s; 			q = s; 			q->next = NULL; 			i++; 		}  	} 	head = head->next; 	return(head); }  /******************检查是否有重复单词*******************/ int check(char arr[], unsigned int count, struct list *head) { 	unsigned int i; unsigned int flag = 0; 	struct list *q; 	for (i = 0; i < strlen(arr); i++) 	if (isalpha(arr[i]) == 0) 	{ 		printf("%s不是一个单词。\n", arr); 		flag = 1; 		break; 	} 	q = head; 	for (i = 0; i < count; i++) 	{ 		 		if (strncmp(q->data, arr, strlen(arr) + 1) == 0) 		{ 			puts("重复的单词！"); 			flag = 1; 		} 		q = q->next; 	} 	return flag; } /************排序函数*************/ struct list *sortlist(struct list *head) { 	struct list *head1, *p, *q, *s, *r; 	head1 = NULL; 	p = head; 	while (p != NULL) 	{ 		s = (struct list*)malloc(LEN); 		strcpy(s->data, p->data); 		s->next = NULL; 		if (head1 == NULL || strcmp(s->data, head1->data)<0)//链为空或着s值小于头结点，s插入表头 		{ 			s->next = head1; 			head1 = s; 		} 		else//寻找s的插入位置，r指向待比较的结点，q指向r的前驱结点 		{ 			q = head1; r = q; 			while (r != NULL&&strcmp(s->data, r->data)>0) 			if (strcmp(s->data, r->data) > 0) 			{ 				q = r; 				r = r->next; 			} 			if (r = NULL) 			{ 				q->next = s; 				s->next = NULL; 			} 			else 			{ 				s->next = r; 				q->next = s; 			} 		} 		p = p->next; 	} 	return(head1); }  /**************主函数***********/ int main() { 	struct list *head; 	struct list *p, *s; 	char a[15]; 	char input; 	puts("\t************************欢迎使用字典排版系统*************\n\n"); 	puts("\ta.构建字典系统并显示出来"); 	puts("\tb.添加新单词"); 	puts("\tc.对已有单词进行排序"); 	puts("\td.退出系统"); 	puts("\n\n\t***************************************************\n"); 	input = get_option(); 	while (input != 'd')//循环不同选择实现不同功能 	{ 		if (input == 'a') 		{ 			head = createlist(); 			struct list *temp = head; 			puts("temp"); 			while (temp != NULL) 			{ 				printf("\t%s\n", temp->data); 				temp = temp->next; 			} 		} 		if (input == 'b') 		{ 			puts("添加词库"); 			puts("请输入新的单词（每行一个，END结束输入）"); 			while (scanf("%s", a)) 			{ 				if (check(a, count, head))  					continue;  				if (strncmp(a, "END", 3) == 0) 					break; 				else 				{ 					s = (struct list *)malloc(LEN); 					strcpy(s->data, a); 					s->next = head; 					head = s; 					count++; 				} 				puts("已有单词"); 				while (head != NULL) 				{ 					printf("\t%s\n", head->data); 					head = head->next; 				}   			}  		} 		if (input == 'c') 		{ 			puts("对单词进行排序："); 			p = sortlist(head); 			p = head; 			printf("排序:\n"); 			while (p != NULL) 			{ 				printf("\t%s\n", p->data); 				p = p->next; 			}  		} 		puts("还要做些什么？"); 		input = get_option(); 	}  	puts("谢谢使用，再见！"); 	return 0; }

没人吗？ 呜呜呜呜


Question: 求修改c语言 多线程server 代码！！

另外楼主你的While(1)，你想过没有，他里面有跳出循环的条件没有？

int main (int argc, char *argv[])   {      int client;         /* client socket descriptor */      int addr_len;       /* used to store length (size) of sockaddr_in */      pthread_t thread;   /* thread variable */    //............... } 试着把client放到你Accept接受客户端连接监听的While循环里头去


Question: c数组输入/出问题

引用 1 楼 qq423399099 的回复:你第一种形式，只给name和num各1个字节的空间，这怎么够？ 因为字符串还需要放入'\0',所以至少各需要2个字节  谢谢qq423399099 ，刚才试了一下2个字节的，能输出正确结果，看来还是我的基本工不到家啊


Question: 用C语言编写聊天程序，

引用 4 楼 cyfcsd 的回复:[quote=引用 3 楼 qq_23152513 的回复:] [quote=引用 1 楼 cyfcsd 的回复:] 这个跟你的程序有关系吧，我记得上次做为了实现两边可以自由收发，用了两个线程分别监视两个端口 我只用了一个端口，这种情况下，可以实现自由收发吗？可不可以推荐一下合适的代码呢？[/quote] 以前用java写的，你要可以发给你[/quote] 好的，谢谢你了

引用 5 楼 qq_23152513 的回复:[quote=引用 4 楼 cyfcsd 的回复:] [quote=引用 3 楼 qq_23152513 的回复:] [quote=引用 1 楼 cyfcsd 的回复:] 这个跟你的程序有关系吧，我记得上次做为了实现两边可以自由收发，用了两个线程分别监视两个端口 我只用了一个端口，这种情况下，可以实现自由收发吗？可不可以推荐一下合适的代码呢？[/quote] 以前用java写的，你要可以发给你[/quote] 好的，谢谢你了[/quote] qq邮箱？23152513是吗？

聊天室就是一次一次广播的啊，你一次可以只发一句话，也可以两句，三句。。。你这个问法好搞笑

引用 3 楼 qq_23152513 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 这个跟你的程序有关系吧，我记得上次做为了实现两边可以自由收发，用了两个线程分别监视两个端口 我只用了一个端口，这种情况下，可以实现自由收发吗？可不可以推荐一下合适的代码呢？[/quote] 以前用java写的，你要可以发给你

引用 1 楼 cyfcsd 的回复:这个跟你的程序有关系吧，我记得上次做为了实现两边可以自由收发，用了两个线程分别监视两个端口 我只用了一个端口，这种情况下，可以实现自由收发吗？可不可以推荐一下合适的代码呢？


Question: math.h文件中关于 #define _ARMABI __declspec(__nothrow)的问题

引用 3 楼 cftxlin 的回复:后面的怎么不是函数，是函数的，是函数声明，至于函数体，是库里面的，我们不用管，__x是参数名，参数可以以下划线开头不是 请问 这些函数体是不是对外不可见的？ 还有下面在这个文件中使用了这个函数  void LPF2pSetCutoffFreq_1(float sample_freq, float cutoff_freq) { 		float fr =0;       float ohm =0;     float c =0; 	 		fr= sample_freq/cutoff_freq; //在这里调用 		ohm=tanf(M_PI_F/fr); 		//...... }  选中这个函数以后，右键选择Go to definition of 'tanf',IDE提示 undefined Definiton我试了试 右键选择Go to Refernece to 'tanf',然后就跳转到了这个math.h 文件，我之前想查看引用的某个函数的定义，都是选择Go to definition of 'tanf',就可以跳转到函数的具体实现部分，这个为什么这么特别？（顺利编译没有报错）

nothrow: 格式：return-type __declspec(nothrow) [call-convention] function-name ([argument-list]) 可用于函数声明。告诉编译器被声明的函数以及函数内部调用的其它函数都不会抛出异常。

__declspec(__nothrow) 函数修饰符，告诉编译器，这个函数不会抛出异常

这个是math.h 中的部分内容  #ifndef __USE_C99_MATH   #if defined(__USE_C99_ALL) || (defined(__STDC_VERSION__) && 199901L <= __STDC_VERSION__)     #define __USE_C99_MATH 1   #endif #endif  #define _ARMABI __declspec(__nothrow) #ifdef __TARGET_ARCH_AARCH64 # define _ARMABI_SOFTFP __declspec(__nothrow) #else # define _ARMABI_SOFTFP __declspec(__nothrow) __attribute__((__pcs__("aapcs"))) # define __HAVE_LONGDOUBLE 1 #endif #define _ARMABI_PURE __declspec(__nothrow) __attribute__((const)) #ifdef __FP_FENV_EXCEPTIONS # define _ARMABI_FPEXCEPT _ARMABI #else # define _ARMABI_FPEXCEPT _ARMABI __attribute__((const)) #endif  /* C99 float versions of functions.  math.h has always reserved these    identifiers for this purpose (7.13.4). */ extern _ARMABI_PURE float _fabsf(float); /* old ARM name */ _ARMABI_INLINE _ARMABI_PURE float fabsf(float __f) { return _fabsf(__f); } extern _ARMABI float sinf(float /*x*/); extern _ARMABI float cosf(float /*x*/); extern _ARMABI float tanf(float /*x*/); extern _ARMABI float acosf(float /*x*/); extern _ARMABI float asinf(float /*x*/); extern _ARMABI float atanf(float /*x*/); extern _ARMABI float atan2f(float /*y*/, float /*x*/); extern _ARMABI float sinhf(float /*x*/); extern _ARMABI float coshf(float /*x*/); extern _ARMABI float tanhf(float /*x*/); extern _ARMABI float expf(float /*x*/); extern _ARMABI float logf(float /*x*/); extern _ARMABI float log10f(float /*x*/); extern _ARMABI float powf(float /*x*/, float /*y*/); extern _ARMABI float sqrtf(float /*x*/); extern _ARMABI float ldexpf(float /*x*/, int /*exp*/); extern _ARMABI float frexpf(float /*value*/, int * /*exp*/) __attribute__((__nonnull__(2))); extern _ARMABI_PURE float ceilf(float /*x*/); extern _ARMABI_PURE float floorf(float /*x*/); extern _ARMABI float fmodf(float /*x*/, float /*y*/); extern _ARMABI float modff(float /*value*/, float * /*iptr*/) __attribute__((__nonnull__(2)));   #ifdef __cplusplus   extern "C++" {     inline float abs(float __x)   { return fabsf(__x); }     inline float acos(float __x)  { return acosf(__x); }     inline float asin(float __x)  { return asinf(__x); }     inline float atan(float __x)  { return atanf(__x); }     inline float atan2(float __y, float __x)    { return atan2f(__y,__x); }     inline float ceil(float __x)  { return ceilf(__x); }     inline float cos(float __x)   { return cosf(__x); }     inline float cosh(float __x)  { return coshf(__x); }     inline float exp(float __x)   { return expf(__x); }     inline float fabs(float __x)  { return fabsf(__x); }     inline float floor(float __x) { return floorf(__x); }     inline float fmod(float __x, float __y)     { return fmodf(__x, __y); }     float frexp(float __x, int* __exp) __attribute__((__nonnull__(2)));     inline float frexp(float __x, int* __exp)   { return frexpf(__x, __exp); }     inline float ldexp(float __x, int __exp)    { return ldexpf(__x, __exp);}     inline float log(float __x)   { return logf(__x); }     inline float log10(float __x) { return log10f(__x); }     float modf(float __x, float* __iptr) __attribute__((__nonnull__(2)));     inline float modf(float __x, float* __iptr) { return modff(__x, __iptr); }     inline float pow(float __x, float __y)      { return powf(__x,__y); }     inline float pow(float __x, int __y)     { return powf(__x, (float)__y); }     inline float sin(float __x)   { return sinf(__x); }     inline float sinh(float __x)  { return sinhf(__x); }     inline float sqrt(float __x)  { return sqrtf(__x); }     inline float _sqrt(float __x) { return _sqrtf(__x); }     inline float tan(float __x)   { return tanf(__x); }     inline float tanh(float __x)  { return tanhf(__x); }      inline double abs(double __x) { return fabs(__x); }     inline double pow(double __x, int __y)                 { return pow(__x, (double) __y); }


Question: xcode中用c语言部分函数报隐式声明错误（非警告）

是Header search Path没有设置对的问题么？也不对，函数的定义是可以找到的，有没有大神啊拉一把

这些函数写在这里又有什么意义？


Question: C语言头插入链表问题

引用 2 楼 fivezero50的回复:[quote=引用 1 楼 zycxnanwang 的回复:] 我来解释一波！ 首先你是用head指针作为形参，函数调用的时候 将会生成一个指针，把head地址上的内容赋给 生成指针，最后的时候你只是将insert的地址赋 给函数生成的指针，函数调用完，指针就delete 所以你的主函数里面的head指针还是指向原来的 地址，你调试可以验证一下！ 所以，我觉得你要想改变函数参数内容，最好用引用！  我所学的知识里，只要传指针给函数，然后就可以改变该指针所指的值，比如： int x =2; void change(int *var) { *var = 3; } int main() { change(&x) printf("%d",x); } 同理，我穿进去的是指针head，为什么就不能改变head的值[/quote] *var=3 你只是将3赋值给指针var指向的内容，var 指向的内容坑定就变了！指针的改变和指针指向内容的改变是不同的！

你要改变指针的指向，必须传二级指针或者一级指针的引用。 单单传一级指针只能改变指针所指向的内存区域的值。

改为 void add_node_to_head_2(NODE **head, NODE *insert) {     NODE *tmp = *head;     insert->next = tmp;     *head = insert;  调用 add_node_to_head_2(&head, insert); }  因为你是想改变指针指向的地址，单单只传指针是没用的，这样做最多只能改变指针内容，只有传入指针的指针，才能改变指针的指向。

我改变如下： void add_node_to_head_2(NODE *head,NODE *insert)//this function is NG { 	NODE *tmp = head; 	insert->next = tmp; 	*head = *insert; } 结果还是不行，打印结果成了死循环。 最后我请教了大神，改成这样就行了: void add_node_to_head_2(NODE **head,NODE *insert)//this function is NG { 	NODE *tmp = *head; 	insert->next = tmp; 	*head = insert; }

引用 1 楼 zycxnanwang 的回复:我来解释一波！ 首先你是用head指针作为形参，函数调用的时候 将会生成一个指针，把head地址上的内容赋给 生成指针，最后的时候你只是将insert的地址赋 给函数生成的指针，函数调用完，指针就delete 所以你的主函数里面的head指针还是指向原来的 地址，你调试可以验证一下！ 所以，我觉得你要想改变函数参数内容，最好用引用！  我所学的知识里，只要传指针给函数，然后就可以改变该指针所指的值，比如： int x =2; void change(int *var) { *var = 3; } int main() { change(&x) printf("%d",x); } 同理，我穿进去的是指针head，为什么就不能改变head的值


Question: Ds1302控制字在C语言中怎样生成的

函数在哪里调用 addr就在哪里给了值

void Ds1302Write(uchar addr, uchar dat) //函数声明 Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);//函数调用	  addr<===> WRITE_RTC_ADDR[n] dat<===>TIME[n]  函数调用时候，会用实参表达式，初始化形参变量


Question: 不理解指针的问题

大部分编译器对于常量区的字符串都是禁止进行写操作的。 只有堆栈上申请的字符串才能修改。

char *num="0"  num指向的内容是常量，不能改 式子等同于 const char *p="0";


Question: C语言怎么直接预览U盘根目录文件内的特定文件

先遍历，取出所有文件名，输出。

C语言遍历文件和目录 ： http://www.2cto.com/kf/201302/187924.html  遍历过程中记录你需要的文件


Question: 初学C程序一直过不去，求debug

char *p[50], *s[50], temp[50], x = '\o';  /*用一个数组来接收缓存区里的字符*/ 	int i = 0, type;  	printf("Direction: \nEnter a string of secret words that include numbers and words, \nwhich both less than 50. \nAnd end with Enter:\n");  	while ((temp[i] = getchar()) != '\n') 	{  		if ('0' <= temp[i]&&temp[i] <= '9') 		{ 			p[f] = &temp[i];  /*指针需要对应到具体字符的地址才行，不能全都指向temp的地址*/ 			cnp[f] = i + 1; 			f++; 		} 		else 		{ 			s[e]=&temp[i]; 			ctp[e] = i + 1; 			e++; 		} 		i++; 	} 你声明的指针数组p和s，里面的每一个数组元素都是指针，按照你的代码，这些指针全都指向的是temp的地址，当然输入会有问题了

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

哪儿过不去啊，注释的那部分吗，没注释的那些没问题啊

引用 4楼user-4 的回复:这个程序要实现什么功能呢对输入的数字和字母进行加密

这个程序要实现什么功能呢

引用 1楼flying_music 的回复:哪儿过不去啊，注释的那部分吗，没注释的那些没问题啊就是输入的部分，输入的数和字母进不到数组里


Question: C语言文件创建

你咋不用 CreateFile

把 / 改成 \ 就可以，


Question: 运行出错

printf 里的 %n 改成 %d

引用 1 楼 user-2 的回复:p_line_num没有初始化就使用了  int ch_num=0,line_num=0,p_line_num=0,ph_num=0; 改了之后也会运行报错


Question: C/C++新人求助STl 问题

可以正常编译，如果有逻辑问题，单步跟踪程序运行，观察分析原因


Question: 怎么用纯c做图像程序

有人推荐SDL

最简单的EasyX，兼容Turbo C绘图函数，用于VC。

仅供参考：#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdio.h> #include <stdlib.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     TextOut(hdc,10,10,"地球人都知道！",14);     MoveToEx(hdc,5,5,NULL);     LineTo(hdc,300,  5);     LineTo(hdc,300, 60);     LineTo(hdc,  5, 60);     LineTo(hdc,  5,  5);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getchar();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }


Question: 关于字符串的问题求大神解答

for(int j=0;j<2;j++)             {                 a[j]=itoa(b[j],str, 10);                 d[i][j]=a[j];                          }         d[i][0]=q[i];  d[i][0]重复赋值 15被覆盖掉了

话是没错，但是我弄了挺长时间，搞不清楚问题在哪，还请赐教了


Question: realloc分配新内存小于原来内存，有什么后果？

realloc()的源码哪儿来的？看注释明显不是官方版本啊

看一下realloc的实现源码就明白了： void *realloc(void *ptr, size_t size) { 	struct free_arena_header *ah; 	void *newptr; 	size_t oldsize;  	if (!ptr) 		return malloc(size);  	if (size == 0) { 		free(ptr); 		return NULL; 	}  	/* Add the obligatory arena header, and round up */ 	size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK;  	ah = (struct free_arena_header *) 	    ((struct arena_header *)ptr - 1);  	if (ah->a.size >= size && size >= (ah->a.size >> 2)) { 		/* This field is a good size already. */ 		return ptr; 	} else { 		/* Make me a new block.  This is kind of bogus; we should 		   be checking the following block to see if we can do an 		   in-place adjustment... fix that later. */  		oldsize = ah->a.size - sizeof(struct arena_header);  		newptr = malloc(size); 		memcpy(newptr, ptr, (size < oldsize) ? size : oldsize); 		free(ptr);  		return newptr; 	} } 从代码看，如果新分配的newsize小于之前的oldsize，那么也只拷贝newsize这么多，拷贝完之后就释放掉原来的ptr，返回新的newptr。这样，就会造成数据的截断，但并不会所谓“自由区域”或“野指针”。

realloc函数，如果原来的内存后面还有足够多剩余内存，或者，重新分配小于原来的大小，realloc还是返回原来内存的地址; 因此地址不会变化，但后面的区域成为自由区域，也就是常说的“野指针”。野指针地址在没有被重新使用和占用的情况下，值是不变的，你按照野指针强制访问，会得到原有的值。 但野指针地址内的值无法保障，如果你在realloc之后malloc一堆指针，那么无法保障这个野指针的值不变，可能会被重新占用。

这种问题 看源码是最好的方案 对提升c功底很有好处

有可能导致数据丢失。。

后果就是可能造成数据丢失，假如用calloc分配20个字节，写入20个字节的数据， 然后用realloc重新分配为10个字节，则之前写入的20个字节数据可能丢失后10个字节的数据。


Question: 关于TSP问题的遗传算法（C）的问题

0 107 241 190 124  80 316  76 152 157 283 133 113 297 228 129 348 276 188 150  65 341 184  67 221 169 108  45 167 107   0 148 137  88 127 336 183 134  95 254 180 101 234 175 176 265 199 182  67  42 278 271 146 251 105 191 139  79 241 148   0 374 171 259 509 317 217 232 491 312 280 391 412 349 422 356 355 204 182 435 417 292 424 116 337 273  77 190 137 374   0 202 234 222 192 248  42 117 287  79 107  38 121 152  86  68  70 137 151 239 135 137 242 165 228 205 124  88 171 202   0  61 392 202  46 160 319 112 163 322 240 232 314 287 238 155  65 366 300 175 307  57 220 121  97 80 127 259 234  61   0 386 141  72 167 351  55 157 331 272 226 362 296 232 164  85 375 249 147 301 118 188  60 185   316 336 509 222 392 386   0 233 438 254 202 439 235 254 210 187 313 266 154 282 321 298 168 249  95 437 190 314 435  76 183 317 192 202 141 233   0 213 188 272 193 131 302 233  98 344 289 177 216 141 346 108  57 190 245  43  81 243 152 134 217 248  46  72 438 213   0 206 365  89 209 368 286 278 360 333 284 201 111 412 321 221 353  72 266 132 111 157  95 232  42 160 167 254 188 206   0 159 220  57 149  80 132 193 127 100  28  95 193 241 131 169 200 161 189 163   283 254 491 117 319 351 202 272 365 159   0 404 176 106  79 161 165 141  95 187 254 103 279 215 117 359 216 308 322   133 180 312 287 112  55 439 193  89 220 404   0 210 384 325 279 415 349 285 217 138 428 310 200 354 169 241 112 238   113 101 280  79 163 157 235 131 209  57 176 210   0 186 117  75 231 165  81  85  92 230 184  74 150 208 104 158 206   297 234 391 107 322 331 254 302 368 149 106 384 186   0  69 191  59  35 125 167 255  44 309 245 169 327 246 335 288   228 175 412  38 240 272 210 233 286  80  79 325 117  69   0 122 122  56  56 108 175 113 240 176 125 280 177 266 243   129 176 349 121 232 226 187  98 278 132 161 279  75 191 122   0 244 178  66 160 161 235 118  62  92 277  55 155 275   348 265 422 152 314 362 313 344 360 193 165 415 231  59 122 244   0  66 178 198 286  77 362 287 228 358 299 380 319   276 199 356  86 287 296 266 289 333 127 141 349 165  35  56 178  66   0 112 132 220  79 296 232 181 292 233 314 253 188 182 355  68 238 232 154 177 284 100  95 285  81 125  56  66 178 112   0 128 167 169 179 120  69 283 121 213 281   150  67 204  70 155 164 282 216 201  28 187 217  85 167 108 160 198 132 128   0  88 211 269 159 197 172 189 182 135    65  42 182 137  65  85 321 141 111  95 254 138  92 255 175 161 286 220 167  88   0 299 229 104 236 110 149  97 108   341 278 435 151 366 375 298 346 412 193 103 428 230  44 113 235  77  79 169 211 299   0 353 289 213 371 290 379 332   184 271 417 239 300 249 168 108 321 241 279 310 184 309 240 118 362 296 179 269 229 353   0 121 162 345  80 189 342    67 146 292 135 175 147 249  57 221 131 215 200  74 245 176  62 287 232 120 159 104 289 121   0 154 220  41  93 218   221 251 424 137 307 301  95 190 353 169 117 354 150 169 125  92 228 181  69 197 236 213 162 154   0 352 147 247 350   169 105 116 242  57 118 437 245  72 200 359 169 208 327 280 277 358 292 283 172 110 371 345 220 352   0 265 178  39   108 191 337 165 220 188 190  43 266 161 216 241 104 246 177  55 299 233 121 189 149 290  80  41 147 265   0 124 263    45 139 273 228 121  60 314  81 132 189 308 112 158 335 266 155 380 314 213 182  97 379 189  93 247 178 124   0 199   167  79  77 205  97 185 435 243 111 163 322 238 206 288 243 275 319 253 281 135 108 332 342 218 350  39 263 199   0 您好，谢谢您的回复，data5里面放的是矩阵数据，我的解读是a[i][j]的数值是i城市到j城市的距离

你那个data5.txt里放的是什么啊？


Question: 杭电ACM1718，为什么不能AC？

调整了一下可以通过了，没有初始化

#include <stdio.h> #include <string.h>  struct stu  {  char num[9];  int score;  };   void main()  {  int n=0,k,rand;  struct stu st[1001],s;  while(scanf("%s",s.num)!=EOF)  {  while (1)  {   scanf("%s %d",st[n].num,&st[n].score);  if(strcmp(st[n].num,s.num)==0)  {  s.score=st[n].score;k=n;  }  if(strcmp(st[n].num,"0")==0&&st[n].score==0)  break;  n++;  }  n--; rand=n;  while(n>=0)  {  if(n!=k&&st[n].score<=s.score)  {  rand--;  }  n--;  }  printf("%d\n",rand+1);  }  } 改了，但是还是不对，我的思路是，找到比该人的成绩低的减一，不是加一

抱歉~打错字符了，应该是scanf("%s",s.num);不是scanf("%d",s.num);

你的字符数组scanf("%s",&s.num);都写错了，s.num本来就是地址，还需要取地址吗？应该是scanf("%d",s.num); 同时注意题目要求是“多组数据” ！！这个题目比较简单，我就不上代码了，来分析一下你的问题！       你的思路是:找出成绩比该人成绩高的人的个数然后再加1。       代码的具体实现可以通过排序(直接sort()最简单)，然后再循环遍历找到目标学号所对应的人，根据其下标就可以得出结果！还可以在读入数据的时候，将目标学号对应的分数记下来，然后再循环遍历记录比该人成绩高的学生的个数，然后都出结果！


Question: calloc分配后储存，如何用普通变量读取？

引用 4 楼 lm_whales 的回复:C更是只有指针可以和动态分配的内存相联系 可否总结为一句话，malloc calloc realloc分配的内存，只能由指针变量读取，不能用普通变量读取。 这句话没错吧？

引用 4 楼 lm_whales 的回复:C更是只有指针可以和动态分配的内存相联系 p1是指针变量，x是普通变量。 int x=0; int *p1=0; p1=calloc(10, sizeof(int)); *p1=1; printf("%p", p1); //p1是用calloc分配出来的指针。 printf("%p", &x); 此时&x必定不等于p1，我不能让x去读取p1位置的值吗？

C更是只有指针可以和动态分配的内存相联系

动态分配的内存，本身是没有名字的对象。 所谓普通变量，是有名字的对象，（或者有名字的引用）。 二者联系的方法，通常就是，用指针---有名对象---- 指向该对象  C++可以对指针加以包装，从而隐藏他是个指针的事实。 例如 stl 的 vector ,sting ,以及 share_ptr. PS： C++动态分配的对象，一般使用指针指向它， 而不是引用跟他绑定。  因为C++引用 都是要绑定明确的对象的， 一般是不需要释放内存的，引用的对象释放内存后， 引用本身的存在，就和野指针类似， 变得不可思议了，这也不符合引用的语义。 C++没有空引用，所有引用  都是在定义的时候，绑定到一个对象上的。 所以不适合绑定到动态分配内存的对象上。

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

仅供参考 #include <stdio.h> #include <stdlib.h> int main(void) {     int *p = NULL; 	int *q = NULL; 	int i = 0;     p = (int*)calloc(10, sizeof(int)); 	for(i=0; i<10; i++){ 		p[i] = i+1; 	} 	q = p; 	while(q != p+10){ 		printf("%d ", *q); 		q++; 	}     return 0; }

C 定义一个某类型名字，和一个固定地址相关的方法是 用宏定义处理  例如已知 0xA0000000 是直接写屏地址(绘制图形模式).  可以这么定义 #define  directDraw   * (char *)( 0xA0000000 ) 定义一个 char 类型的 地址为0xA0000000 的标识符（变量）  或者  #define Cols   1920  #define Rows 1080 typedef Screen COLOREF [Rows][Cols]; #define directDraw *(Screen*)( 0xA0000000 ) 这就相当于 定义一个地址为  0xA0000000的，名为 directDraw COLOREF 类型的二维数组了 但这不是定义变量的方法，只是一个变通的方法。  这种方法的缺点是，如果这个地址，不是保留地址（固定用途的内存区域）。 那么，可能和系统分配的变量，有冲突 从而造成，程序逻辑紊乱。破坏程序的正常运行。

字符串的确特殊一点，C中，字符串是字符[/color[color=#FF0000]]数组类型 因为C数组和指针关系比较紧密，所以很多时候，用指针 来处理字符串 实际上，C也经常用指针处理数组。 至于说，普通变量不能自己把命名和地址联系起来 因为，C语言，变量的地址是系统分配的。 程序员只负责给变量起个名字，定义一个类型，乃至初始化， 通常，并不能直接把变量名，和固定的内存相联系 动态分配的内存（堆内存），才是程序员可以分配的内存 （但是程序员依然没法给他命名，所以其中的对象，是无名对象） PS： 实际上汇编语言，大多也不会把变量和地址直接关联 但是汇编语言，可以定义数据区，代码区， 这样，数据区内部的变量，相对地址是固定的。 有时候，甚至可以绝对定位数据区，代码区的地址， 从而实现数据区的变量，绝对定位的目的（这样变量名，和地址就一一对应了）

引用 14 楼 qq_16774199 的回复:[quote=引用 12 楼 Happy_BC 的回复:] 个人认为不能使用普通变量读取动态分配， 因为普通变量在编译时已经确定地址， 动态获取的内存空间由操作系统分配，操作系统不会把已经使用的内存再分配吧，  因为不重叠， 所以不可以。（局部变量虽然是动态分配的，但系统同样会让局部变量和calloc分配分间不重叠）  我就是想把已确定的普通变量地址给改了，不过看起来C语言是不能让我为所欲为。[/quote]  因为变量地址编译后是在指令中的。如果可以修改代码段，就可以修改指令中的地址了。 C语言可以通过指针访问所有4GB的空间（我也是新手，刚才试了下访问任意内存，发现能通过编译）所以理论上C语言可以修改代码。  当然也就可以修改编译到指令中的地址了。 比如：  int * p = (int *)10;   然后再使用*p    这种方式就可以访问任意4GB空间了。但是因为代码运行在第3层，没有权限（保护模式：一些重要内存，代码段等没权限的访问不了），windows会弹出异常！ 所以不是C语言的问题，是系统保护的问题。

引用 14 楼 qq_16774199 的回复:[quote=引用 12 楼 Happy_BC 的回复:] 个人认为不能使用普通变量读取动态分配， 因为普通变量在编译时已经确定地址， 动态获取的内存空间由操作系统分配，操作系统不会把已经使用的内存再分配吧，  因为不重叠， 所以不可以。（局部变量虽然是动态分配的，但系统同样会让局部变量和calloc分配分间不重叠）  我就是想把已确定的普通变量地址给改了，不过看起来C语言是不能让我为所欲为。[/quote]  你是想int a [10]，然后calloc一个空间，让a变量代表这个空间吗？...就算能编译过，a变量可能还是只有10个元素，万一calloc的长度不是10个元素。。。

引用 13 楼 qq_16774199 的回复:[quote=引用 11 楼 u012947309 的回复:] [quote=引用 楼主 qq_16774199 的回复:] …… 变量过了周期自己就release了，calloc得自己release。不然一直在内存里，系统不管的。  变量过了周期release，calloc过程结束也应该release吧？比如我最开始发的代码虽没有free，但也会自动free吧？[/quote]  这个周期可能比较大。。。程序大了或者内容多了就不好查了。慢慢就习惯了用完就release了。

引用 12 楼 Happy_BC 的回复:个人认为不能使用普通变量读取动态分配， 因为普通变量在编译时已经确定地址， 动态获取的内存空间由操作系统分配，操作系统不会把已经使用的内存再分配吧，  因为不重叠， 所以不可以。（局部变量虽然是动态分配的，但系统同样会让局部变量和calloc分配分间不重叠）  我就是想把已确定的普通变量地址给改了，不过看起来C语言是不能让我为所欲为。

引用 11 楼 u012947309 的回复:[quote=引用 楼主 qq_16774199 的回复:] …… 变量过了周期自己就release了，calloc得自己release。不然一直在内存里，系统不管的。  变量过了周期release，calloc过程结束也应该release吧？比如我最开始发的代码虽没有free，但也会自动free吧？

引用 楼主 qq_16774199 的回复:请教，calloc分配内存后，把数字用（*指针）储存到内存里，然后用（*指针）读取这个数字。可是如何用普通变量读取这个内存位置的内容？难道为了读取calloc分配的内存里储存的第1、2、3组数字，只能用*p1 *(p1+1) *(p1+2)。   #include <stdio.h> #include <stdlib.h> int main(void) { 	int *p1=0; 	int x=0; 	p1=calloc(10, sizeof(int)); 	*p1=1; 	*(p1+1)=2; 	return 0; }    是的呀，普通变量，你or系统知道他指向某个内存空间，这个变量就是这一段内存空间的名字。 int a =10; 系统在内存中开辟了一个4个字节32位长度的空间。命名为a。内存空间存了10这个数。  calloc malloc之类的，在系统内部动态开辟一个空间。但是没有给变量名。变量开辟是编译时候就开辟好了，不是运行时候再开辟。 int *p1=calloc(10, sizeof(int)); 这是相当于开辟了两串内存空间，一串空间是calloc 10 sizeof int； 另一个空间名叫p1，是int *类型，这串内存存的是calloc空间的首地址。 系统根本不知道calloc开辟的那串空间在哪，只知道你让p1存了那串空间的地址。 而且系统不知道calloc那串空间所代表的数据的类型和长度。 系统不知道访问这串空间要隔着一个int为步伐还是以short为步伐。而且不知道这传连续的空间到哪停止。 所以需要p+1 p+2 这种方式读取。哪怕p+11系统也会去读，至于这么位置有没有数据，是什么，就不知道了。 系统只知道你让他读p+1是p这个位置往后1个单位（int）的位置。 所以用calloc的一定记得长度。 另外，因为calloc开辟的空间不像开辟一个变量空间。 变量过了周期自己就release了，calloc得自己release。不然一直在内存里，系统不管的。

引用 9 楼 qq_16774199 的回复:整形、浮点、布尔、字符类型写一章，不易察觉字符串对C来说是整型。 字符串?

引用 7 楼 lm_whales 的回复:[quote=引用 6 楼 qq_16774199 的回复:] [quote=引用 4 楼 lm_whales 的回复:] C更是只有指针可以和动态分配的内存相联系 可否总结为一句话，malloc calloc realloc分配的内存，只能由指针变量读取，不能用普通变量读取。 这句话没错吧？[/quote] 不叫读取，叫记录。指针可以表示地址。  用指针记录一下地址，下次就可以找到他了 可以读，也可以写。  有名字的对象，可以用名字加以区分，也可以用地址加以区分。  没有名字的对象，只好用地址加以区分， 因此，用指针储存，它的地址，就可以随时使用它了。  指针本来就属于普通变量。 不过不是 整型，浮点型这一类表示数学量的类型。 ----bool，也是一种数学类型，c最初没有独立的bool,C++ 有，C99标准也有了-----  也不是记录 自然语言的字符，字符串类型----C中，字符属于整型------ 而是表示计算机本身 的内存地址的类型。  [/quote]  许多C语言书指针单独写一章，初学者误以为指针是另外一种东西。 整形、浮点、布尔、字符类型写一章，不易察觉字符串对C来说是整型。

其实如果，编程语言没有指针类型，也是一样可以操作内存中的数据。 只是没有有指针的语言方便而已。

引用 6 楼 qq_16774199 的回复:[quote=引用 4 楼 lm_whales 的回复:] C更是只有指针可以和动态分配的内存相联系 可否总结为一句话，malloc calloc realloc分配的内存，只能由指针变量读取，不能用普通变量读取。 这句话没错吧？[/quote] 不叫读取，叫记录。指针可以表示地址。  用指针记录一下地址，下次就可以找到他了 可以读，也可以写。  有名字的对象，可以用名字加以区分，也可以用地址加以区分。  没有名字的对象，只好用地址加以区分， 因此，用指针储存，它的地址，就可以随时使用它了。  指针本来就属于普通变量。 不过不是 整型，浮点型这一类表示数学量的类型。 ----bool，也是一种数学类型，c最初没有独立的bool,C++ 有，C99标准也有了-----  也不是记录 自然语言的字符，字符串类型----C中，字符属于整型------ 而是表示计算机本身 的内存地址的类型。


Question: 数据结构 线性表

#include<stdio.h> #include<stdlib.h>  typedef int datatype; #define MAXLEN 20  typedef struct { 	datatype data[MAXLEN]; 	int last; }SeqList;  SeqList* CreatSeqList() { 	int x, i = 0; 	SeqList *P = (SeqList *)malloc(sizeof(SeqList)); 	P->last = 0; 	scanf("%d", &x); 	while (x != -1) 	{ 		P->data[i] = x; 		i++; 		P->last++; 		scanf("%d", &x); 	} 	return P; }  void ShowSeqList(SeqList* L) { 	int i; 	for (i = 0; i<L->last; i++) 		printf("%d ", L->data[i]); }  int main() { 	SeqList *L; 	L = CreatSeqList(); 	ShowSeqList(L); 	return 1; }


Question: c语言简易英文文本编辑器的程序，运行有错误

这是主函数的调佣情况 	case 2:system("cls"); 			Welcome(); 			printf("\t\t\t请输入您需要删除的字符或字符串："); 			getchar(); 			gets(str2); 			Searchtext(str2,temp); 			Deletetext(str2); 			Displaytext(); 			printf("按回车键继续……"); 			getchar(); 			getchar(); 			system("cls"); 			break;

怎么调试我知道的。可是我就想知道是这个函数错了还是怎么，其它的函数调用显示文本函数时显示出来的文本也是不正确的， void Displaytext() {    	int i,j; 	 	Linklist *p; 	p=head->next; 	system("cls"); 	Welcome(); 	printf("当前文本的内容是：\n");     FILE *fp; 	if((fp=fopen("bcd.txt","w"))==NULL) 	{ 		printf("No open!\n"); 		exit(0); 	}  	for(j=0;p!=NULL;j++)//控制行 	{ 		for(i=0;(i<80)&&(p->data[i])!='#';i++)//控制列 		{ 			printf("%c",p->data[i]); 			fprintf(fp,"%c",p->data[i]);	 		} 		p=p->next; } 	fclose(fp); }

Windows： 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。 Linux： 进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

删除we之后的结果如下，出现了不知道为什么的错误，


Question: c语言中非正数就是代表假吗

早期的C语言标准中并没有规定bool类型以及true和false的值，这些值都是程序员自己用#define或者enum自己定义的，一般定义true为1，false为0。而如果着眼于C语言标准，总结一下其中的“假”有以下几种形式： 1. 通过逻辑运算符得到的结果，可以是真或者假。例如 (a < 3) && ( a > 0) 2. 通过关系运算符得到的结果，可以是真或者假。例如 a < 3 3. 还有一种就是更自由的形式。例如 char *p = (char *) malloc(10); if (fp) {} 这里fp直接就被用来作为逻辑值了。其实这里的fp等价于fp != NULL。 也就是这种情况下一般是“零值”（整数0，逻辑表达式或者关系表达式的“假”，或者是空指针，这些都可以看做C语言中的零值）被当做假，非零值就是真。  如果需要确切知道真或者假对应的整型值是0，整数还是负数，可以自己编个程序打印出来测试一下就可以了，例如： int a = 4; printf("%d\n", a < 3);  不同编译器的结果可能不同。

c语言中除了0其他都是真…

0为假，其余为真。

非0为真，0为假。 记住这句话就好了 还有 !8  !5是假。 因为8 和5 是真，他们的非就是假啦。

0才是假，而不是负数

是的，是假  但 ~运算符 则不一定

C 中 !(-1),!(-2),!(1),!(2) 都是 假 ，也就是 0 !0 为真 -1,-2,1,2 都是真（作条件时，相当于转换为 1）,0 为假   浮点数，也跟整数相似

C中，非0 代表真，0 代表假


Question: 关于自动退栈

我现在还不知道 hello 的长度等于多少，我把它交给 1 + mystrlen(ello) 我现在还不知道 ello 的长度等于多少，我把它交给 1 + mystrlen(llo) 我现在还不知道 llo 的长度等于多少，我把它交给 1 + mystrlen(lo) 我现在还不知道 lo 的长度等于多少，我把它交给 1 + mystrlen(o) 我现在还不知道 o 的长度等于多少，我把它交给 1 + mystrlen() 递归到了"\0"串了，返回空串的长度等于0，这个出口很重要，避免了函数的死循环 现在我知道 o 的长度等于 1 现在我知道 lo 的长度等于 2 现在我知道 llo 的长度等于 3 现在我知道 ello 的长度等于 4 现在我知道 hello 的长度等于 5

// Note:Your choice is C++ IDE #include <iostream> using namespace std;  int mystrlen(const char *s) { 	if(*s=='\0') 	{ 		printf("递归到了\"\\0\"串了，返回空串的长度等于0，这个出口很重要，避免了函数的死循环\n"); 		return 0; 	} 	printf("我现在还不知道 %s 的长度等于多少，我把它交给 1 + mystrlen(%s)\n",s,s+1); 	int len=mystrlen(s+1)+1; 	printf("现在我知道 %s 的长度等于 %d\n",s,len); 	return len; } int main() { 	mystrlen("hello");          return 0; }

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

单步跟踪程序运行是最好判断你理解正确与否的方法

你要理解strlen(s+1)是什么？ 第一次调用：strlen("ello") 第五次返回：3+1=4 第二次调用：strlen("llo") 第四次返回：2+1=3 第三次调用：strlen("lo") 第三次返回：1+1=2 第四次调用：strlen("o")  第二次返回：0+1=1 第五次调用：strlen("\0") 第一次返回：0 最后return (*s ? strlen(s+1) +1 :0) ;// *s='H'，所以返回4+1=5


Question: 大家好，请问C语言怎么判断浏览器打开的网址？

引用 11 楼 yyxgs 的回复:[quote=引用 10 楼 u010165006 的回复:] [quote=引用 3 楼 yyxgs 的回复:] [quote=引用 1 楼 u010165006 的回复:] 绿坝不是有类似的功能吗？应该是Hook钩子技术吧。  获取窗口句柄然后判断标题行不行呢?[/quote]  如果网址还没有打开，是没有标题的吧[/quote]  这个我已经解决了，但是我想自己打开本地的网页还得自己做相似的网页，所以算了。。[/quote]  做个最简单的测试网页。

引用 10 楼 u010165006 的回复:[quote=引用 3 楼 yyxgs 的回复:] [quote=引用 1 楼 u010165006 的回复:] 绿坝不是有类似的功能吗？应该是Hook钩子技术吧。  获取窗口句柄然后判断标题行不行呢?[/quote]  如果网址还没有打开，是没有标题的吧[/quote]  这个我已经解决了，但是我想自己打开本地的网页还得自己做相似的网页，所以算了。。

引用 3 楼 yyxgs 的回复:[quote=引用 1 楼 u010165006 的回复:] 绿坝不是有类似的功能吗？应该是Hook钩子技术吧。  获取窗口句柄然后判断标题行不行呢?[/quote]  如果网址还没有打开，是没有标题的吧

明天等老师、高手教你方法，应该不是很简单。

引用 6 楼 u010165006 的回复:[quote=引用 5 楼 yyxgs 的回复:] [quote=引用 4 楼 u010165006 的回复:] 你不会自己想做这个吧？应该不容易吧，改Windows的hosts配置文件不知能否达到目的。 你的Java学到哪里了？  接口，我现在急需要这个判断浏览器打开的网址，然后转到我本地的网页的程序。 请问你知道怎么编程获取浏览器的窗口句柄吗?[/quote]  查找窗口（FindWindow、FindWindowEx）？ [/quote]   知道了，非常感谢！

引用 6 楼 u010165006 的回复:[quote=引用 5 楼 yyxgs 的回复:] [quote=引用 4 楼 u010165006 的回复:] 你不会自己想做这个吧？应该不容易吧，改Windows的hosts配置文件不知能否达到目的。 你的Java学到哪里了？  接口，我现在急需要这个判断浏览器打开的网址，然后转到我本地的网页的程序。 请问你知道怎么编程获取浏览器的窗口句柄吗?[/quote]  查找窗口（FindWindow、FindWindowEx）？ [/quote]  关键是我也不知道类名这些的，参数不知道怎么给。。

引用 5 楼 yyxgs 的回复:[quote=引用 4 楼 u010165006 的回复:] 你不会自己想做这个吧？应该不容易吧，改Windows的hosts配置文件不知能否达到目的。 你的Java学到哪里了？  接口，我现在急需要这个判断浏览器打开的网址，然后转到我本地的网页的程序。 请问你知道怎么编程获取浏览器的窗口句柄吗?[/quote]  查找窗口（FindWindow、FindWindowEx）？

引用 4 楼 u010165006 的回复:你不会自己想做这个吧？应该不容易吧，改Windows的hosts配置文件不知能否达到目的。 你的Java学到哪里了？  接口，我现在急需要这个判断浏览器打开的网址，然后转到我本地的网页的程序。 请问你知道怎么编程获取浏览器的窗口句柄吗?

引用 1 楼 u010165006 的回复:绿坝不是有类似的功能吗？应该是Hook钩子技术吧。  获取窗口句柄然后判断标题行不行呢?

引用 1 楼 u010165006 的回复:绿坝不是有类似的功能吗？应该是Hook钩子技术吧。  好吧，看来挺麻烦。

绿坝不是有类似的功能吗？应该是Hook钩子技术吧。


Question: 关于函数指针的理解

谢谢各位的回复

p();  调用函数，函数指针调用函数是不需要解引用， 但不是：不可以解引用  所以有了(*p)()的出现。。。  解引用还是函数指针，有点特殊  (**p)() 如何解释？？、  解引用两次， *p是函数指针，* *p 还是函数指针  ***p依然是函数指针

没什么奇怪啊，函数指针解引了还是函数指针  上面式子还等于 ***************p

引用 2 楼 Happy_BC 的回复:试了下，int * q;         q=(int *)p;     然后发现*q有一个值,  这就是指令数据吗？ 对，就是那么个意思，但不一定是max函数的代码，跟编译器的实现有关，可能放一条跳转语句，跳转到max函数入口

指针是一种特殊的数据类型，你可以理解它有很多“子类型”，也就是int*和double*是不一样的，指向函数的指针也是不一样的，这里说的不一样不是值不一样，而是类型不一样，类型不一样就体现在运算符作用在它身上时效果不一样，你对一个int型指针解引用，也就是*p得到的就是指向的那个int变量，但你对一个指向函数的指针解引用得到的还是那个入口地址 就本例来说，你定义了一个函数，这个函数的入口地址假如是0x0001，那p作为一种指针，指向这个函数，也就是说p里面放的是0x0001，但p的地址（&p）不是，p是一个指针变量，它的地址是编译器分配的，比如是0x0011，也就是说0x0011的地址内存里放着一个0x0001，而*p该是什么呢？对应int型指针，那是里面放的int变量，但函数指针不是，函数入口放的是代码，怎么能把代码给你呢，所以编译器仍然把*p当做p来使用，那个max也是一样，不过max不是一个变量，只有变量才可以取地址&，但编译器也没有报错，仍然把它当做max来处理 总之，&p，p，*p的关系是由p的类型决定的，至于为什么不让&max这种东西报错，那就是编译器实现的人考虑的问题了，还有，理解指针必须和内存联系起来，没有内存的概念，很难理解透彻的


Question: 问一个C下面scanf的问题……

缓冲区中没内容才会等待输入，有内容就直接取了

引用 1 楼 qq423399099 的回复:如果输入缓冲区内有数据，scanf是不会等待输入的。  新知识get。

如果输入缓冲区内有数据，scanf是不会等待输入的。


Question: C语言 倒计时

我知道问题出在哪里了，我只有移动光标才会跳出那个move函数，才会再执行一遍纪录时间的函数。 但是有一个小问题，请教一下。C语言有没有语句可以判断用户此时是没有输入任何字符的呢？

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h>     #include <process.h>     #define  MYVOID             void #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define ARRSIZE(x) (sizeof(x)/sizeof(x[0])) #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; char logstr[16000]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;       if (NULL==pszFmt||0==pszFmt[0]) return;     if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0;     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }             flog=fopen(logfilename1,"a");             if (NULL==flog) return;         }         fclose(flog);     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int No_Loop=0; MYVOID testThread(void *pcn) {     int n,i;      n=(int)pcn;     i=0;     while (1) {         sleep_ms(1000);         Log("in testThread %d:i==%ds\n",n,++i);         if (i>=5) No_Loop=1;     } } int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL);     pthread_t threads[1];     int threadsN;     int rc; #endif     Log("=========BEGIN==================\n"); #ifdef WIN32     _beginthread((void(__cdecl *)(void *))testThread,0,(void *)1); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,testThread,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif     i=0;     while (1) {         sleep_ms(100);         Log("in main:i==%d\n",++i);         if (No_Loop==1) break;//     }     Log("=========END====================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //2012-06-14 16:27:21.500 =========BEGIN================== //2012-06-14 16:27:21.609 in main:i==1 //2012-06-14 16:27:21.718 in main:i==2 //2012-06-14 16:27:21.828 in main:i==3 //2012-06-14 16:27:21.937 in main:i==4 //2012-06-14 16:27:22.046 in main:i==5 //2012-06-14 16:27:22.156 in main:i==6 //2012-06-14 16:27:22.265 in main:i==7 //2012-06-14 16:27:22.375 in main:i==8 //2012-06-14 16:27:22.484 in main:i==9 //2012-06-14 16:27:22.500 in testThread 1:i==1s //2012-06-14 16:27:22.593 in main:i==10 //2012-06-14 16:27:22.703 in main:i==11 //2012-06-14 16:27:22.812 in main:i==12 //2012-06-14 16:27:22.921 in main:i==13 //2012-06-14 16:27:23.031 in main:i==14 //2012-06-14 16:27:23.140 in main:i==15 //2012-06-14 16:27:23.250 in main:i==16 //2012-06-14 16:27:23.359 in main:i==17 //2012-06-14 16:27:23.468 in main:i==18 //2012-06-14 16:27:23.500 in testThread 1:i==2s //2012-06-14 16:27:23.578 in main:i==19 //2012-06-14 16:27:23.687 in main:i==20 //2012-06-14 16:27:23.796 in main:i==21 //2012-06-14 16:27:23.906 in main:i==22 //2012-06-14 16:27:24.015 in main:i==23 //2012-06-14 16:27:24.125 in main:i==24 //2012-06-14 16:27:24.234 in main:i==25 //2012-06-14 16:27:24.343 in main:i==26 //2012-06-14 16:27:24.453 in main:i==27 //2012-06-14 16:27:24.500 in testThread 1:i==3s //2012-06-14 16:27:24.562 in main:i==28 //2012-06-14 16:27:24.671 in main:i==29 //2012-06-14 16:27:24.781 in main:i==30 //2012-06-14 16:27:24.890 in main:i==31 //2012-06-14 16:27:25.000 in main:i==32 //2012-06-14 16:27:25.109 in main:i==33 //2012-06-14 16:27:25.218 in main:i==34 //2012-06-14 16:27:25.328 in main:i==35 //2012-06-14 16:27:25.437 in main:i==36 //2012-06-14 16:27:25.500 in testThread 1:i==4s //2012-06-14 16:27:25.546 in main:i==37 //2012-06-14 16:27:25.656 in main:i==38 //2012-06-14 16:27:25.765 in main:i==39 //2012-06-14 16:27:25.875 in main:i==40 //2012-06-14 16:27:25.984 in main:i==41 //2012-06-14 16:27:26.093 in main:i==42 //2012-06-14 16:27:26.203 in main:i==43 //2012-06-14 16:27:26.312 in main:i==44 //2012-06-14 16:27:26.421 in main:i==45 //2012-06-14 16:27:26.500 in testThread 1:i==5s //2012-06-14 16:27:26.531 in main:i==46 //2012-06-14 16:27:26.531 =========END====================


Question: 用c语言写一个登陆的界面遇到的问题

查阅MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx


Question: 保留小数问题

不用整数或浮点数来读, 用字符串来读然后输出就是原样了

scanf("%c",&a[i][j]);

定义一个字符串数组，先将数赋值给数组元素 然后输出字符串数组

#include<stdio.h> int main() { 	int i,j,N; 	scanf("%d",&N);  	char a[10][40]={'0'}; 	 	for(i=0;i<N;i++){ 		for(j=0;j<10;j++){ 			scanf("%s",&a[i][j]); 		} 	//	getchar(); 	} 	for(i=0;i<N;i++){ 		for(j=40;j>0;j--){ 			if(a[i][j]!=' ' && a[i][j]!='0' && (a[i][j]>'9' || a[i][j]<'0')) 				printf("%s",a[i][j]); 			printf("\n"); 		} 	}  	return 0; } 这是我的程序，但是一直在输入状态


Question: 请问别人用C语言写了一个小工具，可是每次都要输入他生成的验证码，还是图片里面那种很杂乱的，很难看清楚，请问汇编可以反汇编这个程序，跳过这个输入验证码的步骤吗？

去看雪论坛逛逛。

理论上用跳转指令可以绕过这个过程，或者改变验证过程的结果，结果为不通过时继续。

IDA, OD分析去吧．

理论上可以，实践中要看它加密的复杂度了，可能很简单，分分钟搞定，也可能很复杂，比如把关键部分代码转换为虚拟机程序，这种就比较难搞。一般来说，如果没用加密狗，或者联网验证，都可以搞定。


Question: 请问大家，Windows上我用C语言分配一段内存空间，输出的这些地址都是虚拟地址吗？那我要找到真实地址怎么找呢？

使用WinIO.sys

已知一个虚拟地址0x01AF5518, 则转换的过程如下:  注意: *这里讨论的以Windows下普通模式分页的情况, 也就是2级页表的情况*  1.首先把虚拟地址拆分成3个部分(低12位, 中10位, 高10位), 换成2进制如下: 　　-> 0000 0001 1010 1111 0101 0101 0001 1000   　　按照10, 10, 12的位数重新排列后 　　-> (页目录索引)00 000 00110, (页表项索引)10 1111 0101, (偏移)0101 0001 1000  　　换算成十六进制后可以得到如下结果 　　页目录索引 = 6, 页表项索引 = 0x2f5 , 偏移 = 0x518  2.	根据当前的CR3寄存器中的物理地址定位页目录表基址 　　Cr3中存放的是物理地址, 这个物理地址指向进程的页目录表基址, 由此可以得到 　　页目录表基址(PDE) = Cr3 = 0xAA0E5000  3. 计算页表项的地址 　　页表地址存放在页目录表(PDE)中的第6个项目中, 也就是 　　[0xAA0E5000 + 4 * 6] = [0xAA0E5018] = 0x3D955867, 其中0x00000867为该页表属性值, PTE = 0x3D955000	  3.	计算页面物理地址 　　我们要找的页面在这个页表中的第0x2f5项, 所以虚拟地址所在的页的物理地址为 　　[0x3D955000 + 0x2f5 * 4] = [0x3D955BD4] =  　　假设[0x3D955BD4] = 0x7095e847, 页面的物理地址 x0x7095e000, 0x00000847表示的是页面属性  4.	计算最终的物理地址 　　由虚拟地址分离的偏移可以计算出最终的物理地址为  　　0x7095E000 + 0x00000518 = 0x7095E518.


Question: c语言与与hmi的串口通信（232）不能正确实现功能，求助

仅供参考：void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }


Question: 二叉树的遍历

看来c语言真该好好的复习复习了，谢谢！

1.CreateBiTree函数应该传二级指针或者一级指针的引用才行 2.第23行T == NULL;应该是*T = NULL;   #include<stdio.h> #include<stdlib.h> typedef struct BiTNode{ 	char data; 	struct BiTNode *lchild, *rchild; }BiTNode, *BiTree;  void CreateBiTree(BiTNode **T); int  PreOrderTraverse(BiTNode *T);  int main(){ 	BiTNode *T; 	CreateBiTree(&T); 	PreOrderTraverse(T); }  void CreateBiTree(BiTNode **T){ 	char value; 	printf("请输入结点的值"); 	scanf("%c", &value); 	getchar(); 	if (value == '0'){ 		*T = NULL; 	} 	else{ 		*T = (BiTNode*)malloc(sizeof(BiTNode)); 		(*T)->data = value; 		CreateBiTree(&(*T)->lchild); 		CreateBiTree(&(*T)->rchild); 	}  }  int  PreOrderTraverse(BiTNode *T){ 	if (T == NULL){ 		return 0; 	} 	else{ 		printf("%c", T->data); 		PreOrderTraverse(T->lchild); 		PreOrderTraverse(T->rchild); 	} }