Question: C语言链表，同一个函数，为什么调用位置不一样，一个正常，一个就程序崩溃了呢

自己malloc的空间，用完随手free是个好习惯 #include<stdio.h> #include<malloc.h>  typedef struct List {     int data;     struct List *next; } Sqlist;  void printList(Sqlist *list) {     while (list ->next != NULL) {         list = list -> next;         printf("%d\n", list -> data);     } }  Sqlist * createListByArray(int *a) {     Sqlist *list, *s, *t;     list = (Sqlist *)malloc(sizeof(Sqlist));     t = list;     for(int i = 0; i < 5; i++) {         s = (Sqlist *)malloc(sizeof(Sqlist));         s -> data = *(a + i);         t -> next = s;         t = s;     }     t -> next = NULL;      //位置1     printList(list);     return list; }  void deletelist(Sqlist *head) {     Sqlist *q,*p = head;     while(p != NULL)     {         q = p;         p = p->next;         free(q);         q = NULL;     } }  int main(int argc, char *argv[]) {     int a[] = {1, 2, 3, 4, 5};     Sqlist *list;      list = createListByArray(a);      //位置2     printList(list);      deletelist(list);  }

楼上的谢谢你（没找到怎么直接回复），很抱歉早你一分钟结贴了

位置2中，printList(list);   list并没有指向链表头，只是Sqlist *list;分配的地址。和生成链表函数中list = (Sqlist *)malloc(sizeof(Sqlist));  list的地址是不一样的，这个函数中的list才是指向链表。  #include<stdio.h> #include<malloc.h>  typedef struct List { 	int data; 	struct List *next; } Sqlist;  void printList(Sqlist *list) { 	while (list -> next != NULL) { 		list = list -> next; 		printf("%d\n", list -> data); 	} }  Sqlist * createListByArray(Sqlist *list, int *a) { 	Sqlist *s, *t; 	list = (Sqlist *)malloc(sizeof(Sqlist)); 		printf("2=%#X\n",list); 	t = list; 	for(int i = 0; i < 5; i++) { 		s = (Sqlist *)malloc(sizeof(Sqlist)); 		s -> data = *(a + i); 		t -> next = s; 		t = s; 	} 	t -> next = NULL;  	//位置1 	printList(list); 	return list; }  int main(int argc, char *argv[]) { 	int a[] = {1, 2, 3, 4, 5}; 	Sqlist *list,*h; 	printf("1=%#X\n",list); 	h=createListByArray(list, a); 		printf("3=%#X\n",h);  	//位置2 	printList(h); }   添加了3个printf函数帮助识别list的地址

我知道了，下面是我的理解，做个笔记： 用纯C的话，malloc动态申请内存之后会返回一个指针，而形参为*p时，虽然*p的值与主函数中的*p相同，但是p的地址却不相同，因此对p的赋值（值为mallo的返回值）并没有作用到主函数p上，也就是主函数中的*p其实并没有初始化，所以可以在函数中返回*p，然后主函数中接受函数返回值来初始化主函数的*p； 而使用C++的话，则可以使用*&p，这个传递的是主函数中p的真是地址，函数中对p赋值，即为对主函数中的p赋值； 另外，形参为*&p时候，如fun（int *&p）;不知道为什么不可以直接fun（&a）;而只能int *q = &a; fun（q）;还不知道为啥

有大佬没


Question: printf函数有关的问题


Question: 求哪位帮我看看，一元多次式为什么只输出第一个啊

引用 2 楼 qq_41985711的回复:[quote=引用 1 楼 weixin_42814069的回复:]跪求大神    啊 你的 creatList 函数里面不能实现一次输入多个节点，因为你 指针p的指向没有变，故一直都是给p指向的内存写入数据，在循环中写上这么一句  p = p->next; 删除r = p; 最后在循环外加上  p = NULL; r = p;这样可以一次给多个节点赋值，但是并不能将所有节点返回，只返回头节点，有头节点就可以循环查找。建议:creatList函数只创建一个节点。其次，你上传问题代码之后进行排版和注释方便阅读。（电脑没网络，用的手机，不能打出具体代码，请谅解）[/quote] 没看清代码，见笑了

引用 1 楼 weixin_42814069的回复:跪求大神    啊 你的 creatList 函数里面不能实现一次输入多个节点，因为你 指针p的指向没有变，故一直都是给p指向的内存写入数据，在循环中写上这么一句  p = p->next; 删除r = p; 最后在循环外加上  p = NULL; r = p;这样可以一次给多个节点赋值，但是并不能将所有节点返回，只返回头节点，有头节点就可以循环查找。建议:creatList函数只创建一个节点。其次，你上传问题代码之后进行排版和注释方便阅读。（电脑没网络，用的手机，不能打出具体代码，请谅解）

跪求大神    啊


Question: 找不到错误，挺简单的小程序。

引用 2 楼 user-2 的回复:[quote=引用 1 楼 jyupup 的回复:] 各位帮帮忙。解决了立即采纳。。萌新刚学不久。。  楼主，下面的代码可供参考~~  #include<stdio.h> int main(void) { 	printf("Please input eight numbers:"); 	int i = 0, j = 0; 	double ch[8], sum[8]; 	while (i++ < 8) 		scanf_s("%lf", &ch[i-1]);  	sum[0] = ch[0]; 	while (j++ < 8) 		sum[j] = sum[j - 1] + ch[j];  	i = 0, j = 0; 	while (i++ < 8) 		printf("%lf  ", ch[i - 1]);  	while (j++ < 8) 		printf("%lf  ", sum[j - 1]); 	return 0;  }[/quote] 感谢解答 原来这段代码里已经改正错误了没有仔细看不好意思。。

引用 2 楼 user-2 的回复:[quote=引用 1 楼 jyupup 的回复:] 各位帮帮忙。解决了立即采纳。。萌新刚学不久。。  楼主，下面的代码可供参考~~  #include<stdio.h> int main(void) { 	printf("Please input eight numbers:"); 	int i = 0, j = 0; 	double ch[8], sum[8]; 	while (i++ < 8) 		scanf_s("%lf", &ch[i-1]);  	sum[0] = ch[0]; 	while (j++ < 8) 		sum[j] = sum[j - 1] + ch[j];  	i = 0, j = 0; 	while (i++ < 8) 		printf("%lf  ", ch[i - 1]);  	while (j++ < 8) 		printf("%lf  ", sum[j - 1]); 	return 0;  }[/quote] 感谢你的回答 不过我主要想找到自己程序的问题所在 想先养成自己的风格。。

你的代码数组越界了，while(i++<8)第一次循环i的值已经是1了，而你的代码逻辑以为是0 int main() { 	printf("Please input eight numbers:"); 	int i = 0, j = 0; 	double ch[8], sum[8]; 	while (i++ < 8) 		scanf_s("%lf", &ch[i-1]); 	sum[0] = ch[0]; 	while (j++ <8) 		sum[j] = sum[j - 1] + ch[j]; 	i = 0, j = 0; 	while (i++ < 8) 		printf("%lf  ", ch[i-1]); 	while (j++ < 8) 		printf("%lf  ", sum[j-1]); 	return 0; }

引用 1 楼 jyupup 的回复:各位帮帮忙。解决了立即采纳。。萌新刚学不久。。  楼主，下面的代码可供参考~~  #include<stdio.h> int main(void) { 	printf("Please input eight numbers:"); 	int i = 0, j = 0; 	double ch[8], sum[8]; 	while (i++ < 8) 		scanf_s("%lf", &ch[i-1]);  	sum[0] = ch[0]; 	while (j++ < 8) 		sum[j] = sum[j - 1] + ch[j];  	i = 0, j = 0; 	while (i++ < 8) 		printf("%lf  ", ch[i - 1]);  	while (j++ < 8) 		printf("%lf  ", sum[j - 1]); 	return 0;  }

各位帮帮忙。解决了立即采纳。。萌新刚学不久。。


Question: 三个数 分别取平均值

谢谢 看成1了

scanf ("%lf%lf%lf",&x, &y, &z); 注意输入的是%lf不是%1f;即f前面的是一个l,字母l,大写是L，不是数字1.  即使是1也没关系，但是表达的意思就不一样了。建议查找一下相关的知识（带数字的输入格式）。 scanf ("%lf%lf%lf",&x, &y, &z);     printf("%lf, %lf, %lf\n", x, y, z); 输入之后加一条打印，确保输入的内容和自己想的是否一致，便于定位问题。


Question: 字符与字符串取地址

谢谢，我知道了。

正如楼上所说 char test = 'a'; &a的值是0x00D6F953  而0x00D6F953的内容是

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

因为字符是常量，比如'a'，&'a'取地址怎么理解？我们取地址一般是对于变量来讲的  char ch = 'a'  printf("%p\n", &ch);   字符串本身就是地址，就像数组名就是数组的首地址一样。

char c = 'a'; printf("0x%x", &c); 哪里不能获取字符地址了？


Question: 这是什么情况，有哪位大神指点一下

sscanf 从指定字符串输入，而fscanf 是从文件输入，下面是fscanf的应用#include<stdlib.h> #include<stdio.h> #include<string.h>  int main(void) {     FILE *file;     char name[123];     char password[123];     char name_tmp[123];     char password_tmp[123];     char name_pass[256];     char *ret;     int login_success = 0;      file = fopen("D:\\liu\\lx.txt","r+");     if (file == NULL)     {         printf("文件打开失败！");         return 1;     }      while(1)     {         printf("请输入用户名：");         scanf("%s",name);         printf("请输入密码：");         scanf("%s",password);          while(1)         { //            ret = fgets(name_pass,sizeof(name_pass),file); //            if (ret==NULL)      //判断文件有没有读取成功 //            { //                break; //            } // //            sscanf(name_pass,"%s %s",name_tmp,password_tmp);              fscanf(file,"%s %s",name_tmp,password_tmp);              if((strcmp(name,name_tmp) == 0) && strcmp(password,password_tmp) == 0)             {                 printf("登陆成功！\n");                 break;             }             else             {                 printf("用户名或密码错误！");                 system("pause");                 system("cls");                 break;             }         }     }     fclose(file);     return 0; }

你的第12行char name_pass;应该是想定义成类似如下的字符数组的吧    char name_pass[256]; 这么修改，再加上头文件#include<stdlib.h>至少你贴出来的代码可以运行了，如下#include<stdlib.h> #include<stdio.h> #include<string.h>  int main(void) {     FILE *file;     char name[123];     char password[123];     char name_tmp[123];     char password_tmp[123];     char name_pass[256];     char *ret;      file = fopen("D:\\liu\\lx.txt","r+");     if (file == NULL)     {         printf("文件打开失败！");         return 1;     }      while(1)     {         printf("请输入用户名：");         scanf("%s",name);         printf("请输入密码：");         scanf("%s",password);          while(1)         {             ret = fgets(name_pass,sizeof(name_pass),file);             if (ret==NULL)      //判断文件有没有读取成功             {                 break;             }              sscanf(name_pass,"%s %s",name_tmp,password_tmp);              if((strcmp(name,name_tmp) == 0) && strcmp(password,password_tmp) == 0)             {                 break;             }             else             {                 printf("用户名或密码错误！");                 system("pause");                 system("cls");             }         }     }     return 0; }

好的谢谢。在问一下，fscanf和sscanf的语法有什么区别

能否把代码直接贴出来，测试现象可以截图嘛

#include<stdio.h> #include<string.h>  int main(void) { 	FILE *file; 	char name[123]; 	char password[123]; 	char name_tmp[123]; 	char password_tmp[123]; 	char name_pass; 	char *ret;  	file = fopen("D:\\liu\\lx.txt","r+"); 	if (file == NULL) { 		printf("文件打开失败！"); 		return 1; 	}  	while(1) { 		printf("请输入用户名："); 		scanf("%s",name); 		printf("请输入密码："); 		scanf("%s",password);  		while(1) { 			ret = fgets(name_pass,sizeof(name_pass),file); 			if (ret==NULL) {    //判断文件有没有读取成功 				break; 		}  			sscanf(name_pass,"%s %s",name_tmp,password_tmp);  		if((strcmp(name,name_tmp) == 0) && strcmp(password,password_tmp) == 0) { 			break; 		} else { 			printf("用户名或密码错误！"); 			system("pause"); 			system("cls"); 		} 		} 	} 	return 0;   下面是编译错误代码 aaa.c: In function 'main': aaa.c:26:4: warning: passing argument 1 of 'fgets' makes pointer from integer without a cast [enabled by default] In file included from aaa.c:1:0: c:\mingw\bin\../lib/gcc/mingw32/4.7.1/../../../../include/stdio.h:354:39: note: expected 'char *' but argument is of type 'char' aaa.c:31:4: warning: passing argument 1 of 'sscanf' makes pointer from integer without a cast [enabled by default] In file included from aaa.c:1:0: c:\mingw\bin\../lib/gcc/mingw32/4.7.1/../../../../include/stdio.h:348:37: note: expected 'const char *' but argument is of type 'char' aaa.c:42:2: error: expected declaration or statement at end of input


Question: 请问如何快速按位匹配需要的值

KMP算法吧，这个速度比较快

引用 1 楼 u014444402 的回复:扫一次不就可以了。。也不费时间吧。这个只是一个32位，如果数量多了的话时间就体现出来了。

扫一次不就可以了。。也不费时间吧。


Question: 不用C语言加锁，echo "hello world" >> test.txt能做到原子性吗？

《Windows核心编程》

这不是echo的问题，你打开了再多system(echo)也只不过是打开了很多cmd的进程而已，这些进程有自己的进程空间相互不干扰，都是输出到自己的进程空间。 你想问的其实是>> test.txt 输出到文件，cmd文件的读写应该是不共享写入的，一个cmd进程只能等待test.txt的句柄关闭之后才能写入，这时候cmd的程序本身应该是等待的，你可以测试一下，挂一下NtCreateFile函数 参考 HANDLE WINAPI CreateFile( _In_ LPCTSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile );


Question: 关于链表 为啥这个y输出不了，链表的建立有问题么

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

#include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct a{     int shuzi;     struct a*point; } hei;  //int a = 0; void diy_free(hei *head) {     head = head->point;     hei *p2;     while (head != NULL)     {         p2 = head->point;         free(head);         head = p2;     } }  void diy_jia(hei *head, int number) {     hei* p1, *pnew;      p1 = head;     for (;number > 0; number--) {         pnew = (hei *)malloc(sizeof(hei));         if (!pnew)             return;          p1->point = pnew;         p1 = pnew;     }     p1->point = NULL; #if 0     if (!(head)->point)     {         for (number; number>0; number--)         {             p1 = (hei*)malloc(sizeof(hei));             head->point = p1;             head = p1;         }     }      else     {         while (head->point)             head = head->point;         for (number; number>0; number--)         {             p1 = (hei*)malloc(sizeof(hei));             head->point = p1;             head = p1;         }     }     head->point = NULL; #endif }  void main() {     int y;     hei* head = (hei*)malloc(sizeof(hei));     if (head == NULL)         return;      head->point = NULL;     head->shuzi = 0;      diy_jia(head, 8);      hei* ptemphead = head;     for (y = 0; head->point; head = head->point)         y++;      printf("%d", y);      head = ptemphead;      diy_free(head);      free(head); } 参考一下吧

楼主，你上面的代码，刚开始hei *head;这行代码没有给head初始化，导致编译不通过，还是diy_free里面的代码也存在错误。下面代码可供参考： #include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct a{ 	int shuzi; 	struct a*point;  } hei;  int a = 0; void diy_free(hei *head) { 	head = head->point; 	hei *p2; 	while (head != NULL) 	{ 		p2 = head->point; 		free(head); 		head = p2; 	} }  void diy_jia(hei *head, int number) { 	hei* p1; 	if (!(head)->point) 	{ 		for (number; number>0; number--) 		{ 			p1 = (hei*)malloc(sizeof(hei)); 			head->point = p1; 			head = p1; 		} 	}  	else 	{ 		while (head->point) 			head = head->point; 		for (number; number>0; number--) 		{ 			p1 = (hei*)malloc(sizeof(hei)); 			head->point = p1; 			head = p1; 		} 	} 	head->point = NULL;  }  void main() { 	int y; 	hei* head = (hei*)malloc(sizeof(hei)); 	if (head == NULL) 		return;  	head->point = NULL; 	head->shuzi = 0;  	diy_jia(head, 8);  	hei* ptemphead = head; 	for (y = 0; head->point; head = head->point) 		y++;  	printf("%d", y);  	head = ptemphead;  	diy_free(head);  	free(head); }


Question: 解释一下运行结果为什么是0 0 0 0 0 1 2 3 4

答案并非书上写的0 0 0 0 0 1 2 3 4 。 要搞明白这道题的答案，就需要我们明白变量在内存中的存储位置和存储方式，以及scanf("%d",&c);这句语句的具体执行方式。 首先，作为局部变量i和c，在内存中的存储位置是由高位地址向低位地址存放的，如下图所示。所以整型i的存储起始地址是0060FF08，在内存中0060FF08，0060FF09，0060FF0A和0060FF0B这四个字节表示了i 其次，int类型的i占的这4个字节，也是从高位地址向低位地址存放的，如下图所示。也就是说当i = 1时,地址0060FF0B存储的是i最低位的00000001部分，所以按顺序0060FF0B+0060FF0A+0060FF09+0060FF08组成的值是i  然后就是scanf("%d",&c)的执行方式：当程序要求scanf读入一个整数，应该传递给它一个指向整型的指针。而程序中scanf函数得到的却是个指向字符的指针。由于scanf函数并不能分辨这种情况，所以它只是将这个指向字符的指针作为指向整数的指针而接受，并且在指针指向的位置存储一个整数。 也就是说，由于c是字符，所以只分配了1个字节的内存给c，然后指派了一个指向字符的指针用来指向c（也就是图中的地址0060FF07）；但是scanf明明读到的是个int型啊，所以scanf在往这个地址写东西的时候，确实是把这个读到的整数都写进去了，于是就冲掉了上面i的后三个字节。然后每次循环时i++，变成1后，scanf一读一写，i的最后三个字节就被冲掉了，所以i的值就一直被改写，只要不满足循环的终止条件，就只能一直这么死循环下去。 要验证这个说法，只要在scanf("%d",&c)时输入>=1025的整数，满足条件了，也就终止循环了。  另外，根据scanf函数的特性，如果在scanf("%d",&c)时遇到输入的是非数字字符，比如'a'，scanf也会停止读入，然后scanf()函数把非数字字符放回输入。这意味着在改程序下一次读入时，首先读取到的是上一次丢弃的非数字字符。然后这里就等于没有往c里写值，所以也就能够满足条件，终止循环了。 以下代码供参考  #include<stdio.h>  main() {     int i = 2;     char c;     unsigned char * p = (unsigned char *)(&i);     printf("i %p,sizeof(i) = %d\n",&i,sizeof(i));     printf("c %p,sizoef(c) = %d\n",&c,sizeof(c));      printf("init: 第1字节（最低位）：%d,第2字节：%d,第3字节：%d,第4字节（最高位）：%d\n",*p,*(p+1),*(p+2),*(p+3));     printf("init: 第1字节（最低位）地址：%p,第2字节地址：%p,第3字节地址：%p,第4字节（最高位）地址：%p\n",p,(p+1),(p+2),(p+3));     for(i = 0; i < 5; i++)     {         p = (unsigned char *)(&i);         printf("before scanf: 第1字节：%d,第2字节：%d,第3字节：%d,第4字节：%d\n",*p,*(p+1),*(p+2),*(p+3));         scanf("%d",&c);         p = (unsigned char *)(&i);         printf("after scanf: 第1字节：%d,第2字节：%d,第3字节：%d,第4字节：%d\n",*p,*(p+1),*(p+2),*(p+3));         printf("%d\n",i);     }     printf("\n"); }

建议打出i，c的地址。 i = 0x7fff2eebf604 c = 0x7fff2eebf603  这是我打印出来的地址值。  出现你的问题的原因应该是c是%d格式输入的，因为%d默认是sizeof(int)个字节，这样就会导致每次输入之后就会将i的内容覆盖，导致每次输入之后，i的值都是0，最后是一个死循环（在我的平台上是这样的）。

语言应该没有规定变量地址分布 你那个是未定义行为

在输入时scanf("%d",&c); 是错误的，c是char型，应该用%c 。在修改后，你可以把printf("%x,%x",&i,&c);输出两者的地址，

你的输入是什么‘


Question: C语言基础 大佬帮看看

是你对题意的理解产生了偏差，并非你认为的以40分钟为一个周期。 你可以检查一下，当t = 100时，应该是兔子胜出，但你的程序判断为乌龟胜出。 题目很简单，你可以先用常规思路解决问题，或者先列举前180分钟内每隔10分钟的情况，然后再来找规律。

周期是90分钟，LZ自己画图分析一下

#include <stdio.h>    int compare(int time)  {  	if(time>90)  	{  		printf("time error");  		return 0;  	}  	else if((time>0&&time<30)||(time>45&&time<60))  	{  		printf("^_^ ");  		return 1;//兔子快  	}  	else if(time>30&&time<45||(time>60&&time<90))  	{  		printf("@_@ ");  		return 2;//乌龟快  	}  	else  	{  		printf("-_- ");  		return 3;//一样快  	}  }    int howlong(int who,int time,int cir)  {  	switch(who)  	{  		case 1:if(time<=10){return (cir*270+time*9);}  		       else if(time<=40){return (cir*270+90);}  		       else if(time<=50){return (cir*270+90+time*9);}  		       else if(time<=80){return (cir*270+180);}  		       else if(time<=90){return (cir*270+180+time*9);}  		       else{printf("time error"); return 0;}  		       break;  		case 2:return (cir*270+time*3);break;  		case 3:return (cir*270+time*3);break;  	}  }    void main()  {  	int time,cir;  	printf("how long the time is(min):");  	scanf("%d",&time);  	cir=time/90;  	time%=90;  	printf("%d meter\n",howlong(compare(time),time,cir));  }


Question: 关于指针

引用 12 楼 qq_41985711的回复:[quote=引用 11 楼 qq_41985711的回复:]int *p = &a[0]; 因为二维数组的首元素是a[0]这个数组，所以p要指向a[0]这个数组，就是 *(p+i) 二维数组的第i个元素，也就是二维数组第i个元素的数组名，所以这是一个指针，指向的是二维数组里第i个元素里的第一个元素。而*(*(p+i)+j) 就是二维数组第i个元素里的第j个元素。区别就是 p = a;这个语句指针p指向的内容只有一个字节，而 p = &a[0]指向的是20个字节。 p = &a指向的是16个字节的内容，打错了[/quote] 又打错了  p =&a[0]指向的是16个字节

引用 11 楼 qq_41985711的回复:int *p = &a[0]; 因为二维数组的首元素是a[0]这个数组，所以p要指向a[0]这个数组，就是 *(p+i) 二维数组的第i个元素，也就是二维数组第i个元素的数组名，所以这是一个指针，指向的是二维数组里第i个元素里的第一个元素。而*(*(p+i)+j) 就是二维数组第i个元素里的第j个元素。区别就是 p = a;这个语句指针p指向的内容只有一个字节，而 p = &a[0]指向的是20个字节。 p = &a指向的是16个字节的内容，打错了

引用 8 楼 fafactx 的回复:所有多维数组在内存里均是一纬数组存的。 太武断了你。 参考#5

你的p定义为int* 类型，但是却解引用了两次，肯定有问题。

2楼说的在理，实质上还是类型不匹配的原因。

可以从*(*(p + i)这里思考一下： 楼主那么定义显然p和a是不等价的 首先p是int*的，而a虽然本质上也是个地址但是最起码也是个int**，否则不会有*(*(p + i)这种操作。 但是即使是int** p; p和a也不是等价的。因为指针的“+"操作是需要知道所指向的类型的。*（p+1）到底是指向下一个元素，还是下一行呢？无法知道。因此才会有楼上的这种写法，明确指出（p+1）指针所要移动距离。

所有多维数组在内存里均是一纬数组存的。

#include<stdio.h> int main() {     int a[3][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };     int i,j;     int (*p)[4] = a;     for (i = 0; i < 3; i++)     {         for (j = 0; j < 4; j++)         {             printf("%2d  ", *(*(p + i) + j));         }         printf("\n");     }     return 0; } 改成这样就可以了。类型不匹配

楼主：个人理解，int * p=a;代码是应该指向a二维数组的开始地址a[0]或者&(a[0][0])，而二维数组的存储应该是连续的地址，在代码*(*(p + i) + j)中，(p + i) 表示p向后移动 i 个 int类型大小的内存距离，即p指向新的内存位置(p +i )，而代码*(p + i) 表示去(p+i)指向的内存位置的内容值，即*(p + i)已经表示一个值了，而不是表示一个地址了。而代码*(p + i) + j当然也是表示值了，再代码*(*(p + i) + j)，再值的前面加上*字符，应该就报错了。因为(*(p + i) + j)表示的值而不是地址了。

类型不匹配，出错行int * p=a;编译器警告为：error: cannot convert 'int (*)[4]' to 'int*' in initialization; 显然，根据错误提示，无法将a的指向整型数组的指针（错误提示中的int (*)[4]）类型转换成指向整型变量的指针p（错误提示中的int*），那么我们将定义改为int (*p)[4] = a;就OK了。后序使用时，p用起来就和a没有差别了。 至于“如果将11行改为printf("%d  ", *(*(a + i) + j));就可以正常输出；”，其实是因为，数组名在使用过程中，可以看做是指向该数组下标为0的元素的指针。先看一维数组int a[3] = {1,2,3};用数组的方式理解，也就是a[0] = 1;a[1] = 2;a[2] = 3; 从指针的角度理解，a就是指向下标元素0的指针， 那么，a+0指向的就是数组元素a[0]的地址，所以*(a+0) 即*a那就是a[0]的值1; 同理，a+1指向的就是数组元素a[1]的地址，*(a+1)就是指向数组a中下标为1的元素a[1]的值2； 类推，a+i指向的就是数组元素a[i]的地址，*(a+i)就是指向数组a中下标为i的元素a[i]的值； 所以a[i] = *(a+i)  有了一维数组的例子，那么对于二维数组a[3][4]来说 元素a[i][j]的指针表达，一步一步来，先将a[i]看做整体，那么有之前一维数组的解释a[j] = *(a+j)，我们有：  a[i][j]= *(a[i] + j) 再用一次一位数组的替换，那么就有  *(a[i] + j)= *(*(a+i)+j) 所以a[i][j]= *(a[i] + j)= *(*(a+i)+j)；也就解释了你说的为什么可以正常输出的原因。 如果要计算a[2][3]，表达方式#include<stdio.h> int main() {     int a[3][4] = { {1,3,5,7},{9,11,13,15},{17,19,21,23} };      printf("地址：*(a+1)+2 = %x, a[1]+2 = %x, &a[1][2] = %x\n",*(a+1)+2,a[1]+2,&a[1][2]);     printf("值：*(*(a+1)+2) = %d, *(a[1]+2) = %d, a[1][2] = %d",*(*(a+1)+2),*(a[1]+2),a[1][2]);      return 0; } 结果就是，三者地址一样，如果要取值，就是有这三种表达。 那么，此处我们将定义修改成： int (*p)[4] = a;也就是因为a代表的是有着3个整型数组元素的数组，而且它的每个整型数组元素又是一个有着4个整型变量的数组；比如a[1]是a数组3个元素中的第2个元素，而a[1]这个元素本身是一个有4个整形变量的数组。这么声明，其实就相当于p=a，就可以编译通过并顺利运行。

int * p=a; 这句虽然可以赋值，但编译应该有告警，类型不匹配。 正确用法 1、int *p = &a[0][0];当做一维数组用，打印可以用printf("%d",p[i]); 2、int *p[3];p[i] = a[i];指针数组。

http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组


Question: C 返回结构体数据编译出现错误

引用 1 楼 user-1 的回复:楼主，在FIND_MAXIMUM_SUBARRAY函数中的s1=FIND_MAXIMUM_SUBARRY(a,low,mid);和s2=FIND_MAXIMUM_SUBARRY(a,mid+1,high);的函数名写错了，应该是该FIND_MAXIMUM_SUBARRY为FIND_MAXIMUM_SUBARRAY吧。。。。  我TM。。。。。花了好几个小时。

下面代码，在vs2013编译通过，楼主可以查看一下~~~ # include<stdio.h> # include<stdlib.h>  //分治算法求最大子数组   struct RETURN FIND_CROSSING_SUBARRAY(int*, int, int);    //跨中点寻找最小数组  struct RETURN FIND_MAXIMUM_SUBARRAY(int*, int, int);  struct RETURN { 	int low; 	int high; 	int num; };                                          //定义用于调用函数返回的结构体   int main() { 	int a[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 }; 	struct RETURN s; 	s = FIND_MAXIMUM_SUBARRAY(a, 0, 15); 	printf("数组中最大的子数组为：a[%d]—a[%d],其和为：%d", s.low, s.high, s.num); 	getchar(); 	return 0; }  struct RETURN FIND_CROSSING_SUBARRAY(int *a, int left, int right)      // 跨中点寻找最小数组的实现  { 	int left_sum = -10000; 	int sum = 0, mid = (left + right) / 2; 	//	struct RETURN s={"-1000","1000","-10000"}; 	struct RETURN s; 	for (int i = mid; i >= left; i--){                          //寻找左边最大数组  		sum = sum + a[i]; 		if (sum>left_sum){ 			left_sum = sum; 			s.low = i; 		} 	} 	int right_sum = -10000; 	sum = 0; 	for (int i = mid + 1; i <= right; i++){                       //寻找右边最大数组  		sum = sum + a[i]; 		if (sum >= right_sum){ 			right_sum = sum; 			s.high = i; 		} 	} 	s.num = left_sum + right_sum; 	return s; }  struct RETURN FIND_MAXIMUM_SUBARRAY(int* a, int low, int high)    //分治递归调用函数  { 	struct RETURN s; 	if (high == low){ 		s.low = low, s.high = high, s.num = low; 		return s; 	} 	else{ 		struct RETURN s1, s2, s3; 		int mid = (low + high) / 2; 		s1 = FIND_MAXIMUM_SUBARRAY(a, low, mid); 		s2 = FIND_MAXIMUM_SUBARRAY(a, mid + 1, high); 		s3 = FIND_CROSSING_SUBARRAY(a, low, high); 		if (s1.num >= s2.num&&s1.num >= s3.num) 			return s1; 		else if (s2.num >= s1.num&&s2.num >= s3.num) 			return s2; 		else if (s3.num >= s2.num&&s3.num >= s1.num) 			return s3; 	}  }


Question: C语言转换问题

引用 3 楼 colinfang2006 的回复:这是C#代码吧，如果你想移植到C，必须定义 Steema.TeeChart.Axis这些结构  老铁，麻烦教我一下，我该怎么定义呢？

引用 1 楼 colinfang2006 的回复:编译错误就把编译错误贴上来啊  --------------------Configuration: wwwwwww - Win32 Debug-------------------- Compiling resources... Compiling... wwwwwwwDlg.cpp C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2065: 'Steema' : undeclared identifier C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2228: left of '.TeeChart' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2228: left of '.Axis' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2146: syntax error : missing ';' before identifier 'axis' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2065: 'axis' : undeclared identifier C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2228: left of '.tChart1' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2228: left of '.Axes' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(158) : error C2228: left of '.Left' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(160) : error C2228: left of '.AxisPen' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(160) : error C2228: left of '.Color' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(160) : error C2228: left of '.Red' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(161) : error C2228: left of '.StartPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(162) : error C2228: left of '.EndPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(165) : error C2065: 'Green' : undeclared identifier C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(165) : error C2061: syntax error : identifier 'TeeChart' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(166) : error C2228: left of '.tChart1' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(166) : error C2228: left of '.Axes' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(166) : error C2228: left of '.Custom' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(166) : error C2228: left of '.Add' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(167) : error C2228: left of '.AxisPen' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(167) : error C2228: left of '.Color' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(167) : error C2228: left of '.Green' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(168) : error C2228: left of '.StartPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(169) : error C2228: left of '.EndPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(171) : error C2065: 'Blue' : undeclared identifier C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(171) : error C2061: syntax error : identifier 'TeeChart' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(172) : error C2228: left of '.tChart1' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(172) : error C2228: left of '.Axes' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(172) : error C2228: left of '.Custom' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(172) : error C2228: left of '.Add' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(173) : error C2228: left of '.AxisPen' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(173) : error C2228: left of '.Color' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(173) : error C2228: left of '.Blue' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(174) : error C2228: left of '.StartPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(175) : error C2228: left of '.EndPosition' must have class/struct/union type C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC\Desktop\新建文件夹\wwwwwwwDlg.cpp(215) : error C2143: syntax error : missing ';' before '}' C:\Users\PC

编译错误就把编译错误贴上来啊


Question: 关于insert函数中在头指针前插入结点的求助

非常谢谢，我能问下为什么是这么操作呢？新的指针指向为什么不能赋给头指针？  引用 1 楼 sghcpt 的回复:楼主：你应该在insert函数中的最后*stu = *head这行代码用错了，下面代码可参考一下： #include <stdio.h> #include <stdlib.h> struct Student{ 	int num; 	float score; 	Student *prev; 	Student *next; };  Student *input(); void print(Student *stu); void del(Student *stu, float n); void insert(Student **stu, int m, char direc, Student *ins);  int main() { 	Student *stud, in, *inser; 	float del_score; 	int insert_num; 	char dir; 	stud = input(); 	print(stud);  	printf("Please enter insert student info: "); 	scanf("%d %f", &in.num, &in.score); 	getchar();  	inser = ∈ 	printf("Please enter insert num: "); 	scanf("%d", &insert_num); 	getchar();  	printf("Please enter F or B: ");                         //F是前插，B是后插。 	scanf("%c", &dir); 	getchar();  	insert(&stud, insert_num, dir, inser); 	print(stud);  	system("pause"); 	return 0; }  Student *input() { 	Student *p1, *p2, *head; 	int n = 0; 	p1 = p2 = (Student*)malloc(sizeof(Student)); 	printf("Please enter No.%d student info: ", n + 1); 	scanf("%d %f", &p1->num, &p1->score); 	getchar(); 	head = NULL; 	while (p1->num != 0){ 		n++; 		if (n == 1){ 			head = p1; 			p1->prev = NULL; 		} 		else{ 			p2->next = p1; 			p1->prev = p2; 		} 		p2 = p1; 		p1 = (Student*)malloc(sizeof(Student)); 		printf("Please enter No.%d student info: ", n + 1); 		scanf("%d %f", &p1->num, &p1->score); 		getchar(); 	} 	p2->next = NULL; 	return head; }  void print(Student *stu) { 	Student *p; 	for (p = stu; p != NULL; p = p->next) 		printf("%d %.2f\n", p->num, p->score); }  void del(Student *stu, float n) { 	Student *p, *head; 	for (p = stu, head = p; p != NULL; p = p->next) 	if (p->score == n){ 		if (p == head){ 			head = p->next; 			p->next->prev = NULL; 			head->next = p->next->next; 		} 		else if (p->next == NULL) 			p->prev->next = NULL; 		else{ 			p->prev->next = p->next; 			p->next->prev = p->prev; 		} 	} 	*stu = *head; }  void insert(Student **stu, int m, char direc, Student *ins) { 	Student *p, *head; 	for (p = *stu, head = p; p != NULL; p = p->next){ 		if (p->num == m){ 			if (direc == 'F'){ 				if (p == head){ 					ins->next = p; 					ins->prev = NULL; 					head = ins; 				} 				else{ 					ins->prev = p->prev; 					p->prev->next = ins; 					ins->next = p; 					p->prev = ins; 				} 			} 			else if (direc == 'B'){ 				if (p->next == NULL){ 					p->next = ins; 					ins->next = NULL; 					ins->prev = p; 				} 				else{ 					ins->next = p->next; 					p->next = ins; 					ins->prev = p; 				} 			} 		} 	} 	*stu = head; }

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633


Question: CCS工程编译报错INTERNAL ERROR: Space required for local variables exceeds maximum in m

引用 1 楼 zhao4zhong1 的回复:在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。非常感谢！


Question: c与指针-第一个程序用codeblocks编译报'columns'未声明（在此函数中首次使用）|

后来自己发现了

多一个n ，注意单词拼写

楼主，这行代码中rearrange( output, input, n_columns, columns ); 这个columns 变量应该写错了吧？应该是colums这个变量才对吧。还是read_column_number函数只声明了，还没有定义呢。。下面的代码在vs2013中编译通过，楼主，可以看看~~~ #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX_COLS 20             /* 所能处理的最大行号*/ #define MAX_INPUT 1000          /* 每个输入行的最大长度*/  int read_column_number(int columns[], int max); void rearrange(char *output, char const *input, int n_columns, int const columns[]); int main(void) { 	int n_columns;              /* 进行处理的列表号 */ 	int colums[MAX_COLS];       /* 需要处理的列数 */ 	char input[MAX_INPUT];      /* 容纳输入行的数组 */ 	char output[MAX_INPUT];     /* 容纳输出行的数组 */ 	/* 	** 读取该串列标号 	*/ 	n_columns = read_column_number(colums, MAX_COLS);  	/* 	**读取、处理和打印剩余的输入行 	*/ 	while (gets(input) != NULL){ 		printf("Original input : %s\n", input); 		rearrange(output, input, n_columns, colums); 		printf("Rearranged line: %s\n", output); 	} 	return EXIT_SUCCESS; }  /* ** 读取列标号，如果超出规定范围则不予理会。 */ int read_columns_numbers(int columns[], int max) { 	int num = 0; 	int ch;  	/* 	** 取得列标号，如果所读取的数小于0则停止。 	*/ 	while (num < max && scanf("%d", &columns[num]) == 1 		&& columns[num] >= 0) 		num += 1;  	/* 	** 确认已经读取的标号为偶数个，因为他们是以对的形式出现的。 	*/ 	if (num % 2 != 0){ 		puts("Last columns number is not paired."); 		exit(EXIT_FAILURE); 	}  	/* 	** 丢弃该行中包含最后一个数字的那部分内容。 	*/ 	while ((ch = getchar()) != EOF && ch != '\n') 		; 	return num; }  /* **处理输入行，将指定列的字符连接在一起，输出行以NUL结尾。 */ void rearrange(char *output, char const *input, 	int n_columns, int const columns[]) { 	int col;           /* columns数组的小标 */ 	int output_col;    /* 输出列计数器 */ 	int len;           /* 输入行的长度 */  	len = strlen(input); 	output_col = 0;  	/* 	** 处理每列标号 	*/ 	for (col = 0; col < n_columns; col += 2){ 		int nchars = columns[col + 1] - columns[col] + 1;  		/* 		** 如果输入行结束或输出行数组已满，就结束任务。 		*/ 		if (columns[col] >= len || 			output_col == MAX_INPUT - 1) 			break;  		/* 		** 如果输出行数据空间不够，只复制可以容纳的数据。 		*/ 		if (output_col + nchars > MAX_INPUT - 1) 			nchars = MAX_INPUT - output_col - 1;  		/* 		** 复制相关数据 		*/ 		strncpy(output + output_col, input + columns[col], 			nchars); 		output_col += nchars; 	} 	output[output_col] = '\0'; }  //下面函数需要添加代码 int read_column_number(int columns[], int max) { 	return 0; }

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


Question: sprintf问题请教

谢谢大家的指导。

可以正常运行

char sBuf[256] 这样写没有问题  但如果写成：char* sBuf = .. 就会有问题，因为这个字符串是常量

建议自己用代码调试一下； 从这句代码上来看，不会有问题。

谢谢。我写了个程序，测试了一下。正常。

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


Question: 关于C语言puts输出字符串的问题

首先puts和strlen都是找\0  在有的编译器里，char[]这个东西是根据后面{}里面的内容分配大小的，所以你这三个走下来都是对的，比如我用dev c++编译是对的。  但是有的编译器里，比如vs，会把内存里所有的地址的值都默认为0xcc，但是其他程序可能会使用了某些地址，已经写了一些值，这时你的前两种情况后面的东西是自带\0的，所以前两个char[]在内存上分配到了13，用puts或strlen找到第13位的\0返回12，然后你第三种自己是不带\0的，就是在内存上分配到了12，用puts或strlen的时候会在内存地址上一直往后找\0，所以根据不同的电脑来编译，输出的长度和字符内容都不一样，会有一些乱码。  而你现在的这个就很巧合，内存分配是随机的，但还是有规律，比如就近选取，你的正好就是c的12个后面跟了a或b的13个，所以打下来就是两个hello world！和24，而我自己试验打下来是hello world！烫烫烫烫hello world！，32长度，用十六进制展开就是'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!',0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!','\0'，中文烫的十六进制就是0xcccc  至于当你写成char[100]时，就是abc各申请了连续的100内存，这时候除过三者的12个字符数据不会连在一起，对有限定长度的数组，赋值时，不满100的其他位，vs会直接赋值\0，这些加断点都是可以看到的

引用 9 楼 weixin_42559124 的回复:一个个字符输入字符数组后，系统不会在后面自动加\0，而strlen函数的结束条件是遇到\0自动结束，所以strlen不正确，我按照你的代码试了一下但是输出结果和你的不同输出结果如下：hello world!€ 15Press any key to continue，可能答得不好请多多见谅 。 怎么会是15个字符，长度明明是12个呀！

引用 7 楼 goldenhawking 的回复:程序有问题。没有 \0 结束很危险。 你这是Debug还是Release？如果碰巧数组后面没有0填充，就有意外了。 正确的： const char  * c = "hello world"; char c[] = {'a','b','c',0}; 您看，我定义的char c[]={"..."}和定义的char c[100]={"..."}得到的结果是不一样的

引用 5 楼 zhao_miao 的回复:puts打印字符串，遇到‘\0’会停止，因为你的char c[]没有'\0',所有它打印出hello，world之后会打印随机值。 strlen也是遇到‘\0’停止，char c[]没有'\0'所有打印出来的也是随机值也不随机啊，因为试了好几次都是输出了两遍得hello world！

第一个不是字符串，而是字符数组。因为没有'\0'。 第二个也是字符数组，但是指定了字符数组的长度100，实际字符长度是12个，后面的88个字符是用'\0'填充。因此可以认为是字符串。

就在红框里面，我列出的是三种字符串的表达形式，第三种如果没有规定字符串数组的长度的话，用puts()函数的话输出额是两遍“hello world！”而且看出字符串的长度是上两种表达形式的二倍，但是我给字符串数组规定长度的话（长度为大于12的任意值），三种表达方式输出的结果都一样了，我想知道这是为什么。   很抱歉，这是我第一次问问题，还是菜鸡的说

什么问题也不说，还要别人猜吗？

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素


Question: 二哥养细菌问题，运行时输入完敲回车没反应，不知道哪里错了

//while (HaveZeroFlag=1)             while (HaveZeroFlag==1) 这儿死循环了。因此跳不出循环。判断语句不是赋值语句，建议以后注意

while (HaveZeroFlag=1)  死循环 改成 while (HaveZeroFlag==1)


Question: C语言基础 初学者 大佬帮看一下问题出在哪了

引用 1 楼 zjjone 的回复:sacnf("%lf %lf",&a,&b); sacnf这是什么东西？谢老哥，真是蠢到家了

这种问题编译会描述的很清楚啊

sacnf("%lf %lf",&a,&b); sacnf这是什么东西？


Question: glibc中的源码感觉不完整啊

引用 1 楼 zjjone 的回复:这本来就不是真正的定义，就是一个别名，类似C++的模板，在编译的时候才真正生成定义。 个人理解，不喜勿喷。 那按理说也应该有个具体的定义啊，比如说一个个的去读什么的，这里面只有出现错误时的反应。


Question: 输出最长的单词

考虑到最长的单词可能不止一个，程序修改如下，供参考 另外，在给变量命名时最好取有点意义的名字，或者添加注释，不然回头再看或者修改这个程序，头大。。。 #include<stdio.h> #include<string.h> int n[100] = { 0 }; int i, j, s = 0, m, t, x;  int main() {     void lenthest(char a[]);     char a[100] = { 0 };      gets(a);     a[99] = '\0';      lenthest(a);      return 0; }   void lenthest(char a[]) {     int notonlyoneflag = 0;     int n[100] = { 0 };     int start[100];//开一个数组，用于记录单词的起始位置     int i, j, s = 0, m, t, x = 0;     for (j = 0, i = 0; x < strlen(a); j++)     {         for (i = x; a[i] != ' ' && a[i] != '\0'; i++)        //统计单词数             n[j] = i - x + 1;                              //将每个单词的字母数依次存放在数组n中         start[j] = x;//同步记录第j个单词在字符串中的起始位置         x = x + n[j] + 1;     }      x = j;  //总共x个单词     for (j = 0, m = n[0]; j < (x - 1); j++)              //寻找最长的单词，将其长度记录在m中     {         if (m < n[j + 1])         {             m = n[j + 1];         }     }     printf("length:%d 最长字符串为:", m);      for(i = 0; i < x - 1; i++)     {         if(m == n[i])         {             if(notonlyoneflag) printf(" 和 ");             for(j = start[i];j < start[i]+n[i]; j++)             {                 printf("%c", a[j]);                 notonlyoneflag = 1;             }          }     }     printf("\n");  }

意思是现在已经知道最长单词是第t个单词了，那么就用s作为变量，重头浏览一遍字符串数组，从第0个单词开始意义判断t==s是否成立，如果相等，说明就是他了，输出该单词。不过又判断一遍，有点麻烦。其实上面在记录单词长度的时候就可以同时记录单词的起始位置，然后就可以直接输出了。 引用 3 楼 Schlangemm 的回复:[quote=引用 1 楼 sghcpt 的回复:] 楼主，下面代码可供参考： #include<stdio.h> #include<string.h> int n[100] = { 0 }; int i, j, s = 0, m, t, x;  int main() { 	void lenthest(char a[]); 	char a[100] = { 0 };  	gets(a); 	a[99] = '\0';  	lenthest(a);  	return 0; }   void lenthest(char a[]) { 	int n[100] = { 0 }; 	int i, j, s = 0, m, t, x = 0; 	for (j = 0, i = 0; x < strlen(a); j++) 	{ 		for (i = x; a[i] != ' ' && a[i] != '\0'; i++)		//统计单词数 			n[j] = i - x + 1;                              //将每个单词的字母数依次存放在数组n中  		x = x + n[j] + 1; 	}  	t = 0; 	x = j;                                          //将单词数即数组n中有效长度存放在x中 	for (j = 0, m = n[0]; j < (x - 1); j++)              //寻找最长的单词，并将其顺序存放在t中 	{ 		if (m < n[j + 1]) 		{ 			m = n[j + 1]; 			t = j + 1; 		} 	}  	printf("length:%d 最长字符串为:", m); 	s = 0; 	for (i = 0;  a[i] != '\0'; i++)		//查找最长单词数 	{ 		if (t == s)						//t保存着最长单词数的索引 		{ 			if (a[i] == ' ') 			{ 				break; 			}  			printf("%c", a[i]);			//输出最长单词数 		}  		if (a[i] == ' ')			 //记录多少个单词数 		{ 			++s; 		} 	} } 对最后几行有点疑问，能不能具体解释一下啊    s = 0;     for (i = 0;  a[i] != '\0'; i++)        //查找最长单词数     {         if (t == s)                        //t保存着最长单词数的索引         {             if (a[i] == ' ')             {                 break;             }              printf("%c", a[i]);            //输出最长单词数         }          if (a[i] == ' ')             //记录多少个单词数         {             ++s;         }     } }   [/quote]

帮顶一贴！！！！

引用 1 楼 sghcpt 的回复:楼主，下面代码可供参考： #include<stdio.h> #include<string.h> int n[100] = { 0 }; int i, j, s = 0, m, t, x;  int main() { 	void lenthest(char a[]); 	char a[100] = { 0 };  	gets(a); 	a[99] = '\0';  	lenthest(a);  	return 0; }   void lenthest(char a[]) { 	int n[100] = { 0 }; 	int i, j, s = 0, m, t, x = 0; 	for (j = 0, i = 0; x < strlen(a); j++) 	{ 		for (i = x; a[i] != ' ' && a[i] != '\0'; i++)		//统计单词数 			n[j] = i - x + 1;                              //将每个单词的字母数依次存放在数组n中  		x = x + n[j] + 1; 	}  	t = 0; 	x = j;                                          //将单词数即数组n中有效长度存放在x中 	for (j = 0, m = n[0]; j < (x - 1); j++)              //寻找最长的单词，并将其顺序存放在t中 	{ 		if (m < n[j + 1]) 		{ 			m = n[j + 1]; 			t = j + 1; 		} 	}  	printf("length:%d 最长字符串为:", m); 	s = 0; 	for (i = 0;  a[i] != '\0'; i++)		//查找最长单词数 	{ 		if (t == s)						//t保存着最长单词数的索引 		{ 			if (a[i] == ' ') 			{ 				break; 			}  			printf("%c", a[i]);			//输出最长单词数 		}  		if (a[i] == ' ')			 //记录多少个单词数 		{ 			++s; 		} 	} } 对最后几行有点疑问，能不能具体解释一下啊    s = 0;     for (i = 0;  a[i] != '\0'; i++)        //查找最长单词数     {         if (t == s)                        //t保存着最长单词数的索引         {             if (a[i] == ' ')             {                 break;             }              printf("%c", a[i]);            //输出最长单词数         }          if (a[i] == ' ')             //记录多少个单词数         {             ++s;         }     } }

赞同楼上的改法 你的主要问题就是这段里面陷入了死循环，当遇到第一个空格的时候，内圈for是退出了，但是下一次到内圈for时，i直接取x的话，x里面没有算空格的计数，所以当前内圈for会判定第一个字符之后的空格，然后跳出内圈循环，如此往复进入死循环 for (j = 0, i = 0; x <= strlen(a); j++) 	{ 		for (i = x; a[i] != ' '&&a[i] != '\0'; i++)  //统计单词数 			n[j] = i + 1;                          //将每个单词的字母数依次存放在数组n中 		x = x + n[j]; 	}  其次就是你这个设计无法判定相同长度的两段字符


Question: 关于getchar函数

引用 1 楼 user-1 的回复:你仔细看一下，其实也是循环了10次，只不过gets(name[i])时取到的都是你输入num[i]之后的'\n'： input No.:2 input name:input No.:sd input name:input No.:4 input name:input No.:sd input name:input No.:5 input name:input No.:cvbg input name:input No.:7 input name:input No.:dhh input name:input No.:9 input name:input No.:cgh input name: 具体可以参考：https://bbs.csdn.net/topics/390726616 就是说，使用scanf()时，遇到空格键、Tab键或者回车键结束一次输入，但是不会舍弃最后的回车符或空格或Tab（即还在缓冲区中），需要使用getchar来吸收scanf()执行之后的符号。 gets()会一直读取输入的内容，直至回车（遇到回车则认为输入结束），同时以'\0'代替'\n'这个换行符(意思是'\n'既不会被放到字符数组中，也不会被存入到缓存区，也就是这个回车被舍弃了) 所以，就像你遇到的情况，在没有使用getchar()时，比如输入的是1'\n'，这个1被num[i]接收，但是回车还在缓冲区中，被后面的gets(name[i])接收了（然后舍弃），如此循环10遍。 使用了getchar()之后，这个回车被getchar()接收，那么后序的输入就能正常被gets(name[i])接收，就达到你的预期了。谢谢，我知道是为什么了


Question: 为什么字符串只能输出不全

引用 3 楼 qq_40478293 的回复:put读取的字符串中有空格，所以被终止读取了 最好验证一下再确认你的思路是否正确。  遇到空格是不会终止输出的。 只输出hello的原因是i在变化，s的地址也在发生变化，一次循环其实i向后了2次，但是输出时没有借助i； void  put(char *s) {     int i ;     for (i=0;s[i]!='\0' ;i++ )     {         //putchar(*s++);         putchar(s[i]);     } } 这样就可以全部输出了

赵4老师说得非常有道理，不过有时候也可以通过打印中间变量来调试程序，也可以带来不少收获。 #include <stdio.h> #include <stdlib.h> void  put(char *s);  int main(int argc, char *argv[]) {     char s1[]="hello  world";     put(s1);     putchar('\n');     return 0; } void  put(char *s) {     int i ;     for (i=0; s[i]!='\0' ; i++ )     {         printf("i = %d, putchar(*s++) = ",i);         putchar(*s++);         printf(", after *s++, s = \"%s\", when i = %d,s[%d] = %c\n",s, i+1, i+1, s[i+1]);     } } 结果如图

引用 1 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。我也是经常程序出问题，但是不知道怎么调试，以前用过vc6++设断点调试，但是调试结果和我想得不一样，而输出结果却是正确的，不知道是我自己的断点没设对，还是什么原因，有没有介绍VS调试方面的内容，书或者视频，或者其他的可以推荐一下吗，谢谢

i=0时，s[i]='h'，输出*s++  即打印字符 'h'；同时指针向后移一位，指向e； i=1时，s[i]='l'  ,  输出*s++  即打印字符 'e' ;  同时指针向后移一位，指向l(第一个L)； i=2时，s[i]='o'  ,  输出*s++  即打印字符 'l' ;  同时指针向后移一位，指向l（第二个L）； 依次往下推理，就是s[i]='\0'，已经判断完了，循环结束，putchar才打印到hello这个位置；  可以修改为：putchar(*(s+i));   或  purchar(s[i]);

put读取的字符串中有空格，所以被终止读取了

因为putchar(*s++);这里s++,s应该变了，到hello 输出完的时候s[i]已经是0了。


Question: 看过指针这种输入，输出吗

乘法符号，就是10 × i；pcou+10 *i就是pcou向后偏移10 * i个字节。

引用 6 楼 kfyniriu1 的回复:pcou+10 *i  char是一个字节，pcou+10 *i 表示每次循环向后移10个字节，也就是数组每接收一个字符串，就换到下一行接收下一个字符串。二维数组每一行只保存一个字符串 for语句，第一个是用；不是用， 正确

二维数组。    每次循环就跳到下一行指向下一行的一维数组开头  一共5行

我的天  乌龙了   谢谢大家

引用 4 楼 zhao4zhong1 的回复:10*i 的意思 是 10乘以i 不是 10后面紧跟取i这个指针所指的值 ！  回答正确

10*i 的意思 是 10乘以i 不是 10后面紧跟取i这个指针所指的值 ！

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

回答跑题了 。。。。 我是问 scanf 中   *i   的作用是什么  我之前没看过  这个是一本书里的写法

引用 楼主 qq_40750570 的回复:........ int i; char course [5][10],  *pcou; pcou = course[0]; for (i=0,i<5;i++) {          scanf("  %s  ", pcou+10 *i);  } ***************************************** scanf中的 *i  是什么意思   之前没看过  楼主，个人认为，因为pcou指针指向二维数组char* course [5][10]，而二维数组course的内存是连续的，所以在for循环的五次执行中，pcou分别指向如下： 1) pcou+ 0  -->等于course[0 2) pcou + 10 -->等于course[1] 3) pcou + 20 -->等于course[2] 4) pcou + 30 -->等于course[3] 5) pcou + 40 -->等于course[4]  即5次输入的scanf类似如下： 1）scanf("  %s  ", course[0]); 2）scanf("  %s  ", course[1]); 3）scanf("  %s  ", course[2]); 4）scanf("  %s  ", course[3]); 5）scanf("  %s  ", course[4]);


Question: c语言，求助什么意思

i，j，k都没有定义啊？

代码不全 是作业吧

不懂，代码不全吧，3个向量?

引用 2 楼 donjin9 的回复:不懂，代码不全吧，3个向量? 同意，都不知道那个是什么

《立体几何》


Question: 关于紫书(刘汝佳) 悲剧文本 UVA11988 的问题

建议你先用udebug上跑一下11988的测试数据，看看会不会TLE，顺便可以验证一下程序到底对不对。 https://www.udebug.com/UVa/11988


Question: C语言三天打鱼两天筛网的程序 求教 ！找了好久没找出问题，大神看看是逻辑问题吗？万分感谢

修改代码： numy=year(Nyear); numm=month(Nmonth, Nyear);  你子函数里的numy、numm是局部变量，return后需要变量接收，而你main里的numy、numm和子函数的numy、numm不是一回事，除非你把numy、numm申明在main外面作为全局变量，才能这么写  在插说一下，你这程序设计上的东西，不说一月和一月天数不一样、闰年闰月的问题，你这是从2001年1月1日起算的把，月份等于1的时候，加31天合适吗？

不是，已经解决了

numy numm没赋值吧，在循环里改改看。 numy = year(Nyear); numm = month(Nmonth,Nyear);


Question: 小白初学C语言

小白不要用复杂的编译器，你用C/C++程序设计学习与实验系统（可以切换三种编译器）吧，以后可以用dev-C++（简洁大方），如果是每次要新建项目的那种，强烈建议小白不要用这种。

没有错啊我用的是DevC++ 你可以换个编译器试看看

创建的文件类型不对,你都说学的是C,可你的文件命名为obj.请更改文件后缀为.c就可以了

文件名例如：helloworld.c

C语言是.C文件

obj是旧的，清除整个编译。重新编译整个工程

年轻人，先问是不是，在问为什么。

是不是用了全角的分号,看下英文提示

VC6.0是void main，int main 一般都是CFREE。推荐将代码复制一下，关闭重启一下软件，确保正确的情况下新建工程，将代码粘贴过来编译应该就会好了

Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt

是不是工程创建错误了

英文错误没有贴出来。

程序有重大不规范。我就是不说哈哈。。。。自己百度。int main（void）和int main（）；区别。用gcc编译学习。

最关键的错误信息不发出来！

确定创建的win32控制台应用？

你用的什么软件，我用vs2017和vc++6.0都可以正常显示啊

创建的文件类型不对

ide有问题

程序的确没问题，难道是用了传说中的VC 6.0？


Question: 关于三重循环if无法判断的问题

引用 4 楼 user-2 的回复:[quote=引用 3 楼 zangfong 的回复:] [quote=引用 2 楼 user-2 的回复:] 1楼的程序直接拷贝运行，输入972没有问题，输出的结果是YES。  但建议将for语句的判断条件由1000次减少到素数个数一样大小的次数 原程序中的sum并不等于素数之和啊，大哥。。。 for循环的取值范围是必须降的，因为a[1000]是局部变量，都没有初始化，a[168]后面的值都是随机的啊[/quote]  我记得结果是2+3+967，你可以运行下程序看看[/quote]  我试过，按照原来的程序，输出的结果是972 = 11+3+89，要不你调试一下试试？

引用 3 楼 zangfong 的回复:[quote=引用 2 楼 user-2 的回复:] 1楼的程序直接拷贝运行，输入972没有问题，输出的结果是YES。  但建议将for语句的判断条件由1000次减少到素数个数一样大小的次数 原程序中的sum并不等于素数之和啊，大哥。。。 for循环的取值范围是必须降的，因为a[1000]是局部变量，都没有初始化，a[168]后面的值都是随机的啊[/quote]  我记得结果是2+3+967，你可以运行下程序看看

引用 2 楼 user-2 的回复:1楼的程序直接拷贝运行，输入972没有问题，输出的结果是YES。  但建议将for语句的判断条件由1000次减少到素数个数一样大小的次数 原程序中的sum并不等于素数之和啊，大哥。。。 for循环的取值范围是必须降的，因为a[1000]是局部变量，都没有初始化，a[168]后面的值都是随机的啊

是你的三层循环写的有问题，以下代码供参考： #include <stdio.h> #include <stdlib.h> #include <math.h> int isPrime(int n)            //1000内判断素数 {     int i;     for(i = 2;i<=(int)sqrt(n);i++)         if(n%i == 0)             return 0;     return 1; } int main() {     int n,i,k,sum;     int a[1000];     int j=0;     int prime_cnt;      for(n=2;n<=1000; n ++)         if(isPrime(n))             a[j++] = n;     prime_cnt = j;     scanf("%d",&n);           //将1000内素数存放入数组里     if(n==1)         printf("No\n");     else{         for(i=0;i<prime_cnt;i++){             sum=a[i];             for(j=0;j<prime_cnt;j++){                 sum=sum+a[j];                 for(k=0;k<prime_cnt;k++){                     sum=sum+a[k];                     if(sum==n){                         printf("Yes,%d = %d+%d+%d\n",n,a[i],a[j],a[k]);                         return 0;                     }                     sum -= a[k];                 }                 sum -= a[j];             }         }         printf("No\n");         return 0;     }     return 0; }


Question: 统计字符串中字母、数字、空格数目

引用 10 楼 Schlangemm 的回复:已经找到了自己原来程序的错误，看久了就会头脑不清楚恭喜恭喜，加油加油！

引用 9 楼 Schlangemm 的回复:[quote=引用 5 楼 zangfong 的回复:] [quote=引用 4 楼 Schlangemm 的回复:] 你好，我想问一下，我用VS2017用不了gets函数，有其他替代的函数吗 试试fgets(text,sizeof(text),stdin); 或者gets_s(text,sizeof(text)) [/quote] 用gets函数会出现警告，但是程序还是能正常运行，我想请问一下这个有关系吗；还要那个sizeof（text）就是直接可以用的函数吗，我看的c语言的书里使用strlen函数来测得字符数组的实际长度，这两个有什么区别吗 [/quote]出现警告在本题中肯定是没啥关系，但是用gets不太安全，所以编译时会给出警告，可以用fgets取代。具体请百度gets与fgets，可以找个自己看得懂的解释。 sizeof是关键字，直接可用，返回的是一个对象或者类型所占的内存字节数，所以本题中sizeof(text) = sizeof(char) * 80 = 1 * 80 =80；而strlen是函数，返回的是text字符串的长度(碰到第一个字符串结束符'\0'为止的长度)。举例，如果你输入了“12345”，sizeof(text)还是80, strlen(text) = 5。

已经找到了自己原来程序的错误，看久了就会头脑不清楚

引用 5 楼 zangfong 的回复:[quote=引用 4 楼 Schlangemm 的回复:] 你好，我想问一下，我用VS2017用不了gets函数，有其他替代的函数吗 试试fgets(text,sizeof(text),stdin); 或者gets_s(text,sizeof(text)) [/quote] 用gets函数会出现警告，但是程序还是能正常运行，我想请问一下这个有关系吗；还要那个sizeof（text）就是直接可以用的函数吗，我看的c语言的书里使用strlen函数来测得字符数组的实际长度，这两个有什么区别吗

6楼写得匆忙，重新对最后一个代码补充 char a=getchar() int i=0; while(a!='\n') { str[i]=a; i++; a=getchar(); } str[i]='\0';  最后字符串需要加上结束符

for (i = 0; i != '\0'; i++) 这样的设计循环一次也不会执行，因为'\0'就等于0；当i= 0；时，i != '\0'就是假 改成： for (i = 0; str[i] != '\0'; i++)

程序主要问题出在 for (i = 0; i != '\0'; i++) 循环条件 i!='\0' 处。  这个条件是不成立的，可以修改为  str[i]!='\0'  或者添加头文件#include<string.h> 使用strlen函数  for语句前添加：int j=strlen(str);    将 i!='\0' 替换成  i<strlen  在或者用while语句 int i=0; while(str[i]!='\0') { ......(for语句里面的内容) i++; }  以上可以解决for循环处的问题。  scanf("%s", text); 是不能读取到空格键的，需要读取空格键，可以修改为：scanf("%[^\n]", text)； 或者 gets(text);   再或者： char a=getchar() int i=0; while(a!='\n') { str[i]=a; i++; a=getchar(); }

引用 4 楼 Schlangemm 的回复:你好，我想问一下，我用VS2017用不了gets函数，有其他替代的函数吗 试试fgets(text,sizeof(text),stdin); 或者gets_s(text,sizeof(text))

你好，我想问一下，我用VS2017用不了gets函数，有其他替代的函数吗

你的运行的结果输出所有参数都是0，这是由你的for循环引起的for (i = 0; i != '\0'; i++)以上代码等同于for (i = 0; i !=0; i++)所以。。。 另外，用scanf("%s", text);的话遇到空格就停止接收后面的字符，所以估计也达不到你的预期目的，应该如同sghcpt所述进行修改，改成gets(text);或者scanf("%[^\n]", text);  以下代码供参考 #include<stdio.h> int alph, num, spa, other; int main() {      void statistics(char str[]);     char text[80];     alph = 0;     num = 0;     spa = 0;     other = 0;     //scanf("%[^\n]", text);     gets(text);     statistics(text);     printf("alphabet=%d\nfigure=%d\nspace=%d\nother=%d\n", alph, num, spa, other);     return 0; }  void statistics(char str[]) {     int i;     for (i = 0; str[i] != '\0'; i++)         if ((str[i] >= 'A'&&str[i] <= 'Z') ||( str[i] >= 'a'&&str[i] <= 'z'))             alph++;         else if (str[i] >= '0'&&str[i] <= '9')             num++;         else if (str[i] == ' ')             spa++;         else other++; }

楼主：改为下面的代码试试： #include<stdio.h> int alph, num, spa, other; int main() { 	void statistics(char str[]); 	char text[80] = { 0 }; 	alph = 0; 	num = 0; 	spa = 0; 	other = 0; 	scanf_s("%79[^\n]", text, (unsigned)_countof(text)); 	statistics(text); 	printf("alphabet=%d\nfigure=%d\nspace=%d\nother=%d\n", alph, num, spa, other); 	return 0; }  void statistics(char str[]) { 	int nLen = strlen(str); 	int i; 	for (i = 0; i < nLen; i++) 	if ((str[i] >= 'A'&&str[i] <= 'Z') || (str[i] >= 'a'&&str[i] <= 'z')) 		alph++; 	else if (str[i] >= '0'&&str[i] <= '9') 		num++; 	else if (str[i] == ' ') 		spa++; 	else other++; }  网上说scanf或者scanf_s函数如果遇到输入字符串中存在空格时，会认为字符串输入已经结束，所以如果你上面输入空格字符的，那么你给出的代码会只能接收到空格字符前面的字符，所以需要使用“%[^\n]”这样的输入格式才可以接收到空格字符的输入。

循环处改成int len = strlen(str); 	for (int i = 0; i <len; i++)


Question: if else if的顺序和二次指针

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

楼主：个人认为，你第二张图的代码运行过程应该是这样的： 1.第一步应该运行if (key < (*p)->key) p = &(*p)->left;或者if (key > (*p)->key) p = &(*p)->right;    这时因为没有给左节点和右节点分配内存，所以这时左节点和右节点应该指向非法内存或者为空的。 2.第二步，因为第一步没有跳出while循环，所以再执行while循环里面的代码语句，这时p指向的内存非法或者为空，   所以就会出现异常情况出现了。  而第一张图的代码，估计应该是先执行if ((*p)->key == 0)里面的语句，就创建新的根节点和左右节点，并且执行完后就 跳出了while循环。所以正确的。

contex不一样


Question: STM32实现位绑定遇见的难题，请各路大神支支招

你参考一下这里 https://blog.csdn.net/hk604296024/article/details/41870963 对比你的BitBand这个宏的定义。 这里做底层的比较少，http://www.openedv.com/这里多一点。 现在STM的开发一般用HAL库，标准库已经不更新了。用HAL库， 再使用stm32cubemx 配置就可以用了。

老哥，我刚开始学，我这个位绑定的函数的功能实现不了，也没有报错，麻烦帮我看看问题出在哪里？？

。。。都2018年了怎么还用这种代码。用Cube一配置，后面的东西再用函数一封装就可以了。


Question: node的类型是什么意思

typedef起了别名叫node吧

我好像明白了，我在这个工程里的另一个文件里建立了node类型的结构体外部变量。是不是这个原因。。。。

你的结构体是 typedef struct  { ..... }node; 类型吗？


Question: error C2440: “=”:无法从“int (__cdecl *)(void)”转换为“int (__cdecl *)(int,int)”

第一个 #include <stdlib.h> 内定义了MAX函数，在程序中用MAX（），会提示错误（），不过这个不是主要的问题。 主要问题在第二个，“int（*p）（int，int）”,2010vc里是类型转换问题，“int (__cdecl *)(void)”转换为“int (__cdecl *)(int,int)”计算机识别不了。 建议改一下： INT MAX(INT,INT); INT (*P)(INT,INT); 这可以解决报错的问题。

你看的书太老了，1980年前的C使用函数声明，只要声明其返回值类型就行了，参数不用说明；ansi c建议有函数原型，参数个数和类型必须说明

这段程序是在以前的教材上找的，，，感谢各位了，，哈哈哈

明白了，，，万分感谢

#include <stdio.h> #include <stdlib.h> int max(int x,int y);  void main() { int (*pl)(int,int); int a,b,c; pl=max; scanf("%d,%d",&a,&b);     c=(*pl)(a,b);     printf("a=%d,b=%d,max=%d",a,b,c); system("pause"); }  int max(int x,int y) { int z; if(x>y) z=x; else z=y; return z; }

int max（）； 你声明是无参


Question: OJ显示memory limit exceed,不知道哪里溢出了，求大神解答

授人之渔，你可以在所有malloc和free的地方更新当前程序申请内存的总大小。 内存溢出无非就是死循环申请内存没释放呗


Question: 关于Scanf，一个很奇怪的问题

提醒：scanf是开源的！ C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c

具体不知道你要实现什么功能，所以只针对第一段代码，即输入 ：1 2 3 输出：0 0 0 0 0 0 0 0 0 3 0 0 0 说明一下这样的结果是怎么产生的：  首先申明一个会用到的知识点，即超范围赋值，uchar的范围是0~255 ，这时候如果你写uchar a=560； 那结果是什么，是会截断，560的二进制是1000110000，对于uchar一个字节，只会截取后面8位，及a=00110000（B）=48，从这里可以看出超限甚至说int到char的强转，都是按先取低位的规则来的（及先取右边）  再看你的代码，第一次循环，i=11，scanf("%x",&a[11]); 这句代码的第一步是用 x%的类型去取界面输入的值，然后把这个值放到第二个参数所指的位置（注意&代表的是取地址），那首先界面的1以x%类型写完整就是0x00000001(二进制是0000 0000 0000 0000 0000 0000 0000 0001)，然后&找到了a[11]的地址，将二进制数截断最后8位放进a[11]，即a[11]=0x01，但是没有结束，与int到char的强转会舍弃高位不同，现在是个数组(或者理解为指针)，用&获取了首地址后，会继续赋值，直到将x%代表的一个四字节uint数完全赋给uchar，即a[12]= 0000 0000=0x00  a[13]=0000 0000=0x00 a[14]=0000 0000=0x00，这一句scanf就赋值了四个char  同理i=10的时候，a[10]=0x02 a[11]=0x00 a[12]=0x00 a[13]=0x00, a[11]的位置被0x00覆盖 i=9的时候，a[9]=0x03 a[10]=0x00 a[11]=0x00 a[12]=0x00, a[10]的位置被0x00覆盖  最后就会得到 0 0 0 0 0 0 0 0 0 3 0 0 0

hhx ,1x ,2x ,3x  都能正常输出 是出在长度上？

引用 6 楼 user-3 的回复:用 %hhx 为什么 i--的时候有问题，哪里出了问题？

谢谢！  明白了

用 %hhx

那如果想输入 1byte 16进制 那怎么定义

编译器0错误0警告

而且你都不看编译器警告的吗？printf scanf这种错误很多新的编译器都会提示

因为%x要求的类型是unsigned int啊

求解 原因 在i--的时候 如果将类型改为int ，正常输出 如果在i--中scanf("%x",&a[i]);改为scanf("%x",&b); a[i]=b;  输出的也是正常的


Question: c 语言函数库

GlobalMemoryStatus The GlobalMemoryStatus function obtains information about the computer system's current usage of both physical and virtual memory.   VOID GlobalMemoryStatus(   LPMEMORYSTATUS lpBuffer   // pointer to the memory status structure );  Parameters lpBuffer  Pointer to a MEMORYSTATUS structure. The GlobalMemoryStatus function stores information about current memory availability into this structure.  Return Values This function does not return a value.   Remarks You can use the GlobalMemoryStatus function to determine how much memory your application can allocate without severely impacting other applications.   The information returned by the GlobalMemoryStatus function is volatile. There is no guarantee that two sequential calls to this function will return the same information.   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 winbase.h.   Import Library: Use kernel32.lib.  See Also Memory Management Overview, Memory Management Functions, GlobalMemoryStatusVlm, MEMORYSTATUS    MEMORYSTATUS The MEMORYSTATUS structure contains information about the current state of both physical and virtual memory. The GlobalMemoryStatus function stores information into a MEMORYSTATUS structure.   typedef struct _MEMORYSTATUS { // mst      DWORD dwLength;        // sizeof(MEMORYSTATUS)      DWORD dwMemoryLoad;    // percent of memory in use      DWORD dwTotalPhys;     // bytes of physical memory      DWORD dwAvailPhys;     // free physical memory bytes      DWORD dwTotalPageFile; // bytes of paging file      DWORD dwAvailPageFile; // free bytes of paging file      DWORD dwTotalVirtual;  // user bytes of address space      DWORD dwAvailVirtual;  // free user bytes  } MEMORYSTATUS, *LPMEMORYSTATUS;   Members dwLength  The size in bytes of the MEMORYSTATUS data structure. You do not need to set this member before calling the GlobalMemoryStatus function; the function sets it.  dwMemoryLoad  Specifies a number between 0 and 100 that gives a general idea of current memory utilization, in which 0 indicates no memory use and 100 indicates full memory use.  dwTotalPhys  Indicates the total number of bytes of physical memory.  dwAvailPhys  Indicates the number of bytes of physical memory available.  dwTotalPageFile  Indicates the total number of bytes that can be stored in the paging file. Note that this number does not represent the actual physical size of the paging file on disk.  dwAvailPageFile  Indicates the number of bytes available in the paging file.  dwTotalVirtual  Indicates the total number of bytes that can be described in the user mode portion of the virtual address space of the calling process.  dwAvailVirtual  Indicates the number of bytes of unreserved and uncommitted memory in the user mode portion of the virtual address space of the calling process.  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 winbase.h.  See Also Memory Management Overview, Memory Management Structures, GlobalMemoryStatus

引用 1 楼 user-3 的回复:楼主，引用网上的对coreleft的说明：链接：http://www.cnblogs.com/amanlikethis/archive/2014/06/02/3764600.html 二、coreleft 函数来源：TC2.0 函数名: coreleft 功 能: 返回未使用内存的大小 返回值：未使用内存的大小 函数原型: 　　 unsigned long coreleft(void);（摘自TC2.0的alloc.h） 注意：此函数在VC6.0以及Ubuntu的gcc中均没有找到。++


Question: 如图1所示   整数就应该得0吗？还有1怎么用？如徒儿所示  c和d哪个是错的?本人小白请各位解释详细点

3.9 整型变量不存在四舍五入，1÷2=0，  结果是1的话，2÷2=1       2÷3=1。  只取整数部分，小数部分舍去 3.7 题目交换的是a和b的值，选项c交换的是b和t的值，a作为中间变量。选项d，交换了a和b的值，t作为中间变量。具体过程如下 1、先把变量a的值赋予t  t=a;  此时t的值等于a； 2、将变量b的值赋予a   a=b；  此时a的值等于b； 3、最后将变量a的值赋予b； 上面a的值已经等于b了，此时就需要借助中间变量t，t的值等于a；那么就有 b=t；

对楼上补充下3.7的A选项：         a = a+b;          -------------> 此时a的值已经改变，为原先的(a+b)         b = a-b;              = (a+b)-b             = a               ------------->此时b的值也已改变，为原先的a         a = a-b;            = (a+b)-a            = b               ------------->此时a值再次改变，为原先的a。

1.a 2.c  1.整形不存在小数位。且C语言除法不存在四舍五入，只要不足1就全部舍弃。1/2在程序中的的详细运行步骤：首先将1/2这个运算转换为1除以2并求余数，结果是1除以2=0余1。而1/2则取前面的数作为结果“0”，1%2（求余）取后面的数作为结果“1”。 2.a是可以实现的，你可以随便放几个数进去试试看；b也是正确的，同理D也正确。故C错误。 t中的值是个不定值（如果没有初始化的话），将t中的值给a明显错误。

图二d中中间那个事b=a


Question: c求最大值

if(m=a[i]) n=i; //可以拆解为：①将a[i]赋值给m ②赋值成功（一般都会成功），则代码等同于if(true) n=i;赋值失败，代码等同于if(false) n=i;ture为1，false为0。所以你现在的问题是每次if都赋值成功，然后if后面的东西每次都执行  改为if(m==a[i]) n=i;//可以拆解为：①判断当前a[i]里面的值是否等于当前m里的值，m==a[i]和a[i]==m可以认为一样的  ②判定相等，则代码等同于if(true) n=i;判断不等于，代码等同于if(false) n=i;ture为1，false为0。

同上。 写判断语句时要注意，如果你要写一个表达式，就要开始留心。表达式中的比较符基本上都是2个字符：==、！=、<=、>=、||、&&等。如果只写了一个，程序也不会报错，检查起来可能就比较费时间。所以在写判断语句时得留心了

if(m=a[i]) n=i; 这个判断语句改一下  if(m==a[i]) n=i; 注意赋值语句和判断语句的用法


Question: 求助啊！！   Codeblocks  ！

网上有说，可以试下，可能是“下载的版本有问题，没有安装编译器；卸载之后，重新下载一个带有编译器的，在安装的时候选择安装编译器就可以了”


Question: CSV如何在最后一行新建一行并填入数据呢

楼主，如果排查问题，可以先 1)先看看CsvFile文件打开是否成功，f_lseek，f_truncate函数操作是否成功？ 2)在写入完数据后，可以尝试一下关闭CsvFile文件，看看是否写入的数据还在缓存中，没有实际保存到文件中？ 3)判断一下，是否char *buff参数传进来的数据是否为空或者长度为0，如果是，写入的内容就是你之前的内容了？ 4)又或者单独在WCsvFile_Newndex函数中删除之前存在的文件，重新重建文件，重新写入数据，看是否成功？

lz这段代码是FatFS的函数吧。 建议lz关注下f_lseek，f_truncate这两个函数的返回值

感谢各位大佬回答，我已经写出来了。。void WCsvFile_NewRowData(char *buff) { 	char *CsvMemory; 	 	u8 buffsize; 	u32 CsvMemorySize;//申请内存的尺寸 	 	buffsize = strlen(buff);//计算字符串 字符个数  	CsvMemorySize = CsvDataSize + buffsize;//计算申请内存的尺寸 	CsvMemory = mymalloc(SRAMEX,CsvMemorySize);//申请一段总内存 	if(CsvMemory == NULL) return;//申请不到数据 	memset(CsvMemory,0,CsvMemorySize); 	memcpy(CsvMemory,CsvDataSpace,CsvDataSize);			//把前一段内存拷贝进去 	memcpy(CsvMemory + CsvDataSize,buff,buffsize);//存入更改数据	 	f_lseek (CsvFile ,0);//指针移到文件开头 	f_truncate (CsvFile);//截断(清除)当前文件指针后的文件数据 避免数据坑余	 	f_write(CsvFile,CsvMemory,CsvMemorySize,&Csv_bw); //存入后一段数据  (整段新数据) 	myfree(SRAMEX,CsvDataSpace);//清空之前的申请旧数据的内存 	 	CsvDataSize = CsvMemorySize;//更新数据尺寸 	  	CsvDataSpace = CsvMemory;//更新数据,交换内存指向新数据地址  }  和昨天发的应该没大区别，是在别的函数影响下写入不正常


Question: 请教fgets()读取一个整数的“玄学”问题

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);     } }  电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

667953 == 0xA3131 -858993460 == 0xCCCCCCCC VS是有选项的，可以控制调试时显示十进制还是十六进制。

引用 1 楼 Saleayas 的回复:fget 把传入的整形数组当作字符串数组了，写入的是字符串的 "11" 加上0A 换行而已。 谢谢答复！也就是说我输入的是“11”，fgets()存储的是“11\n”，可因为我的数组设置成了int型不是char型，所以它存储的数据值就被转化成667953这样一个在计算机内部存储的整型数字，是吗？

引用 4 楼 qq_38319117 的回复:fgets的默认参数是char*，你现在写的a是一个int*，有的编译器编译不过去的，会报错，原理上就是个强转 等同 fgets((char*)a, MAX,stdin);  键盘输11,在fgets看来，就是  新行'1''1'  即0x0a 0x31 0x31 然后把它放到一个四字节的int里，就变成0x0a3131，解成十进制就是667953  谢谢答复！你这样一说我就全明白了。但是我想fgets()处理的应该还是"11\n"，但是估计用的是小端存放方式，所以计算成0x0a 0x31 0x31。 再说一句：非常感谢。


Question: 如图a小于b时   后面一部分怎么理解

要从小到大排序，ab要调换位置； 用一个t作为中转站。

（if）如果a<b成立的话，那么就将a的值与b的值进行调换。但我们知道这种换值是需要第三个变量来帮助我们实现的，否则在赋值的过程中会出现值丢失的情况，通过图中代码可看出，先将a的值给t（第三个变量），再将b的值给a，最后将t的值给b。这样就实现了两个数值的调换。

if中实现的功能是a<b时，交换a和b的值，即如果a=4,b=20,执行完if后变为a=20,b=4  但是要交换a和b的值，不能直接a=b;b=a; 因为a=b的时候，a原本的值会被b的值覆盖，这时执行b=a时，a的值是刚刚b赋给a的，所以需要一个中间量t先把a的值存起来，在b的值交给a后，再把t中存的a的值交给b

后面是实现a、b之间数值的交换；先将a的值赋给t保存起来，再将b的值赋给a，最后将t里面保存的a的值赋给b

后面再来一行 a > c ? printf("%d", a) : printf("%d", c); 就能达成目标了。

1、先把变量a的值赋予t  t=a;  此时t的值等于a； 2、将变量b的值赋予a   a=b；  此时a的值等于b； 3、最后将变量a的值赋予b； 上面a的值已经等于b了，此时就需要借助中间变量t，t的值等于a；那么就有 b=t；

说错了是从大到小

a小于b时，由于要从小到大排序，ab要调换位置； 这时如果用a=b;b=a;来的话就会出现问题（a的值已替换为b，而之前的a的值已经不复存在，传给b的也还是b之前的值。） 所以要t=a;a=b;b=t;这样来写。先把a的值传给t保存，然后把b的值给a，最后b从t这个中间变量中取出a的值给自己，就实现了a和b的位置调换

楼主，按照你代码中的说明，是应该判断三个数哪个大，然后再打印最大值，从你给出的代码来看，你上面说的回复是正确的，应该缺少一些代码呢~~~~没有实现功能。

想问一下楼主，程序就这么多吗？我认为这段代码只能判断出来ab的大小并按照从大到小排列，只有输入，还没有输出，还没有和c进行比较判断。 当a<b时，把a给t，b给a（大的给a），再把t给b（小的给b）。就是用了个中间变量交换了一下位置！ 所以从目前这段代码我认为就只能看出来这么多了吧，希望能对你有用。

很经典的入门问题..网上资料很多

当a<b时，后面的部分是交换a和b内存空间的值。t是中间变量


Question: 0x0F8AD3EC (ucrtbased.dll)处(位于 Not.exe 中)引发的异常: 0xC0000005: 写入位置 0x00900000 时发生访

scanf_s("%s", cha, 30); 对于%s而言，楼主的是缺少一个参数，即字符数组的长度～

犯了类似错误 我来挖个fen。。。 scanf_s("%s", cha); 这里少了&这个  取地址符号！！加上就好了！

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

逗号写错了 #include<stdio.h>   int main() { char cha[30]; scanf_s("%s", cha,20);   printf("%s", cha);   system("pause"); return 0; }

#include<stdio.h>  int main() { char cha[30]; scanf_s("%s", cha，20);  printf("%s", cha);  system("pause"); return 0; }看一下scanf_s的用法

楼主，应该是下面的用法才对：  #include<stdio.h> int main() { 	char cha[30] = { 0 }; 	scanf_s("%29s", cha, (unsigned)_countof(cha));  	printf("----\n%s", cha); 	system("pause"); 	return 0; }  出现你上面的错误，应该是访问内存越界了吧。。。


Question: C 语言 想外部输入16进制的数，保存在数组中，如何判断数是否输完，数的长度未知

这些采集的数据将作为非字符传输

引用 20 楼 Slzde_sub 的回复:  你这个有点懵啊   要么0  要么FF  要么eof   还想怎样  谁提的需求 。  叫他出来 让输入数据的人血溅当场的时候，就是数据输入完的时候！

为什么不学debug的a命令，连续两次回车结束输入呢？

原始问题？ 通信输入，缓存读空就没了 按键输入可以做延时读空等

仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.  结合fgets(buf,len,stdin);

不要提问这种你自己思考一半的问题 把原始的问题贴出来

gets回来再解析呗。。。

引用 11 楼 qq_42711337 的回复:[quote=引用 10 楼 jha334201553 的回复:] [quote=引用 9 楼 qq_42711337 的回复:] 请问 getch和 isprint 的具体函数？还有0x1b代表的是什么意思 两个库函数 #include <conio.h> #include <ctype.h> [/quote]  是否有其他方法？ conio.h 貌似不是标准的头文件[/quote] 你这属于能力不够，又喜欢折腾。你自己完全可以标准化重写一个 getch

引用 10 楼 jha334201553 的回复:[quote=引用 9 楼 qq_42711337 的回复:] 请问 getch和 isprint 的具体函数？还有0x1b代表的是什么意思 两个库函数 #include <conio.h> #include <ctype.h> [/quote]  是否有其他方法？ conio.h 貌似不是标准的头文件

数据传入的时候，不能添加#  之前考虑过EOF 但是还是被否决了

设定一个结束符号，比如以#表示结束。那么： do { int x = scanf("%x", a); } while ((char)x != '#');

如何使用scanf的返回值  如果是字符串的话是以回车为结束 如果是scanf("%x",a); 是以空格为结束 ，但是输入的时候是以空格分隔的 ，只能输入一个数 ，后续的数都保存不了

用scanf的返回值。

因为不知道数组的长度 所以不能采用n<16  问题是：输入一个未知长度的数组（而且是16进制） 如何判断是否已经输入完

看你怎么放了，如果你是数组里1个单元放1个数字，那就循环16次啊；   int n=0,num[16]; while(n<16) {     n++;     scanf("%d",num[n]); }

引用 9 楼 qq_42711337 的回复:请问 getch和 isprint 的具体函数？还有0x1b代表的是什么意思 两个库函数 #include <conio.h> #include <ctype.h>

请问 getch和 isprint 的具体函数？还有0x1b代表的是什么意思

用getch完事啦，自己判断是什么字符，比如： esc是 0x1b char ch; while( (ch = getch()) != 0x1b ) {     if (isprint(ch))     {         putch(ch);     } }

请教各位大佬


Question: MFC贴图问题！！

引用 15 楼 sghcpt 的回复:OnCtlColor函数是The framework calls this member function when a child control is about to be drawn.是子控件将要给重画时调用的，如果有多个控件就可能画多个，但是指定控件ID，那么画的就是指定ID的控件才会画~~~~~~~~ 我用了你的代码修改了下实现了我要的效果，但我想请问一下怎么实现我贴图想贴哪个坐标就哪个坐标而不是贴在空间上面 还有你说调用CreateCompatibleDC函数就已经使用了双缓冲，但这怎么和我百度看的双缓冲有点出入。

如果我要实现贴图贴在我我指定的X,Y点的话怎么实现不会卡速度慢，且不出现我上面发的图那样出现三张一样的图？  CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP7);  CDC memDC; memDC.CreateCompatibleDC(pDC);  memDC.SelectObject(&bitmap);  pDC->BitBlt(79,225,34,34,&memDC,0,0,SRCCOPY);

引用 13 楼 qq_42388955 的回复:[quote=引用 10 楼 sghcpt 的回复:] 双缓存的实现是应该为了防止窗口重画时，出现闪烁的情况多~~~用在dui界面上尤其需要的。。。 大哥我用了你的代码修改了一下，为什么你的贴图不会有卡顿的，速度也很快，我用了你的代码把位图贴在了位图控件上实现了我要的效果，也不会卡，但我想问一下你的这段代码没有用双缓冲为什么速度也那么快，我的代码和你的区别是我贴图贴在指定的位置，你贴图贴在指定的控件，这俩者之间的区别是什么[/quote]  如果你没有指定控件，那么上面OnCtlColor函数就会调用画图很多次，假如你界面上有N个控件，那么久调用N次画图，而如果你指定哪个控件画，那么只会在指定的控件需要重画的时候才调用一次。感觉应该是这个区别吧。。还有调用CreateCompatibleDC创建的内存DC已经用了双缓存了呀。。

引用 10 楼 sghcpt 的回复:双缓存的实现是应该为了防止窗口重画时，出现闪烁的情况多~~~用在dui界面上尤其需要的。。。 大哥我用了你的代码修改了一下，为什么你的贴图不会有卡顿的，速度也很快，我用了你的代码把位图贴在了位图控件上实现了我要的效果，也不会卡，但我想问一下你的这段代码没有用双缓冲为什么速度也那么快，我的代码和你的区别是我贴图贴在指定的位置，你贴图贴在指定的控件，这俩者之间的区别是什么

引用 10 楼 sghcpt 的回复:双缓存的实现是应该为了防止窗口重画时，出现闪烁的情况多~~~用在dui界面上尤其需要的。。。 还有就是你们在贴图的时候怎么解决一贴图上去就速度很慢的问题，双缓冲用了说刷出来的速度会变得很快为什么我没什么感觉，是不是我哪里弄错了？？ CBitmap bitmap; 		bitmap.LoadBitmap(IDB_BITMAP7);  		CDC memDC; 		memDC.CreateCompatibleDC(pDC);  		memDC.SelectObject(&bitmap);  		CBitmap BkMap; 		BkMap.CreateCompatibleBitmap(pDC,34,34);//w,h表示窗口的宽和高 		CDC BkDC; 		BkDC.CreateCompatibleDC(pDC); 		BkDC.SelectObject(&BkMap);  		BkDC.BitBlt(0,0,34,34,&memDC,0,0,SRCCOPY);  		pDC->BitBlt(79,225,34,34,&BkDC,0,0,SRCCOPY);

引用 10 楼 sghcpt 的回复:双缓存的实现是应该为了防止窗口重画时，出现闪烁的情况多~~~用在dui界面上尤其需要的。。。 没有啊我OnPaint函数里没有添加代码，都在OnCtlColor这里处理我的代码啊

楼主：OnCtlColor函数是The framework calls this member function when a child control is about to be drawn.是子控件将要给重画时调用的,我在mfc工程中实现下面函数： HBRUSH CMFCApplication1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { 	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 	if (pWnd->GetDlgCtrlID() == IDC_BUTTON1) 	{ 		CBitmap bitmap; 		BOOL bRetCode = bitmap.LoadBitmap(IDB_BITMAP7);  		CDC memDC; 		memDC.CreateCompatibleDC(pDC);  		memDC.SelectObject(&bitmap);  		pDC->BitBlt(79, 25, 60, 12, &memDC, 0, 0, SRCCOPY); 	} 	return hbr; }  只输出了一张图片，你会不会在OnPaint函数中也调用了画这张图片的代码呢？而且位置信息不同，所以就在不同的地方画了多次了，显示多张图片了？

引用 6 楼 user-2 的回复:就单单这个贴图代码，我在OnPaint里面是可以正确画出来的呀，而且只有一张呀 而且我感觉我参考网上那些代码，试了一下双缓冲没发现和普通贴图有什么区别啊。不是说速度上会有很大的跳跃吗

引用 6 楼 user-2 的回复:就单单这个贴图代码，我在OnPaint里面是可以正确画出来的呀，而且只有一张呀 我上面发的图片显示出来都是些按键，我的软件按下这些对应的按键然后贴不一样颜色状态的图，所以一个位置会有三种颜色的图片，初始常态，按下的状态，被按下过后的常态这三种不同的图

引用 4 楼 qq_42388955 的回复:[quote=引用 3 楼 user-2 的回复:] 为啥不放在OnPaint函数里呢？一般画图不是放在这个函数的嘛。 放在别的函数会有不同的变化吗？ 我这一贴就是三张一样的，而且速度很慢[/quote] 如果只有这一个地方画了，坐标都一样，不可能出现在三个不同的坐标处吧？还是你其他地方代码影响了？

就单单这个贴图代码，我在OnPaint里面是可以正确画出来的呀，而且只有一张呀

引用 3 楼 user-2 的回复:为啥不放在OnPaint函数里呢？一般画图不是放在这个函数的嘛。 放在别的函数会有不同的变化吗？ 我这一贴就是三张一样的，而且速度很慢

为啥不放在OnPaint函数里呢？一般画图不是放在这个函数的嘛。

上键是贴图，其他的都是画刷刷出来的。为什么这一贴图就出现三张一样的？？？


Question: 如何用c语言编写  关闭应用  却 不关闭应用

引用 7 楼 jha334201553 的回复:窗口显示与关闭都是自己控制的啊，想关闭哪个关闭哪个。别拿console窗口出来，那个是另类对啊是想关闭那个就关闭那个，有必要么？还要用鼠标。我是想少点几下。

引用 2 楼 colinfang2006 的回复:Window.hide() 楼主还是把自己的诉求说明白点吧→A网页，B代表网页的功能，A包含B，从功能来说B是A的功能(从B图片上那个叉代表的内个功能的角度讲)。？→如何关闭A，不关闭B的进程

想了半天什么叫“关闭应用 却 不关闭应用”

引用 3 楼 yiyefangzhou24 的回复:想了半天什么叫“关闭应用 却 不关闭应用”X和关闭进程

Window.hide() 楼主还是把自己的诉求说明白点吧

“编写 关闭应用 却 不关闭应用”------> 应用程序窗口隐藏了，看起来好像关闭了，实际上还在~~~~


Question: 求解答：求1到1888888之间的平衡数。所谓i（十进制数）是平衡数是满足下列要求的数，1到i之间的十进制数中出现1的个数总和与i相等。

这代码没问题，我用了其他一种方法验算了下，输出结果是一致的。

没看懂你说的平衡数是什么意思。按照你的说法，只有1才是平衡数。其他的任意一个数，出现1的次数都不会比这个数大。

for (int i = 1 ; i < 1888888; i++)  { //这里加上 cnt = 0;


Question: 怎样将 UInt16 * 转为 wchar_t *?

可以用MultiByteToWideChar。 UInt16*转为CHAR*

可以直接转吧。  比如  A 为 UInt16 *型指针，B为wchar_t *型指针 可以直接写 B= (wchar_t *) A； 这样强转，可能有的编译器会有警告。  也可以这样转，如果你的系统指针是4个字节的话，  B= (wchar_t *)((Uint32) A)；

直接转不行么？ 这两个不都是指针么？ 也就是访问类型，那直接转应该能行把？ 不过就要承受转换后带来的后果了  不同的数据类型访问的地址大小长度肯定是不一样了

你不会的话可以先转成别的类型在转成wchar_t * 比如把 UInt16 * 转成string 、char、或者char[]之类，再转化一次


Question: 关于c表达式++i++的问题。

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

引用 7 楼 zangfong 的回复:可以从i++和++i的实现来分析： 首先对于i++的实现是：    int   temp;   temp   =   i;    i   =   i+1;   return   temp;  i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通 过地址对temp进行操作.(换句话说就是不能作为左值)，因为temp是一个临时变量。  而++i的实现是：    i   =   i+1;   return   i; 返回的就是变量i本身，所以没有问题。 回到j = ++i++;根据运算符++自右向左的结核性，上面的代码等同于j = ++(i++);则(i++)返回temp之后，不能作为左值，所以也就报错error: lvalue required as increment operand 反过来，如果改成j = (++i)++;就没有问题了。分析的可以

引用 7 楼 zangfong 的回复:可以从i++和++i的实现来分析： 首先对于i++的实现是：    int   temp;   temp   =   i;    i   =   i+1;   return   temp;  i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通 过地址对temp进行操作.(换句话说就是不能作为左值)，因为temp是一个临时变量。  而++i的实现是：    i   =   i+1;   return   i; 返回的就是变量i本身，所以没有问题。 回到j = ++i++;根据运算符++自右向左的结核性，上面的代码等同于j = ++(i++);则(i++)返回temp之后，不能作为左值，所以也就报错error: lvalue required as increment operand 反过来，如果改成j = (++i)++;就没有问题了。 感觉解释的很对，赞一个

引用 17 楼 hemowolf 的回复:[quote=引用 14 楼 qq_38319117 的回复:] [quote=引用 13 楼 shiyanbo_1006 的回复:] 研究这问题？你确定工作中会用？ 别把有限的时候浪费在无用的扯蛋上面了  假设，人家在工程中想精简代码，用一句代码写“i+1赋值给j，然后i++”的功能，应该写j=i+++1;结果有个大胆的想法写了j=++i++;发现报错，想知道为什么错了，难道是要加括号，然后来问问，你的工作是逛论坛吗，不然你在无用的扯蛋吗[/quote]  发现C/C++论坛里对这种问题讨论的热忱还是蛮高涨的，如果是在Java/C#组里这种写法早就被人怼回去了！在Java/C#里，这类写法除了用来装B没有任何作用，反而降低了程序的可读性。  不知道在C/C++里，这种代码的精简有多大现实性的意义，能给软件产品带来明显的性能提升吗？楼上大侠说的这个功能，非要写到一条语句里吗，如果写成两条语句就造成严重的后果吗？还是说，C/C++的软件工程师就是纯粹地为了追求代码上的美感？ [/quote] 我在研究编译原理。

j = ++i++; 这一句错误，++i++相当于++（i++）,其中i++返回的是右值，相当于6，导致不能再自增了

引用 14 楼 qq_38319117 的回复:[quote=引用 13 楼 shiyanbo_1006 的回复:] 研究这问题？你确定工作中会用？ 别把有限的时候浪费在无用的扯蛋上面了  假设，人家在工程中想精简代码，用一句代码写“i+1赋值给j，然后i++”的功能，应该写j=i+++1;结果有个大胆的想法写了j=++i++;发现报错，想知道为什么错了，难道是要加括号，然后来问问，你的工作是逛论坛吗，不然你在无用的扯蛋吗[/quote] 首先声明我这是休息时间，我自己的时间。 如果我们组有人在产品中写这样的代码，代码审核的时候我一定会要求改掉。而且组里的所有人都会如此做。

需要左值吧，这样的问题适可而止吧，两个++还好，再多就不要管了，这个问题你可以一下什么叫左值和右值，然后就知道它为什么报错了

引用 13 楼 shiyanbo_1006 的回复:研究这问题？你确定工作中会用？ 别把有限的时候浪费在无用的扯蛋上面了  假设，人家在工程中想精简代码，用一句代码写“i+1赋值给j，然后i++”的功能，应该写j=i+++1;结果有个大胆的想法写了j=++i++;发现报错，想知道为什么错了，难道是要加括号，然后来问问，你的工作是逛论坛吗，不然你在无用的扯蛋吗

研究这问题？你确定工作中会用？ 别把有限的时候浪费在无用的扯蛋上面了

j = ++i++;  ++i ，这是一个表达式，而  n++ ，这里的n，应该是一个变量，或者一个属性。 表达式不行。  刚开始学习，不知道说的对不对。

这种代码只有大学考试中见到。

毛病出在“++i++ ”上面。 自增运算符(就是++)的结合性是从右至左，也就是说它是执行顺序是++(i++)。 自增运算符如果放在变量的右边，返回的是就是右值，右值是不可以改变的。 之后再做左边的自增运算时就会出错了。

引用 14 楼 qq_38319117 的回复:[quote=引用 13 楼 shiyanbo_1006 的回复:] 研究这问题？你确定工作中会用？ 别把有限的时候浪费在无用的扯蛋上面了  假设，人家在工程中想精简代码，用一句代码写“i+1赋值给j，然后i++”的功能，应该写j=i+++1;结果有个大胆的想法写了j=++i++;发现报错，想知道为什么错了，难道是要加括号，然后来问问，你的工作是逛论坛吗，不然你在无用的扯蛋吗[/quote]  发现C/C++论坛里对这种问题讨论的热忱还是蛮高涨的，如果是在Java/C#组里这种写法早就被人怼回去了！在Java/C#里，这类写法除了用来装B没有任何作用，反而降低了程序的可读性。  不知道在C/C++里，这种代码的精简有多大现实性的意义，能给软件产品带来明显的性能提升吗？楼上大侠说的这个功能，非要写到一条语句里吗，如果写成两条语句就造成严重的后果吗？还是说，C/C++的软件工程师就是纯粹地为了追求代码上的美感？

我就看一看~~~

引用 8 楼 xaioxiaoguai 的回复: 我用的是freebsd操作系统

引用 7 楼 zangfong 的回复:可以从i++和++i的实现来分析： 首先对于i++的实现是：    int   temp;   temp   =   i;    i   =   i+1;   return   temp;  i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通 过地址对temp进行操作.(换句话说就是不能作为左值)，因为temp是一个临时变量。  而++i的实现是：    i   =   i+1;   return   i; 返回的就是变量i本身，所以没有问题。 回到j = ++i++;根据运算符++自右向左的结核性，上面的代码等同于j = ++(i++);则(i++)返回temp之后，不能作为左值，所以也就报错error: lvalue required as increment operand 反过来，如果改成j = (++i)++;就没有问题了。 这个解答完整详细  赞！！！

加个括号就明白了： ++i++ 等同于  ++（i++），先计算括号，i++，得到的返回值是一个数值，再作 （++某数值），++操作符是对变量用的，对一个值操作当然不行


Question: 求助，为什么我这个吧整数转换为字符串的函数不正确，谢谢!

非常感谢！！！

sizeof返回指针的大小，通常是4 strlen返回0结尾的字符串长度 两者都表达不了dst指向地址开始的可用字节数这个概念

引用 1 楼 zhao4zhong1 的回复://将一个整数转化为字符串  void MyIntToStr(unsigned char *dst, int len,uint16_t data) { //itoa(data,(char*)dst, 10); snprintf((char *)dst, len, "%d" , data); }  unsigned char wrbuf[9]; MyIntToStr(wrbuf,9-1, 9999);      实现了，这个是可以 为什么 void MyIntToStr(unsigned char *dst, uint16_t data) {     //itoa(data,(char*)dst, 10);     int len = strlen((const char*)dst);     snprintf((char *)dst, len, "%d", data); }  也不行阿?


Question: linux C TCP UDP server 接收多个客户端同时连接的多线程

同IP同port两个程序同时接收可以实现么?

引用 2 楼 user-3 的回复:楼主：应该是下面的代码由问题吧？ ptr_arg.protocol = 'T'; ptr_arg.fd = tcp_connectfd; memcpy((char *)&ptr_arg.sock, (const char *)&client_addr,sizeof(struct sockaddr_in)); ptr_arg.num = i; if(pthread_create(&pthid, NULL, deal_send_pth, (void *)&ptr_arg) < 0) 其中ptr_arg变量，每次接受到一个新客户端连接时，就把这个这个变量值赋值为最新的，而之前保存的那些字应该给覆盖了。所以最后只有一个fd有效了，因为你把以指针参数的方式传给线程使用。楼主可以动态分配ptr_arg值，每次新客户端连接进来就动态分配一个，再传个线程，这样就应该可以了。  不是这个问题，现在问题已经解决了，非常感谢。

参考epoll源代码相关片断。


Question: 求助，怎么把[100, 254][1001, 2542]这样字符串中的数字提取出来变成整形数字？

首先 if ((*str > '0') || (*str < '9'))  这里加不加等于号我不清楚，但是根据你的注释来看 ，“||”应该改成  “&&”   然后你说的下一个问题，既然实现了单个，你把这整套方法加到循环里，多次执行不就能识别出多个来了吗。你这个函数里整体是顺序执行的，局部循环只是为了找出方括号里的数字字符，肯定不能实现多个类似格式数据的查找。

int x, y; 	char* str = "[100,10]"; 	int ret = sscanf(str, "[%d,%d]", &x, &y);

这是我自己写的，有点问题，单个[100,100]的时候可以，多个的时候不行，能否指点一下

void str2int1(char *str) {       len_point = 0;  //[10,500][20,300]     mid_point = 0;      if (*str == '[' )  //如果第一个字符是 [     {                  //则移到下一个字符         str++;      }     while(*str != 0 )     {         if ( (*str == ',') )  //如果当前字符是 ,         {                     //则退出循环            break;         }         if ((*str > '0') || (*str < '9'))  //如果当前字符是数字         {               //mid_point = mid_point * 10 + (*str - '0'); //如果当前字符是数字则计算数值           mid_point = mid_point * 10 + (*str) - '0';             str++;      //移到下一个字符         }     }      if (*str == ',' )  //如果第一个字符是 ,     {                      //则移到下一个字符         str=str+2;     }     while(*str != 0 )     {         if ( (*str == ']') )  //如果当前字符是 ]         {                     //则退出循环            break;         }         if ((*str >'0') || (*str < '9'))  //如果当前字符是数字         {              //len_point = len_point * 10 + (*str - '0'); //如果当前字符是数字则计算数值             mid_point = mid_point * 10 + (*str) - '0';             str++;      //移到下一个字符         }     }   }

识别数字前后的字符，当做判断条件


Question: 关于指针：为什么局部变量销毁后，p的值还是不变啊？？

你再运行一个新的函数 里面的数据就会变化了 临时变量是在堆栈里面的, 你退出了一个函数 堆栈往前移动,  你进入一个函数 堆栈往后移动

还没有人覆盖这个内存的内容，但是允许其他人覆盖，所以不建议这样写

所以stack攻击才得以成立。

调用f()函数时，开辟了个临时int空间（设该空间地址为1234），存放b的值并吧b的地址给了p； 当执行第一个printf语句时，存放在（空间1234）里的值还没被重置， 当执行完第一个printf语句后，空间（1234）里的值就被重置了 所以第二个printf语句输出0； 调用完f()后，函数里面的变量b是被销毁了的，但存放b的值的地址空间是没办法销毁的 不过里面的值会在执行一个语句后刷新重置； 如果b是全局变量，调用f()后就不会被销毁，存放b的值的地址空间的值也就不会刷新，多少次printf值都不会变 以上是我个人理解

栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……

栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，[color=#FF00FF]没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。[/color] 而栈中的类变量退出其作用域时，会自动执行其析构函数，……

因为被调函数进行了压栈的操作，当返回时，尽管函数栈被销毁，但实际上只是栈顶的指向被修改了而已，这块内存实际上还是可以被访问的。如果这时候你再去调另外一个函数，这个值可能就发生变化了，你可以试验一下。

3楼说的有理，讨论这个没有多大的意义，关键是你要理解指针是怎么回事  另外在f（）里面，这样用是不妥的，返回了一个局部变量的一个地址，这个地址实际上出了函数就不要用了才是

p的值是地址，释放的是存在这个地址里的内容，但是这个地址本身是不变的。

那块内存没有被其他程序使用，所以值没有被修改

说的都很好

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

先把堆栈和指针理解了，在看，你的问题自己就解决了。  #include <stdio.h>  int *f()  // normal func return type int* { 	int b = 0xcafe9abe; //int value b = 0xcafe9abe; 	int *p1 = &b;           // p1 is a point value = b 's address; 	return p1;                // return value is a int * point value = b's address (一旦函数结束，int b 的地址（栈）已经被操作系统释放） }  void g() { 	int b = 0xdeadbeee; }  int main() { 	int *p = f(); 	printf("%X\n", *p); 	//g(); 	printf("%X\n", *p); }  不是俩个函数的局部变量名字一样就在内存里一样。仔细看书吧。

都说的很好111

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

之所以一样，是因为f函数使用的空间未被其他函数占用。局部变量在函数调用结束后是会被自动释放，自动释放的意思就是这部分栈空间可以被其他的函数栈使用，如果继续读取已经释放的栈空间是未定义行为。 如果已经释放的栈空间被别的函数栈使用，那么b的内存空间可能被写入新的值。因此输出的就不是原来的值了。

函数返回后，函数里局部变量的内存空间回归操作系统，因此里面的内容不可预期。 在你的例子中，如果这段内存空间操作系统还没有写入，内容不变；操作系统写入了，内容就有变化。 对于开发者而言，只需记住：函数返回局部变量是不可取的。

就是你刚写过，虽然你放弃了他 但是你放弃的是访问他的权力，他还是那样没有变 直到有人在此访问他改变他的值啊

使用已经销毁的指针是未定义行为，讨论这个毫无意义 要想知道为什么第一次可以第二次不行请自行单步汇编去理解，简单地说就是第一次堆栈的值并没有被覆盖，第二次因为之前调用了一次printf，堆栈已经被覆盖了


Question: 求任意两个数的最小公倍数

这种方法不是很好，我们求解最小公倍数和最大公约数问题一般都是采用辗转相除法。 其中，辗转相除法可以这样表示，用函数递归的思想 int X(int a,int b) {    if(b==0) return a;   else      return X(b,a%b); }

使用辗转相除法

辗转相除法求最大公约数 然后两个数相乘除以最大公约数  你这样写时间复杂度太高

#define _CRT_SECURE_NO_WARNINGS 1  #include<stdio.h> #include <windows.h>  int main() { 	int a, b; 	printf("请输入两个数:"); 	scanf("%d %d", &a, &b); 	int i = a; 	for (;; i++) 	{ 		if (i%a == 0 && i%b == 0) 		{ 			printf("最小公倍数为:%d\n", i); 			break; 		} 	} 	system("pause"); 	return 0; }

可以用辗转相除法求最大公因式，然后求最小公倍数

#include<stdio.h> #include <stdlib.h>  	void main() { 	int a,b; 	scanf("%d%d",&a,&b); 	int i=1,j; 	for(;;i++) 		if(i%a==0 && i%b==0) 		{ 			printf("最小公倍数为:%d\n",i); 			break; 		} 		system("pause"); }

一般算法是先计算 a和b的最大公约数，然后通过最大公约数计算最小公倍数

for(;;i++)              if(i%a==0 && i%b==0)              {                  printf("最小公倍数为:%d\n",i)              } 这是一个死循环的逻辑。建议加上break跳出循环

一个是花括号的使用，一个是for循环没有退出，如果是初学者的话，用这个遍历的方法就够了，再难一点就是写算法计算最小公倍数，因为如果数很大的话，遍历费时间  void main() { 	int a,b;     scanf("%d%d",&a,&b);     int i=1,j;     for(;;i++)       { 	      if(i%a==0 && i%b==0)           {              printf("最小公倍数为:%d\n",i);              break;//找到值后退出for循环            }              	  } 	   	getch();//暂停以显示  }

呃 你放这段代码想干嘛？


Question: 代码里的错误判断，怎么写最简洁啊，感觉好多重复呢

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

BOOL FUN() {     BOOL retval = FALSE;     WSADATA WSAData;     if (WSAStartup(MAKEWORD(2,0), &WSAData))          return FALSE;     SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);     if (sock != INVALID_SOCKET)      {         do          {              ......              BOOL bOptVal = TRUE;             if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, sizeof(BOOL)))             {                 break;             }             if (sendto(sock, (const char *)MagicP, sizeof(MagicP), 0, (struct sockaddr *)&RecvAddr, sizeof(RecvAddr)) == SOCKET_ERROR)             {                 break;             }             retval = TRUE;         } while (FALSE);         closesocket(sock);     }     WSACleanup();     return retval; }

谁来说说，LS谁是比较优的代码

1. goto语句 2. 封装类 3. try...catch...

感觉习惯就好

不用goto，这么写试试  BOOL FUN() { 	WSADATA WSAData; 	if (WSAStartup(MAKEWORD(2,0), &WSAData)) return FALSE;  	BOOL bRet = FALSE; 	SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); 	do  	{ 		if (sock == INVALID_SOCKET)  		{ 			break; 		}  		...... 		BOOL bOptVal = TRUE; 		if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, sizeof(BOOL))) 		{ 			break; 		} 		if (sendto(sock, (const char *)MagicP, sizeof(MagicP), 0, (struct sockaddr *)&RecvAddr, sizeof(RecvAddr)) == SOCKET_ERROR) 		{ 			break; 		} 		bRet = TRUE; 	} while (0);  	closesocket(sock); 	WSACleanup();  	return bRet; }

C语言的话，用goto吧，不要迷信有些教科书说goto不好，好不好看你怎么用。

1、如果是C语言，可考虑用goto跳至函数末尾，执行清理操作 2、如果是C++，建议封装成类对象，在析构时会自动释放资源，这样则可直接return就行

C++语言用 try 结构也是一个不错的选择 try { } catch() { } finally { }

可以把那几个方法封装一下，比如定义一个MySocket类，里面定义诸如setsockopt这些方法，这些方法的实现就是调真实的setsockopt，然后再析构函数里，加上 closesocket(sock); WSACleanup(); 这两句，这样局部变量在函数退出前，一定会调用析构函数

20%实现功能，80%错误处理。 这很正常！

虎头蛇尾是俗人的习惯， 有始有终是君子的操守。

一个产品中的代码，这些错误判断是必不可少的，不可省略。不过这段代码里return过多，会导致错误处理的遗漏和不统一。而且不易修改。可以修改成这样：  BOOL FUN() {     WSADATA WSAData;     int wsi=-1;          if (wsi=WSAStartup(MAKEWORD(2,0), &WSAData))     {          goto err_exit;     }     SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);     if (sock == INVALID_SOCKET)      {         goto err_exit;     }           ......       BOOL bOptVal = TRUE;     if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&bOptVal, sizeof(BOOL)))     {         goto err_exit;     }     if (sendto(sock, (const char *)MagicP, sizeof(MagicP), 0, (struct sockaddr *)&RecvAddr, sizeof(RecvAddr)) == SOCKET_ERROR)     {         goto err_exit;     }     closesocket(sock);     WSACleanup();     return TRUE; err_exit:     if (sock != INVALID_SOCKET)    closesocket(sock);     if (!wsi)        WSACleanup();      return FALSE; }   如果不想用goto 跳转，也可以把错误处理这几条定义成宏，在出错处理的地方调用宏ERR_EXIT      :  #define ERR_EXIT      if (sock != INVALID_SOCKET)    closesocket(sock); \     if (!wsi)        WSACleanup(); \      return FALSE;

goto

楼主，把重复的代码，放到函数FUN外面，通过FUN返回值，再做相关处理~~~这样可以否？？


Question: 关于c语言如何监控全局键盘按键

RegisterHotKey The RegisterHotKey function defines a system-wide hot key.   BOOL RegisterHotKey(   HWND hWnd,         // window to receive hot-key notification   int id,            // identifier of hot key   UINT fsModifiers,  // key-modifier flags   UINT vk            // virtual-key code );  Parameters hWnd  Handle to the window that will receive WM_HOTKEY messages generated by the hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.  id  Specifies the identifier of the hot key. No other hot key in the calling thread should have the same identifier. An application must specify a value in the range 0x0000 through 0xBFFF. A shared dynamic-link library (DLL) must specify a value in the range 0xC000 through 0xFFFF (the range returned by theGlobalAddAtom function). To avoid conflicts with hot-key identifiers defined by other shared DLLs, a DLL should use the GlobalAddAtom function to obtain the hot-key identifier.  fsModifiers  Specifies keys that must be pressed in combination with the key specified by the nVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers parameter can be a combination of the following values. Value Meaning  MOD_ALT Either alt key must be held down.  MOD_CONTROL Either ctrl key must be held down.  MOD_SHIFT Either shift key must be held down.  MOD_WIN Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo.    vk  Specifies the virtual-key code of the hot key.  Return Values If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, callGetLastError.  Remarks When a key is pressed, the system looks for a match against all hot keys. Upon finding a match, the system posts the WM_HOTKEY message to the message queue of the thread that registered the hot key. This message is posted to the beginning of the queue so it is removed by the next iteration of the message loop.   This function cannot associate a hot key with a window created by another thread.   RegisterHotKey fails if the keystrokes specified for the hot key have already been registered by another hot key.   If the window identified by the hWnd parameter already registered a hot key with the same identifier as that specified by the id parameter, the new values for the fsModifiers and vk parameters replace the previously specified values for these parameters.   Windows CE: Windows CE versions 2.0 and later support an additional flag, called MOD_KEYUP, for the fsModifiers parameter. If you set the MOD_KEYUP flag, the window will be sent a WM_HOTKEY message on a key up event as well as on a key down event.  RegisterHotKey can be used to register hot keys across threads.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in winuser.h.   Import Library: Use user32.lib.  See Also Keyboard Input Overview, Keyboard Input Functions,GlobalAddAtom, UnregisterHotKey, WM_HOTKEY

搜一下键盘钩子

在其他時期，沒有捕捉鍵盤信號？


Question: C语言编写某公司旗下的车辆使用管理系统 目前还缺少主函数和菜单将三个表连接到一起    个人能力有限，只能写一部分了，还望各位大神帮帮忙！

用php写更方便吧

引用 1 楼 weixin_42562729 的回复:很好奇拿C语言写管理系统，一般C不是底层硬件开发的么？开发管理系统C语言有交互界面么？用起来不是不方便？  感觉打基础用C语言来写正好，逻辑清楚，就是比较复杂

引用 1 楼 weixin_42562729 的回复:很好奇拿C语言写管理系统，一般C不是底层硬件开发的么？开发管理系统C语言有交互界面么？用起来不是不方便？ C语言写这个确实不是很好的选择，里面特别是用链表实现动态存储的时候，需要考虑的东西不少，但是作者应该是课程设计或者项目设计吧，或者是刚学完C，拿来练手，不管怎么说，除了没有界面，其他的还是很挺好的。  主函数也挺简单的，就定义一个链表当做头结点，把你的其他表挂到里面当做普通变量，然后该传啥传啥，该干嘛干嘛，保证始终操作的是主函数那个头所在的那块地址就好了，然后注意使用的时候判断节点是否为空，不是循环链表判断是否到达链表末尾，就没啥大问题了。


Question: 刚学链表，写了个程序，可能是指针地址不对，有大佬帮忙看看吗

引用 1 楼 zhao4zhong1 的回复:数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633 谢谢老师，我先看看

引用 2 楼 hou09tian 的回复:改了以下，VS2015编译通过了  // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 //  #include "stdafx.h" #include <stdlib.h> struct sz { 	int num; 	char name; 	int money; 	struct sz *next; }; struct sz *create() { 	struct sz *p1, *p2, *head; 	struct sz p0; 	int num, money; 	char name; 	int n = 0; 	head = NULL; 	p1 = p2 = &p0; 	p1 = p2 = (struct sz*)malloc(sizeof(struct sz)); 	printf("\n\t\t 请输入编号,名称，金额："); 	scanf("%d,%s,%d", &p1->num, &p1->name, &p1->money); 	while (p1->num != 0) 	{ 		n++; 		if (n == 1)	head = p1; 		else p2->next = p1; 		p2 = p1; 		p1 = (struct sz*)malloc(sizeof(struct sz)); 		printf("\n\t\t 请输入编号,名称，金额："); 		scanf("%d,%s,%d", &p1->num, &p1->name, &p1->money); 	} 	p2->next = NULL; 	return head; }  void printlist(struct sz *head) { 	struct sz *p; 	p = head; 	p = (struct sz*)malloc(sizeof(struct sz)); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *编号*名称*    金额    * \t\n"); 	if (head != NULL) 	{ 		/*do 		{ 		printf("\n\t\t %d,%s,%d",p->num,p->name,p->money); 		p=p->next; 		}while(p!=NULL); 		*/ 		while (p->next != NULL) 		{ 			printf("\n\t\t %d %s %d", p->num, p->name, p->money); 			p = p->next; 		} 	} 	printf("\n\t\t ************************ \t"); } //按照日期删除  struct sz *deletenode(struct sz *head, int num) { 	struct sz *p1, *p2=NULL; 	if (head == NULL)	printf("\n\t\t The List is NULL.\n"); 	else 	{ 		p1 = head; 		while (p1->next != NULL && p1->num != num) 		{ 			p2 = p1; 			p1 = p1->next; 		} 		if (p1->num == num) 		{ 			if (p1 == head) 				head = p1->next; 			else 				p2->next = p1->next; 		} 		else 			printf("\n\t\t Can not find list num.\n"); 	} 	return head; }  void wlc() { 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *      个人收支服务    * \t"); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *      1.收入管理      * \t"); 	printf("\n\t\t *      2.支出管理      * \t"); 	printf("\n\t\t *      3.关闭系统      * \t"); 	printf("\n\t\t ************************ \t\n"); 	printf("\n\t\t 请输入你的选择："); }  int in() { 	struct sz *head = NULL; 	system("cls"); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *       收入管理       * \t"); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *      1.添加收入      * \t"); 	printf("\n\t\t *      2.删除收入      * \t"); 	printf("\n\t\t *      3.打印收入      * \t"); 	printf("\n\t\t ************************ \t\n"); 	printf("\n\t\t 请输入你的选择："); 	int a; 	scanf("%d", &a); 	switch (a) 	{ 	case 1: 	{ 		head = create(); 	}	break; 	case 2: 	{ 		printf("\n\t\t 请输入需删除的编号："); 		int num; 		scanf("%d", &num); 		deletenode(head, num); 		getchar(); 		printlist(head); 	}break; 	case 3: 	{ 		printlist(head); 		getchar(); 	}break; 	case 4: 	{ 	}break; 	} 	return 0; } void ex() { 	//---------------需要添加代码！！！ } void end() { 	system("cls"); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *      个人收支服务    * \t"); 	printf("\n\t\t ************************ \t"); 	printf("\n\t\t *                      * \t"); 	printf("\n\t\t *     感谢您的使用！   * \t"); 	printf("\n\t\t *                      * \t"); 	printf("\n\t\t ************************ \t\n"); } void choice() { 	int a; 	scanf("%d", &a); 	while (a != 0) 		switch (a) 		{ 		case 1:do { 			in(); 		} while (in() == 4); break; 		case 2:ex(); break; 		case 3:end(); break; 		} }  int main() { 	wlc(); 	choice();  	return 0; }  我用的DEV，这样只是从崩溃变成了闪屏。还是没有打印。


Question: 小顶堆排序出了点问题救助。

for循环中的取值范围设置不当  for (j=2*s+1;j< m;j=j*2+1) for(i=L->length/2-1;i>=0;i--)  排序代码供参考。还有，数据能解决的问题，为啥搞得这么复杂。。。 #include<stdio.h>  typedef struct {     int r[12];     int length; }List;  void HeapAdjust(List *L, int s, int m) {     int temp,j;     temp=L->r[s];     for (j=2*s+1;j< m;j=j*2+1)     {         if(j+1<m && (L->r[j] > L->r[j+1]))         {             ++j;         }          if(temp < L->r[j]) break;          L->r[s] = L->r[j];         s=j;     }     L->r[s] = temp; }  void HeapSort(List *L) {     int i;     for(i=L->length/2-1;i>=0;i--)         HeapAdjust(L,i,L->length);      for(i = L->length-1; i >= 0; i--)     {         int temp = L->r[0];         L->r[0] = L->r[i];         L->r[i] = temp;          HeapAdjust(L,0,i);     } }  int main(int argc, const char * argv[]) {     List a;      List *L = &a;     L->length = 11;  L->r[0]=111;     L->r[1]=333;     L->r[2]=222;     L->r[3]=666;     L->r[4]=555;     L->r[5]=999;     L->r[6]=444;     L->r[7]=777;     L->r[8]=888;     L->r[9]=101;     L->r[10]=121;      HeapSort(L);       for(int i=0;i<11;i++)     {         printf("%d\n",L->r[i]);     }      return 0; }

有没有大佬啊


Question: 虚拟地址和物理地址的存储与提取

怎么搞的呀，虚拟内存和申请空间

到底已经获取了地址还是没有获取？ // ReadPEInfo.cpp : 定义控制台应用程序的入口点。 //   #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <Dbghelp.h>   void ReadNTPEInfo(PIMAGE_NT_HEADERS pImageNtPE); ULONG RvaToOffset(IMAGE_NT_HEADERS * pNtHeader,ULONG Rva);   #define pNtHeaders pImageNtHeaders   int _tmain(int argc, _TCHAR* argv[]) {       char file[]="win32.exe";       //DOS头     PIMAGE_DOS_HEADER pImageDosHeader;       //NT头(包括PE标识+Image_File_Header+OptionHeader)     PIMAGE_NT_HEADERS pImageNtHeaders;       //标准PE头、     PIMAGE_FILE_HEADER pImageFileHeader;         //扩展PE头     IMAGE_OPTIONAL_HEADER32 pImageOptionHeaders;         HANDLE hFile;       HANDLE hMapObject;      //DOS头     PUCHAR uFileMap;       hFile= CreateFile(file,GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);     if(hFile==NULL)     {         printf("打开文件失败\n");         system("pause");         return 0;     }       hMapObject=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);     if(hMapObject==NULL)     {         printf("创建文件映射内核对对象失败\n");         system("pause");         return 0;     }       //PE基址     uFileMap=(PUCHAR)MapViewOfFile(hMapObject,FILE_MAP_READ,0,0,0);     if(uFileMap==NULL)     {         printf("映射到进程地址空间失败\n");         system("pause");         return 0;     }       pImageDosHeader=(PIMAGE_DOS_HEADER)uFileMap;     if(pImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)     {         printf("不是PE结构\n");         system("pause");         return 0;     }       //定位到NT PE头     pImageNtHeaders=(PIMAGE_NT_HEADERS)((PUCHAR)uFileMap+pImageDosHeader->e_lfanew);           //导入表的相对虚拟地址(RVA)     ULONG rva_ofimporttable=pImageNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress;     //根据相对虚拟(rva)地址计算偏移地址(offset)     ULONG offset_importtable=RvaToOffset(pImageNtHeaders,rva_ofimporttable);     if(!offset_importtable)     {         printf("获取导入表偏移地址失败\n");         system("pause");         return 0;     }       PIMAGE_THUNK_DATA s;           //取得导入表的地址     IMAGE_IMPORT_DESCRIPTOR *pImportTable=(IMAGE_IMPORT_DESCRIPTOR *)((char*)uFileMap+offset_importtable);         IMAGE_IMPORT_DESCRIPTOR null_iid;     IMAGE_THUNK_DATA null_thunk;     memset(&null_iid, 0, sizeof(null_iid));     memset(&null_thunk, 0, sizeof(null_thunk));       //每个元素代表了一个引入的DLL。     for(int i=0; memcmp(pImportTable + i, &null_iid, sizeof(null_iid))!=0; i++)     {         char *dllName= (char*)(uFileMap+RvaToOffset(pImageNtHeaders,pImportTable[i].Name));           //拿到了DLL的名字           printf("模块[%d]: %s\n", i, (char*)dllName);         PIMAGE_THUNK_DATA32 pThunk=(PIMAGE_THUNK_DATA32)(uFileMap+RvaToOffset(pImageNtHeaders,pImportTable[i].FirstThunk));                   while(pThunk->u1.Ordinal!=NULL)         {             PIMAGE_IMPORT_BY_NAME pname=(PIMAGE_IMPORT_BY_NAME)(uFileMap+RvaToOffset(pImageNtHeaders,pThunk->u1.AddressOfData));             printf("函数编号: %d 名称: %s\n",pname->Hint,pname->Name);             pThunk++;         }     }     system("pause");     return 0; }     void ReadNTPEInfo(PIMAGE_NT_HEADERS pImageNtPE) {     printf("运行平台:   0x%04X\n",pImageNtPE->FileHeader.Machine);     printf("节数量:   %d\n",pImageNtPE->FileHeader.NumberOfSections);     printf("PE属性:   0x%04X\n",pImageNtPE->FileHeader.Characteristics); }           //计算Offset ULONG RvaToOffset(IMAGE_NT_HEADERS * pNtHeader,ULONG Rva) {     //PE节     IMAGE_SECTION_HEADER *p_section_header;     ULONG sNum,i;     //取得节表项数目     sNum=pNtHeader->FileHeader.NumberOfSections;     //取得第一个节表项     p_section_header=(IMAGE_SECTION_HEADER *)                           ((BYTE *)pNtHeader+sizeof(IMAGE_NT_HEADERS));     for(i=0;i<sNum;i++)     {         //printf("PE 节名称: %s\n",p_section_header->Name);         if((p_section_header->VirtualAddress<=Rva)&&Rva<(p_section_header->VirtualAddress+p_section_header->SizeOfRawData))         {             return Rva-p_section_header->VirtualAddress+p_section_header->PointerToRawData;         }            p_section_header++;         }     return 0; }

昨天晚上搞成功了，谢谢哦

定义一个全局变量呗 typedef struct mAddress　　　　{ 　　　　int physicalAddress;               int virtualaddress; 　　　　}Address; Address.physicalAddress= xxxx; mAddress.virtualaddress= xxxx;

现在就是定义的一个全局变量的 typedef struct tagMyAddr {      HI_U32 *pVirAddr ;      HI_U32   u32PhyAddr ; }MYADDR;  static MYADDR *g_addr;  可是还是不行，需要初始化，我在free的时候怎么确定虚拟地址和物理地址是一一对应的那？还有怎么根据虚拟地址去寻找物理地址那？可以帮忙写下吗？


Question: 关于gets（）后面的代码会被跳过的问题

void spt(struct student** q) { int i; for (i = 0; i < *q; ++i) { printf("请输入第%d个学生信息：\n", i + 1); printf("姓名："); gets(q[i]->name); printf("年龄："); scanf_s("%d", &q[i]->age); printf("成绩："); scanf_s("%f", &q[i]->score); return; } } 这个逻辑不会发现有问题吗？*q是循环变量的最大值，怎么循环体内还对q[i]->name等呢？

scanf_s("%d", &*p); 这个有问题的（*p是取p指向的内存单元的值，&是取地址，取地址一般是对变量的，&*p是对常量取地址，并且这个地址也是不可读写的值）。为什么绕个弯呢，直接一下就好了  scanf_s("%d", p);

给结构体指针分配地址时，len还没有得到输入，它的值是0，因此此处没有分配到内存，接下来的操作就出现非法内存访问了。 第二个问题，函数spt中的循环终止条件是*q，这是地址而不是数组长度，应该跟arr函数一样传入一个学生个数的参数。 另外，传入学生个数不必传地址。


Question: 好想知道这个关于餐馆点菜的程序哪里出错了，运行时只能进入管理员账户无法创建新用户进入主管和服务员页面

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。


Question: 链表删除结点的问题

引用 2 楼 heabby2010 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633  谢谢老师，我再研究研究[/quote] 看链接中帖子#43

楼主，可以参考参考下面代码： typedef struct LNODE { 	data_t data; 	struct LNODE * next; }Node_t, *PNode;   int Delete(PNode* PHead, data_t data) { 	int status = -2; 	PNode PCur = *PHead; 	PNode prevNode = NULL; 	while (PCur) 	{ 		if (data.sn == PCur->data.sn) 		{ 			if (prevNode != NULL) 				prevNode->next = PCur->next;  			PNode tempNode = PCur; 			PCur = PCur->next;  			if (prevNode == NULL) 				*PHead = PCur;  			free(tempNode); 			tempNode = NULL;  			status = 0;//success 			break; 		}  		prevNode = PCur; 		PCur = PCur->next; 	} 	return status;//NULL or get it. }

引用 1 楼 zhao4zhong1 的回复:数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633  谢谢老师，我再研究研究