Question: 很尴尬的问题

引用 4 楼 qcx1221 的回复:[quote=引用 2 楼 qq423399099 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  请问版主能否在博客出波专门的教程？ 新手完全不懂以上操作。 比如程序员必备技能解说。 [/quote] 赵4老师可以

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

只帮你改了语法问题：  typedef struct yuangong {  	int hao; 	char name[20]; 	int age; 	int worktime; char sex[5]; char hunyin[10]; int grade; int wage; char tired[5]; }Yuangong; typedef struct LNode { 	Yuangong date; 	struct LNode *next; }LNode; int kouling(); int menu(LNode*); int chuangjian(LNode *head); //创建 int chuangjian(LNode *head) { 	char choice; 	Yuangong a; 	LNode *H,*s; 	s=head; 	while(1) 	{ 		printf("请输入员工号\n"); 		scanf("%d",&a.hao); 		printf("请输入姓名\n"); 		scanf("%s",a.name); 		printf("请输入年龄\n"); 		scanf("%d",&a.age); 		printf("请输入工龄\n"); 		scanf("%d",&a.worktime); 		printf("请输入性别\n"); 		scanf("%s",a.sex); 		printf("请输入婚姻状况\n"); 		scanf("%s",a.hunyin); 		printf("请输入级别\n"); 		scanf("%d",&a.grade); 		printf("请输入工资\n"); 		scanf("%d",&a.wage); 		printf("请输入是否在职\n"); 		scanf("%s",a.tired); 		H=(LNode *)malloc(sizeof(LNode)); 		if(H==NULL)return 0; 		H->date=a; 		H->next=NULL; 		s->next=H; 		s=H;  		printf("您想继续吗?(y/n)\n"); 		scanf(" %c",&choice); 		if(choice=='Y'||choice=='y')//决定是否继续此选项 		{ 			continue; 		} 		else 		{ 			system("cls"); 			menu(head); 		} 	} 	return 0;      } //显示全部 int liulan(LNode *head) { 	LNode *p; 	p=head; 	system("cls"); 	//printf("＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊\n"); 	//printf("＊      ＊      ＊      ＊员工信息表            ＊      ＊      ＊        ＊\n"); 	printf("\t\t\t\t员工信息表\n"); 	printf("员工号");  	printf("\t姓名"); 	printf("\t年龄"); 	printf("\t工龄"); 	printf("\t性别"); 	printf("\t婚姻状况"); 	printf("\t级别"); 	printf("\t工资"); 	printf("\t是否在职\n");  	while(p->next!=NULL) 	{ 		p=p->next; 		printf("%d",p->date.hao); 		printf("%6s",p->date.name); 		printf("\t%-3d",p->date.age); 		printf("\t%-2d",p->date.worktime); 		printf("\t%2s",p->date.sex); 		printf("\t%4s",p->date.hunyin); 		printf("\t\t%-1d",p->date.grade); 		printf("\t%-5d",p->date.wage); 		printf("\t%2s\n",p->date.tired);  	} 	system("pause"); 	menu(head);  	return 0;  } //查询 int chaxun(LNode *head) { 	int i,m=0; 	LNode *s; 	char a[20]; 	s=head; 	printf("请输入要查询员工的姓名："); 	scanf("%s",&a); 	while(s->next) 	{ 		s=s->next; 		for(i=0;s->date.name[i]!='\0'&&a[i]!='\0';i++) 		{ 			if(s->date.name[i]==a[i]) 			{ 				m=1; 				continue; 			} 			else 			{ 				m=0; 				break; 			}  		} 		if(m==1) 		{ 			printf("员工号"); 			printf("\t姓名"); 			printf("\t年龄"); 			printf("\t工龄"); 			printf("\t性别"); 			printf("\t婚姻状况"); 			printf("\t级别"); 			printf("\t工资"); 			printf("\t是否在职\n"); 			printf("%d",s->date.hao); 			printf("%6s",s->date.name); 			printf("\t%-3d",s->date.age); 			printf("\t%-2d",s->date.worktime); 			printf("\t%2s",s->date.sex); 			printf("\t%4s",s->date.hunyin); 			printf("\t\t%-1d",s->date.grade); 			printf("\t%-5d",s->date.wage); 			printf("\t%2s\n",s->date.tired); 			system("pause"); 			menu(head); 		}    	} 	if(m==0) 	{ 		printf("对不起，没有你输入叫%s员工！",a); 		system("pause"); 		menu(head); 	} 	return 0;  } //修改 int xiugai(LNode *head) {  	LNode *s; 	int  a; 	static int b=2; 	s=head; 	printf("请输入要修改员工号："); 	scanf("%d",&a); 	while(s->date.hao!=a) 	{  		s=s->next; 		if(s==NULL) 		{ 			printf("没有这个员工\n"); 			system("pause"); 			xiugai(head); 		}   	} 	if(s!=NULL) 	{ 		printf("请输入新员工号\n"); 		scanf("%d",&s->date.hao); 		printf("请输入姓名\n"); 		scanf("%s",s->date.name); 		printf("请输入年龄\n"); 		scanf("%d",&s->date.age); 		printf("请输入工龄\n"); 		scanf("%d",&s->date.worktime); 		printf("请输入性别\n"); 		scanf("%s",s->date.sex); 		printf("请输入婚姻状况\n"); 		scanf("%s",s->date.hunyin); 		printf("请输入级别\n"); 		scanf("%d",&s->date.grade); 		printf("请输入工资\n"); 		scanf("%d",&s->date.wage); 		printf("请输入是否在职\n"); 		scanf("%s",s->date.tired); 		printf("修改成功\n"); 		system("pause"); 		menu(head);  	} 	else  	{ 		printf("没有你要找的员工！"); 		system("pause"); 		menu(head); 	}  	return 0; } //添加 int tianjia(LNode *head) { 	int a,i=0; 	LNode *s,*p; 	s=head; 	p=(LNode *)malloc(sizeof(LNode)); 	if(p==NULL)return 0; 	printf("请输入员工号\n"); 	scanf("%d",&p->date.hao); 	printf("请输入姓名\n"); 	scanf("%s",p->date.name); 	printf("请输入年龄\n"); 	scanf("%d",&p->date.age); 	printf("请输入工龄\n"); 	scanf("%d",&p->date.worktime); 	printf("请输入性别\n"); 	scanf("%s",p->date.sex); 	printf("请输入婚姻状况\n"); 	scanf("%s",p->date.hunyin); 	printf("请输入级别\n"); 	scanf("%d",&p->date.grade); 	printf("请输入工资\n"); 	scanf("%d",&p->date.wage); 	printf("请输入是否在职\n"); 	scanf("%s",p->date.tired); 	p->next=NULL; 	printf("请输入要添加的位置："); 	scanf("%d",&a); 	while(i<a-1) 	{ 		if(s!=NULL) 		{ 			s=s->next; 			i++; 		} 		else 			printf("请输入插入的正确位置"); 	} 	if(s->next!=NULL) 	{ 		p->next=s->next; 		s->next=p; 	} 	else 	{ 		s->next=p;  	} 	printf("添加信息成功：\n"); 	Sleep(500); 	system("cls"); 	printf("返回菜单\n"); 	Sleep(500);  	menu(head);  	return 0;  } //删除 int  shanchu(LNode *head) { 	int a; 	LNode *s,*p; 	s=head; 	p=s; 	printf("请输入要删除员工的员工号"); 	scanf("%d",&a); 	while(s->date.hao!=a) 	{  		s=s->next; 		if(s==NULL) 		{ 			printf("没有这个员工\n"); 			system("pause"); 			xiugai(head); 		}   	} 	while(p->next!=s) 	{ 		p=p->next; 	} 	p->next=NULL; 	printf("删除信息成功\n"); 	printf("\t\t\t\t删除员工的信息\n"); 	printf("员工号"); 	printf("\t姓名"); 	printf("\t年龄"); 	printf("\t工龄"); 	printf("\t性别"); 	printf("\t婚姻状况"); 	printf("\t级别"); 	printf("\t工资"); 	printf("\t是否在职\n"); 	printf("%d",s->date.hao); 	printf("%6s",s->date.name); 	printf("\t%-3d",s->date.age); 	printf("\t%-2d",s->date.worktime); 	printf("\t%2s",s->date.sex); 	printf("\t%4s",s->date.hunyin); 	printf("\t\t%-1d",s->date.grade); 	printf("\t%-5d",s->date.wage); 	printf("\t%2s\n",s->date.tired); 	system("pause"); 	free(s);  	Sleep(500); 	system("cls"); 	printf("返回菜单\n"); 	Sleep(500);  	menu(head);  	return 0;  } //口令 int kouling(LNode *head) { 	int i,m,n,o; 	char a[]="1540610622",b[20]; 	printf("请输入口令："); 	i=3; 	o=0; 	while(i) 	{ 		scanf("%s",&b); 		for(m=0;m<10;m++) 		{ 			if(a[m]==b[m]) 			{  				o=o+1; 				n=1; 			} 			else 			{ 				m++;  				n=0; 				break; 			}   		}  		if(n==1&&o==10) 		{ 			printf("你是合法用户."); 			Sleep(500); 			system("cls"); 			printf("请稍后。。。"); 			Sleep(500); 			printf("。。。"); 			Sleep(500); 			printf("。。。"); 			Sleep(500); 			menu(0); 		} 		else 		{ 			printf("你是非法用户。\n"); 			printf("你还有%d次机会\n",i-1); 			i--;  		} 		if(i==0) 			exit(0); 		o=0;   	} 	return 1; } //入库 int ruku(LNode *head) { 	LNode *p; 	FILE *fp; 	p=head->next;  	fp=fopen("d:\\职工信息管理系统.txt","ab"); 	if(fp==NULL) 	{ 		printf("不能打开文件\n"); 		exit(0); 	} 	while(p!=NULL) 	{ 		fprintf(fp,"%d",p->date.hao); 		fprintf(fp,"%6s",p->date.name); 		fprintf(fp,"\t%-3d",p->date.age); 		fprintf(fp,"\t%-2d",p->date.worktime); 		fprintf(fp,"\t%2s",p->date.sex); 		fprintf(fp,"\t%4s",p->date.hunyin); 		fprintf(fp,"\t\t%-1d",p->date.grade); 		fprintf(fp,"\t%-5d",p->date.wage); 		fprintf(fp,"\t%2s\n",p->date.tired); 		p=p->next; 	} 	fclose(fp); 	return 0;  } //出库 int chuku(LNode *head) { 	LNode *p; 	FILE *fp; 	p=head->next;  	fp=fopen("d:\\职工信息管理系统.txt","ab"); 	if(fp==NULL) 	{ 		printf("不能打开文件\n"); 		exit(0); 	} 	while(!feof(fp)) 	{ 		fscanf(fp,"%d",&p->date.hao); 		fscanf(fp,"%6s",p->date.name); 		fscanf(fp,"\t%-3d",&p->date.age); 		fscanf(fp,"\t%-2d",&p->date.worktime); 		fscanf(fp,"\t%2s",p->date.sex); 		fscanf(fp,"\t%4s",p->date.hunyin); 		fscanf(fp,"\t\t%-1d",&p->date.grade); 		fscanf(fp,"\t%-5d",&p->date.wage); 		fscanf(fp,"\t%2s\n",p->date.tired);  	} 	fclose(fp); 	return 0; } //菜单 int menu(LNode *head = NULL) { 	int a,ch1;  	system("cls"); 	printf("****************************************************************\n"); 	printf("*                                                              *\n"); 	printf("*                    欢迎使用本职工信息管理系统                *\n"); 	printf("*    1。创建职工信息                     2。查询职工信息       *\n"); 	printf("*    3。修改职工信息                     4。添加职工信息       *\n"); 	printf("*    5。查询职工信息                     6。删除职工信息       *\n"); 	printf("*    7。入库                             8。出库               *\n"); 	printf("*    9。退出                                                   *\n"); 	printf("*                                                              *\n"); 	printf("*                         请输入相应编号：                     *\n"); 	printf("*                                                              *\n"); 	printf("****************************************************************\n"); 	scanf("%d",&a); 	while(1) 	{  		switch(a) 		{ 		case 1:chuangjian(head); 			fflush(stdin); 			break; 		case 2:liulan(head); 			fflush(stdin); 			break; 		case 3:xiugai(head); 			fflush(stdin); 			break; 		case 4:tianjia(head); 			fflush(stdin); 			break; 		case 5:chaxun(head); 			fflush(stdin); 			break; 		case 6:shanchu(head); 			fflush(stdin); 			break; 		case 7:ruku(head); 			break; 		case 8:chuku(head); 			break; 		case 9:printf("\t>>>请问您确定退出程序吗？(Y/N)"); 			fflush(stdin);//清除输入缓存 			ch1=getchar(); 			if(ch1=='y'||ch1=='Y') 				return 0;//exit(0);; 			break; 		} 	} 	return a; } int main() { 	LNode *head; 	head=(LNode *)malloc(sizeof(LNode)); 	if(head==NULL)return 0; 	head->next=NULL; 	if(1==kouling(head)) 		menu(head); 	return 0; }

没有输入东西就能出入一串数据，而且最后崩了


Question: codingame这个编程游戏的玩法请问谁知道

printf("%d %d 50\n", nextCheckpointY, nextCheckpointY); //改为:printf("%d %d 70\n", nextCheckpointX, nextCheckpointY); 其它自己慢慢琢磨.


Question: 删除数组中指定元素 出错求修改

delete是关键词，不能用作函数名，换一个名字

#include<stdio.h> void mdelete(int *p,int m) { 	int i; 	for(i=m-1;i<=5;i++) 	{ 		*(p+i)=*(p+i+1); 	} 	*(p+6)=0; } int main() { 	int a[]={1,2,3,4,4,5,6}; 	int m,i; 	int *p; 	for(i=0;i<=6;i++) 		printf("%d",a[i]); 	printf("please input the position you want to delete"); 	scanf("%d",&m); 	p = &a[0]; 	mdelete(p,m); 	for(i=0;i<=5;i++) 		printf("%d",a[i]); 	return 0; }


Question: 关于C变量的作用域

for中n与外面的n是不同的两个变量，for中声明的n（for(int n = ....)）只在for循环范围内有效（当然这一点在VC6里不是）

谢谢各位！其实这是C primer plus上的例子，自己不会这样写程序的。

不建议LZ在以后写程序时这样做；因为代码可读性很差,对自己对别人都是可读性差呀~

第二个循环的n就是使用的初始定义的n的变量,第二个循环把n的值重新赋值了,就是赋值为1了,然后就进入循环；循环之后就是3；

因为你第二个for比第一个for少了个int


Question: 大神求指点？？？

DOS下地址0处的4个字节用来保存的中断0的服务程序的入口地址。

我们的程序在使用的是系统给定的一个段，程序中的零值指针指向这个段的开端，为了保证NULL概念，系统为我们这个段的开头64K内存做了苛刻的规定，根据虚拟内存访问权限控制，我们程序中（低访问权限）访问要求高访问权限的这64K内存被视作是不容许的，所以会必然引发Access Volitation 错误，而这高权限的64K内存是一块保留内存（即不能被程序动态内存分配器分配，不能被访问，也不能被使用），就是简单的保留，不作任何使用。

windows把内存地址0X00000000到0X0000ffff指定为分配null指针的地址范围,如果程序试图访问这一地址，则认为是错误。c/c++编写的程序通常不进行严格的错误检查，当采用malloc来分配内存而可供分配的地址空间不够的情况下返回null指针。


Question: 结构体中函数指针的问题？

引用 8 楼 x303687305 的回复:引用 7 楼 paschen 的回复:[quote=引用 5 楼 x303687305 的回复:]CLARKE *和Unit32可以通过强转来通过调用，他两的内存模型是一样的即为4字节的地址  那请问一下，(void(*)(Uint32))clarke_calc ， 是什么意思啊？[/quote]  void(*)(Uint32) 是一个函数指针，指针指向参数为Uint32，无返回的函数  不同类型的指针是不能隐式转换的  在这里是做强制转换，让他转换成这种类型函数指针  正如(int)a  就是将a转换成int类型[/quote]  非常非常感谢，我好像明白了。请问你们这些东西都是在哪学的啊？有没有好一点的书推荐一下？我有一本谭浩强的C程序设计教程，是大学时候C语言的书，写得非常浅显。  我本人并不是学编程的，是学电气的。但是很多控制算法都需要编程来实现，所以我C语言有一些弱[/quote]C primer plus也可以学习使用，建议看看或者到网上找些电子版关于c的

引用 7 楼 paschen 的回复:引用 5 楼 x303687305 的回复:CLARKE *和Unit32可以通过强转来通过调用，他两的内存模型是一样的即为4字节的地址  那请问一下，(void(*)(Uint32))clarke_calc ， 是什么意思啊？[/quote]  void(*)(Uint32) 是一个函数指针，指针指向参数为Uint32，无返回的函数  不同类型的指针是不能隐式转换的  在这里是做强制转换，让他转换成这种类型函数指针  正如(int)a  就是将a转换成int类型[/quote]  非常非常感谢，我好像明白了。请问你们这些东西都是在哪学的啊？有没有好一点的书推荐一下？我有一本谭浩强的C程序设计教程，是大学时候C语言的书，写得非常浅显。  我本人并不是学编程的，是学电气的。但是很多控制算法都需要编程来实现，所以我C语言有一些弱

引用 5 楼 x303687305 的回复:CLARKE *和Unit32可以通过强转来通过调用，他两的内存模型是一样的即为4字节的地址[/quote]  那请问一下，(void(*)(Uint32))clarke_calc ， 是什么意思啊？[/quote]  void(*)(Uint32) 是一个函数指针，指针指向参数为Uint32，无返回的函数  不同类型的指针是不能隐式转换的  在这里是做强制转换，让他转换成这种类型函数指针  正如(int)a  就是将a转换成int类型

引用 4 楼 renwotao2009 的回复:[quote=引用 3 楼 x303687305 的回复:] [quote=引用 2 楼 renwotao2009 的回复:]  void(*calc)( Uint32); // 改成这样，C和C++都是强类型语言，不符合定义编译不过   你这么一改，还真就成功了！！谢谢你！！可是我不太明白其中的原理，能再给我讲讲吗？  为什么用void(*calc)( Uint32); 这样的形式就能行呢？ Uint32 代表了这个函数的参数，是无符号的32位数据类型。  可是，我实际装载的函数，是void clarke_calc(CLARKE *v)，这个函数的参数，是CLARKE *v 啊？  [/quote]CLARKE *和Unit32可以通过强转来通过调用，他两的内存模型是一样的即为4字节的地址[/quote]  那请问一下，(void(*)(Uint32))clarke_calc ， 是什么意思啊？

引用 3 楼 x303687305 的回复:[quote=引用 2 楼 renwotao2009 的回复:]  void(*calc)( Uint32); // 改成这样，C和C++都是强类型语言，不符合定义编译不过   你这么一改，还真就成功了！！谢谢你！！可是我不太明白其中的原理，能再给我讲讲吗？  为什么用void(*calc)( Uint32); 这样的形式就能行呢？ Uint32 代表了这个函数的参数，是无符号的32位数据类型。  可是，我实际装载的函数，是void clarke_calc(CLARKE *v)，这个函数的参数，是CLARKE *v 啊？  [/quote]CLARKE *和Unit32可以通过强转来通过调用，他两的内存模型是一样的即为4字节的地址

引用 2 楼 renwotao2009 的回复: void(*calc)( Uint32); // 改成这样，C和C++都是强类型语言，不符合定义编译不过   你这么一改，还真就成功了！！谢谢你！！可是我不太明白其中的原理，能再给我讲讲吗？  为什么用void(*calc)( Uint32); 这样的形式就能行呢？ Uint32 代表了这个函数的参数，是无符号的32位数据类型。  可是，我实际装载的函数，是void clarke_calc(CLARKE *v)，这个函数的参数，是CLARKE *v 啊？

C 试试 要不强制转换


Question: 写入和读取文件莫名出错

运行出错的时候点中断，通过调用堆栈定位出错位置，然后观察分析原因

引用 1 楼 zhao4zhong1 的回复:请判断每个函数的返回值。尤其是fscanf++ fscanf，fread 等标准库函数的返回值，都是有它的用途的 使用这些函数的时候， 应该知道返回值的含义，并尽可能的使用它

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

老师您能说明白点吗

请判断每个函数的返回值。尤其是fscanf


Question: 关于数组的问题

请楼主准时参加赵4老师的公开课《C语言指针与汇编内存地址（三、四）——通过静态和动态一、二、三维数组实例了解指针与数组对应的汇编内存地址。》

int ** arr_2d(int m,int n){ 	int **p=(int **)malloc(sizeof(int*)*m); 	int i; 	p[0] = (int*)malloc(sizeof(int)*m*n); 	for(i=1;i<m;i++){ 		p[i]=p[0]+i*n; 	} 	return p; }   void free_arr_2d(int **p){      free(p[0]); 	 free(p); }  也许这么做可以，你试试

因为动态分配的数据，没有每一维 大小，相关的类型信息 所以 *（a+i）+j 没法计算

int main(){  	char _array[3][4]; 	char *a = (char *)_array; 	printf("_array:%p  &_array[1][2]:%p  *(_array+1)+2:%p\n", _array ,  &_array[1][2],  *(_array+1)+2); 	printf("a:%p ,(a+1*4)+2:%p\n", a, (a+1*4)+2);  	return 0; }  楼主拿这个代码去执行，自己悟一下？  注意："*a代表的是&a[0][0]"这个说法是不对的，它们的类型不一样的...... 比方说char *pc=NULL， int *pi=NULL pc和pi都是null，但是pc+1和pi+1的结果就完全不一样了


Question: 请教下windows下的管道操作.

引用 3 楼 CharlesSimonyi 的回复:WriteFile最后一个参数就是用来进行异步IO操作的，关于Windows上的异步IO，《Windows核心编程》第10章有讲，可以找本电子书看一下   感谢回复, 查了下匿名管道不支持异步. 退而求其次, 我查了下命名管道的用法, 写出来后不阻塞, 但数据不对,是否我取文件描述符取的不对?      const char *pStrPipeName = "\\\\.\\pipe\\NamePipe_MoreWindows";     DWORD dwLen = 0;     OVERLAPPED ov;     memset(&ov, 0, sizeof(OVERLAPPED));  	HANDLE hPipe = CreateNamedPipe(pStrPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, 0);     if (WaitNamedPipe(pStrPipeName, NMPWAIT_WAIT_FOREVER) == FALSE) {         return NULL;     }      WriteFileEx(hPipe, data_source, data_source_len, &dwLen, &ov);      int file_des = _open_osfhandle((intptr_t)hPipe, 0);

已经对照msdn手册学会用了,多谢大家...

引用 1 楼 user-2 的回复:windows下面默认是同步IO，异步IO的话，仔细看看官方的文档就行了： https://msdn.microsoft.com/en-us/library/windows/desktop/aa365748(v=vs.85).aspx  感谢回复  能否给个例子.


Question: vs中关于opencv附加依赖项lib文件添加的疑问

引用 13 楼 Scutum_hy 的回复:各位大佬，为啥会有这个错误“>LINK : fatal error LNK1104: 无法打开文件“opencv_core330d.lib””啊。。很迷 全盘搜索opencv_core330d.lib，如果没有，生成之；如果有，将其所在文件夹对应全路径填写到 项目、属性、链接器、常规、附加库目录：填写附加依赖库所在目录 分号间隔多项 中

有人说多个lib麻烦，但WindowsXP之后的很多系统dll TMD 都拆分成好多个小dll了！

引用 9 楼 CharlesSimonyi 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] [quote=引用 7 楼 CharlesSimonyi 的回复:] [quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 CharlesSimonyi 的回复:] 都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。[/quote] 刚试了一下，好象x64才能用。[/quote]  X86也有的，编译的时候X64 x86都编译一份[/quote] 不知道我漏编译了哪个项目。[/quote]  我装的是opencv3.0.0，里面提供了编译好的X86 X64的bin。 现在最新的opencv3.1.0，里面只提供了编译好的x64的bin。 但是可以自行编译一下，用cmake创建VS解决方案sln。 VisualStudio打开，编译一个X86的bin。[/quote] 这位大神,请问如何编译x86并将其编译结果集中在一个lib里面?好像它自带的64位opencv_world320.lib一样. 我编译出来就是好多个lib觉得麻烦.

cmd到存放lib目录，用“dir *.lib”显示所有依赖项，再复制，很方便

引用 7 楼 CharlesSimonyi 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 CharlesSimonyi 的回复:] 都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。[/quote] 刚试了一下，好象x64才能用。[/quote]  X86也有的，编译的时候X64 x86都编译一份[/quote] 不知道我漏编译了哪个项目。

引用 8 楼 zhao4zhong1 的回复:[quote=引用 7 楼 CharlesSimonyi 的回复:] [quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 CharlesSimonyi 的回复:] 都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。[/quote] 刚试了一下，好象x64才能用。[/quote]  X86也有的，编译的时候X64 x86都编译一份[/quote] 不知道我漏编译了哪个项目。[/quote]  我装的是opencv3.0.0，里面提供了编译好的X86 X64的bin。 现在最新的opencv3.1.0，里面只提供了编译好的x64的bin。 但是可以自行编译一下，用cmake创建VS解决方案sln。 VisualStudio打开，编译一个X86的bin。

引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 CharlesSimonyi 的回复:] 都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。[/quote] 刚试了一下，好象x64才能用。

引用 4 楼 CharlesSimonyi 的回复:都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。

引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 CharlesSimonyi 的回复:] 都是手动输，第一次麻烦点，以后直接复制粘贴。 也可以用OpenCV3 基本上只有一个文件了opencv_world300.lib 学习了。[/quote] 刚试了一下，好象x64才能用。[/quote]  X86也有的，编译的时候X64 x86都编译一份

用pragma comment(lib,"XXX.lib")方便点

用文本编辑器（写字板之类）打开工程对应的*.vcxproj文件，找到 <Lib>       <AdditionalDependencies> 的地方，把你的lib名字一股脑填进去

那就自己写个小程序，把目录下所有文件名输出到文本文件中


Question: 分班

此题要问小学老师，博士未必打得出，

引用 14 楼 u014444402 的回复:看了各位的回复，思路都是逐个的平衡，但是这样的话会出现某种组合会比我们逐个平衡的小。 所以我觉得应该在分班后调整，即先随便分，然后再两个班中调整，但是如何调整？目前还没好想法。  试下这种； 先随便分并对两个班排序，然后看两个班总分数相差多少，比如相差20分 然后找将两个班中差值最接近20的一组进行调换 重复这个过程直到总分差值不再减小

引用 23 楼 Rewen 的回复:我的思路    1， 先算平均值 av   2， 各个分数 - av 得到 差值  var   3， 设置2个Flag ， FlagA = FlagA + var , FlagB = FlagB + var   4， 在var list中取得值，是FlagA 和FlagB 都接近于0. 有无伪代码?看得不是很明白.

这是个0/1背包问题，可以用动态规划搞，看这里 http://blog.csdn.net/pegasuswang_/article/details/25081783

引用 25 楼 lqbk1 的回复:人数要一样？ 那就看这个 http://www.cppblog.com/baby-fly/archive/2009/09/24/92392.html 嗯,很精彩的讲解.多谢.   引用 26 楼 paschen 的回复:[quote=引用 14 楼 u014444402 的回复:] 看了各位的回复，思路都是逐个的平衡，但是这样的话会出现某种组合会比我们逐个平衡的小。 所以我觉得应该在分班后调整，即先随便分，然后再两个班中调整，但是如何调整？目前还没好想法。  试下这种； 先随便分并对两个班排序，然后看两个班总分数相差多少，比如相差20分 然后找将两个班中差值最接近20的一组进行调换 重复这个过程直到总分差值不再减小[/quote] 我刚开始就是这样想的, 但是问题就在这个"组"上了,一组是1个数字,2个?还是好几个,到底是哪几个..好像又引进组合了.

N有取值范围吗？

引用 15 楼 qq_29120981 的回复:两个班总分之差最小,即两个班总分都是接近(所有学生成绩总分和)/2,然后贪心 怎么贪?具体一点?有伪代码最好.

两个班总分之差最小,即两个班总分都是接近(所有学生成绩总分和)/2,然后贪心

仅供参考：//给出12个随机数,分成三组求和,每组的个数不定,要求求出来的三个数之间相差最小,最完美的情况是三个数相等. #include <stdlib.h> #include <stdio.h> #include <time.h> #include <math.h> #include <limits.h> int i,j,k; int g[12][3]={//可能的分组大小     { 1, 1,10},     { 1, 2, 9},     { 1, 3, 8},     { 1, 4, 7},     { 1, 5, 6},     { 2, 2, 8},     { 2, 3, 7},     { 2, 4, 6},     { 2, 5, 5},     { 3, 3, 6},     { 3, 4, 5},     { 4, 4, 4}, }; int n[12]; int m[12]; int f[12];//当前最小时各数 int g1,g2,g3;//1,2,3组可分配的个数 int n1,n2,n3;//1,2,3组已分配的个数 int f1,f2;//当前最小时1,2组的个数 int s1,s2,s3;//123组的和 int d;//1-2,2-3,3-1组中各数和之间差的绝对值之和 int dmin=INT_MAX;//保存当前d的最小值 void swap(int *pi1,int *pi2) {     int t;     t=*pi1;*pi1=*pi2;*pi2=t; } void test() {     s1=0;     for (i=0;i<g1;i++) s1=s1+n[i];     s2=0;     for (i=g1;i<g1+g2;i++) s2=s2+n[i];     s3=0;     for (i=g1+g2;i<12;i++) s3=s3+n[i];     d=abs(s1-s2)+abs(s2-s3)+abs(s3-s1);     if (d<dmin) {         dmin=d;         f1=g1;         f2=g2;         for (i=0;i<12;i++) f[i]=n[i];         printf("(");         for (i=0;i<g1;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);         printf(") %4d\n",dmin);     } else {         printf("(");         for (i=0;i<g1;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);         printf(") %4d\n",d);     } } void main() {     srand(time(NULL));     for (i=0;i<12;i++) m[i]=rand()%100;     for (i=0;i<12;i++) printf("%2d,",m[i]);     printf("\n");     for (i=1;i<12;i++) {         for (j=0;j<i;j++) {             if (m[i]>m[j]) swap(&m[i],&m[j]);//冒泡排序从大到小         }     }     for (i=0;i<12;i++) printf("%2d,",m[i]);     printf("\n");     for (k=0;k<12;k++) {//在12种分组方法中         //取第i种分组方法         g1=g[k][0];         g2=g[k][1];         g3=g[k][2];         printf("%2d-%2d,%2d,%2d\n",k,g1,g2,g3);         //将从大到小12个数双向轮流分配到三个组中         n1=0;         n2=0;         n3=0;         for (j=0;j<12;j++) {             switch (j%6) {             case 0:         redo:                 if (n1<g1) {                     n[n1]=m[j];                     n1++;                     break;                 }             case 1:                 if (n2<g2) {                     n[g1+n2]=m[j];                     n2++;                     break;                 }             case 2:                 if (n3<g3) {                     n[g1+g2+n3]=m[j];                     n3++;                     break;                 }             case 3:                 if (n3<g3) {                     n[g1+g2+n3]=m[j];                     n3++;                     break;                 }             case 4:                 if (n2<g2) {                     n[g1+n2]=m[j];                     n2++;                     break;                 }             case 5:                 if (n1<g1) {                     n[n1]=m[j];                     n1++;                     break;                 }             default:goto redo;             }         }         test();     }     printf("---------------------------------------------------\n");     g1=f1;     g2=f2;     for (i=0;i<12;i++) n[i]=f[i];     printf("(");     for (i=0;i<g1;i++) printf("%2d,",n[i]);     printf(")  (");     for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);     printf(")  (");     for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);     printf(") %4d\n",dmin); }

引用 20 楼 zhao4zhong1 的回复:[quote=引用 19 楼 zhao4zhong1 的回复:] N为1时，…… https://www.baidu.com/s?wd="一班就两个学生"[/quote]  引用 19 楼 zhao4zhong1 的回复:N为1时，…… 不要捣乱.

引用 19 楼 zhao4zhong1 的回复:N为1时，…… https://www.baidu.com/s?wd="一班就两个学生"

N为1时，……

再加100分,求解答.

有点意思好 哈哈

看了下各楼的回复。我自己总结了个想法，经过手动举例验证还是不对的，先想到这里了，先贴出来。  （1）求出2N个同学成绩的平均值，记为变量average； （2）对2N个铜须的成绩进行排序，从小到大，和从大到小都可以； （3）选出2N个数（2N个同学的的成绩），离平均值最近的两个数，比如说是x1，x2。           把x1,x2任意分配到对应的A班和B班，比如分数为x1对应的同学分到A班，分数为x2对应的同学分配到B版。 （4）选出距离平均值第二近的两个数，比如说是y1,y2。A班的成绩记为sumA，B班的成绩记为sumB。          如果把y1分配到A班，则A班现在的成绩是sumA = x1 + y1，B班现在的成绩是sumB = x2 + y2; 	 如果把y2分配到A班，则A班现在的成绩是sumA = x1 + y2，B班现在的成绩是sumB = x2 + y1; 	  	 如果((x1 + y1) - (x2 + y2))的绝对值 > ((x1 + y2) - (x2 + y1))的绝对值，则将分数y2对应的同学分配到A班，分数y1对应的同学分配到B班。 	 这样保证每班两个同学时，分数总和的差距是最小的。 （5）以此类推，保证每班多分一个学生时，分数总和的差距都是最小。  举个最简单的实例：4个同学（2N中的N=2），成绩分别是60,55,80,78。 （1）平均值是68.25； （2）排序结果是55,60,78,80; （3）离平均值最近的两个数是60,78; 60对应的同学分到A班，78对应的同学分到B班； （4）距离平均值第二近的两个数是55,80。|(60+55)-(78+80)| > |(60+80)-(78+55)|， 	故将55,78的同学分到A班，60,80的同学分到B班，这样成绩总差为7是最小的。 	 	但是（60 + 78） - （55 + 80） = 3，将60,78的同学分到A班，55,80的同学分配到B班分数差才是最小的…… 	所以最开始将60和78分开就是个bug……

另一个办法 从最大分数开始，安插 保持两个班级的平衡 新安插的优先安插总分低的班级，总分相同，A，或者B优先安插（或者随机优先安插）

先排序 然后按照最接近分数平均值，安排一个班即可


Question: 新人小白求助诸位大神！！

scanf("%d\n",&n);多了一个\n

scanf("%d\n",&n);多了一个\n 改成scanf("%d",&n);


Question: 扫雷游戏代码，vc6.0 运行总是踩到雷

炸炸更健康！

在必要的地方加断点，运行时断下来看，同时可采用单步调试等技术，观察分析原因

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


Question: 0x0f57cab8 (msvcr100d.dll) 处最可能的异常: 0xC0000005: 写入位置 0x00150000 时发生访问冲突

Properties是个什么东西？ Properties[i]又是个什么东西  一次往&Properties[i]写14字节的东西，内存分配好了吗？

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


Question: 急，c语言头文件

包含这个头文件就可以了：#include "Que.h"    如果这个头文件不在工作目录下，需要使用完整路径

直接include就行了啊 自己编译链接的话，记得把cpp文件对应的obj链接进来

同一目录直接 #include 如果要提供给其他目录或者程序用 就安装到 /usr/local/include 或者其他PATH下

不是一样用include就可以了吗？？？

#include "Que.h"   or  #include <Que.h>   问度娘  C  include

如果你的一个.c文件要用到Que.h里声明的函数或变量，那就在该.c文件的开头写上include"Que.h"就可以了         编译时编译器会自动将Que.h里的所有内容复制粘贴到include"Que.h"这个地方，你下面的程序就可以用Que.h里声明的函数或变量了.


Question: remalloc异常，抛出SIGSEGV、SIGABRT等信号

小心驶得万年船。

越界访问导致出错

多线程读/写或malloc、realloc、free竞争资源需要加锁。

我自己先抛一种情况： 当发生内存越界操作，导致这块内存临接的下一块内存被篡改（下块内存头长度信息被覆盖），此时进行remalloc时就会触发异常（具体处理方式与内核有关），如SIGSEGV。 但是我这次并没有越界操作。唯一我能知道的异常方式是：该内存已经被我释放，对野指针进行remalloc触发了SIGSEGV，因为该对象确实存在并发操作，有被删除的可能，而且没做资源保护。


Question: 求修改~~谢谢  把一段字符串后面部分替换掉

引用 1 楼 user-6 的回复:你的scanf 到底要拿什么？    scanf 就是从哪开始替换

建议先养个好习惯：变量名 尽量用英文 见名知意 ，不然一周后你自己看代码又得花很长时间。 函数前面写一段注释 说明这个函数做什么的，返回值是什么，需要特别注意的是什么。  至于这段代码的问题 楼上的都给你解决了。

VS环境  #define _CRT_SECURE_NO_DEPRECATE   #include <stdio.h>   #include <string.h>    /********************************************************************  *  Function：  my_strstr()  *  Description: 在一个字符串中查找一个子串;  *  Input：      ps: 源;      pd：子串  *  Return :    0：源字符串中没有子串; 1：源字符串中有子串;  *********************************************************************/   char * my_strstr(char * ps, char *pd)   {       char *pt = pd;       int c = 0;       while (*ps != '\0')       {           if (*ps == *pd)           {               while (*ps == *pd && *pd != '\0')               {                   ps++;                   pd++;                   c++;               }           }           else           {               ps++;           }           if (*pd == '\0')           {               return (ps - c);           }           c = 0;           pd = pt;       }       return 0;   }      /********************************************************************  *  Function：  my_memcpy()  *  Description: 复制一个内存区域到另一个区域;  *  Input：      src: 源;  count: 复制字节数.  *  Output：      dest: 复制目的地;  *  Return :      dest;  *********************************************************************/   void * my_memcpy(void * dest, const void *src, size_t count)   {       char *tmp = (char *)dest, *s = (char *)src;       while (count--)           *tmp++ = *s++;       return dest;   }      /********************************************************************  *  Function：  str_replace()  *  Description: 在一个字符串中查找一个子串，并且把所有符合的子串用  另一个替换字符串替换。  *  Input：      p_source:要查找的母字符串； p_seach要查找的子字符串;  p_repstr：替换的字符串;  *  Output：      p_result:存放结果;  *  Return :      返回替换成功的子串数量;  *  Others:      p_result要足够大的空间存放结果，所以输入参数都要以\0结束;  *********************************************************************/   int str_replace(char *p_result, char* p_source, char* p_seach, char *p_repstr)   {       int c = 0;       int repstr_leng = 0;       int searchstr_leng = 0;       char *p1;       char *presult = p_result;       char *psource = p_source;       char *prep = p_repstr;       char *pseach = p_seach;       int nLen = 0;       repstr_leng = strlen(prep);       searchstr_leng = strlen(pseach);          do {           p1 = strstr(psource, p_seach);           if (p1 == 0)           {               strcpy(presult, psource);               return c;           }           c++;  //匹配子串计数加1;           //printf("结果:%s\r\n", p_result);           //printf("源字符:%s\r\n", p_source);           // 拷贝上一个替换点和下一个替换点中间的字符串           nLen = p1 - psource;           memcpy(presult, psource, nLen);           // 拷贝需要替换的字符串           memcpy(presult + nLen, p_repstr, repstr_leng);           psource = p1 + searchstr_leng;           presult = presult + nLen + repstr_leng;       } while (p1);          return c;   }   #define MAX 200   int main(void)   {       int i = 0;       char s[MAX] = { 0 };        //存放源字串       char s1[MAX] = { 0 };        //存放子字串       char s2[MAX] = { 0 };        //存放替换字串       char result_a[2000] = { 0 };//存放替换结果;       puts("Please input the string for s:");       gets_s(s,MAX);       puts("Please input the string for s1:");       gets_s(s1, MAX);       puts("Please input the string for s2:");       gets_s(s2, MAX);       i = str_replace(result_a, s, s1, s2);       printf("替换%d个子字符串;\r\n", i);       printf("替换后结果:%s\r\n", result_a);   	return 0; }

#include<stdio.h> void fun(char *st,int n,int m) {     char *p1,*p;    //p1野指针     p=st;     while(p<st+m)     {         p++;         p1++;    //此处加没有意义     }     for(p=st+m;p<st+n;p++)    //此处p在上面做了++此处p又指向了st+m,则上面的操作没意义     {         *p=*p1;         *p++;         *p1++;     }     *p1='\0'; } main() {     char st[20];     int i;     printf("please input a string:\n");     scanf("%d",&i);     fun(st,20,i);    //st没有初始化和赋值,所以调用函数fun没有意义     printf("%s",st); }  对多处做了注释,问题先逐步修改；问题也比较模糊,建议你在提问时,可以适当举个例子,让别人能理解你的需求和要求；

你是想输入i 作为替换开始的位置吧         但有一个大问题在于fun（）函数里的指针变量p1 一开始你就没有绑定指向的位置，这样p1是一个野指针非常危险，之后你又p1++，然后*p1，p1你都不知道指向哪儿怎么取值呢？        建议养成好习惯，每定义一个指针变量马上给他绑定

你应该先输入原始字符串…… 然后输入替换位置 最后输入要替换的字符串

你的scanf 到底要拿什么？


Question: 子函数怎么返回多个值

传个指针过去,用指针操作.

指针、引用的方式传递参数

用指针吧。。或者定义结构体

利用地址传递的特性，将返回的多个值存放于数组或者结构体，最后返回只想这种数据类型的指针就可以了

通过返回结构体类型的变量可以获取多个参数；把想要返回的数据放入结构体里； 另外,也可以通过传入传出参数实现,但是不建议将函数参数数目超过5个；

tuple?

1.返回结构体 2.通过指针/引用传参的方式将结果带出子函数


Question: 求大神助攻！==

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

typedef struct { 	char ch; 	int bit[96]; }codenode;  codenode huffman_code[20];//编码 数组  void get_code(huff_node *T, int k, char aim,int zifu,int ceng) { 	int i; 	if (T!=NULL) 	{ 		for (i = 0; i < k; i++) 		{ 			int m = ceng+1; 			get_code(huffmanT[T->child[i]], k, aim, zifu, m);//递归到叶节点 			if (T->weight.letter == aim)//若找到 			{ 				huffman_code[zifu].bit[ceng-1] = i; 				f_flag = 1;//标记找到正确路径 				huffman_code[zifu].bit[ceng] = 9;//随便定义一个数作为结束标志 			} 			else if (f_flag == 1&&t_flag==0)//路径正确，而且未到根节点 			{ 				if (T == huffmanT[all])//回到根节点 					t_flag = 1; 				huffman_code[zifu].bit[ceng-1] = i; 				return;//无需访问其他儿子节点 			} 		} 	} } 这样的。zifu是指编码数组 huffman_code的游标，ceng是每个字符的编码数组bit的游标

看不清你的源程序

你还说没有修改, 你看你的代码中标红的地方是在做什么 void get_code(huff_node *T, int k, char aim,int zifu,int ceng) { int i; if (T!=NULL) { for (i = 0; i < k; i++) { int m = ceng+1; get_code(huffmanT[T->child[i]], k, aim, zifu, m);//递归到叶节点 if (T->weight.letter == aim)//若找到 { huffman_code[zifu].bit[ceng-1] = i; f_flag = 1;//标记找到正确路径 huffman_code[zifu].bit[ceng] = 9;//随便定义一个数作为结束标志 } else if (f_flag == 1&&t_flag==0)//路径正确，而且未到根节点 { if (T == huffmanT[all])//回到根节点 t_flag = 1; huffman_code[zifu].bit[ceng-1] = i; return;//无需访问其他儿子节点 } }


Question: 求修改 复制字符串的问题

第一，字符串是char*，字符是char 第二，你主函数中的的p都没有申请内存，你不能直接使用*p  所以：   #include<stdio.h> char* copying(char *p) { 	char *p1; 	while(*p!='\0') 	{ 		*p1=*p; 		p1++; 		p++; 	} 	*p1='\0'; 	return p1; } main() { 	char *p,s[80]; 	printf("please input astring:\n"); 	scanf("%s",s); 	p=copying(s); 	printf("%s",*p); }

1.返回的应该是char * 2.应该在copying函数里malloc一块空间用来存放拷贝的字符串 3.用一个指针记录p1最初始的位置，因为你之后有++操作，p1指向会后移  #include<stdio.h> #include<stdlib.h> char *copying(char *p) { 	char *p1 = (char *)malloc(80); 	char *res = p1; 	while(*p!='\0') 	{ 		*p1=*p; 		p1++; 		p++; 	} 	*p1='\0'; 	return res; } void main() { 	char *p,s[80]; 	printf("please input astring:\n"); 	scanf("%s",s); 	p=copying(s); 	printf("%s\n",p); }

不看其他的，首先main函数里char *p，*p=...就错了

#include<stdio.h> char copying(char *p) { char *p1; while(*p!='\0') { *p1=*p;//这是一个错误的做法。p1声明后，没有分配内存块，直接指向*p的值.p1会把值存放在哪里，这是一个未知的. p1++; p++; } *p1='\0';//这里j是什么意思？ return *p1;//返回'\0'？？？？ } main() { char *p,s[80]; printf("please input astring:\n"); scanf("%s",s);//这里不能用scanf，楼主可以调试一下，如果用scanf获取字符串。然后把s做为实参给copying函数，会发现只得到两个字符。strlen(p)也得不到一个正常的长度。 *p=copying(s);   //copying函数里最后return *p1  是返回'\0'，楼主你知道吗？就算copying函数里前面的步骤不出错，这里也是错误的。 printf("%s",*p); }

引用 12 楼 ghx287524027 的回复: #include<stdio.h> #include<stdlib.h> char * copying(char *p) { 	char *p1,*p2;//申请一个p2用来记录p1的起始位置，因为后面p1的志向发生了变化，返回时要返回p2 	p2=p1=(char *)calloc(1,100); 	while(*p!='\0') 	{ 		*p1=*p; 		p1++; 		p++; 	} 	*p1='\0'; 	return p2; }  void main() { 	char *p=NULL,s[80]; 	printf("please input astring:\n"); 	scanf("%s",s); 	p=copying(s); 	printf("%s\n",p);	//输出的是p而不是*p }   内存用完之后可以free掉，切记free的是内存而不是指针

1   #include<stdio.h>                                                                                1          2 #define    MAX_LEN    128     3          4 char *copying(char *p)     5 {    >>  6     char *p1 = malloc(sizeof(char) * MAX_LEN);     7     if (NULL == p1) {    //判断申请结果 >>  8     |   fprintf(stderr, "malloc Error: %s\n", strerror(errno));     9     |   return NULL;    10     }    11     char *ptmp = p1;    12     while(*p!='\0') {    13     |   *ptmp++ = *p++;    14     }    15     *ptmp = '\0';    //字符串结束标志,添加上    16         17     return p1;    18 }       19 int main(void)    20 {       21     char *p = NULL, s[80];    22     printf("please input astring:\n");    23     scanf("%s", s);    24     p = copying(s);    25     printf("%s\n", p); >> 26     free(p);    //用完释放    27         28     return 0;    29 }

引用 6 楼 qq_35109846 的回复:楼上的不对啊 有错  你copying函数里也要分配内存，上面代码没帮你改

引用 7楼我是你的主体 的回复:四楼正解   可是我之前很少用到*res   啥时候要用这个只是保存一下p1最初始的地址，否则的话你之后++了，return的时候返回的是最后一个\0的地址

引用 1 楼 chendepeng17 的回复:#include<stdio.h> #include "string.h" void copying(char *p) { char p1[80]; int i=0; int clen=strlen(p);//获得长度 while(i<clen) { p1[i]=*p; p++; i++; } for(int j=0;j<clen;j++) { 	printf("%c",p1[j]); } printf("\n"); } main() { char *p,s[80]; printf("please input astring:\n"); gets(s); copying(s); }  帮你修改了一下。                运行不了

四楼正解   可是我之前很少用到*res   啥时候要用这个

楼上的不对啊 有错


Question: c语言问题

还有，疑惑的地方，多加括号，可以避免一些奇怪的问题

VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898

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

#define PI (3.1415926)  类似的 #define SUM ((NUM) + (NUM)) 能用括号尽量用括号，不管优先级 如果是C++程序，舍弃define，用const typedef 可以自己定义类型

还有就是 #define PI （3.1415926） 这样定义的话 也能编译通过，求解释


Question: 一个二级指针+一个缓冲区大小的函数原型要如何实现？

引用 2 楼 zhao4zhong1 的回复:外部分配内存。 传进来的Length限制你填写信息的总字节长度。  谢谢，是这样的，后面把二级指针改成一级指针了。

引用 4 楼 SXJIAKE 的回复:unsigned int GetSysInfo1(     char *SysInfo,     unsigned int Length ); // 常见方式直接传指针和长度 SystemInfomation sysInfo; GetSysInfo1(&sysInfo, sizeof(sysInfo));unsigned int GetSysInfo2(     char **SysInfo );  // 传二级指针方式，通常都不需要长度 SystemInfomation *lpSysInfo; if (GetSysInfo2(&lpSysInfo) > 0) {     printf("%?\n", lpSysInfo->xxx);     // 如果成功，则需要释放。API 编写者提供一个对应的释放函数。     // 如 Windows 中经常有 LocalFree、ILFree/CoTaskMemFree 等     xxxFree(lpSysInfo); }  谢谢，后面的接口已经改了，二级指针改成了一级指针。

外部分配内存。 传进来的Length限制你填写信息的总字节长度。

目前不知道你的系统信息是一个什么结构的，是数组（二维），还是二维的指针； 通过改函数想获取系统信息，将系统信息存放在SysInfo中，然后通过调用改函数将一个二重的指针（根据你的参数是否要申请空间）或二重数组作为实参传给改函数；调用结束实参里存放的是系统信息；


Question: 两个单链表的合并，一直提示有个错误，可是我不明白哪里错了，为什么

#include<stdio.h>  #include<stdlib.h>    typedef struct LNode  {   	int data;   	struct LNode *next;  }LNode,*LinkList; LinkList L;  LinkList createList(LinkList L,int n)//构建链表 {      	LinkList s=NULL,r=NULL,res=NULL; 	int i; 	res=r=(LinkList)calloc(1,sizeof(LNode));  	for(i=0;i<n;i++)  	{   		s=(LinkList)malloc(sizeof(LNode)); 		scanf("%d",&s->data);  		r->next=s;//表尾插入法,输入的s插到r后面。 		r=s;//移动指针r（向后移一位） 	}  	r->next=NULL; 	return res; }  LinkList MergeList(LinkList La,LinkList Lb,LinkList Lc) {     LinkList a=NULL,b=NULL,c=NULL;     a=La->next;b=Lb->next;Lc=c=La;     while(a&&b) 	{         if(a->data<=b->data) 		{             c->next=a; 			c=a; 			a=a->next;         }         else 		{             c->next=b; 			c=b; 			b=b->next;         }     }     c->next=a?a:b;     free(Lb); 	return Lc; }   void OutPutList(LinkList L)//输出链表 {   	LinkList p=NULL; 	//p=(LinkList)malloc(sizeof(LNode));//删掉这句还是可以运行 	p=L->next; 	printf("表中值为:");   	while(p)  	{   		printf("%d ",p->data);  		p=p->next;  	}   	printf("\n");  }  int main()  {    	LinkList La=NULL,Lb=NULL,Lc=NULL; 	int a,b; 	printf("请输入表长："); 	scanf("%d",&a); 	printf("请输入数："); 	La=createList(La,a); 	OutPutList(La); 	printf("请输入表长："); 	scanf("%d",&b); 	printf("请输入数："); 	Lb=createList(Lb,b); 	OutPutList(Lb); 	Lc=MergeList(La,Lb,Lc); 	printf("合并后"); 	OutPutList(Lc); 	return 0; }

那如果我一开始就把La，Lb，Lc定义成全局变量呢？

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

注意大小写 main函数里Mergelist改成MergeList

结构体指针使用的问题，在create的时候就没有返回有效的la指针。  建议进行调试，F11进入调试，F10单步执行，通过调试查看变量以及内存的情况

#include<stdio.h>                                                                                1 #include<stdlib.h>   2     3 typedef struct LNode   4 {   5     int data;   6     struct LNode *next;   7 }LNode,*LinkList;   8     9 //LinkList L;    //Not used  10    11 void createList(LinkList *L,int n)//构建链表  12 {  13     LinkList s,r;  14     int i;  15     *L = r = (LinkList)malloc(sizeof(LNode));  16     for(i=0;i<n;i++) {  17     |   s=(LinkList)malloc(sizeof(LNode));  18     |   scanf("%d",&s->data);  19     |   r->next=s;//表尾插入法,输入的s插到r后面。  20     |   r=s;//移动指针r（向后移一位）  21     }  22     r->next = NULL;  23 }  24    25 void MergeList(LinkList La,LinkList Lb,LinkList *Lc)  26 {  27     LinkList a,b,c;  28     a = La->next;  29     b = Lb->next;  30     *Lc = c = La;  31     while(a&&b)     32     {      33     |   if(a->data<=b->data)  34     |   {  35     |   |   c->next=a;  36     |   |   c=a;    37     |   |   a=a->next;  38     |   }  39     |   else   40     |   {  41     |   |   c->next=b;  42     |   |   c=b;    43     |   |   b=b->next;  44     |   }  45     }      46     c->next=a?a:b;  47     free(Lb);  48 }         void OutPutList(LinkList L)//输出链表  31 {  30     LinkList p;  29     p=(LinkList)malloc(sizeof(LNode));//删掉这句还是可以运行  28     p=L->next;  27     printf("表中值为:");  26     while(p) {  25     |   printf("%d ",p->data);  24     |   p=p->next;  23     }  22     printf("\n");  21 }  20    19 int main()  18 {  17     LinkList La, Lb, Lc;  16     La = Lb = Lc = NULL;  15     int a,b;  14     printf("请输入表长：");  13     scanf("%d",&a);  12     printf("请输入数：");  11     createList(&La,a);  10     OutPutList(La);   9     printf("请输入表长：");   8     scanf("%d",&b);   7     printf("请输入数：");   6     createList(&Lb,b);   5     OutPutList(Lb);   4     MergeList(La, Lb, &Lc);    //Function's name is error   3     printf("合并后");   2     OutPutList(Lc);   1     return 0; 84  }

#include<stdio.h>                                                                                1 #include<stdlib.h>   2                      3 typedef struct LNode   4 {                    5     int data;        6     struct LNode *next;   7 }LNode,*LinkList;    8                      9 //LinkList L;    //Not used  10                     11 void createList(LinkList *L,int n)//构建链表  12 {                   13     LinkList s,r;   14     int i;          15     *L = r = (LinkList)malloc(sizeof(LNode));  16     for(i=0;i<n;i++) {  17     |   s=(LinkList)malloc(sizeof(LNode));  18     |   scanf("%d",&s->data);  19     |   r->next=s;//表尾插入法,输入的s插到r后面。  20     |   r=s;//移动指针r（向后移一位）  21     }               22     r->next = NULL;  23 }                   24                     25 void MergeList(LinkList La,LinkList Lb,LinkList *Lc)  26 {                   27     LinkList a,b,c;  28     a = La->next;   29     b = Lb->next;   30     *Lc = c = La;   31     while(a&&b)     32     {               33     |   if(a->data<=b->data)  34     |   {           35     |   |   c->next=a;  36     |   |   c=a;    37     |   |   a=a->next;  38     |   }           39     |   else        40     |   {           41     |   |   c->next=b;  42     |   |   c=b;    43     |   |   b=b->next;  44     |   }           45     }               46     c->next=a?a:b;  47     free(Lb);       48 }                   49                     50                     51 void OutPutList(LinkList L)//输出链表  52 {                   53     LinkList p;     54     p=(LinkList)malloc(sizeof(LNode));//删掉这句还是可以运行  #include<stdio.h>                                                                                1 #include<stdlib.h>   2                      3 typedef struct LNode   4 {                    5     int data;        6     struct LNode *next;   7 }LNode,*LinkList;    8                      9 //LinkList L;    //Not used  10                     11 void createList(LinkList *L,int n)//构建链表    //需要传L的地址的地址，不然不能把新创建的链表的首地址获取；想获取只能通过函数的返回值来实现了  12 {                   13     LinkList s,r;   14     int i;          15     *L = r = (LinkList)malloc(sizeof(LNode));  16     for(i=0;i<n;i++) {  17     |   s=(LinkList)malloc(sizeof(LNode));  18     |   scanf("%d",&s->data);  19     |   r->next=s;//表尾插入法,输入的s插到r后面。  20     |   r=s;//移动指针r（向后移一位）  21     }               22     r->next = NULL;  23 }                   24                     25 void MergeList(LinkList La,LinkList Lb,LinkList *Lc)    //Lc需要传地址的地址，不然不能把新的链表的首地址即首节点的地址获取  26 {                   27     LinkList a,b,c;  28     a = La->next;   29     b = Lb->next;   30     *Lc = c = La;   31     while(a&&b)     32     {               33     |   if(a->data<=b->data)  34     |   {           35     |   |   c->next=a;  36     |   |   c=a;    37     |   |   a=a->next;  38     |   }           39     |   else        40     |   {           41     |   |   c->next=b;  42     |   |   c=b;    43     |   |   b=b->next;  44     |   }           45     }               46     c->next=a?a:b;  47     free(Lb);       48 }                   49                     50                     51 void OutPutList(LinkList L)//输出链表  52 {                   53     LinkList p;     54     p=(LinkList)malloc(sizeof(LNode));//删掉这句还是可以运行            p=L->next;  27     printf("表中值为:");  26     while(p) {  25     |   printf("%d ",p->data);  24     |   p=p->next;  23     }  22     printf("\n");  21 }  20    19 int main()  18 {  17     LinkList La, Lb, Lc;  16     La = Lb = Lc = NULL;  15     int a,b;  14     printf("请输入表长：");  13     scanf("%d",&a);  12     printf("请输入数：");  11     createList(&La,a);  10     OutPutList(La);   9     printf("请输入表长：");   8     scanf("%d",&b);   7     printf("请输入数：");   6     createList(&Lb,b);   5     OutPutList(Lb);   4     MergeList(La, Lb, &Lc);    //Function's name is error   3     printf("合并后");   2     OutPutList(Lc);   1     return 0; 84  }


Question: 例句搜索

找一个全文检索方面的开源项目参考之。

一次投资终身受益

一次建立，之后查找效率会很高

索引只建立一次吧，只要不是画上几小时的，都能接受。


Question: c语言传送带问题求解

分类讨论都差不多，其实重点是算法的优化！

最多时间是完全不跑 tm 最少时间是完全跑    t0  如果 t0<=t 那么t0 是最快的 否则  如果 t <t0，那么最块时间在 t0~tm之间，t时间跑步， 剩余时间 休息，这要安排好这跑步时间，让他没跑的路程花费时间最短。

///最快可能时间为 ：t0 =Sum(Si/(Vi+dv)); ///最慢可能时间为：tm =Sum(Si/Vi) 当 t0<= t 的时候，最快时间为 t0 当 t0 > t 的时候,t 用完，也不能过全部传送带 此时 ///  T= (tm-t) -Sum(ti*dV/Vi); ///  条件是 0 <=ti <= Si/(Vi+dV); ///求 T的最小值，即可 这是约束条件下的极值问题啊

引用 7 楼 sds428的回复:呵呵，没看明白 呃，确实稍微理解起来难了点

引用 5 楼 赵4老师的回复:这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 你说的很对！谢谢你，正在一步一步的实践~

这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。

引用 1 楼 lm_whales的回复:就是个讨论题  如果全程跑不超时 就全程跑， 否则，在各个带上分配跑的时间，力求最短时间通过 也许可以看成背包 具体实现应该怎么做呢？

引用 2 楼 fangcheng'的回复:這個題目不應該是貪心嗎？ 嗯吧，先在速度最慢的传送带上跑，最后时间最短，但是我写不出来

這個題目不應該是貪心嗎？


Question: 大神们求解，关于收发包的问题

仅供参考：#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("AD sizeof %d\n", sizeof(AD));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("A1 sizeof %d\n", sizeof(A1));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("A2 sizeof %d\n", sizeof(A2));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("A4 sizeof %d\n", sizeof(A4));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("A8 sizeof %d\n", sizeof(A8));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("A16 sizeof %d\n", sizeof(A16));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 //AD sizeof 32 // //A1.a 0 //A1.b 4 //A1.c 17 //A1 sizeof 25 // //A2.a 0 //A2.b 4 //A2.c 18 //A2 sizeof 26 // //A4.a 0 //A4.b 4 //A4.c 20 //A4 sizeof 28 // //A8.a 0 //A8.b 4 //A8.c 24 //A8 sizeof 32 // //A16.a 0 //A16.b 4 //A16.c 24 //A16 sizeof 32 // //  再供参考：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);     } }

引用 1 楼 zhao4zhong1 的回复:推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了额。。好像没有很明白你说的意思i


Question: 关于字符串打印的基础问题

fgets(...)读入文本行时的两种情况。  1. 如果n大于一行的字符串长度，那么当读到字符串末尾的换行符时，fgets(..)会返回。并且在s的最后插入字符串结束标志'\0'。 而s缓冲区剩余的位置不会再填充。  2. 如果n小于等于一行的字符串的长度，那么读入n-1个字符，此时并没有读入\n因为并没有到行尾   example： 12345 fgets(str,5,stdin); 此时，读入4个字符，12345\n,实际上还有最后的'\0',所以，strlen(s)=4。

第一个输入12345输出1234是因为你定义的是一个字符型数组，在最后要加上一个字符串结束标记‘\0’，所以只读了1234并输出，你可以把fgets函数中的5换成6


Question: [交流]寻求一种算法效率高于使用mod（求余）操作

这是基于当时的处理器说的，现在可以忽略 当时加减法指令，移位指令比较快 乘法指令比除法快 求余用的是除法指令，所以比较慢  尽管如此，多用 +，-*,等运算和位操作等依然有一定优势

建议楼主至少三年后再学习优化。  无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

就你这例子而言，PrintDigit((N %10));就是脱了裤子放P，前面都确保N<10了，直接PrintDigit(N);完事

想多了，程序应该优化该优化的部分，如果确定这个操作是瓶颈，消耗了可观的CPU资源(>10%)再去优化也不迟。 不要为了若干个CPU周期忽略了大头

对特定的值应该是有一些优化方案，但是如果对任意值求余，你应该相信编译器厂商的实力。


Question: C中控制台鼠标双击触发单击问题(利用ReadConsoleInput)

这样判断：   		if(irInBuf.Event.MouseEvent.dwEventFlags == 0)//单击（包括按下或释放） 		{ 			if(irInBuf.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)//左键按下 			{  			} 			else if(irInBuf.Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)//右键按下 			{  			} 			else if(irInBuf.Event.MouseEvent.dwButtonState == FROM_LEFT_2ND_BUTTON_PRESSED)//滚轮 			{  			} 			//释放的时候： 			else if(irInBuf.Event.MouseEvent.dwButtonState == 0) 			{  			} 		} 		else if(irInBuf.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)//双击 		{  		} 		else if(irInBuf.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)//移动 		{  		}

解决思路应该是每次触发单击时先暂时不响应，仅设置一个标志，等一定时间过后如果无双击触发，清除标志，执行实际的单击操作；如果有双击触发，清除标志，执行实际的双击操作。

好象Windows下也是如此。  WM_LBUTTONDBLCLK The WM_LBUTTONDBLCLK message is posted when the user double-clicks the left mouse button while the cursor is in the client area of a window. If the mouse is not captured, the message is posted to the window beneath the cursor. Otherwise, the message is posted to the window that has captured the mouse.   WM_LBUTTONDBLCLK  fwKeys = wParam;        // key flags  xPos = LOWORD(lParam);  // horizontal position of cursor  yPos = HIWORD(lParam);  // vertical position of cursor    Parameters fwKeys  Value of wParam. Indicates whether various virtual keys are down. This parameter can be any combination of the following values: Value Description  MK_CONTROL Set if the ctrl key is down.  MK_LBUTTON Set if the left mouse button is down.  MK_MBUTTON Set if the middle mouse button is down.  MK_RBUTTON Set if the right mouse button is down.  MK_SHIFT Set if the shift key is down.    xPos  Value of the low-order word of lParam. Specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.  yPos  Value of the high-order word of lParam. Specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.  Return Values If an application processes this message, it should return zero.   Remarks Only windows that have the CS_DBLCLKS style can receive WM_LBUTTONDBLCLK messages, which the system generates whenever the user presses, releases, and again presses the left mouse button within the system's double-click time limit. Double-clicking the left mouse button actually generates four messages: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, and WM_LBUTTONUP again.   An application can use the MAKEPOINTS macro to convert the lParam parameter to a POINTS structure.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.  See Also Mouse Input Overview, Mouse Input Messages, GetCapture, GetDoubleClickTime,MAKEPOINTS,POINTS, SetCapture, SetDoubleClickTime, WM_LBUTTONDOWN, WM_LBUTTONUP


Question: apue的错误处理函数是不是有问题

引用 4 楼 zhaom_916 的回复:这个地方不用+2  +1就可以了吧 char    buf[MAXLINE+2];//+2 for "\n"  [quote=引用 3 楼 zhao4zhong1 的回复:]  char    buf[MAXLINE]; 应改为  char    buf[MAXLINE+2];//+2 for "\n"[/quote] 你是对的。我+2也不能说是错，可以说是“兼容”。

这个地方不用+2  +1就可以了吧 char    buf[MAXLINE+2];//+2 for "\n"  引用 3 楼 zhao4zhong1 的回复:char    buf[MAXLINE]; 应改为  char    buf[MAXLINE+2];//+2 for "\n"

你要看上面两句最多写入了多少字符啊，然后留了多少字符空间出来

是


Question: 一个关于scanf()函数的问题

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

引用 7 楼 Kris_Yang_2016 的回复:[quote=引用 3 楼 qq423399099 的回复:] scanf("%9s", word) 表示最多拷贝9个字符  可以在格式化字符串中的"%"各格式化规定符之间加入一个整数，表示任何读操作中的最大位数。 举个例子啊，比如第一次读取的时候，读取了9个字符，word中不应该是THE BUY /n吗，输入到message1种的不也应该是THE BUY /n吗，但是实际上空格起到了分隔的作用，这是为什么。[/quote] scanf不能读入空格，空格会被当做空白符（空格(space)、制表符(tab)和新行符(newline)）达到分隔的作用

引用 3 楼 qq423399099 的回复:scanf("%9s", word) 表示最多拷贝9个字符  可以在格式化字符串中的"%"各格式化规定符之间加入一个整数，表示任何读操作中的最大位数。 举个例子啊，比如第一次读取的时候，读取了9个字符，word中不应该是THE BUY /n吗，输入到message1种的不也应该是THE BUY /n吗，但是实际上空格起到了分隔的作用，这是为什么。

引用 1 楼 user-4 的回复:先要了解stdin、stdout、stderr，即标准输入，标准输出，标准错误。然后使用scanf函数从缓冲区内读取内容，读取的最大长度为9个字符（char word[10]的最后一位要存储字符串结束符），然后利用fprintf 函数输入到manager1和manager2中（第偶数个单词输入到message1.txt，第奇数个单词输入到message2.txt中）  举个例子啊，比如第一次读取的时候，读取了9个字符，word中不应该是THE BUY /n吗，输入到message1种的不也应该是THE BUY /n吗，但是实际上空格起到了分隔的作用，这是为什么。

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

引用 1 楼 user-4 的回复:先要了解stdin、stdout、stderr，即标准输入，标准输出，标准错误。然后使用scanf函数从缓冲区内读取内容，读取的最大长度为9个字符（char word[10]的最后一位要存储字符串结束符），然后利用fprintf 函数输入到manager1和manager2中（第偶数个单词输入到message1.txt，第奇数个单词输入到message2.txt中）  应该是第奇数个单词输入到message1.txt，第偶数个单词输入到message2.txt


Question: error LNK2019: 无法解析的外部符号 "bool __cdecl AddItem(struct Telphone,struct list

引用 4 楼 user-2的回复:链接器链接时找不到XXX函数的具体实现，如果这个函数不是自己实现的函数，通常需要将依赖的库文件添加到项目设置中。  具体位置在：项目属性——链接器——输入——附加依赖项 谢谢啦，发现问题了:自己实现的函数写错了，和声明不一致

引用 5 楼 小灸舞的回复:检查AddItem(struct Telphone,struct list *)这个函数的声明和实现 查看是否只有声明而没有实现，是不是函数名拼写错了，参数个数，参数类型是否一致 谢谢你！原来不是缺少库，而是自己实现函数写错了，跟声明函数不一致。终于找到问题了

d3dx9.lib 添加好了，又回到了开始的问题。  error LNK2019: 无法解析的外部符号 "bool __cdecl AddItem(struct Telphone,struct list *)" (?AddItem@@YA_NUTelphone@@PAUlist@@@Z)，该符号在函数 _main 中被引用------------这个问题又出来了

查看d3dx9.lib在哪个目录下 然后在库目录添加上该目录

知道是缺少d3dx9.lib  了。但在在VS.NET中的项目/属性/配置属性/连接器/输入/附加依赖项中添加d3dx9.lib 后编译。出现 错误	1	error LNK1104: 无法打开文件“d3dx9.lib”


Question: c语言开发服务器，并发问题

最简单的就是select模型啊，  记录对端的ip和端口号啊，  记录ip干嘛？   楼主不知道， 多个客户端可以在一台机器上？

引用 11 楼 mLee79 的回复:我在我本子上试了下 epoll,    一个线程, 从4, 5 台虚拟机一共创建了 80万个连接的情况下,  响应时间在 1秒以下,  没啥问题的.  几百个连接就毛毛雨..    WIN 下用 select/poll ,  2000来个连接也完全木问题,   我测试时大概在 3,4万连接开始卡卡卡...  就懒得 ASIO 了..  嗯，这种场景下，一个线程足以........

引用 1 楼 yangyunzhao 的回复:直接上libevent，妥妥的  楼主，听听这哥们的吧

weblogic可以支持20000个线程同时运行呢，更加何况你是C的代码。

补充下：几百个线程并不多。只不过创建销毁线程太多的话 CPU会耗在这个上面，所以建议使用线程池

用你说的模型，然后加上线程池。  至于具体的我没法说，google或者baidu。我只能提供思路。

epoll ？

直接上libevent，妥妥的

你都说了是select了，还想要什么？

如果几百台同时连接，那么就要开几百个线程。占用的资源确实很大。帮顶

就是普通的select模式阿,连windows下的iocp都不是,应该也和linux下的epoll有差别,咋没什么人回答呢???


Question: 在vc可以编译，但在Linux下不行，麻烦帮我看一下什么问题！谢谢

前置声明又没有用，前置声明只能使用指向不完整类型的指针

会了，谢谢帮忙！

前面加上声明：struct student;   #include<stdio.h> #define N 3 struct student; void input(struct student stu[]); void  highavg(struct student stu[]); void avg(struct student stu[]);  struct student { 	char no[3],name[5]; 	unsigned int classno; 	int course1grade,course2grade,course3grade; 	int avg;  }stu[N];  int main() { 	struct student *p;  	p=stu; 	input(p); 	highavg(p); 	avg(p); 	return 0; }  void input(struct student stu[]) { 	int i; 	for(i=0;i<N;i++) 	{       		scanf("%s%s%d%d%d%d",&stu[i].no,&stu[i].name,&stu[i].classno,&stu[i].course1grade,&stu[i].course2grade,&stu[i].course3grade); 		stu[i].avg=(stu[i].course1grade+stu[i].course2grade+stu[i].course3grade)/3;  	} 	printf("学号 姓名 班级 课程1 课程2 课程3 平均分\n"); 	for(i=0;i<N;i++) 		printf("%4s %4s %4d %4d %4d %4d  %d\n",stu[i].no,stu[i].name,stu[i].classno,stu[i].course1grade,stu[i].course2grade,stu[i].course3grade,stu[i].avg);   }  void  highavg(struct student stu[]) { 	int m=0,i=0; 	for(i=0;i<N;i++) 	{ 		if(stu[i].avg>stu[m].avg) 			m=i; 	} 	printf("输出3门课平均成绩最高的同学信息:\n"); 	printf("%4s %4s %4d %4d %4d %4d %d\n",stu[m].no,stu[m].name,stu[m].classno,stu[m].course1grade,stu[m].course2grade,stu[m].course3grade,stu[m].avg);  }     void avg(struct student stu[]) { 	int i; 	int sum1=0,sum2=0,sum3=0; 	int avg1=0,avg2=0,avg3=0; 	for(i=0;i<3;i++) 	{  		sum1+=stu[i].course1grade; 		sum2+=stu[i].course2grade; 		sum3+=stu[i].course3grade;  	} 	avg1=sum1/3; 	avg2=sum2/3; 	avg3=sum3/3; 	printf("输出全班同学3门课的平均成绩:\n"); 	printf("course1 course2 course3 \n"); 	printf("%7d %7d %7d\n",avg1,avg2,avg3); }

楼主这样写student是个不完整类型，不能在还没出现该结构体的完整定义之前直接定义对象 把struct student{.......};的定义放到函数声明前面才行  #include<stdio.h> #define N 3  struct student { 	char no[3],name[5]; 	unsigned int classno; 	int course1grade,course2grade,course3grade; 	int avg;  }stu[N];  void input(struct student stu[]); void  highavg(struct student stu[]); void avg(struct student stu[]);   int main() { 	struct student *p;  	p=stu; 	input(p); 	highavg(p); 	avg(p); 	return 0; }  void input(struct student stu[]) { 	int i; 	for(i=0;i<N;i++) 	{       		scanf("%s%s%d%d%d%d",&stu[i].no,&stu[i].name,&stu[i].classno,&stu[i].course1grade,&stu[i].course2grade,&stu[i].course3grade); 		stu[i].avg=(stu[i].course1grade+stu[i].course2grade+stu[i].course3grade)/3;  	} 	printf("学号 姓名 班级 课程1 课程2 课程3 平均分\n"); 	for(i=0;i<N;i++) 		printf("%4s %4s %4d %4d %4d %4d  %d\n",stu[i].no,stu[i].name,stu[i].classno,stu[i].course1grade,stu[i].course2grade,stu[i].course3grade,stu[i].avg);   }  void  highavg(struct student stu[]) { 	int m=0,i=0; 	for(i=0;i<N;i++) 	{ 		if(stu[i].avg>stu[m].avg) 			m=i; 	} 	printf("输出3门课平均成绩最高的同学信息:\n"); 	printf("%4s %4s %4d %4d %4d %4d %d\n",stu[m].no,stu[m].name,stu[m].classno,stu[m].course1grade,stu[m].course2grade,stu[m].course3grade,stu[m].avg);  }     void avg(struct student stu[]) { 	int i; 	int sum1=0,sum2=0,sum3=0; 	int avg1=0,avg2=0,avg3=0; 	for(i=0;i<3;i++) 	{  		sum1+=stu[i].course1grade; 		sum2+=stu[i].course2grade; 		sum3+=stu[i].course3grade;  	} 	avg1=sum1/3; 	avg2=sum2/3; 	avg3=sum3/3; 	printf("输出全班同学3门课的平均成绩:\n"); 	printf("course1 course2 course3 \n"); 	printf("%7d %7d %7d\n",avg1,avg2,avg3); }


Question: 关于二级函数指针

c语言使用的过程中&函数名简化为函数名，&go实际上还是go

因为 你的 *p 访问的地址不合法，想用的话你得先分配个内存给他才能解除引用，用楼上说的那种一级指针吧，这种纯属没事找事

不是int (*p)(int a, int b) = &&go;  而是int (*p)(int a, int b) = &go;

int (*p)(int a, int b) = &go; int (**pp)(int a, int b) = &p;

但是为什么用二级函数指针就不能修改了？  比如 :      int  类型。 int **是可以去间接改变int *的值的。

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

这样不就行了？  #include "stdio.h" #include "stdlib.h" #include "Windows.h"   int go6688(int a, int b) { 	MessageBoxA(0, "劫持指令", "你已经被劫持" ,0); 	return 0; }  int go(int a, int b) { 	printf("haha\n"); 	return 0; }    void main() { 	int i = 1; 	int (*p)(int a, int b) = &go; 	p = go6688;             	printf("%p %p\n", go, go6688); 	system("pause"); }


Question: c语言问题

安装WinRAR，右键点击你的程序目录——添加到xxxxxxx.rar

引用 1 楼 zhao4zhong1 的回复:cd /d "C:\Program Files\WinRAR" rar a myprog_setup d:\mydir\myprog.exe rar s myprog_setup copy myprog_setup.exe d:\mydir  谢谢赵老师，因为我是初学者，您写的我看不懂啊。。。能不能详细写一下？？


Question: 文件指针使用循环打开文件在关闭为什么会出错！

已  引用 1 楼 user-1 的回复:if (   fp = fopen(str, "r") == NULL  )  改成 if ((fp = fopen(str, "r")) == NULL)  忘记括号了 感谢！


Question: 别人问的，这个错误怎么解决，求大神，跪谢，今天交作业啊。。。。

c=malloc(sizeof(int*)*len1); //改为: c=(int**)malloc(sizeof(int*)*len1);

14行改为： c = (int **)malloc(sizeof(int *) * len1);


Question: 请教问题，函数返回不成功。

引用 19 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];  感谢赵老师指教！ 另外最后这段，我个人理解的是：将输入的整数型字符 看成一个数组，其中s[0]储存整数型字符，s[1]及s[2]储存‘\n'。 不知道这样理解是否正确。

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

引用 21 楼 zhao4zhong1 的回复:scanf("%c",&c);不能自动跳过若干个空白字符（包括空格，Tab字符，换行符）， scanf("%1s",s);能跳过若干个空白字符（包括空格，Tab字符，换行符），读取1个非空白字符到s[0]中，s[1]里面保存'\0‘  感谢赵老师为我这初学者解释这么初浅的问题。争取之后不再问这种问题。

引用 17 楼 zhao4zhong1 的回复:我承认我有点为炫而炫了。  别说对新人了，对十几年的老人都不一定看得懂啊！（借机又炫了一次）  赵老师，以及各位。 12楼的程序在vs2015中出现了这个问题。。

赵老师，这个我还看不懂。 暂仅学到字符输入/输出与输入确认。   引用 15 楼 zhao4zhong1 的回复:偶特来炫一下C和C++挑出N重循环和函数调用的招： #include <stdio.h> #include <setjmp.h> jmp_buf mark; int i=0; void c() {     printf( "c in\n");     if (1==i%2) longjmp( mark, i );     printf( "c out\n"); } void b() {     printf( "b in\n");     c();     printf( "b out\n"); } void a() {     printf( "a in\n");     b();     printf( "a out\n"); } void main( void ) {    int jmpret;    jmpret = setjmp( mark );    printf( "Start %d\n",jmpret);    if( jmpret == 0 ) {        printf( "First\n");        a();        i++;        a();    } else {        printf( "Second\n");    } } //Start 0 //First //a in //b in //c in //c out //b out //a out //a in //b in //c in //Start 1 //Second //  #include <iostream> using namespace std; struct MyStruct {     int Nodedata;     MyStruct *pLeft;     MyStruct *pRight; } s1,s2,s3,s4,s5,s6,s7,s8; void ashow(MyStruct * p) {     if (p != nullptr) {         ashow(p->pLeft);         ashow(p->pRight);         cout << p->Nodedata << endl;         if (p->Nodedata == 4) {             throw 1;//退出递归.直接返回.         }     } } int main() {     MyStruct *pRoot;//根      pRoot = &s1;     s1.Nodedata = 1;     s2.Nodedata = 2;     s3.Nodedata = 3;     s4.Nodedata = 4;     s5.Nodedata = 5;     s6.Nodedata = 6;     s7.Nodedata = 7;     s8.Nodedata = 8;      s1.pLeft = &s2;     s1.pRight = &s3;      s2.pLeft = &s4;     s2.pRight = &s5;      s3.pLeft = &s6;     s3.pRight = &s7;     try {         ashow(pRoot);     } catch (int err) {         cout<<"catch err "<<err<<endl;     }     return 0; } //4 //catch err 1 //

引用 13 楼 qcx1221 的回复:唯一的缺陷： default里面的q to quit无法启动。。 当输入q的时候可以返回一个特殊值，在main函数中检测这个值，当该值被返回时，退出main函数。不过因为层级比较深，操作起来有点麻烦，视情况而定吧

唯一的缺陷： default里面的q to quit无法启动。。

根据版主qq423399099及ghx287524027及的指教： 特修正如下: #include <stdio.h> #include <windows.h> void meum(void); double xuanze(char ch); void jisuan(double base); int main(void) { 	double base = 0.00; 	char ch;  	meum(); 	while((ch = getchar()) != 'q'){ 		base = xuanze(ch); 		jisuan(base); 		fflush(stdin); 		meum(); 	} 	system("pause"); 	return 0; }  void meum(void) { 	printf("*************************************************************************\n"); 	printf("a)$8.75/hr                          b)$9.33/hr\n"); 	printf("c)$10.00/hr                         d)$11.20/hr\n"); 	printf("q)quit  \n"); 	printf("*************************************************************************\n"); 	printf("请根据以上选项输入您的每小时的基本工资（q to quit)： "); }  double xuanze(char ch) { 	double base; 	int flag = 1;  	while(1) 	{ 		flag = 1; 		switch (ch) { 			case 'a': 			case 'A': base = 8.75; break; 			case 'b': 			case 'B': base = 9.33; break; 			case 'c': 			case 'C': base = 10.00; break; 			case 'd': 			case 'D': base = 11.20; break; 			default:  				{ 				printf("请输入a、b、c、d，q to quit.\n"); flag = 0; fflush(stdin); ch = getchar();break; 				 } 		} 		if(flag) 			break; 	} 	printf("您的基本工资为%.2f/H.\n", base); 	return base; }  void jisuan(double base) { 	const int jbsj = 40; 	const double shui15 = 0.15; 	const double shui20 = 0.20; 	const double shui25 = 0.25; 	const int jd1 = 300; 	const int jd2 = 450; 	double gz, sj, shui, jgz; 	gz = sj = shui = jgz = 0.00;  	printf("请输入您工作的时间： \n"); 	scanf_s("%lf", &sj); 	if (sj > jbsj) 		sj = 40 + (sj - 40)*1.5; 	gz = sj * base; 	if (gz <= 300)  		shui = gz * shui15; 	else if (gz <= 450)  		shui = jd1 * shui15 + (gz - jd1) * shui20; 	else  		shui = jd1 * shui15 + (jd2 - jd1) * shui20 + (gz - jd1) * shui25; 	jgz = gz -shui; 	printf("您的工资为%.2f，税金为%.2f，净工资为%.2f.\n\n\n", gz, shui, jgz); }

从优化角度上来说，第一，变量定义后最好初始化；第二，应该加个循环，以增加鲁棒性；第三，对于字符型输入，应设置为不区分大小写

类似这样：  double xuanze(char ch) { 	double base; 	int flag; 	while(1) 	{ 		flag = 1; 		switch (ch) { 		case 'a': base = 8.75; break; 		case 'b': base = 9.33; break; 		case 'c': base = 10.00; break; 		case 'd': base = 11.20; break; 		default: 			{ 				printf("请输入a、b、c、d，q to quit.\n"); flag = 0;fflush(stdin);ch = getchar(); break; 			} 		} 		if(flag) 			break; 	}  	printf("您的基本工资为%.2f/H.\n", base); 	return base; }

引用 7 楼 qq423399099 的回复:第五行的声明有问题，改成这样就行了： void jisuan(double base);  另外，在 xuanze定义函数中输入非abcd的值都导致错误，这里面是否应该添加个循环。正确时候跳出，错误时循环。

最终根据两位给予的指点，完成以下代码，请继续指点： #include <stdio.h> #include <windows.h> void meum(void); double xuanze(char ch); void jisuan(void); int main(void) { 	double base; 	char ch;  	meum(); 	while((ch = getchar()) != 'q'){ 		base = xuanze(ch); 		jisuan(base); 		fflush(stdin); 		meum(); 	} 	system("pause"); 	return 0; }  void meum(void) { 	printf("*************************************************************************\n"); 	printf("a)$8.75/hr                          b)$9.33/hr\n"); 	printf("c)$10.00/hr                         d)$11.20/hr\n"); 	printf("q)quit  \n"); 	printf("*************************************************************************\n"); 	printf("请根据以上选项输入您的每小时的基本工资（q to quit)： "); }  double xuanze(char ch) { 	double base; 	switch (ch) { 		case 'a': base = 8.75; break; 		case 'b': base = 9.33; break; 		case 'c': base = 10.00; break; 		case 'd': base = 11.20; break; 		default: printf("请输入a、b、c、d，q to quit.\n"); break; 	} 	printf("您的基本工资为%.2f/H.\n", base); 	return base; }  void jisuan(double base) { 	const int jbsj = 40; 	const double shui15 = 0.15; 	const double shui20 = 0.20; 	const double shui25 = 0.25; 	const int jd1 = 300; 	const int jd2 = 450; 	double gz, sj, shui, jgz;  	printf("请输入您工作的时间： \n"); 	scanf_s("%lf", &sj); 	if (sj > jbsj) 		sj = 40 + (sj - 40)*1.5; 	gz = sj * base; 	if (gz <= 300)  		shui = gz * shui15; 	else if (gz <= 450)  		shui = jd1 * shui15 + (gz - jd1) * shui20; 	else  		shui = jd1 * shui15 + (jd2 - jd1) * shui20 + (gz - jd1) * shui25; 	jgz = gz -shui; 	printf("您的工资为%.2f，税金为%.2f，净工资为%.2f.\n\n\n", gz, shui, jgz); }

引用 3 楼 qcx1221 的回复:[quote=引用 2 楼 ghx287524027 的回复:] 将第二层while循环放到第一层循环之中，如下：  while((ch = getchar()) != 'q'){     base = xuanze(ch);     printf("请输入您工作的时间： \n"); //  while ((scanf_s("%lf", &sj)) == 1.00) {     while ((sj = getchar()) != 'q'){         if (sj > jbsj)             sj = 40 + (sj - 40)*1.5;         gz = sj * base;         if (gz <= 300) {             shui = gz * shui15;             jgz = gz - shui;         }         else if (gz <= 450) {             shui = jd1 * shui15 + (gz - jd1) * shui20;             jgz = gz - shui;         }         else {             shui = jd1 * shui15 + (jd2 - jd1) * shui20 + (gz - jd1) * shui25;             jgz = gz - shui;         }         printf("您的工资为%.2f，税金为%.2f，净工资为%.2f.\n\n\n", gz, shui, jgz);           fflush(stdin);         meum();     } }   另外，你输入的时间为什么要和‘q’比较，这样没什么意义吧。 时间可以以 scanf("%lf",&sj) 的形式输入，不过要在输入之前清空一下缓冲区，即应该是： fflush(stdin);  scanf("%lf",&sj)；   感谢您的回复与指教。 根据您的指点，我修改成为以下代码： #include <stdio.h> #include <windows.h> void meum(void); double xuanze(char ch); int main(void) { 	const int jbsj = 40; 	const double jb = 1.5; 	const double shui15 = 0.15; 	const double shui20 = 0.20; 	const double shui25 = 0.25; 	const int jd1 = 300; 	const int jd2 = 450; 	double sj, base, gz, shui, jgz; 	char ch;  	meum(); 	while((ch = getchar()) != 'q'){ 		base = xuanze(ch); 		printf("请输入您工作的时间： \n"); 		fflush(stdin); 		scanf_s("%lf", &sj); 		if (sj > jbsj) 				sj = 40 + (sj - 40)*1.5; 			gz = sj * base; 		if (gz <= 300) { 				shui = gz * shui15; 				jgz = gz - shui; 		} 		else if (gz <= 450) { 				shui = jd1 * shui15 + (gz - jd1) * shui20; 				jgz = gz - shui; 		} 		else { 				shui = jd1 * shui15 + (jd2 - jd1) * shui20 + (gz - jd1) * shui25; 				jgz = gz - shui; 		} 		printf("您的工资为%.2f，税金为%.2f，净工资为%.2f.\n\n\n", gz, shui, jgz); 		fflush(stdin); 		meum(); 		} 	system("pause"); 	return 0; }[/quote]  这样可以，应该就是你想要的吧

这是vc环境下的写法：  #include <stdio.h> #include <windows.h> void meum(void); double xuanze(char ch); int main(void) {     const int jbsj = 40;     const double jb = 1.5;     const double shui15 = 0.15;     const double shui20 = 0.20;     const double shui25 = 0.25;     const int jd1 = 300;     const int jd2 = 450;     double sj, base, gz, shui, jgz;     char ch;       meum();      while((ch = getchar()) != 'q'){ 		base = xuanze(ch); 	 		printf("请输入您工作的时间： \n"); 		fflush(stdin); 		scanf("%lf", &sj); 		if (sj > jbsj) 			sj = 40 + (sj - 40)*1.5; 		gz = sj * base; 		if (gz <= 300) { 			shui = gz * shui15; 			jgz = gz - shui; 		} 		else if (gz <= 450) { 			shui = jd1 * shui15 + (gz - jd1) * shui20; 			jgz = gz - shui; 		} 		else { 			shui = jd1 * shui15 + (jd2 - jd1) * shui20 + (gz - jd1) * shui25; 			jgz = gz - shui; 		} 		printf("您的工资为%.2f，税金为%.2f，净工资为%.2f.\n\n\n", gz, shui, jgz); 		meum(); 		fflush(stdin); 	}     system("pause");     return 0; }   void meum(void) {     printf("*************************************************************************\n");     printf("a)$8.75/hr                          b)$9.33/hr\n");     printf("c)$10.00/hr                         d)$11.20/hr\n");     printf("q)quit  \n");     printf("*************************************************************************\n");     printf("请根据以上选项输入您的每小时的基本工资(q to quit)： "); }   double xuanze(char ch) {     double base;     switch (ch) {         case 'a': base = 8.75; break;         case 'b': base = 9.33; break;         case 'c': base = 10.00; break;         case 'd': base = 11.20; break;         default: printf("请输入a、b、c、d，q to quit.\n"); break;     }     printf("您的基本工资为%.2f/H.\n", base);     return base; }


Question: C 下数字相减导致数据异常的问题。

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

计算过程是这样的， 上面是我没写清楚， 本来是想把变量的 类型直接带在前面的：  ttt = x -((unsigned long) y - (unsigned long) z) -sizeof(aaa);

引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 因为只有一个core文件，暂时复现不了， 然后用core文件里面的数据，打桩 对这个地方单元测试，也没出现上面的问题。  这个地方的内存被踩的问题，我也初步排除了。 我把这个数据附近的内存，都打印出来了， 除了正常赋值的部分，没有发现其他 异常地址那里有这个异常数据（也就是初步排除了memcpy这些内存之类的操作，导致的踩内存覆盖）。 还有一个就是 指针++ 导致的 踩内存，这个 还不确定，是不是有这个问题，不过在上面那个表达式附近，没有指针++的操作，所以应该也不是这个问题导致的。

Type-Cast Conversions You can use type casts to explicitly convert types.   Syntax  cast-expression :  unary expression ( type-name ) cast-expression  type-name :  specifier-qualifier-list abstract-declarator opt  The type-name is a type and cast-expression is a value to be converted to that type. An expression with a type cast is not an l-value. The cast-expression is converted as though it had been assigned to a variable of type type-name. The conversion rules for assignments (outlined in Assignment Conversions) apply to type casts as well. Table 4.5 shows the types that can be cast to any given type.  Table 4.5   Legal Type Casts  Destination Types Potential Sources  Integral types Any integer type or floating-point type, or pointer to an object  Floating-point Any arithmetic type  A pointer to an object, or (void *) Any integer type, (void *), a pointer to an object, or a function pointer  Function pointer Any integral type, a pointer to an object, or a function pointer  A structure, union, or array  None  Void type Any type    Any identifier can be cast to void type. However, if the type specified in a type-cast expression is not void, then the identifier being cast to that type cannot be a void expression. Any expression can be cast to void, but an expression of type void cannot be cast to any other type. For example, a function with void return type cannot have its return cast to another type.   Note that a void * expression has a type pointer to void, not type void. If an object is cast to void type, the resulting expression cannot be assigned to any item. Similarly, a type-cast object is not an acceptable l-value, so no assignment can be made to a type-cast object.   Microsoft Specific —>  A type cast can be an l-value expression as long as the size of the identifier does not change. For information on l-value expressions, see L-Value and R-Value Expressions.   END Microsoft Specific  You can convert an expression to type void with a cast, but the resulting expression can be used only where a value is not required. An object pointer converted to void * and back to the original type will return to its original value.

引用 10 楼 ghx287524027 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote]  我在想，楼主用的什么编译器呢，那么写竟然还能编过去[/quote] gcc的编译器呢， 我不是太清除，我写了那个地方 编译器不让 编译。 愿意请教，呵呵。

引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote] 确实有点晕，知道的不是非常清除。 愿听赵老师详解。

引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote]  我在想，楼主用的什么编译器呢，那么写竟然还能编过去

引用 8 楼 ghx287524027 的回复:对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。

引用 5 楼 ghx287524027 的回复:你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？ 这就是一个算包长度的过程，包整个长度  减包头的长度，得到包的长度，很简单的一个问题

引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 只有一个core文件，无法复现  引用 5 楼 ghx287524027 的回复:你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？ 代码就是上面的那个啊，只是用  X, Y , Z代替了。 我看了一下整个代码，因为这个ttt的数据， 传递给下一个函数的时候，不是指针，直接是变量传值，然后我用gdb把栈上，所有这个变量的赋值看过(因为不是指针传进去的，所以肯定不会出现某个修改导致其他地方看到的这个数据都被修改了)，都是这个值，所以这个值肯定是一开始就算错了，不会是因为越界把数据踩了导致的， 上面那个地方就是最开始算数据的地方，只是我没看明白，为啥算了个巨大无比的数据出来了。

你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？

int  ttt = (unsigned short) x -((unsigned long) y - (unsigned long) z) -sizeof(aaa);

把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出

引用 1 楼 ghx287524027 的回复:char *y = 0x7fd33d232036，char*z = 0x7fd322e86800  这不是指针类型吗，怎么直接拿来做运算了？？？ 算长度用的，应该很常见吧


Question: 使用异或进行文件内容加密时出现问题

引用 2楼赵4老师 的回复:不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了但是，为什么先将文件内容写入数组后再进行异或运算，并将结果写入文件就可以，两种方式都是用的getc来读取，putc输出的，区别就只是一个是先写进数组，再进行异或运算，一个是在读取时就进行，应该说产生的字符是一样的才对，好纠结。

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

引用 5楼ghx287524027 的回复:两种方式的完整代码怎么写的？贴出来看看吧刚刚看了下，是我看错了，以文本方式读取都无法异或回去，想来原因应该就是异或后产生的特殊字符函数无法操作吧

两种方式的完整代码怎么写的？贴出来看看吧

引用 2 楼 zhao4zhong1 的回复:不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  对，以字节的形式读写就没问题了，按字符读写的话，有的特殊符号是操作不了的

这和具体异或出来的值有关，对于一些特殊的值，fgetc和fputc是无法操作的


Question: C语言遍历C盘所有.exe文件并将路径与文件名输出到TXT文件中出现问题

强势围观看看

fwrite试试

一个这么简单的功能写了100行，我用python写不会超过20行

我之前写过一个：http://blog.csdn.net/wangyaninglm/article/details/8668132

如何写的正确答案

写代码过滤fc命令的输出。

引用system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。 如果嫌system黑窗口一闪，将system("...")替换为WinExec("cmd /c ...",SW_HIDE); 那能不能用shell比较两个TXT文件不同，并显示出不同的地方，这里的TXT文件都是逐行分析的，我用了windows下 fc 命令，但是有点不理想，把两个文件都显示出来了

会不会是权限不够？不能在C盘目录下写入文件，换个盘试试 或者单步调试检查每一步的变量值和各个返回值。 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

建议单步跟踪程序运行（特别是最后输出那一部分）以分析原因

就是调用系统的shell是吧，这实现了，然后还得从allfilesinsub.txt文件中逐行读取，计算文件MD5再保存进去，就还是要用到格式化输入输出函数了


Question: //使用返回指针的函数查找最大值  帮看下哪里错了 运行不了 调试可以

我弄错了 不好意思

引用 1 楼 zxh707wk 的回复:#include<stdio.h>  int* findmax(int* a,int n) {     int* max=a;     int i=0 ;     for(i=1;i<n;i++)     {         if(*max<*(a+i))         {             max=a+i;         }     }     return max ; } int main() {     int a[10];     int i;     int* max;     printf("please input 10 number");     for(i=0;i<10;i++)     	scanf("%d",&a[i]);     max=findmax(a,10);     printf("%d",*max);     return 0; }   一楼有错啊

你下面四句的逻辑有问题 max=p+i;     //max指向p+i所指向的元素 *(p+i)=*(p+i+1);  //用后一个元素的值覆盖前一个 *(p+i+1)=*(p+i);  //用前一个元素的值又赋值给后面一个元素？？？ max=(p+i);        //又执行一遍max=p+i？？  而且你这个return的位置也不对，for循环就行一次就return了

很多问题  *findmax(int *a,int n) 改成 int* findmax(int *a,int n)  另外for(p=a;p<a+10;p++) 这里p没有定义  另外不懂你思路，写的很混乱

帮忙看下怎么修改我的  楼上的方法我知道


Question: C语言问题，谢谢

弧度/角度

拿PI的实际值减去公式计算的值进行比较


Question: 没有error 为啥不能运行？

帮楼主稍微改了改  #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 3 struct telebook{ 	char num[4]; 	char name[10]; 	char phonenumber[15]; 	char email[20]; 	struct telebook *next; }; struct telebook *list=0; struct telebook *p=0; struct telebook *r=0; struct telebook *t=0; struct telebook *k=0; struct telebook *l=0; struct telebook *o=0; void inputrecord() { 	int i,j; 	list=NULL; 	for(i=0;i<N;i++) 	{ 		p=(struct telebook*)malloc(sizeof(struct telebook)); 		p->next=NULL; 		printf("num:"); 		printf("\n"); 		scanf("%s",p->num); 		printf("name:"); 		scanf("%s",p->name); 		printf("phonenumber:"); 		scanf("%s",p->phonenumber); 		printf("email:"); 		scanf("%s",p->email); 		if(list==NULL) 			list=p; 		else 			r->next=p; 		r=p; 		printf("确认输入下一个联系人？\n1.yes    2.no"); 		scanf("%d",&j); 		if(j==2) 			break; 	}  } void insertrecord() { 	p=(struct telebook*)malloc(sizeof(struct telebook)); 	p->next=NULL; 	printf("num:"); 	printf("\n"); 	scanf("%s",p->num); 	printf("name:"); 	scanf("%s",p->name); 	printf("phonenumber:"); 	scanf("%s",p->phonenumber); 	printf("email:"); 	scanf("%s",p->email); 	r->next=p; 	r=p; } void displayrecord() { 	for(t=list;t!=NULL;t=t->next) 	{ 		printf("%S   %s   %s   %s",t->num,t->name,t->phonenumber,t->email); 		printf("\n"); 	}  }  void deleterecord() { 	char num[10]; 	printf("please input the num you want to delete:"); 	scanf("%s",num); 	k=list; 	while(strcmp(num,(k->next)->num)!=0) 	{ 		k=k->next; 	} 	k=(k->next)->next; }  void searchrecord() { 	char name[10]; 	printf("please input the name you want to find:"); 	scanf("%s",name); 	l=list; 	while(strcmp(name,l->name)!=0) 	{ 		l=l->next; 	} 	printf("%s  %s  %s  %s",l->num,l->name,l->phonenumber,l->email); } void modifyrecord() { 	char name[10]; 	printf("input the name you want to modify:"); 	scanf("%s",name); 	o=list; 	while(strcmp(name,o->name)!=0) 	{ 		o=o->next; 	} 	printf("num:"); 	printf("\n"); 	scanf("%s",o->num); 	printf("name:"); 	scanf("%s",o->name); 	printf("phonenumber:"); 	scanf("%s",o->phonenumber); 	printf("email:"); 	scanf("%s",o->email); }  int main() { 	int j; 	void inputrecord(); 	void insertrecord(); 	void displayrecord(); 	void deleterecord(); 	void searchrecord(); 	void modifyrecord(); 	while(1) 	{ 		printf("************************The telephone --book Management System！");  		printf("\n"); 		printf("1.input record\n2.display record\n3.delete record\n4.search record\n5,insert record\n6.modify record\n"); 		printf("please choose:"); 		scanf("%d",&j); 		switch(j) 		{ 		case 1:inputrecord();break; 		case 2:displayrecord();break; 		case 3:deleterecord();break; 		case 4:searchrecord();break; 		case 5:insertrecord();break; 		case 6:modifyrecord();break; 		default:printf("wrong!"); 		}  	} }

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

p=(struct telebbook*)malloc(sizeof(struct telebook));前面的 telebbook和后面的 telebook都不一样的  char num[10]; 。。。  scanf("%s",num[10]);内的num[10]，不行的吧，已经越界了最大为num[9]吧

void inputrecord(); void insertrecord(); void displayrecord(); void deleterecord(); void searchrecord(); void modifyrecord(); 这些东西，似乎放外部的，调用的上面就行吧，不应放main内的

#include<stdio.h> #include<stdlib.h> #include<string.h> #define N 3 struct telebook{ char num[4]; char name[10]; char phonenumber[15]; char email[20]; struct telebook *next; }; struct telebook *list=0; struct telebook *p=0; struct telebook *r=0; struct telebook *t=0; struct telebook *k=0; struct telebook *l=0; struct telebook *o=0; void inputrecord() { int i,j; list=NULL; for(i=0;i<N;i++) { p=(struct telebook*)malloc(sizeof(struct telebook)); p->next=NULL; printf("num:"); printf("\n"); scanf("%s",p->num); printf("name:"); scanf("%s",p->name); printf("phonenumber:"); scanf("%s",p->phonenumber); printf("email:"); scanf("%s",p->email); if(list==NULL) list=p; else r->next=p; r=p; printf("确认输入下一个联系人？\n1.yes    2.no"); scanf("%d",&j); if(j==2) break; }  } void insertrecord() { p=(struct telebook*)malloc(sizeof(struct telebook)); p->next=NULL; printf("num:"); printf("\n"); scanf("%s",p->num); printf("name:"); scanf("%s",p->name); printf("phonenumber:"); scanf("%s",p->phonenumber); printf("email:"); scanf("%s",p->email); r->next=p; r=p; } void displayrecord() { for(t=list;t!=NULL;t=t->next) { printf("%S   %s   %s   %s",t->num,t->name,t->phonenumber,t->email); printf("\n"); }   }   void deleterecord()  {     char num[100];     printf("please input the num you want to delete:");     scanf("%s",num[10]);     k=list;      while(strcmp(&num[10],(k->next)->num)!=0)      {         k=k->next;  }  k=(k->next)->next;  }    void searchrecord()  {  	char name[100];  	printf("please input the name you want to find:");  	scanf("%s",name[10]);  	l=list;      while(strcmp(&name[10],l->name)!=0)      {         l=l->next;  } printf("%s  %s  %s  %s",l->num,l->name,l->phonenumber,l->email);  }  void modifyrecord()  {  	char name[100];  printf("input the name you want to modify:");  scanf("%s",name[10]);  o=list;      while(strcmp(&name[10],o->name)!=0)      {         o=o->next;  }  printf("num:"); printf("\n"); scanf("%s",o->num); printf("name:"); scanf("%s",o->name); printf("phonenumber:"); scanf("%s",o->phonenumber); printf("email:"); scanf("%s",o->email);   }  void creatrecord() { 	return; }   int main()   {   	int j; void inputrecord(); void insertrecord(); void displayrecord(); void deleterecord(); void searchrecord(); void modifyrecord();   	while(1)   	{   	printf("************************The telephone --book Management System！");          printf("\n");         printf("1.input record\n2.display record\n3.delete record\n4.search record\n5,insert record\n6.modify record\n");   	printf("please choose:");   	scanf("%d",&j);   	switch(j)   	{   	case 1:creatrecord();break;   	case 2:displayrecord();break;   	case 3:deleterecord();break;   	case 4:searchrecord();break;   	case 5:insertrecord();break; case 6:modifyrecord();break; default:printf("wrong!");   }   	     } 	return 0;   }  ////初步改了下，这样才可以编译运行的，至于效果，还要改的哦

编译时没有错误并不能保证运行时也没有错误，运行错误建议出错时断下通过调用堆栈、变量监视窗口等观察分析原因

我其实不懂为啥Link会有问题，

前面和后面的telebook为啥不一样啊

没有error?为什么没有error，lz用的什么编译器。 好大的一个链接错误, creatrecord没有实现，甚至连申明都没有


Question: 请问这段代码是什么意思？谁能帮我解释下，有偿

CCS中运行数据从可以通过串口读过来

sscanf ？？？ 是scanf 吧

呃。。你可以把代码复制到编译器vc++或者gcc或者vs，编译运行。就知道这段代码什么意思了。无奈╮（╯＿╰）╭

现在的码农竟然99%都不会在cmd窗口中输入cd命令设置当前目录为程序所在目录，输入程序名运行程序了！


Question: C语言新手求助帖

（const typeof(((type *)0)->member)* __mptr=(ptr);） 这句应该是给类或者结构体中的成员变量指针赋值。


Question: 小弟求解，关于代码优化的问题，这段代码改如何优化

首先看你的这个是否符合你们的要求，如果效率不够那么再来看瓶颈在哪。 接着说看瓶颈：    粗糙的：你可以直接写个时间统计（简单的那种计时）    精确的：google intel都有性能测试工具

https://blogs.msdn.microsoft.com/visualstudioalm/2015/07/20/performance-and-diagnostic-tools-in-visual-studio-2015/ 先用工具找出性能瓶颈，然后改进……  再给个例子 https://www.zhihu.com/question/27768721 楼主自己按类似的套路搞吧，自己搞出来的东西，印象才深刻

感觉是for循环太多，不过可以在里面插入循环计数值，看看能否在算法上优化。  可以参考一下这个代码 http://blog.csdn.net/jia20003/article/details/16369143

有没大神解答一下啊，，，

分析性能，查看哪里是主要耗时，然后再看怎么优化  http://www.jb51.net/article/35771.htmhttp://

设置输出Release版。


Question: VS中C语言0x0f6d20a7 (msvcr100d.dll) 处有未经处理的异常: 0xC0000005: 读取位置 0x00369e9时发生访问冲突

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

已经改了，但读出来的数据还是乱码

引用 4 楼 yanzi0310 的回复:c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\atlstr.h(16): fatal error C1189: #error :  ATL requires C++ compilation (use a .cpp suffix) 出现错误 将你的源代码扩展名由.c改为.cpp

str.Format(_T("%d年%d月%d日%d时%d分%d秒"),year,month,day,hour,minute,second); _ftprintf(out,_T("%s %lf %lld %lld %hd %.11s %.7s\n"),str, buffer[i].GpsDataTime,buffer[i].t0Counter,buffer[i].t0Frequency,buffer[i].SatelliteNum,buffer[i].Latitude,buffer[i].Altitude);

GetLocalTime(&buffer[i].OldSystemTime); 		 int year,month,day,hour,minute,second; 		 year =buffer[i].OldSystemTime.wYear; 		 month = buffer[i].OldSystemTime.wMonth; 		 day = buffer[i].OldSystemTime.wDay; 		 hour = buffer[i].OldSystemTime.wHour; 		 minute = buffer[i].OldSystemTime.wMinute; 		 second = buffer[i].OldSystemTime.wSecond; 		 CString str; 		 		str.Format(L"%d年%d月%d日%d时%d分%d秒",year,month,day,hour,minute,second); 		fprintf(out,"%s %lf %lld %lld %d %s %s\n",str.Format(L"%d年%d月%d日%d时%d分%d秒",year,month,day,hour,minute,second), 			buffer[i].GpsDataTime,buffer[i].t0Counter,buffer[i].t0Frequency,buffer[i].SatelliteNum,buffer[i].Latitude,buffer[i].Altitude); 这块不知道怎么写了

SYSTEMTIME这个不能直接%s格式化吧，你要先用字符串转一次


Question: 关于结构体数组输入和输出的一个小问题。

引用 9 楼 lm_whales 的回复:常有的事情，有时候会出现多了，少了个分号，大括号的错误 结果往往系统报错是某某头文件错误 偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

先学会跟踪代码，再学会写代码。

引用 4 楼 paschen 的回复:[quote=引用 3 楼 setihomesfl 的回复:] [quote=引用 2 楼 paschen 的回复:] 两处 for (j = 0; j < 5; j++) 这个后面都多了一个分号  是的 就是这一个疏忽导致[/quote]  如果调试时单步跟踪程序运行，我想你不应该花4小时才发现 [/quote] 因为是小程序所以就没有跟踪,也因为是简单所以就没有往这方面想.

引用 3 楼 setihomesfl 的回复:[quote=引用 2 楼 paschen 的回复:] 两处 for (j = 0; j < 5; j++) 这个后面都多了一个分号  是的 就是这一个疏忽导致[/quote]  如果调试时单步跟踪程序运行，我想你不应该花4小时才发现

引用 2 楼 paschen 的回复:两处 for (j = 0; j < 5; j++) 这个后面都多了一个分号  是的 就是这一个疏忽导致

两处 for (j = 0; j < 5; j++) 这个后面都多了一个分号

#define Printfshuchu printf("%s %d %s %d",xuesheng[j].name,xuesheng[j].number,xuesheng[j].csex,xuesheng[j].igrade); Printfshuchu(printf);

引用 6 楼 zhao4zhong1 的回复:先学会跟踪代码，再学会写代码。 主要是没几句代码,感觉没必要用. 也没往细节那去想 以为是别的问题.太大意了.


Question: 关于ListView_SetCheckStatic()函数的问题，为什么它不起作？

if (!AdjustPrivileges()) {         printf("Error:Couldn't AdjustPrivileges!\n");         exit(1);     }

引用 1 楼 赵4老师的回复:bool AdjustPrivileges() {     HANDLE hToken;     TOKEN_PRIVILEGES tp;     TOKEN_PRIVILEGES oldtp;     DWORD dwSize=sizeof(TOKEN_PRIVILEGES);     LUID luid;      if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {         if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) return true;         else return false;     }     if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {         CloseHandle(hToken);         return false;     }     ZeroMemory(&tp, sizeof(tp));     tp.PrivilegeCount=1;     tp.Privileges[0].Luid=luid;     tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;     /* Adjust Token Privileges */     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {         CloseHandle(hToken);         return false;     }     // close handles     CloseHandle(hToken);     return true; }  请问这个函数怎么使用？

引用 2 楼 赵4老师的回复:void MyGetListViewItem(HWND hWindow,TStrings *strlist) {     const nMaxLen=1023;     char szBuf[nMaxLen+1];     char buf[nMaxLen+1];      int          nLVItemCount;     int          nColumns;     DWORD        dwProcessID;     HANDLE       hProcess;     HANDLE       hHeaderCtrl;     LVITEM       lvItemLocal;     HDITEM       hdItemLocal;     DWORD        dwBytesRead, dwBytesWrite;     bool         bSuccess,bWriteOK;      //注意：本文来自www.ccrun.com，by ccrun(老妖)，转载请注明出处。     //本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=583&d=eahk4z     //为防止某些不负责任的转载者，故出此下策，在代码中加入声明，请大家原谅。      GetWindowThreadProcessId(hWindow,&dwProcessID);     hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessID);     if(!hProcess)  //得不到指定进程的句柄         return;     //在指定进程内分配存储空间     LPVOID lpTextRemote=VirtualAllocEx(hProcess,NULL,nMaxLen+1,MEM_COMMIT,PAGE_READWRITE);     LPVOID lpListItemRemote=VirtualAllocEx(hProcess,NULL,sizeof(LVITEM),MEM_COMMIT,PAGE_READWRITE);     LPVOID lpHeadItemRemote=VirtualAllocEx(hProcess,NULL,sizeof(HDITEM),MEM_COMMIT,PAGE_READWRITE);     if((!lpTextRemote) || (!lpListItemRemote) || (!lpHeadItemRemote)) //不能在指定进程内分配存储空间         return;      nLVItemCount=ListView_GetItemCount(hWindow);     hHeaderCtrl=ListView_GetHeader(hWindow);     nColumns=Header_GetItemCount(hHeaderCtrl);     if (nColumns<=0) {         nColumns=1;     } else {         buf[0]=0;         for (int j=0;j<nColumns;j++) {             ZeroMemory(szBuf,nMaxLen+1);             bWriteOK= WriteProcessMemory(hProcess,lpTextRemote,(LPVOID)szBuf,nMaxLen+1,(LPDWORD)&dwBytesWrite);             if(!bWriteOK) //写内存错误                 return;             hdItemLocal.mask=HDI_TEXT;             hdItemLocal.cchTextMax=nMaxLen;             hdItemLocal.pszText=(LPTSTR)lpTextRemote;             dwBytesWrite=0;             bWriteOK=WriteProcessMemory(hProcess,lpHeadItemRemote,(LPVOID)&hdItemLocal,sizeof(HDITEM),(LPDWORD)&dwBytesWrite);             if(!bWriteOK) //写内存错误                 return;              SendMessage(hHeaderCtrl,HDM_GETITEM,(WPARAM)j,(LPARAM)lpHeadItemRemote);             bSuccess=ReadProcessMemory(hProcess,lpTextRemote,szBuf,nMaxLen+1,&dwBytesRead);             //从指定进程存储空间读取文本             if(!bSuccess) //不能在指定进程内读取文本                 return;             if (j>0) strcat(buf,"|");             strcat(buf,AnsiString(szBuf).c_str());         }         strlist->Add(buf);     } //  strlist->Add("ListView的Columns数: " + String(nColumns)); //  strlist->Add("---------------------------");      for (int i=0;i<nLVItemCount;i++) {         buf[0]=0;         for (int j=0;j<nColumns;j++) {             ZeroMemory(szBuf,nMaxLen+1);             bWriteOK= WriteProcessMemory(hProcess,lpTextRemote,(LPVOID)szBuf,nMaxLen+1,(LPDWORD)&dwBytesWrite);             if(!bWriteOK) //写内存错误                 return;             lvItemLocal.iItem=i;             lvItemLocal.iSubItem=j;             lvItemLocal.mask=LVIF_TEXT;             lvItemLocal.cchTextMax=nMaxLen;             lvItemLocal.pszText=(LPTSTR)lpTextRemote;             dwBytesWrite=0;             bWriteOK=WriteProcessMemory(hProcess,lpListItemRemote,(LPVOID)&lvItemLocal,sizeof(LVITEM),(LPDWORD)&dwBytesWrite);             if(!bWriteOK) //写内存错误                 return;             SendMessage(hWindow,LVM_GETITEMTEXT,(WPARAM)i,(LPARAM)lpListItemRemote);             bSuccess=ReadProcessMemory(hProcess,lpTextRemote,szBuf,nMaxLen+1,&dwBytesRead);             //从指定进程存储空间读取文本             if(!bSuccess) //不能在指定进程内读取文本                 return;             if (j>0) strcat(buf,"|");             strcat(buf,AnsiString(szBuf).c_str());         }         strlist->Add(buf);     }//end of for(i)     //在指定进程内释放存储空间     VirtualFreeEx(hProcess,lpHeadItemRemote,0,MEM_RELEASE);     VirtualFreeEx(hProcess,lpListItemRemote,0,MEM_RELEASE);     VirtualFreeEx(hProcess,lpTextRemote,0,MEM_RELEASE);     //关闭指定进程句柄     CloseHandle(hProcess); } //---------------------------------------------------------------------------  我怎么找不到那个 TStrings类型的变量呢？


Question: 用getchar输入4个字符到数组，输出数组时，结果却很奇怪，求助！

引用 11 楼 qq423399099 的回复:因为你char str1[]="7777999999999999999999999999sdfsdfsdfdsff";这样写意味着编译器只会为他分配42+1个字节的空间 后面可能紧挨着别的变量或者一些有用的信息 你如果拼接以后就会越界写入，可能覆盖了一些重要的信息，比如VS下变量周围地址含调试信息，会报异常的  谢谢！

引用 9 楼 qq423399099 的回复:vs下报异常。 明明就是strcat的效果…… 函数那样写没啥大问题，但不能这样去调用  是的，就是strcat效果。 为什么函数可以这么写，而main中不能这么写呢？

这个代码是将字符串str2附加到str1。str2附加到str1上后，str1和没附加前比，应该算越界了。但代码运行是正常的。   #include <stdio.h> #include <string.h>  void copy(char *p,const char *q); int main(void) { 	//将字符串str2附加到str1  	char str1[]="7777999999999999999999999999sdfsdfsdfdsff"; 	char str2[] ="hello,world!sdfsdfsfsdfsfdsfdsffdsdfdsfdsfdsfsdf";  	copy(str1,str2); 	puts(str1); 	 	 	return 0; };  void copy(char *p,const char *q) { 	char *temp = p; 	while(*temp != '\0') { 		temp++; 	} 	 	while(*q != '\0') { 		*temp=*q; 		q++; 		temp++; 	} 	 	*temp = '\0'; 	 }

加printf("%p %p %p %p %p\n", &a, &b, &c, &d, str1); 后的截图：

我在看《C语言程序设计现代方法》，这本书里有个例子，字符串复制例子，复制时，字符数组也没有声明长度。指针移动到'\0'处开始复制目标字符串中的字符。  我现在是有些晕菜。

引用 4楼我是你的主体 的回复:用的是Dev C++加上printf("%p %p %p %p %p\n", &a, &b, &c, &d, str1); 后运行结果再截个图

用的是Dev C++

楼主用的什么IDE? 我这里VS编译跑出来结果是对的  楼主再多跑几次结果还是这样？ 那就在char d = getchar();下面加一句： printf("%p %p %p %p %p\n", &a, &b, &c, &d, str1); 可能分配地址的时候d是紧挨着str1的，执行*p++=b;（刚好覆盖掉char d的内存） 也就是内存中是这样的：str1--d--c--b--a  PS：归根结底还是你代码有问题char str1[]="";这样写会造成越界 改成char str1[5]="";

是的，%c打印数组内容，%d是打印的地址。  我发现数组1和数组3的值是一样后，就用%d查看地址是否一致，发现1和3的地址是不一致的，但数值却是一致的。  不知道怎么回事？

%d打印的是指针位置


Question: C语言的main函数中竟然允许定义子函数？

少不了

任何编译器都上不了那么几个“方言”。

引用 1 楼 qq423399099 的回复:楼主的编译器是？ mingw编译OK， VC2013 fail

应该是gcc扩展支持嵌套函数。

楼主的编译器是？