Question: c语言建立双向链表 打印不出来 马上要交作业 急急急~

这排版。。还是告别编程吧

//#include"stdio.h" //#include"stdlib.h" #include <stdio.h> #include <stdlib.h>  typedef struct  dlink_node{     int info;     struct dlink_node *llink, *rlink; }dnode;  dnode *init() {     return NULL; }  void display(dnode *head) {     dnode *p, *q;     p = q = head;      if (!p)  {         printf("\n链表是空的\n");         return;     }     printf("双链表中的值从左到右为\n");     while (p) {         printf("%d ", p->info);         q = p;         p = p->rlink;     }     putchar(10);     printf("双链表中的值从右到左为：\n");     p = q;     while (p) {         printf("%d ", p->info);         p = p->llink;     }     putchar(10); }  dnode *find(dnode *head, int i) {     int j = 1;     dnode *p = head;     if (i < 1) { printf("\n第%d个结点不存在\n", i);return NULL; }     while (p&&j != i)     {         p = p->rlink;j++;     }     if (!p) { printf("\n第%d个结点不存在\n",i); return NULL; }     return p; }  dnode *insert(dnode *head, int x, int i) {     dnode *p, *q;     p = (dnode*)malloc(sizeof(dnode));     p->info = x;     if (i == 0)     {         p->llink = NULL;         p->rlink = head;         if (!head) { head = p; }         else { head->llink = p;head=p; }         return head;     }     q = find(head, i);     if (!q) { printf("第%d个结点不存在，无法插入",i);free(p);return head; }     else if (q->rlink == NULL)     {         p->rlink = NULL;         q->rlink = p;         p->llink = q;     }     else     {         p->rlink = q->rlink;         q->rlink->llink = p;         q->rlink = p;         p->llink = q;     }     return head; }  dnode *dele(dnode *head,int x) {     dnode *q;     if (!head) { printf("双链表为空，不能删除"); return NULL; }     q = head;     while (q&&q->info != x) q = q->rlink;     if (!q)printf("没有找到值为%d的结点~不能删除~",x);     if (q == head && !head->rlink)     {         free(q); return NULL;/*变成空的了耶qwq*/     }     if (q == head && head->rlink)     {         head = head->rlink;head->llink = NULL; free(q);         return head;     }     else     {         if (!q->rlink)         {             q->llink->rlink = NULL; free(q);             return head;         }         else         {             q->llink->rlink = q->rlink;             q->rlink->llink= q->llink;             free(q); return head;         }     } }  int main() {     puts("≡ω≡");     dnode *s;     dnode *head = NULL;     int length,data,i, x, num,j;      s = head;     printf("请定义双向链表的长度：");     scanf_s("%d", &length);     dnode *A;/*创建一个链表*/     //A=init();/*初始化*/     A = NULL;/*初始化*/      dnode *tail = NULL;     printf("请输入元素:\n");     for(j = 0;j <length;j++)     {         s = (dnode *)malloc(sizeof(dnode));         scanf_s("%d", &data);         s->info = data;         s->llink = NULL;         s->rlink = NULL;         if (!A) {             A = s;             tail = A;         } else {             s->llink = tail;             tail->rlink = s;             tail = s;         }     }      /*逐个获取*/     display(A);     while (1)     {         printf("\n请选择功能:\n");         printf("1、插入 2、删除\n");         scanf_s("%d", &num);         switch (num)         {             case 1: printf("请输入想要插入的元素:\n");                     scanf_s("%d", &x);                     printf("请选择想要插入的位置:\n");                     scanf_s("%d", &i);//插入                     insert(A, x, i); display(A);                     break;              case 2: printf("请输入想要删除的元素:\n");                     scanf_s("%d", &x);//删除                     dele(A, x); display(A);                     break;         }     } } 参考一下吧  代码风格建议注意下，代码不单单是运行出结果，更多的是代码的可读性要好，别人看着才会舒心。  创建和显示都修改了，查找和插入建议自己继续改一下

没看完，感觉好多问题： 1， 那个Init完全没啥实际意义，估计想保存head，但实际没有做到 2， display函数中逻辑有问题， 从右到左应该永远不会打出东西 printf("双链表中的值从左到右为\n"); while (p) { printf("%d", p->info);p = p->rlink; } printf("双链表中的值从右到左为：\n"); while (p) { printf("%d", p->info);p = p->llink; } 3， main 函数里面获取节点有不少问题， 分配了空间没初始化， 左节点未赋值，head和A没关系导致你根本没操作链表（） s = (dnode*)malloc(sizeof(dnode)); scanf_s("%d", &data); s->info = data;s = s->rlink;

在你的基础上修改了下，改的地方基本都加了注释了。编程这一路任重而道远啊  #include"stdio.h" #include"stdlib.h" typedef struct  dlink_node{ 	int info; 	struct dlink_node *llink, *rlink; }dnode;  dnode *init() { 	return NULL; }  void display(dnode *head) { 	dnode *p; 	p = head; 	if (!p) printf("\n链表是空的\n"); 	else 	{ 		printf("双链表中的值从左到右为\n"); 		while (p) { printf("%d  ", p->info);p = p->rlink; } 		printf("\n双链表中的值从右到左为：\n"); 		p = head; //需要重新初始化p指针位置 		while(p->rlink) 			p = p->rlink; 		while (p) { printf("%d  ", p->info);p = p->llink; } 	} }  dnode *find(dnode *head, int i) { 	int j = 1; 	dnode *p = head; 	if (i < 1) { printf("\n第%d个结点不存在\n", i);return NULL; } 	while (p&&j != i) 	{ 		p = p->rlink;j++; 	} 	if (!p) { printf("\n第%d个结点不存在\n",i); return NULL; } 	return p; }  dnode *insert(dnode *head, int x, int i) { 	dnode *p, *q; 	p = (dnode*)malloc(sizeof(dnode)); 	p->info = x; 	if (i == 0) 	{ 		p->llink = NULL; 		p->rlink = head; 		if (!head) { head = p; } 		else { head->llink = p;head=p; } 		return head; 	} 	q = find(head, i); 	if (!q) { printf("第%d个结点不存在，无法插入",i);free(p);return head; } 	else if (q->rlink == NULL) 	{ 		p->rlink = NULL; 		q->rlink = p; 		p->llink = q; 	} 	else 	{ 		p->rlink = q->rlink; 		q->rlink->llink = p; 		q->rlink = p; 		p->llink = q; 	} 	return head; }  dnode *dele(dnode **heads,int x) { 	//修改一级指针的值，需要传二级指针，也就是一级指针的地址 	dnode * head = *heads; 	dnode *q; 	if (!head) { printf("双链表为空，不能删除"); return NULL; } 	q = head; 	while (q&&q->info != x) q = q->rlink; 	if (!q)printf("没有找到值为%d的结点~不能删除~",x); 	if (q == head && !head->rlink) 	{ 		free(q); 		*heads = NULL; 		return NULL;/*变成空的了耶qwq*/ 	} 	if (q == head && head->rlink) 	{ 		*heads = head->rlink; 		(*heads)->llink = NULL; 		free(q); 		return NULL; 	} 	else 	{ 		if (!q->rlink) 		{ 			q->llink->rlink = NULL; free(q); 			return head; 		} 		else 		{ 			q->llink->rlink = q->rlink; 			q->rlink->llink= q->llink; 			free(q); return head; 		} 	} }  int main() { 	puts("≡ω≡"); 	dnode *s; 	dnode *head = NULL; 	s = head; 	int length,data,i, x, num,j; 	printf("请定义双向链表的长度："); 	scanf("%d",&length); 	dnode *A;/*创建一个链表*/ 	A=init();/*初始化*/ 	printf("请输入元素:\n"); 	for(j = 0;j <length;j++) 	{ 		if(A == NULL){ 			A = (dnode*)malloc(sizeof(dnode)); 			scanf("%d", &data); 			A->info = data; 			A->llink = NULL; 			A->rlink = NULL; 		} 		else{ 			int len =  1; 			dnode* findPtr = A; 			scanf("%d", &data); 			while (findPtr->rlink){ 				++len; 				findPtr = findPtr->rlink; 			} 			insert(A, data, len); 		}  	}/*逐个获取*/ 	display(A); 	while (1) 	{ 		printf("\n请选择功能:\n"); 		printf("1、插入 2、删除\n"); 		scanf("%d", &num); 		switch (num) 		{ 		case 1: printf("请输入想要插入的元素:\n"); 			scanf("%d", &x); 			printf("请选择想要插入的位置:\n"); 			scanf("%d", &i);//插入 			insert(A, x, i); display(A);break; 		case 2: printf("请输入想要删除的元素:\n"); 			scanf("%d", &x);//删除 			dele(&A, x); display(A);break; 		} 	} }


Question: 程序输入问题

应该是缓冲区残留，没有取走，或者没有清空，下一次scanf就直接取走了。

引用 4 楼 cfjtaishan 的回复:程序没问题，应该是缓冲区理解的问题。scanf输入之后，其实有一个换行符“残留”在输入缓冲区里，因此第二个while正好接收到了这个'\n'。 程序没问题，应该是缓冲区理解的问题。scanf输入之后，其实有一个换行符“残留”在输入缓冲区里，因此第二个个体插入()正好接收到了这个'\n'。并将其“吸收”了。

引用 1 楼 jianwen0529 的回复:ch=getchar();	 获取流中的下一个字符，在你这个操作中也就是换行/回车符 红色标注的代码作用主要就是丢弃掉这个字符 那请问没有这行代码的话，为什么第二个printf函数就会自动换行呢？


Question: c语言  用指针传递函数返回值总是失败

引用 4 楼 Slzde_sub的回复:[quote=引用 3 楼 adlay 的回复:] 返回局部变量的指针, 程序行为是未定义的. 数组 a 在 create 函数返回后内存已被回收, 可能用于存放其他的数据了.   。。。为什么我认为这程序就不该被编译成功，本身就是错误的返回类型[/quote] 两个问题都存在

引用 43 楼 蓝鲸灵的回复:声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值时一个常量,指向这段空间的起始位置。 数组名是符号地址常量，在编译时求值并存在编译器的符号表里面，其值就是个内存地址；所以可以认为程序没有给a分配空间，数组名只是代表了那个数组空间；与指针不一样，指针指向一块空间，同时指针本身也存储在某个空间；可以认为数组名存在在符号表里，符号表是编译器用的，我们管不到；a和&a值是一样的，本来对常量取地址是非法的，但是标准组织没有定对数组名取地址是非法还是合法，所以因编译器而异，VC是合法的。 http://m.blog.chinaunix.net/uid-10221131-id-350168.html   具体可以看这里

为什么没人提到对于return &a，c++编译器报错是无法从int*[8]转换成int*呢

函数内的局部变量返回以后函数栈会被回收，返回局部变量指针就会出现未定义行为。

函数内部创建的堆变量最好不要返回，不然使用者可能不知道这是堆变量从而忘记delete

局部变量离开作用域就失效了，返回的指针应该是无效的

#include<cstdlib> #include<cstdio> #include<cstring> int* create() { 	int* a = new int[8]; 	int b[8] = { 1, 2, 3, 5, 2, 3, 5, 6 }; 	memcpy(a, b, sizeof(b)); 	int i;  	for (i = 0; i < 8; i++) 	{ 		printf("%hd\n", a[i]); 	}  	return a;//返回得到的整型数组的指针。 }   int main() { 	int i; 	int* b; 	b = create();  	for (i = 0; i < 8; i++) 	{ 		printf("%hd\n", b[i]); 	}  	delete b; 	system("pause"); }

#include <stdio.h>  int *p; int a[8] = {1,2,3,5,2,3,5,6}; int *create() {                                 //  a[8] = {1,2,3,5,2,3,5,6}; //	a[0]=1;  	p=a;     return p;//返回得到的整型数组的指针  }   void main() { 	int i;  //	int b[8] = {1,2,3,5,2,3,5,6}; //	p=b; 	p = create();  	for(i = 0; i < 8; i++) 	{ 		printf("%d\n",*p); 		p++; 	} } 我是这样写的

a是一个int数组，它的类型是int*，&a是取a的地址，它的类型应该是int** 另外a数组是在栈上创建的，其作用域在create()函数内部，函数返回后数组所占用的内存会被释放 可以使用malloc()函数在堆上动态分配内存

void create(int *p) { *p＝num1; *(p+1)＝num2; … }

a本身就是个指针，指向a[0]，不需要return &a;，直接return a;。但你这个数组a是栈变量，在函数结束后会被清理，会导致错误，所以需要在参数中传一个指针，在函数中改变这个指针指向的值，返回void

数组 a 在 create 函数返回后内存已被回收

指针作为函数返回值，返回的是指向内容的地址。  栈上申请的内存（new方式，会在堆上申请内存，需要自己主动释放），在退出其作用域时，自动释放。  int array[3] = {1, 2, 3};   // 栈上内存，，退出作用域时，自动释放。  所以，函数返回的指针，所指向的内容（栈上），在退出函数（int *create()）时，已经释放了。 所以，指向的内存地址，是一块未知的、非法的内存地址（不知道是啥内容）。  额外： 1.  指针和数组（首地址），是两个概念，最好不要把指针当成数组来用。 2.  补一下，堆与栈的知识吧。

引用 5 楼 weixin_40101242的回复:[quote=引用 3 楼 adlay 的回复:] 返回局部变量的指针, 程序行为是未定义的. 数组 a 在 create 函数返回后内存已被回收, 可能用于存放其他的数据了.  那这个应该怎么解决呢，网上好多都是这么写的[/quote] 数组定义为static

引用 12 楼 Slzde_sub 的回复:但是事实上编译器会对这个返回进行报错，因为返回类型和函数类型不同 你用的什么编译器会报错? 试试把你的文件扩展名改成 .c, 而不是 .cpp . 用 C 语言的编译器来编译, 不是用 C++ 的编译器来编译. 毕竟这里是 C 语言区, 讨论的是 C 语言.    引用 13 楼 Slzde_sub 的回复:当然。  a  等价于  &a[0]  这个我是支持的   ，但是我不认为 &a 可以和 a 等价， 你可以打印 printf("%p", a) 和 printf("%p", &a) 来看他们的值是否是一样的就知道了. 一个数组只对应内存中一块连续的内存, 无论是 a, 还是 &a 都是这块内存的首地址, 没有多余的内存, 也就没有多余的内存地址的.  引用 14 楼 hjwang77 的回复:不是吧，如果&a 等价于 &a[0], 那如果数组a 的元素是int *, 那 *a 和 *a[0]岂不是也一样？二维数组和一维数组不是混乱了？  在 C 语言里面, 二维数组本身就和一位数组没什么区别, 也只是一块连续的内存而已, 把二维数组转换成 int*p 后, 二维数组都可以按照一维数组的方式访问:  p[y * width + x], 二维数组的 a[x][y] 访问方式不过是一个语法糖而已.   引用 15 楼 hjwang77 的回复:不考虑栈的问题，函数定义的是返回int *, 而函数实现返回的是int **,没有强制转换编译起码是个警告 把返回类型认为是 int** 就错的有点离谱了. 注意数组 a 直接表示了一块内存, 而不是 a 定义了一个指针, 这个指针来指向一块内存, 注意这个区别:    建议看一下 C专家编程 这本书, http://blog.adintr.com/43

你返回的是数组a的地址，在主函数中得到的也是a函数的地址，但自定义函数creat结束后，会对数组a进行销毁，所以主函数得到了a的地址也没用，因为那个地址存放的数据已被销毁

那个变量a是临时变量，函数返回的时候就被回收了，返回地址也没有意义。

a  等价于  &a[0]

a  等价于  &a[0]  这个我是支持的   ，但是我不认为 &a 可以和 a 等价


Question: Matlab怎么转成C语句的，求解答，不能把程序放到下面，我就截图了，看起来不太方便，希望有大佬指导，谢谢啦

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

如果自己手动写个C版本的话，这个很麻烦，不过可以直接用命令转成C语言的，你可以参考：  https://blog.csdn.net/zzlzzh/article/details/45044905  或者：  https://blog.csdn.net/zyqdragon/article/details/71512790

Matlab to C（ or other )     function satpos = get_satpos(t,sv,eph);  % get_satpos 用来确定卫星的位置， % t为给出的接收机记录的卫星接收信号的时刻，是当前gps周的秒数 % sv 为卫星编码 % eph 为从nav file(*.yrN)读出来的卫星的定位信息  % 万有引力常数 GM = 3.986004418e14;  % 地球自转 , rad/s Omegae_dot = 7.2921151467e-5;  % 选出指定卫星的信息，既是指定卫星在所有时刻的定位信息 col = find(eph(1,:)==sv); eph = eph(:,col);  % 选定离时刻t最近的参考历元    [y,col] = min(abs(t-eph(18,:)));  % 选定指定卫星在离参考时刻最近的定位信息所在的列， eph = eph(:,col);  % read ephemerides svprn   =   eph(1); af2     =   eph(2); M0      =   eph(3); roota   =   eph(4); deltan  =   eph(5); ecc     =   eph(6); omega0  =   eph(7); cuc     =   eph(8); cus     =   eph(9); crc     =  eph(10); crs     =  eph(11); i0      =  eph(12); idot    =  eph(13); cic     =  eph(14); cis     =  eph(15); Omega0  =  eph(16); Omegadot=  eph(17); toe     =  eph(18); af0     =  eph(19); af1     =  eph(20); toc     =  eph(21);  %%%%%%%%%      开始计算卫星的位置         %%%%%%%%%%  %A为轨道长半轴 A = roota*roota;  %计算到参考历元的时间差 tk = t - toe;  % 计算t时刻的平近点角 M = M0 + (sqrt(GM/A^3)+deltan)*tk;  % 利用开普勒公式迭代求解偏近点角  E_old = M; dE = 1;   while (dE > 1e-12)     E = M + ecc*sin(E_old);     dE = abs(E-E_old);     E_old=E;   end  % 计算真近点角 v = atan2(sqrt(1-ecc^2)*sin(E), cos(E)-ecc);  %计算改正后的升交点经度 Omega = Omega0 + (Omegadot-Omegae_dot)*tk - Omegae_dot*toe;  phi = omega0 + v; phi = rem(phi,2*pi);  % 计算升角角距 omega = omega0 + cuc*cos(2*phi) + cus*sin(2*phi);  % 计算向径 r = A*(1-ecc*cos(E)) + crc*cos(2*phi) + crs*sin(2*phi);  %计算倾角 i = i0 + idot*tk + cic*cos(2*phi) + cis*sin(2*phi);  % 旋转矩阵，从卫星轨道平面坐标系转换到地心地固坐标系 R = [cos(Omega)*cos(omega)-sin(Omega)*sin(omega)*cos(i) -cos(Omega)*sin(omega)-sin(Omega)*cos(omega)*cos(i)  sin(Omega)*sin(i);      sin(Omega)*cos(omega)+cos(Omega)*sin(omega)*cos(i) -sin(Omega)*sin(omega)+cos(Omega)*cos(omega)*cos(i) -cos(Omega)*sin(i);      sin(omega)*sin(i)                                   cos(omega)*sin(i)                                      cos(i)       ];  % 计算卫星在轨道平面坐标系下的坐标 satpos_in = [r*cos(v)              r*sin(v)              0];  % 利用旋转矩阵计算在地心地固坐标系下的位置 satpos = R * satpos_in;  % 计算卫星钟差 dt = af0 + af1*tk + af2*tk^2; satpos = [satpos; dt];


Question: 新手入门，求指教！

引用 3 楼 ab17171313 的回复:第一题， （1）x=-1    y=-1    z=-1 这个直接赋值应该没问题 （2）x=-1    y=0     z=0   首先&&的优先级高于||，所以先看++y&&++x，++y等于0则&&不会再计算++x（因为与任一为假则为假，编译器是如此执行的），所以x的值仍为-1；计算完&&再计算||，&&的左边为0所以&&计算结果为0，但||左边为0还要继续计算右边，所以++z，z为0 （3）x=0     y=0     z=-1  这个道理与（2）相同 NB，忘了逻辑与了

引用 5 楼 阿七七七 的回复：第二题，答案C A中switch参数和case都不为整数 B中case不为整数 D中case不能为变量名  多看看定义，书上都有写 所写的任何switch语句都必须遵循以下规则： 只能针对基本数据类型中的整型类型使用switch，这些类型包括int、char等。对于其他类型，则必须使用if语句。 switch()的参数类型不能为实型 。 case标签必须是常量表达式(constantExpression)，如42或者"42"。 case标签必须是惟一性的表达式；也就是说，不允许两个case具有相同的值。感谢

引用 3 楼 ab17171313 的回复:第一题， （1）x=-1    y=-1    z=-1 这个直接赋值应该没问题 （2）x=-1    y=0     z=0   首先&&的优先级高于||，所以先看++y&&++x，++y等于0则&&不会再计算++x（因为与任一为假则为假，编译器是如此执行的），所以x的值仍为-1；计算完&&再计算||，&&的左边为0所以&&计算结果为0，但||左边为0还要继续计算右边，所以++z，z为0 （3）x=0     y=0     z=-1  这个道理与（2）相同 呃，其实&&和||的优先级就可以看成数学的*和+

x=-1    y=-1    z=-1 x=-1    y=0     z=0 x=0     y=0     z=-1  C  1

-1  -1  -1 0  0  0 0 0 -1  C  1


Question: 最后一个putchar（ch）是什么意思？不是原样输出吗？

isalpha() 是用来判断你输入的字符是否是英文字母的 #include <stdio.h> #include <ctype.h> #include<stdlib.h>　　 int main(void) {     char ch;     while ((ch = getchar()) != '\n')	// 当一行未结束时     {         if (isalpha(ch))	//判断你输入的字符是否是英文字母              putchar(ch + 1);//是，则输出该字符ch在ascii码表中的后一个字符          else             putchar(ch);	//否，原样输出该字符ch，比如空格，!,之类的标点，数字，等等     }     putchar(ch);//打印换行符     system("pause");     return 0; }

最后一个putchar()是输出的换行符'\n'，因为最后一个getchar()赋值给ch，然后判断是是'\n'，因此不满足条件，执行while循环后的一个putchar(ch);即换行符


Question: 可变参数宏定义编译报错“未找到用户定义的文本计算符号”，但是不影响实际使用。请问到底错在哪里？

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


Question: C语言网的一个题，不知道是不是编译器的问题？

while 里面rest的值有重新赋值么？没有while咋符合退出条件？

while中没有跳出循环的条件，因此逻辑就是一个死循环（若条件满足）。

引用 2 楼 qq_31917799 的回复:while(1){         y1=(y0+x/y0)/2.0;         t=y1;         y0=y1;        if(fabs(y1-t) < 0.00001)               break;     }里面顺序改下才行 ok

#include <stdio.h> #include<math.h> int main() { 	double x, y0, y1, t; 	bool rest = true;//把rest类型修改为bool 	y0 = 1.0; 	y1 = 2.0; 	scanf("%lf", &x); 	while (rest) {  		y1 = (y0 + x / y0) / 2.0; 		t = y1; 		rest = fabs(t - y0)<0.00001;//使用fabs替代abs，并将rest赋值语句放在while循环中 		y0 = y1; 		 	} 	printf("%.3lf", y1); 	 	return 0; }

引用 1 楼 Slzde_sub 的回复:fabs是浮点数绝对值  abs是整数绝对值 还是不行，debug，rest的值一直是1


Question: 链表的指向

引用 12 楼 kang2618 的回复:[quote=引用 8 楼 M_lty63 的回复:] [quote=引用 5 楼 这个冬天有点冷灬的回复:]就这两句而言，第一句没有意义 new->next=tail->nextw为什么这么指，不懂，他们好像没联系[/quote] 你的需求是尾部插入新的节点吗？可以考虑下面的代码  tail->next=new tail=tail->next [/quote] 前提是你tail还有作用，不然tail=tail->next也是没有意义的

引用 8 楼 M_lty63 的回复:[quote=引用 5 楼 这个冬天有点冷灬的回复:]就这两句而言，第一句没有意义 new->next=tail->nextw为什么这么指，不懂，他们好像没联系[/quote] 你的需求是尾部插入新的节点吗？可以考虑下面的代码  tail->next=new tail=tail->next

引用 10 楼 英雄@末路的回复:[quote=引用 7 楼 M_lty63 的回复:] [quote=引用 6 楼 英雄@末路的回复:]第二句把第一句覆盖了，如果没有其他有特殊含义的上下文，那前一行没用。 new->next=tail->nextw为什么这么指，不懂，他们好像没联系[/quote] 这个是讲新节点插入队尾，这个和你在主题里可是不一样的！这个操作的目的是保存（或者说初始化）新节点的next元素 [/quote] 我要说的就是这个.怎么指得

引用 7 楼 M_lty63 的回复:[quote=引用 6 楼 英雄@末路的回复:]第二句把第一句覆盖了，如果没有其他有特殊含义的上下文，那前一行没用。 new->next=tail->nextw为什么这么指，不懂，他们好像没联系[/quote] 这个是讲新节点插入队尾，这个和你在主题里可是不一样的！这个操作的目的是保存（或者说初始化）新节点的next元素

第二句把第一句覆盖了，如果没有其他有特殊含义的上下文，那前一行没用。

引用 2 楼 赵4老师的回复:数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633 new->next=tail->nextw为什么这么指，不懂，他们好像没联系

引用 5 楼 这个冬天有点冷灬的回复:就这两句而言，第一句没有意义 new->next=tail->nextw为什么这么指，不懂，他们好像没联系

引用 6 楼 英雄@末路的回复:第二句把第一句覆盖了，如果没有其他有特殊含义的上下文，那前一行没用。 new->next=tail->nextw为什么这么指，不懂，他们好像没联系

就这两句而言，第一句没有意义

引用 1 楼 自信男孩的回复:tail->next=new->next tail->next=new 第一句和第二句都是修改tail->next指针的指向。有点重复的意思，不过这个还要看你的需求，但从这两句来看是重复的意思。 但从这两句可以考虑这样： new->next = tail->next; tail->next = new; 我不知道tail->next=new->next到底是什么意思，为什么这么指


Question: 指针写冒泡排序，不知道程序哪里错了

#include<stdio.h>  void paixu(float *p, int n) {     int i,j;     float a;     for(j = 0; j < n; j++)     {         for(i = 0; i < n-j - 1; i++)         {             if(*(p+i) > *(p+i+1))             {                 a = *(p+i);                 *(p+i) = *(p+i+1);                 *(p+i+1) = a;             }         }     } } int main() {     int i;     float num[10]={1,10,6,20,50,3,7,14,21,12};     float *p = num;      paixu(p, 10);      for(i=0;i<10;i++) {         printf("%-8.2f",*(p+i));     }     putchar(10);      return 0; } 无意义的返回值。应该去掉，另外返回int类型，但是*p是float类型。

#include<stdio.h>  int paixu(float *p, int n) {     int i,j;     float a;     for(j = 0; j < n; j++)     {         for(i = 0; i < n-j - 1; i++)         {             if(*(p+i) > *(p+i+1))             {                 a = *(p+i);                 *(p+i) = *(p+i+1);                 *(p+i+1) = a;             }         }     }     return *p; } int main() {     int i;     float num[10]={1,10,6,20,50,3,7,14,21,12};     float *p = num;      paixu(p, 10);      for(i=0;i<10;i++)     {         printf("%-8.2f",*(p+i));     }     return 0; } 参考一下吧  判断条件是i < n - j - 1;否则数组越界了。当j=0时，i < 10 - 0，即i < 10，那么当i= 9时，p + i + 1即p+10已经越界了。因为p+9已经是指向最后一个元素了。

下面当然也需要减一，大方向没错，只是有点瑕疵。

for(j=0;j<n-1;j++)//这里需要－1 	{ 		for(i=0;i<n-j-1;i++) 		{ 			if(*(p+i)>*(p+i+1)) 			{ 				a=*(p+i); 				*(p+i)=*(p+i+1); 				*(p+i+1)=a; 			} 		} 	} 10个数 第一次遍历只需要比较9次，n个数 第一次需要比较n-1次


Question: C语言自加问题，帮忙看下如何一个过程

正解， printf 参数入栈是从右到左的执行的

printf的入栈顺序是从右到左的，会先执行z++

原题 int x = 3, y = 3, z = 1; int m = 0; printf("%d,%d\n", (++x, y++, x + y + z), z++);  首先有两个知识点： 1、printf输出是先从右往左计算，再从左往右输出(编译器之间可能存在差异，没测试，我用的vs2017) 2、++i，i自增1。i++，系统会拷贝出一个副本+1，也就是有一个i，还有一个副本是i+1 这个题z=1，先计算z++，z生成了一个副本也就是2，然后再从左往右计算逗号运算符， 逗号运算符里计算的z是z的副本，也就是2，printf输出第二个变量z的时候，输出的是他的原版本也就是1,所以最后输出的是10,1

找个通用编译器看汇编，就讲汇编的执行顺序

兩個要點:1、printf入參順序從右往左，2、逗號表達式從左往右依次執行，結果為最後一個表達式

这种问题就看反汇编喽，以前也碰到过同一代码，不同版本的编译器计算结果不一样，这时候就分析一下汇编，很容易的发现相同代码的执行在不同的编译器里面执行不一样。有可能是编译器本身的问题，也可能是语言标准的变化（比如C++11和C++9）。

++i与i++的区别。

跟编译器有关系，跟系统没关系。

sequence point  函数参数右结合

函数参数的处理顺序，和逗号表达式不一样

感谢各位。 感谢，统一回复。其实我也不想纠结这样的问题，这种问题在工程应用中根本不存在，但是现在我是在一个职业学校教书，教C语言，没办法，考试要考这中问题。

引用 5 楼 shihengzhen101 的回复:这种事别就纠结了，搞懂++x和x++就行了，个人意见！ 感谢，其实我也不想纠结这样的问题，这种问题在工程应用中根本不存在，但是现在我是在一个职业学校教书，教C语言，没办法，考试要考这中问题。

百度sequence point，你就不再会纠结这种问题

6楼正解，函数参数右结合

函数参数的计算顺序造成的吧，从右往左。你可以看一下汇编代码（windows下codeblocks的汇编），先计算的z，然后是前面的参数，按照逗号表达式顺序，先x，再y，然后是x+y+z，0x401340	push   %ebp 0x401341	mov    %esp,%ebp 0x401343	and    $0xfffffff0,%esp 0x401346	sub    $0x20,%esp 0x401349	call   0x401960 <__main> 0x40134e	movl   $0x3,0x1c(%esp);x 0x401356	movl   $0x3,0x18(%esp);y 0x40135e	movl   $0x1,0x14(%esp);z 0x401366	movl   $0x0,0x10(%esp);m 0x40136e	mov    0x14(%esp),%eax 0x401372	lea    0x1(%eax),%edx 0x401375	mov    %edx,0x14(%esp) 0x401379	addl   $0x1,0x1c(%esp) 0x40137e	addl   $0x1,0x18(%esp) 0x401383	mov    0x1c(%esp),%ecx 0x401387	mov    0x18(%esp),%edx 0x40138b	add    %edx,%ecx 0x40138d	mov    0x14(%esp),%edx 0x401391	add    %ecx,%edx 0x401393	mov    %eax,0x8(%esp) 0x401397	mov    %edx,0x4(%esp) 0x40139b	movl   $0x403024,(%esp) 0x4013a2	call   0x401bd0 <printf> 0x4013a7	mov    $0x0,%eax 0x4013ac	leave 0x4013ad	ret 不过不同的编译器出来的结果可能会不同。

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

对了，补充下，是在Windows的平台下编译运行

正如6楼所说，printf()函数的入栈顺序是从右向左；所以先执行z++；此时z的值变为2，所以最后的输出是10

lz跟编译器较啥劲啊，不确定的话，就一步一步执行喽

10,1结果是这么来的. printf 参数入栈是从右到左的.  所以先执行表达式z++, 再执行表达式(++x, y++, x + y + z) z++  ==> z =2  但++在后, 对于printf来说, 参数入栈 1  然后吞逗号表达式是从左到右.   先执行++x  ==> x = 4 再执行 y++ ==> y=4 (++x, y++, x + y + z) 最终结果 ===> (4, 3, 4+4+2) ==> 10  printf最终结果: ==>  printf("%d,%d\n", 10, 1);


Question: 链表逆序算法实现

pr是干什么的？好像没什么用

代码没看出什么问题，所以，你的问题是？

非常感谢各位帮忙看，我理解错了

引用 3 楼 baidu_33083779 的回复:pr是干什么的？好像没什么用 pr是保存下一个节点的地址，是非常有用的，否则找不到下一个节点，链表就会出问题。


Question: 这个链表要怎么改，感觉没错啊，怎么就不行呢

你的add函数和明显的不是尾插法，因为tail直接指向了头指针，你的插入方式是每次插到头结点的下一个节点。 尾插法应该是:首先要找到最后一个节点，然后将新节点插到最后一个节点的末尾。但是你的逻辑并没有找到最后一个节点

student*add(student*hear)//添加.tail是尾指针 {     student*tail = NULL;     //tail = (student*)malloc(sizeof(student));    //redundant     tail = hear;     student *new = NULL;     new = (student*)malloc(sizeof(student));      printf("name>");     scanf("%s", new->name);     printf("age>");     scanf("%d", &new->age);     printf("sex>");     scanf("%s", new->sex);      new->next = tail->next;      tail->next = new;     //tail = new;     //redundant     //tail->next = NULL; //error      return hear; }   int print(student*hear) {     student*s = NULL;     //s = (student*)malloc(sizeof(student));    //redundant     //s->next= hear->next;    //redundant     s = hear;      while(s->next!=NULL)     {         printf("%s\t%d\t%s\n",s->name,s->age,s->sex);         s = s->next;     }      return 0; } 参考一下吧。 程序中有冗余代码，也有逻辑错误的代码。 冗余和

1、tail为什么要分配内存呢？你分配的内存也没被使用到，要指向链表头就只需要tail指向hear指向的内容就可以了。====>内存泄漏 2、新节点加入需要找到链表尾部，在链表尾部添加新节点，通过hear循环遍历链表可以找到链表尾部。 3、print函数内部也不应该分配内存，把链表头传入，加一个临时指针就可以循环遍历链表打印


Question: 求排列组合的程序为何只运行到一半就完了？

用手机怎么结贴给分阿

引用 3 楼 自信男孩的回复:n = 17;     zdlx *aa = (zdlx *)malloc(n*n*n * sizeof(zdlx)); 这两条语句调换一下先后。否则n是随机数，最大为255,最小可能为0。因此malloc的空间可能会导致溢出，当n随机数小于17时，就会导致溢出。 是的 搞错了 非常感谢

引用 2 楼 King_of_Kindom的回复:显示问题吧，有4000多的。 还有zdlx *aa = (zdlx *)malloc(n*n*n*sizeof(zdlx)); 你这空间申请的大小，你会知道是多少吗？n没有初始化 嗯 看到了 非常感谢

#include <stdio.h> #include <stdlib.h> typedef struct {     int n;     char b[3];  }zdlx; void zd(zdlx a[], unsigned char n) { unsigned char i,j,t; int cn; cn=0; for (i=0;i<n;i++)  for (j=0;j<n;j++)   for (t=0;t<n;t++)     {        a[cn].n=cn; 	  a[cn].b[0]=i; 	  a[cn].b[1]=j; 	  a[cn].b[2]=t;	 	  cn=cn+1; 	  printf("cn=%d i=%d j=%d t=%d\n",cn,i,j,t);     }   	} int main(void)  {     int  ii;    unsigned char n;     zdlx *aa = (zdlx *)malloc(n*n*n*sizeof(zdlx));    n=17;    zd(aa,n); 	for(ii=0;ii<n*n*n;ii++) 	 { 	 	 printf("a=%d %c %c %c\n", aa[ii].n,aa[ii].b[0],aa[ii].b[2],aa[ii].b[2]);   	 } 	}


Question: 和16进制数据处理这段什么意思

用于显示的是字符，字符的值是个整数，ASCII字符表的连续字符的值也是连续的，在表范围内，一个字符减去几个数字就是前面第几个字符，加上个数字，就是后面第几个字符，比如'1'+2='3'，'F'-3='B','a'+25='z'

引用 4 楼 justkoomega 的回复:E1R1date1和E1R1date1分别是r1_Buff1[k]的低四位和高四位，就是数字啊，无关什么进制。 然后把存的数字 转成 16进制表示 的字符 的ASCII码。 你把2个8位的存在16位寄存器，不要移动8位么。 为什么又要转ASCII码，直接用16进制不行吗

先确认E1R1date1 的赋值，是某个数组元素（字节）的低四bit 然后确认 0x30, 0x40的意义，分别对应ascii 吗的'0'和 '@'， 而'@' 字符ascii 码的下一个字符是‘A’，这个才是我们关心的。 其实那个 if(E1R1date1 > 9) { } else { } 的目的就是把该字节的低四比特换成ASCII码对应的字符（数组0~9变成字符‘0’~‘9’，赋值A~F 变成字符'A' ~'F'）。

移动八位是因为一个字节就是八位，比如0x3A就是一个字节

变成0X41和0X42有什么用， RD[11200+k]是16位的寄存器，

引用 1 楼 user-5 的回复:1. 是用十六进制表示：10变成A（0x41），11变成B（0x42），…… 2. 要看RD数组元素类型了  E1R1date1和 E1R1date2的数据是十进制还是16进制的？如果是16进制的只会是A至F，哪会有10和11呢  RD[11200+k]是整形32位数值， E1R1asc2和 E1R1asc1得到的是ASCII码数据吗？ 中间是不是少了一个将ASCII码转 为16进制的数在赋值给 RD[11200+k]？


Question: 求非空链表变成空表

记录两条链表的长度len。然后分别回收两条链表的每个结点，然后用一个循环执行以下操作 printf("NULL\n");len--;当len=0时跳出循环，如果你想合并置空之后再遍历结点这是做不到的，因为当你把结点置空了之后就访问不到它所指向的结点了，指针是在堆里面的，你可以把它理解为一个间址寻址的存储单元，当你把它置空(c语言保证NULL绝对不是有效的内存地址),当你试图访问它所在的结点的时候，MAR（这是负责在内存地址里面找到指定内存单元的一个存储器)会寻址失败，然后操作系统产生中断，程序运行失败，这也就是我们常说的空指针异常

引用 2 楼 King_of_Kindom 的回复:你的打印出NULL是指打一个还是原本每个元素的地方你都想打出NULL？如果置空了，应该顶多只能打出一个NULL吧 //置NULL      L1 = NULL;     L2 = NULL; 注意这两句是否可以将调用函数里的实参L1，L2赋值为NULL呢？

合并为一个链表就是创建新的链表，将2个L1，L2链表的节点添加到一个新链表上（创建一个新链表）。原来两个链表就没有节点了。自然头结点指向了NULL

//list是链表结构图，L1是链表1的头指针，L2是链表2的头指针（L1，L2非空）  list*  combine(list* L1, list* L2) { 	//新链表  	list* new_list = (list*)malloc(sizeof(list)); 	 	//新链表指向L1的next  	new_list = L1->next; 	 	//寻找L1的最后一个元素  	list* p = L1; 	while(NULL != (p->next)) p++; 	 	//L1的最后一个元素指向L2的next  	p->next = L2->next; 	 	//置NULL  	L1 = NULL; 	L2 = NULL; 	 	return new_list; }


Question: 有个小小的问题，希望大家可以帮忙解决一下？

书上错的，第一个阶段费用重复加了！

要么改为 #define BASE3  (BASE2+(RATE3*(BREAK3-BREAK2))) 要么改为 #define BASE2  (RATE2*(BREAK2-BREAK1))

红线处是错的，按红线处的写法，重复收了第一阶段的电费。

如你所说的 原文确实错了 应该按照你改成的那样

原文确实是错的

不是，红线处是正确的。 要清楚电费的计费方式，它不是在某个越界点处往下计算的，而是从基础电费开始往上计算的。 打个比如，有3个越界点a,b,c，分别对应3种费率Pa,Pb,Pc，它是先收每个取越界点的费用后，再计算越出的电量，所以如果你的电量b<t<=c，那么它先收取a点的电费，再收取b点的电费（b点的电费又依赖a点），最后再计算越出电量的电费，以上结果相加，才是总电费。


Question: VS2013 error LNK2001: 无法解析的外部符号

程序动态库没有加载正确。确认程序中包含了动态库的头文件和库文件（lib和dll），并且要把动态库文件拷贝到指定位置。 请参考《动态库相关知识》 希望能够帮到你

dll或者 你的lib没加载对。

这一看就是没有连接所需的静态库或者动态库的导入库，连接上就可以了

如果调用的第三方库 查下lib是否引用了？或者lib使用时有特定的宏未定义？ 找库的demo来查比较方便些

你用了錯誤信息中提到的Slice之類的類和接口嗎？應該是沒有正確include進來或庫沒安裝好吧。


Question: c语言在子函数中使用malloc，会自动free吗？return后我该怎么办？

可以用智能指针

定义的函数 return 后，后面语句就不执行，也可以用 if判断，多个 return，返回不同的结果   char* get_num_bit() {     /*子函数体片段*/     static  char* buf = (char*)malloc(1024 * 64);     strcpy(buf, "hello world!");     return buf; }  可以试试这样，函数多次使用，也不会内存浪费了

你的这个程序很简单，虽然在子函数中没有free，确实有内存泄漏，但是整个程序执行完成之后，系统还是会回收你malloc申请的str的空间的，因此对于你现在的这段程序来说，也不会对系统造成啥负担。 子函数到了return，程序就已经结束并返回相关结果了，renturn后面的代码是肯定不会运行了的。如果要free，可以这样 #include<stdio.h> #include<stdlib.h>  char * get_num_bit() {     /*子函数体片段*/     char * str = (char*)malloc(sizeof(char)*100);     str = "hello world!";     return str; }  int main()/*主函数*/ {     char *p = get_num_bit();     printf("%s\n",p);     system("pause");     free(p);     return 0; }

3、4行删掉。 main返回后，程序对应进程退出，操作系统会自动释放。 如果想自己free,可将函数的返回值保存到比如一个char*类型的变量s中，等不用时free(s);即可。


Question: C语言 函数for循环内递归的问题

做成参数往下传递了

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

另外设置一个数组，rec函数里记录递归层数，然后根据递归层数保存j在数组里


Question: 想请教一下ccf的通信网络问题QAQ

会不会是你没做边界处理，对方用超出范围的数据测试发生了overflow，0分


Question: 如果只想修改文件的一两个字节，那么利用标准IO函数可以吗？

引用 28 楼 zhao4zhong1 的回复:[quote=引用 27 楼 wodeyouxian 的回复:] C语言自已的库函数貌似是做不到对文件直接修改，最容易实现的方法还是先打开读到内存里，修改好后，再次打开文件，重新写入 扯[/quote] ============= 我试了好几次，用a+的方式打开文件时，可以在文件最后面增加内容，但这不符合楼主的要求;用r+和w+打开文件时，文件的长度直接变为0了，不知道你们有什么方法可以直接修改C的文件？能贴上可用的代码吗？

引用 21 楼 boxmanstan 的回复:[quote=引用 19 楼 weixin_39158150 的回复:] [quote=引用 17 楼 boxmanstan 的回复:] 你们在争什么？  1. fopen r+ 2. fseek到你要修改的位置 3. fwrite写入你要修改的内容，设置要修改的大小，只会修改你写入大小的内容，后面的不变  不就这么个事吗  即便是r+，只要一经写入，就会立刻清空为空文件，大哥你都不实际操作看看的吗？[/quote]   VS2013测试OK[/quote] 我去，还真的可行，之前这个方案我测试过的，明明不行的来着，感谢老哥！

引用 22 楼 zhouqunhai 的回复:读入，判断修改，重新写入 请问是指文件全部读入吗？

引用 27 楼 wodeyouxian 的回复:C语言自已的库函数貌似是做不到对文件直接修改，最容易实现的方法还是先打开读到内存里，修改好后，再次打开文件，重新写入 扯

引用 23 楼 zhao4zhong1 的回复:[quote=引用 17 楼 boxmanstan 的回复:] 你们在争什么？  1. fopen r+ 2. fseek到你要修改的位置 3. fwrite写入你要修改的内容，设置要修改的大小，只会修改你写入大小的内容，后面的不变  不就这么个事吗 文件大小大于2GB时，fseek就不好用了。[/quote]  理解你的意思，offset是long型。 这个人一直在强调fwrite写入清空这个事，你给解释一下呗

引用 17 楼 boxmanstan 的回复:你们在争什么？  1. fopen r+ 2. fseek到你要修改的位置 3. fwrite写入你要修改的内容，设置要修改的大小，只会修改你写入大小的内容，后面的不变  不就这么个事吗 文件大小大于2GB时，fseek就不好用了。

读入，判断修改，重新写入

引用 19 楼 weixin_39158150 的回复:[quote=引用 17 楼 boxmanstan 的回复:] 你们在争什么？  1. fopen r+ 2. fseek到你要修改的位置 3. fwrite写入你要修改的内容，设置要修改的大小，只会修改你写入大小的内容，后面的不变  不就这么个事吗  即便是r+，只要一经写入，就会立刻清空为空文件，大哥你都不实际操作看看的吗？[/quote]   VS2013测试OK

When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.

fwrite之前fopen时参数mode带a或w，清空很正常； fwrite之前fopen时参数mode不带a或w而是r+b或rb+,就不会清空。

这段代码VS2008可以。   #include <stdio.h>  int main() { 	FILE *pflIO = NULL; 	FILE *pflOut = NULL;  	pflOut = fopen("test.bin", "wb"); 	if (NULL ==pflOut) 	{ 		printf("创建文件失败"); 		return -1; 	} 	else 	{ 		for (char ch= 0; ch<100; ch++) 		{ 			fwrite(&ch, 1, 1, pflOut); 		} 		fclose(pflOut); 	}  	pflIO = fopen("test.bin", "rb+"); 	if (NULL == pflIO) 	{ 		printf("打开要修改的文件错误"); 	} 	else 	{ 		fseek(pflIO, 10, SEEK_SET); 		char ch = 0; 		fwrite(&ch, 1, 1, pflIO); 		fclose(pflIO); 	}  	return 0; }

引用 17 楼 boxmanstan 的回复:你们在争什么？  1. fopen r+ 2. fseek到你要修改的位置 3. fwrite写入你要修改的内容，设置要修改的大小，只会修改你写入大小的内容，后面的不变  不就这么个事吗  即便是r+，只要一经写入，就会立刻清空为空文件，大哥你都不实际操作看看的吗？

引用 13 楼 weixin_39158150 的回复:[quote=引用 3 楼 adlay 的回复:] 用内存映射, Windows CreateFileMapping, Linux mmap 这个在windows上可行吗？[/quote] Windows上可以使用内存映射文件

内容读出来，修改后再写回去

这个源码 查看文件头 3字节。如果已经有就不添加 如果没有文件头BOM， 就分配文件大小+3的内存，读取整个文件，修改后再写回去

仅供参考：#include <conio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> FILE *f; char ln[64+1];//Because sscanf(argv[66],"%hx",&ln[66-3]); modify ln[63] and ln[64] ! int i; __int64 hexoffset64; void main(int argc,char *argv[]) {     if (argc<=3) {         cprintf("Locate & Replace, designed by zhao4zhong1@163.com\n\r");     HELP:         cprintf("Usage: LR filename.ext hexoffset64 byte1 byte2 byte3 ...");         return;     }     if (argc>64+3) {         cprintf("Up to 64 bytes\a");         return;     }     if ((f=fopen(argv[1],"r+b"))==NULL) {         cprintf("Can not open %s\a",argv[1]);         return;     }     if (1!=sscanf(argv[2],"%I64x",&hexoffset64)) {fclose(f);goto HELP;}     if (hexoffset64>=_filelengthi64(_fileno(f))) {         cprintf("hexoffset64==%016I64x >= %016I64x==_filelengthi64 of file %s\a",hexoffset64,_filelengthi64(_fileno(f)),argv[1]);         fclose(f);         return;     }     for (i=3;i<argc;i++) {         if (1!=sscanf(argv[i],"%hx",&ln[i-3])) {fclose(f);goto HELP;}     }     if (hexoffset64!=_lseeki64(_fileno(f),hexoffset64,SEEK_SET)) {         cprintf("_lseeki64 to %I64x fail\a",hexoffset64);         fclose(f);         return;     }     if ((int)fwrite(ln,1,argc-3,f)!=argc-3) {         cprintf("fwrite %d bytes fail\a",argc-3);         fclose(f);         return;     }     fclose(f); }

引用 3 楼 adlay 的回复:用内存映射, Windows CreateFileMapping, Linux mmap 这个在windows上可行吗？

引用 11 楼 user-8 的回复:FILE* f = fopen(it->wholePath.c_str(), "rb"); if (!f) {     cerr << "Error: Cannot open" << it->wholePath << endl;     continue; } unsigned char buf[10]; fread(buf, 1, 3, f);  // Get file size: fseek(f, 0, SEEK_END); const long N = ftell(f); fclose(f);  if (buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) {     cout  << "Skipping (already has BOM): " << it->wholePath << endl;     continue; }  // Add BOM: ======================================= // Read the whole file: unsigned char* fil_buf = new unsigned char[N + 3]; fil_buf[0] = 0xEF; fil_buf[1] = 0xBB; fil_buf[2] = 0xBF;  f = fopen(it->wholePath.c_str(), "rb"); fread(fil_buf + 3, 1, N, f); fclose(f);  // Write new version: f = fopen(it->wholePath.c_str(), "wb"); fwrite(fil_buf, 1, N + 3, f); fclose(f);  delete[] fil_buf;  cout << "Added BOM: " << it->wholePath << endl;   老哥，你这个程序是把文件内容都读入内存然后再重新写入这个文件是吗？


Question: setvbuf给stdin设置无缓冲或者满缓冲，为什么最后效果都是行缓冲？

可以试下禁用终端的标准模式ICANON:  struct termios tio; tcgetattr(0, &tio); tio.c_lflag &= ~(ICANON) | ECHO; tio.c_cc[VTIME] = 0; tio.c_cc[VMIN] = 1; tcsetattr(0, TCSADRAIN, &tio);  可以参考https://blog.csdn.net/mr_raptor/article/details/8349323的说明

引用 15 楼 turmary 的回复:这个是系统提供的缓冲区，而stdio库的setbuf,setvbuf只是操作C库的缓冲，不管系统的。 我想了解的就是C函数，并不是单纯地想实现某种功能

Windows下可以看 https://stackoverflow.com/questions/51726140/console-with-enable-line-input-doesnt-pass-r https://docs.microsoft.com/en-us/windows/console/setconsolemode  Linux可以看 <Unix环境高级编程>

引用 12 楼 六道佩恩 的回复:[quote=引用 11 楼 千寻1997 的回复:] 这个问题我也遇到了，使用setbuf就是你要的效果 其中的原因您知道吗？[/quote]我不知道。当时我用setbuf试了一下，有一次成功了，然后，我就去试setvbuf，后来看到你的问题，就回复了。我想复现setbuf设置输入流为空又失败了。所以setbuf可能不行。

这个问题我也遇到了，使用setbuf就是你要的效果

引用 11 楼 千寻1997 的回复:这个问题我也遇到了，使用setbuf就是你要的效果 其中的原因您知道吗？

提醒stdin是开源的。

用getch解决问题

Stdin确实改不成no buffer,操作系统的原因吧。底层的东西不是很懂。

引用 6 楼 user-8 的回复:我。。。 你现在是从标准输入读取，如果不回车，你在cmd窗口中的输入怎么才算结束？你的程序不就是在等待你的输入终止么。当然是要等你按了回车才继续的啊。 滞留区只是玩笑而已。 试试下面这段，从标准输入获取，你可以试试输入"abcdefghijk"然后回车看看。 #include<stdio.h> #include<windows.h> char buff[10]; int main() {     int c;     setvbuf(stdout, buff, _IOFBF, 10);     while(putchar(getchar())!='\n');     printf("done!");     Sleep(2000);     fflush(stdout);      return 0; }   [quote=引用 4 楼 weixin_39158150 的回复:] [quote=引用 2 楼 user-8 的回复:] 我试了下，至少可以正常显示，不明白你所说的接收函数没反应的意思。你也可以写到文件试试。  还有，按照你的输入“abcdefghijklmnopqrst\n\n”，最后缓冲区里面也就只剩"\n\n"了，如果是“\n\nmnopqrst”，那缓冲区还叫缓冲区么，那不是滞留区了么。。。 #include<stdio.h> #include<windows.h> char buff[10];  int main() {    fprintf(stdout, "启用满缓冲\n");    setvbuf(stdout, buff, _IOFBF, 10);     fprintf(stdout, "abcdefghijklmnopqrst\n\n...done");    Sleep(2000);     return(0); }  老哥，我觉得你没明白我的意思啊。我试的是stdin啊，如果无缓冲的话，那个getchar接收时，应该输入一个字符后就自动接收了，但是仍然是等到按了回车后才开始读取的。满缓冲也是，我输入的内容已经超过缓冲区很多了，仍然没有开始读取，而是等我按了回车后才开始读取的。我不明白你说的滞留区是什么意思，只是实际测试是如此，如果输入太多缓冲区不够装的话，他就会来回装填直到装完缓冲区。其实，我说一个我个人的看法不知道你觉得如何，我认为这个缓冲区是只属于我们这个程序的缓冲区，系统对于键盘输入有自己的缓冲区，那么我们的缓冲区只是在按了回车后从那个缓冲区复制过来的数据而已。[/quote][/quote]  老哥。。。我要改变的就是标准输入啊。。。我实在不明白你的程序到底想干啥

我。。。 你现在是从标准输入读取，如果不回车，你在cmd窗口中的输入怎么才算结束？你的程序不就是在等待你的输入终止么。当然是要等你按了回车才继续的啊。 滞留区只是玩笑而已。 试试下面这段，从标准输入获取，你可以试试输入"abcdefghijk"然后回车看看。 #include<stdio.h> #include<windows.h> char buff[10]; int main() {     int c;     setvbuf(stdout, buff, _IOFBF, 10);     while(putchar(getchar())!='\n');     printf("done!");     Sleep(2000);     fflush(stdout);      return 0; } 引用 4 楼 weixin_39158150 的回复:[quote=引用 2 楼 user-8 的回复:] 我试了下，至少可以正常显示，不明白你所说的接收函数没反应的意思。你也可以写到文件试试。  还有，按照你的输入“abcdefghijklmnopqrst\n\n”，最后缓冲区里面也就只剩"\n\n"了，如果是“\n\nmnopqrst”，那缓冲区还叫缓冲区么，那不是滞留区了么。。。 #include<stdio.h> #include<windows.h> char buff[10];  int main() {    fprintf(stdout, "启用满缓冲\n");    setvbuf(stdout, buff, _IOFBF, 10);     fprintf(stdout, "abcdefghijklmnopqrst\n\n...done");    Sleep(2000);     return(0); }  老哥，我觉得你没明白我的意思啊。我试的是stdin啊，如果无缓冲的话，那个getchar接收时，应该输入一个字符后就自动接收了，但是仍然是等到按了回车后才开始读取的。满缓冲也是，我输入的内容已经超过缓冲区很多了，仍然没有开始读取，而是等我按了回车后才开始读取的。我不明白你说的滞留区是什么意思，只是实际测试是如此，如果输入太多缓冲区不够装的话，他就会来回装填直到装完缓冲区。其实，我说一个我个人的看法不知道你觉得如何，我认为这个缓冲区是只属于我们这个程序的缓冲区，系统对于键盘输入有自己的缓冲区，那么我们的缓冲区只是在按了回车后从那个缓冲区复制过来的数据而已。[/quote]

引用 1 楼 cfjtaishan 的回复:https://blog.csdn.net/wangjiaoyu250/article/details/8629136  https://blog.csdn.net/fjt19900921/article/details/8122313  可以看一下这两个例子 我觉得第二个帖子说的是错的，如果按他说的交接控制权，那么其实就是在说程序之间用的输入缓冲区是同一个，如果是这样的话，那我同时运行两个程序，那是不是我在一个程序输入另一个程序也可以读取数据？还有就是这两篇文章跟我的问题没什么关系，不过还是要谢谢你。

引用 2 楼 user-8 的回复:我试了下，至少可以正常显示，不明白你所说的接收函数没反应的意思。你也可以写到文件试试。  还有，按照你的输入“abcdefghijklmnopqrst\n\n”，最后缓冲区里面也就只剩"\n\n"了，如果是“\n\nmnopqrst”，那缓冲区还叫缓冲区么，那不是滞留区了么。。。 #include<stdio.h> #include<windows.h> char buff[10];  int main() {    fprintf(stdout, "启用满缓冲\n");    setvbuf(stdout, buff, _IOFBF, 10);     fprintf(stdout, "abcdefghijklmnopqrst\n\n...done");    Sleep(2000);     return(0); }  老哥，我觉得你没明白我的意思啊。我试的是stdin啊，如果无缓冲的话，那个getchar接收时，应该输入一个字符后就自动接收了，但是仍然是等到按了回车后才开始读取的。满缓冲也是，我输入的内容已经超过缓冲区很多了，仍然没有开始读取，而是等我按了回车后才开始读取的。我不明白你说的滞留区是什么意思，只是实际测试是如此，如果输入太多缓冲区不够装的话，他就会来回装填直到装完缓冲区。其实，我说一个我个人的看法不知道你觉得如何，我认为这个缓冲区是只属于我们这个程序的缓冲区，系统对于键盘输入有自己的缓冲区，那么我们的缓冲区只是在按了回车后从那个缓冲区复制过来的数据而已。

引用 2 楼 user-8 的回复:我试了下，至少可以正常显示，不明白你所说的接收函数没反应的意思。你也可以写到文件试试。  还有，按照你的输入“abcdefghijklmnopqrst\n\n”，最后缓冲区里面也就只剩"\n\n"了，如果是“\n\nmnopqrst”，那缓冲区还叫缓冲区么，那不是滞留区了么。。。 #include<stdio.h> #include<windows.h> char buff[10];  int main() {    fprintf(stdout, "启用满缓冲\n");    setvbuf(stdout, buff, _IOFBF, 10);     fprintf(stdout, "abcdefghijklmnopqrst\n\n...done");    Sleep(2000);     return(0); } getchar、scanf一类的输入函数


Question: ctrl+F5行，F5不行，这是啥原因？

Ctrl + F5强制刷新后台读取 F5只是从缓存中读，有则直接读取

用vs的话 scanf用scanf_s   结尾要加  system("pause");

引用 1 楼 hou09tian 的回复:system("pasue"); 改为 system("pause");  这个正解了

F5：开始调试/Start Debugging Ctrl + F5：开始执行（不调试）/Start Without Debugging  如果F5调试的话，没有设置断点，也没有system("pause")或者getchar()之类的话，cmd窗口显示完运行结果，然后就会立马关闭。 Ctrl + F5是开始执行，如果是win32控制台应用程序这样的项目，就会有一个cmd执行窗口，显示运行结果，然后窗口一直保留。  你这里就是system("pasue"); 语句中的pause拼错了，所以才一闪而过的。

你怕是用的vs  然后F5在调试。。

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

system("pasue"); 改为 system("pause");


Question: 关于过滤换行符的问题

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

引用 2 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  不要写连自己也预测不了结果的代码！谢谢，有时候这类言论也起到很重要的指导作用。

引用 4 楼 cfjtaishan 的回复:scanf是格式化输入，由于'\n'不匹配%d，所以会一直在输入缓存里，直到被ch接收； 第二个getchar就是起到吸收'\n'，然后才能继续循环。否则遇到ch = getchar()得到'\n'就会退出循环。 感谢回答，相互学习！

引用 3 楼 user-3 的回复:首先，你的代码需要稍稍修改，才能运行 #include<stdio.h>  void display(char cr,int lines,int width) {     int row,col;     for(row=1;row<=lines;row++)     {         for(col = 1; col <= width; col++)             putchar(cr);         putchar('\n');     }    //结束一行并开始新的一行 }  int main(void) {     int ch;             //待打印字符     int rows,cols;  //行数和列数      printf("Enter a character and two integers:\n");     while((ch=getchar()) != '\n')     {         if(scanf("%d %d",&rows,&cols) != 2)             break;         display(ch,rows,cols);         while(getchar() != '\n')             continue;         printf("Enter another character and two integers:\n");         printf("Enter a newline to quit.\n");     }     printf("bye.\n");     return 0;  }  第二，你说的对，如果注释掉main函数中的while(getchar()!='\n')  continue;  这两句，则程序在输入完c 2 3                //c（空格）2（空格）3（回车）就直接退出了。  第三，关于你的问题：请问while(getchar()!='\n')  continue;  这两句对回车做了什么，在最后一个回车的时候while(getchar()!='\n')不是直接跳过吗？  当你的程序在运行时输入C 2 3（回车）之后，缓冲区中的内容为：C 2 3 （回车）。字符c在ch=getchar()被读取到ch中，2和3也由scanf("%d %d",&rows,&cols) != 2被读取到rows和cols之中，那么缓冲区中还剩下一个(回车)。while(getchar()!='\n')  continue; 就是把这个回车读入，然后吃掉，不然这个回车要留到while循环，会导致程序退出。这就回到上面的第二点去了。  其实，while(getchar()!='\n')  continue; 的作用，是把你正常输入之后所产生的乱七八糟的输入一直到回车全部干掉。比如，你的正常输入应该是c 2 3(回车)，那么它就干掉这个回车，如果你的输入是c 2 3 d 5 6 x y z(回车)，这个语句的作用就是把你输入的 d 5 6 x y z(回车)从你的缓冲区里吃掉，那么你的程序就仍然可以正常运行。非常感谢你认真细致的回答，学习了，正是我想要的答案！  ^-^


Question: 求该算法题的C语言编程，大佬帮帮忙，写不下去了，要能运行的

大佬。chuali

请大佬帮忙看看啊，小弟很急


Question: 如何安全的分配scanf输入的字符串空间？

Linux做不到scanf，windows有scanf_s可以输入长度，但是这个机制也只是将输入的字符串截断，而不能正好分配。所以这个还是编程人员自己控制

看下你的应用会不会有恶意破坏的人，如果有，就控制最大输入，如果没有，按照业务控制，稍微留大一点就可以了，现在的内存以g为单位，你加多个1k都是微不足道的

一般情况下 都会预估输入值得大小，预留出一些空间，你也可以改用sacnf_s()，指定最大输入。


Question: 关于closesocket()关闭套节字传递EOF的问题

我一般recv 返回小于等于0 就认为断开了。。大于0才表示有数据。

原书的代码贴在这里了： 服务器端： #define BUF_SIZE 100 #define MAX_CLNT 256  unsigned WINAPI HandleClnt(void * arg); void SendMsg(char * msg, int len); void ErrorHandling(char * msg);  int clntCnt=0; SOCKET clntSocks[MAX_CLNT]; HANDLE hMutex;  int main(int argc, char *argv[]) { 	WSADATA wsaData; 	SOCKET hServSock, hClntSock; 	SOCKADDR_IN servAdr, clntAdr; 	int clntAdrSz; 	HANDLE  hThread; 	if(argc!=2) { 		printf("Usage : %s <port>\n", argv[0]); 		exit(1); 	} 	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) 		ErrorHandling("WSAStartup() error!");     	hMutex=CreateMutex(NULL, FALSE, NULL); 	hServSock=socket(PF_INET, SOCK_STREAM, 0);  	memset(&servAdr, 0, sizeof(servAdr)); 	servAdr.sin_family=AF_INET;  	servAdr.sin_addr.s_addr=htonl(INADDR_ANY); 	servAdr.sin_port=htons(atoi(argv[1])); 	 	if(bind(hServSock, (SOCKADDR*) &servAdr, sizeof(servAdr))==SOCKET_ERROR) 		ErrorHandling("bind() error"); 	if(listen(hServSock, 5)==SOCKET_ERROR) 		ErrorHandling("listen() error"); 	 	while(1) 	{ 		clntAdrSz=sizeof(clntAdr); 		hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr,&clntAdrSz); 		 		WaitForSingleObject(hMutex, INFINITE); 		clntSocks[clntCnt++]=hClntSock; 		ReleaseMutex(hMutex); 	 		hThread= 			(HANDLE)_beginthreadex(NULL, 0, HandleClnt, (void*)&hClntSock, 0, NULL); 		printf("Connected client IP: %s \n", inet_ntoa(clntAdr.sin_addr)); 	} 	closesocket(hServSock); 	WSACleanup(); 	return 0; } 	 unsigned WINAPI HandleClnt(void * arg) { 	SOCKET hClntSock=*((SOCKET*)arg); 	int strLen=0, i; 	char msg[BUF_SIZE]; 	 	while((strLen=recv(hClntSock, msg, sizeof(msg), 0))!=0) 		SendMsg(msg, strLen); 	 		 	 	WaitForSingleObject(hMutex, INFINITE); 	for(i=0; i<clntCnt; i++)   // remove disconnected client 	{ 		if(hClntSock==clntSocks[i]) 		{ 			while(i++<clntCnt-1) 				clntSocks[i]=clntSocks[i+1]; 			break; 		} 	} 	clntCnt--; 	ReleaseMutex(hMutex); 	closesocket(hClntSock); 	return 0; } void SendMsg(char * msg, int len)   // send to all { 	int i; 	WaitForSingleObject(hMutex, INFINITE); 	for(i=0; i<clntCnt; i++) 		send(clntSocks[i], msg, len, 0);  	ReleaseMutex(hMutex); } void ErrorHandling(char * msg) { 	fputs(msg, stderr); 	fputc('\n', stderr); 	exit(1); }  客户端： #define BUF_SIZE 100 #define NAME_SIZE 20 	 unsigned WINAPI SendMsg(void * arg); unsigned WINAPI RecvMsg(void * arg); void ErrorHandling(char * msg); 	 char name[NAME_SIZE]="[DEFAULT]"; char msg[BUF_SIZE]; 	 int main(int argc, char *argv[]) { 	WSADATA wsaData; 	SOCKET hSock; 	SOCKADDR_IN servAdr; 	HANDLE hSndThread, hRcvThread; 	if(argc!=4) { 		printf("Usage : %s <IP> <port> <name>\n", argv[0]); 		exit(1); 	} 	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0) 		ErrorHandling("WSAStartup() error!");   	sprintf(name, "[%s]", argv[3]); 	hSock=socket(PF_INET, SOCK_STREAM, 0); 	 	memset(&servAdr, 0, sizeof(servAdr)); 	servAdr.sin_family=AF_INET; 	servAdr.sin_addr.s_addr=inet_addr(argv[1]); 	servAdr.sin_port=htons(atoi(argv[2])); 	   	if(connect(hSock, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR) 		ErrorHandling("connect() error"); 	 	hSndThread= 		(HANDLE)_beginthreadex(NULL, 0, SendMsg, (void*)&hSock, 0, NULL); 	hRcvThread= 		(HANDLE)_beginthreadex(NULL, 0, RecvMsg, (void*)&hSock, 0, NULL);  	WaitForSingleObject(hSndThread, INFINITE); 	WaitForSingleObject(hRcvThread, INFINITE); 	closesocket(hSock); 	WSACleanup(); 	return 0; } 	 unsigned WINAPI SendMsg(void * arg)   // send thread main { 	SOCKET hSock=*((SOCKET*)arg); 	char nameMsg[NAME_SIZE+BUF_SIZE]; 	while(1)  	{ 		fgets(msg, BUF_SIZE, stdin); 		if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n"))  		{ 			closesocket(hSock); 			exit(0); 		} 		sprintf(nameMsg,"%s %s", name, msg); 		send(hSock, nameMsg, strlen(nameMsg), 0); 	} 	return 0; } 	 unsigned WINAPI RecvMsg(void * arg)   // read thread main { 	int hSock=*((SOCKET*)arg); 	char nameMsg[NAME_SIZE+BUF_SIZE]; 	int strLen; 	while(1) 	{ 		strLen=recv(hSock, nameMsg, NAME_SIZE+BUF_SIZE-1, 0); 		if(strLen==-1)  			return -1; 		nameMsg[strLen]=0; 		fputs(nameMsg, stdout); 	} 	return 0; } 	 void ErrorHandling(char *msg) { 	fputs(msg, stderr); 	fputc('\n', stderr); 	exit(1); }


Question: 演示用户交互是发生冲突，什么原因？

printf的格式话输出%s没有对应的变量，这个说的对的，仔细看了下，的确是少个变量！

再加个头文件#include<stdlib.h>，如果用system函数的话。

#include<stdio.h> #include<string.h>  #define DENSITY 62.4  int main() {     float weight, volume;     int size, letters;     char name[40];     printf("Hi! what's your first name?\n");     scanf("%s", name);     printf("%s, what's your weight in pounds?\n",name);     scanf("%f", &weight);     size = sizeof name;     letters = strlen(name);     volume = weight / DENSITY;     printf("Well,%s, your volume is %2.2f cubic feet.\n",name,volume);     //printf("Also,%s, your first name has %d letters,\n",letters);     printf("Also,%s, your first name has %d letters,\n", name, letters);     printf("And we have %d bytes to store it.\n", size);     system("pause");     return 0; } printf的格式话输出%s没有对应的变量

size = sizeofname;这个语句写的有问题吧


Question: 求解define后多赋值变量语法。

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

楼主找一下define后的标识符在程序里是怎么用的，比如搜索一下EMIT_CLEAR(addr)，然后用( (OPCODE_CLEAR     << 4 ) | 1 ) , addr替换掉。也许看完代码就明白了。

就是在程序中嵌入机器码，和汇编中在代码段中用db嵌入机器码类似。 EMIT_MASKWRITE(addr,mask,val) 在引用的地方会生成：0x33 xx xx xx，后三段是addr,mask,val的值

从代码来看就是替换啊  #define EMIT_MASKWRITE(addr,mask,val)     ( (OPCODE_MASKWRITE << 4 ) | 3 ) , addr, mask, val 用EMIT_MASKWRITE(addr,mask,val)   替换( (OPCODE_MASKWRITE << 4 ) | 3 ) , addr, mask, val 至于( (OPCODE_MASKWRITE << 4 ) | 3 ) , addr, mask, val是实现什么功能这谁知道，又没有代码，只有你自己去看啊

那就不太清楚了，我对他的理解仅限于此，坐等大佬来解答。

#define OPCODE_EXIT                            0U #define OPCODE_CLEAR                         1U #define OPCODE_WRITE                         2U #define OPCODE_MASKWRITE               3U #define OPCODE_MASKPOLL                 4U #define OPCODE_MASKDELAY               5U #define NEW_PS7_ERR_CODE                  1  /* Encode number of arguments in last nibble */ #define EMIT_EXIT()                                      ( (OPCODE_EXIT      << 4 ) | 0 ) #define EMIT_CLEAR(addr)                           ( (OPCODE_CLEAR     << 4 ) | 1 ) , addr #define EMIT_WRITE(addr,val)                      ( (OPCODE_WRITE     << 4 ) | 2 ) , addr, val #define EMIT_MASKWRITE(addr,mask,val)   ( (OPCODE_MASKWRITE << 4 ) | 3 ) , addr, mask, val #define EMIT_MASKPOLL(addr,mask)           ( (OPCODE_MASKPOLL  << 4 ) | 2 ) , addr, mask #define EMIT_MASKDELAY(addr,mask)         ( (OPCODE_MASKDELAY << 4 ) | 2 ) , addr, mask 寄存器值取得是逗号前边的值，但是不太理解怎么写是啥意思！！！？而且变量与本身宏没有啥相关性，代码是SDK编译自动生成的，平台vivado16.3 标准c代码，之前从没遇到过类似的写法，不明其意？

define 的作用就是原样替换，而且只是原样替换，你的这个好像不是返回一个值的吧。。     Example:  #define x(a,b)  (a+b)*(a-b) cout << x(1,2) << endl; ====>cout << (1+2)*(1-2) << endl;

你的这个好像是函数的参数吧， 比如函数原型为 void xxxx(类型1 a, 类型2 b,类型3 c,类型4 d) {.......} ===调用的时候 就可以 xxxx(EMIT_MASKWRITE(b,c,d)); 还是那句话，只是原样替换。。。


Question: 给解释下代码的意思；

谢谢 大家的解答

两个unsigned char类型的数组。里面的内容是0x是表示16进制数。MAC地址一般是16进制表示的

存储的是网卡的MAC地址，这些地址由IEEE管理和分配，所以每个厂商都有一个唯一的标识，前面3个字节代表厂商编码，后面3个字节由厂商自行分配，这样就保证了全球唯一性。

这两个变量应该都表示计算机的MAC地址，MAC地址就是6个部分，每个部分是一个字节的十六进制数

应该是存的48位MAC地址


Question: 直接对磁盘的读写会不会被操作系统记录下来？

引用 8 楼 zhao4zhong1 的回复:不会 赵老师，谢谢啦，也不好意思哈

windows里面createfile  操作系统不会记录  覆不覆盖看位置，有些夹缝、标记已写的不覆盖（可以利用这一点来藏私密信息）

引用 5 楼 weixin_39158150 的回复:[quote=引用 3 楼 ckc 的回复:] 不会形成文件，不过看你写在哪里，有可能会修改文件或者修改文件系统 普通人不需要用这个函数，别折腾这个了 我不是要用这种函数，我只是在想，用这种函数在磁盘上写的数据，操作系统会认为这里是已经有数据的还是空闲区域，这里会不会在以后被其他文件覆盖[/quote] 看你写的位置，如果写的地方已经被用了，比如是某文件的一部分，那么你实际上破坏了那个文件。甚至于你写在重要的区域可能直接导致文件系统甚至分区被破坏。如果写的地方没被用，是空的，那以后可能会被操作系统分配写入其它数据。 基本上除非很特殊的情况，我们不需要直接写磁盘

引用 9 楼 Mr_sandman1994 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] 不会 看你把赵老师逼的[/quote]

引用 8 楼 zhao4zhong1 的回复:不会 看你把赵老师逼的

不会

引用 4 楼 zhao4zhong1 的回复:[quote=引用 3 楼 ckc 的回复:] 不会形成文件，不过看你写在哪里，有可能会修改文件或者修改文件系统 普通人不需要用这个函数，别折腾这个了 其实我已经相当于回答了，只是你不识货。[/quote] 不识货没错，可我本就是一个小白问问题，想听一个一两句话的直白回答，为什么要搞这么复杂的回答，我的确没从这个网页里看出什么

引用 3 楼 ckc 的回复:不会形成文件，不过看你写在哪里，有可能会修改文件或者修改文件系统 普通人不需要用这个函数，别折腾这个了 我不是要用这种函数，我只是在想，用这种函数在磁盘上写的数据，操作系统会认为这里是已经有数据的还是空闲区域，这里会不会在以后被其他文件覆盖

引用 3 楼 ckc 的回复:不会形成文件，不过看你写在哪里，有可能会修改文件或者修改文件系统 普通人不需要用这个函数，别折腾这个了 其实我已经相当于回答了，只是你不识货。

引用 1 楼 zhao4zhong1 的回复:FDump - Dumping File Sectors Directly from Disk using Logical Offsets http://www.codeproject.com/Articles/32169/FDump-Dumping-File-Sectors-Directly-from-Disk-usin 赵老师，这个网页只是介绍了一种API来操作磁盘，并没有回答我的问题啊


Question: 关于指针的指针，何时是个尽头？

你说的是对的，没有尽头，直到内存满了。是可以一直指针下去，如楼上所说的，就是一直指向其他的内存，但是没有什么意义

一个数据就放在一个内存单元中，它有地址，可以没有指针，你所谓的指向它的指针，只是又在另一个空间保存了这块地址，这个空间就是个指针，当你不在这个空间保存它的地址的时候，它就没有指针，所以不存在指针的指针，我刚学的时候也想过这个问题，那是因为你以为指针必须有指针保存它的地址，而事实上是一个变量数据就是一个空间地址，不需要指针，指针只是你在另一个空间保存了它的地址罢了

难道得一个比较热烈的帖子

指针可以指回自身，那就真的没有尽头了。 ：）

引用 58 楼 赵4老师的回复:[quote=引用 57 楼 weixin_43209425 的回复:] 指针理论是存在尽头的，因为指针也要占用内存，而一台机器的内存是有限的，所以，指针不能无限下去! 那循环链表呢？[/quote] 循环链表就相当于一个圆圈，是数据结构的一种特殊形式，你问一个圆圈有没有尽头不是一个没有意义的问题么。再者，循环链表的每一个指针指向都已经确定了，只是不断重复而已！

引用 57 楼 weixin_43209425 的回复:指针理论是存在尽头的，因为指针也要占用内存，而一台机器的内存是有限的，所以，指针不能无限下去! 那循环链表呢？

好厉害好厉害啊

没有尽头的没有的 别反抗

指针的指针只是你编程的时候需要，首先你要确定你要干什么，编程中根据需要确定使用几级指针，没必要纠结这个，都是人为定义的。

在指针指了n次之后，那个内存里存的东西是不是个指针，如果是就继续指下去，如果不是就到头了。

项目中出现三级指针都要被老大骂了。。。

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

楼主说的是多级指针，理论上可以无限极，但是工作中最多也就二级指针了，三级的都没有遇到，所以不用纠结了呀

没有指针的指针的。 通常这样说是简化了，是指向指针变量的指针。 只有变量才有地址的，指针变量是存储指针（地址）的变量。 任何变量都是有地址的（auto 变量除外），也就说都是有指针的，这是递归定义。

指针是一个变量，它的值用于保存其它数据的地址。从这个最基本概念出发，指针真的没什么难理解的，别被人渲染指针有多难理解唬住了。

呀呀呀哈哈哈哈哈哈哈哈哈哈哈

指针就是地址 差不多是对的，不完全对，因为指针还有类型，同一个地址，用int *解析它，还是char *解析它，还是struct Student *解析，是各不相同的。  楼主应该了解内存，比如系统有1M的内存（打个比方），就是1024x1024个字节，你可以想象成100万（多）个格子，每个格子都有编号（从0开始），编号就是地址。比如int i，i变量被分配在编号为第100~103个格子（分配的位置是由系统决定的），如果赋值i=10，那么这4个格子里面存储的就是 00000000 00000000 00000000 00001010（等于整数10，这里还有内存字节序的问题，可以先不管），i的地址，就是&i，等于100（编号）。如果有一个int* p，p是一个指针变量，p变量被分配在编号为第104~107个格子，如果赋值p=&i，那么这4个格子里面存储的就是 00000000 00000000 00000000 01100100 （等于整数100），也就是p==100，p变量本身的地址，也就是&p，等于104。  常量，比如const int i=100，是不为i分配空间的，程序编译的时候自动把使用i的地方用100代替。 const char *str="Hello,world", "Hello,world"字符串字面量位于进程内存空间中的文字常量区，比如分配在编号第200~211个格子（每个格子存一个字符，最后有一个'\0'是自动添加的），如果用printf("%p:%s",str,str)输出，结果就是200:Hello,world，200表示str变量指向的地址，str变量可能被分配在108~111个格子（这4个格子里面存的值就等于200），而str变量的地址&str==108。

C 语言中需要修改指针的值，才用到二级指针，也就是指针的指针，一般三级都很少用了。当然你可以无限制创建下去，但意义何在？ 引用 30 楼 zhao4zhong1 的回复:见第一贴附带“四季青90后女孩在家无聊玩手机，存款惊 呆父母”广告模特。四季青，暴露位置了！我这里大半年都是“张江27岁刘某辞去保安工作，半年存款惊呆众人！”。

指针是指向某一数据类型的，而指针也只一种数据类型，因此没有尽头。楼主可能觉得指针不是实在的数据类型，而是一种间接的表达方式，才会有这种想法。


Question: 小白求助，关于CreateRemoteThread远程注入代码

不明觉厉。。。

仅供参考：/*     Application:    Code Injection in Explorer     Author:     @_RT     Compiled on:    Feb 2014     URL:http://www.codeproject.com/Tips/732044/Code-Injection-2      We will see the different steps involved to perform a code injection into an already running process.      Following are the quick steps through the process of injection.     1.Get the API addresses that you will be calling from the injected code.     2.Prepare shell code of your function that you want to get executed from the injected process.     3.Get the process ID of the running process that you wish to inject into by enumerating through the       list of processes or by finding the process's window (in case it's a GUI application) by class name or title.     4.Open the process using its Pid with All Access rights.     5.Allocate different memory spaces in the process that you are going to inject to with desired access       rights for holding different segments of your shell code.         Code part (executable instructions)         Data part (strings, function parameters, etc.)     6.Write the allocated memories with the respective values (code and data).     7.Call CreateRemoteThread API and pass to it the start of allocated memory address where you have       written your shell code from the process we are injecting. */  #include <windows.h> #pragma comment(lib,"user32.lib")  LPVOID addr; LPVOID addr2;  BOOL InjectExecutable(DWORD dwPid,LPVOID si,LPVOID pi,int sisize,int pisize) {     LPVOID hNewModule;     HANDLE hProcess;     CHAR S[]    = { "C:\\Windows\\system32\\notepad.exe" };     BYTE byt[]  = {0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x01, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x68};                  //push  0   , push     0, push     0, push     1, push     0, push     0, push     0, push 0xXXXXXXXX     BYTE byt2[] = {0xE8};//call 0xXXXXXXXX     BYTE byt3[] = {0x68};//push 0xXXXXXXXX      hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);     if (hProcess == NULL)     {         return FALSE;     }      LPVOID staddr = VirtualAllocEx(hProcess, NULL, sizeof(S), MEM_COMMIT, PAGE_READWRITE);     WriteProcessMemory(hProcess, staddr, S, sizeof(S), NULL);     LPVOID fnaddr = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);     WriteProcessMemory(hProcess, fnaddr, pi, sisize, NULL);     LPVOID fnaddr2 = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);     WriteProcessMemory(hProcess, fnaddr2, si, pisize, NULL);      hNewModule = VirtualAllocEx(hProcess, NULL, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);     if (hNewModule == NULL)     {         return FALSE;     }     LPTHREAD_START_ROUTINE strtaddr = (LPTHREAD_START_ROUTINE)hNewModule;      WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));     WriteProcessMemory(hProcess, hNewModule, &fnaddr, sizeof(fnaddr), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr));                    // push &pi ;lpProcessInformation     WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));     WriteProcessMemory(hProcess, hNewModule, &fnaddr2, sizeof(fnaddr2), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr2));                   // push &si ;lpStartupInfo     WriteProcessMemory(hProcess, hNewModule, byt, sizeof(byt), NULL);           // push 0 , push 0, push 0, push 1, push 0, push 0, push 0, push 0xXXXXXXXX==&S[0];"C:\\Windows\\system32\\notepad.exe"     hNewModule = (LPVOID)((int)hNewModule + sizeof(byt));                       // lpCurrentDirectory,lpEnvironment,dwCreationFlags,bInheritHandles,lpThreadAttributes,lpProcessAttributes,lpCommandLine,lpApplicationName     WriteProcessMemory(hProcess, hNewModule, &staddr, sizeof(staddr), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(staddr));     WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));                      // call CreateProcessA     addr = (LPVOID)((int)addr - ((int)hNewModule + 4));     WriteProcessMemory(hProcess, hNewModule, &addr, sizeof(addr), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(addr));     WriteProcessMemory(hProcess, hNewModule, byt, 2, NULL);     hNewModule = (LPVOID)((int)hNewModule + 2);                                 // push 0 ;DWORD dwExitCode   // exit code for this thread     WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);     hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));                      // call ExitThread     addr2 = (LPVOID)((int)addr2 - ((int)hNewModule + 4));     WriteProcessMemory(hProcess, hNewModule, &addr2, sizeof(addr2), NULL);      CreateRemoteThread(hProcess, 0, 0, strtaddr, NULL, 0, NULL);     return TRUE; }  int main() {     _STARTUPINFOA si;     PROCESS_INFORMATION pi;      ZeroMemory(&si, sizeof(si));     si.cb = sizeof(si);     ZeroMemory(&pi, sizeof(pi));      DWORD dwPid;     HMODULE ldlib = LoadLibraryA("Kernel32.dll");     addr = GetProcAddress(ldlib, "CreateProcessA");     addr2 = GetProcAddress(ldlib, "ExitThread");     HWND hWnd1=FindWindow(NULL, "Program Manager");     if (NULL==hWnd1) {         return 1;     }     GetWindowThreadProcessId(hWnd1, &dwPid);      InjectExecutable(dwPid,&si,&pi,sizeof(si),sizeof(pi));      return 0; }

哎，难受死了

一点头绪都没有

弄好了弄好了，远程线程函数我用汇编写了一遍就好了，有可能是编译器自己给我加了一些没用的汇编代码吧可能

去搜一下吧。论坛有些相关的吧。内存分配疑难

第一次在CSDN上发帖，有些地方不太懂

这代码困扰我两天啦！！！求大佬来帮个忙看看哪里错啦！！！谢谢各位大佬啦！！！

我只会inject dll 代码一抓一大把。 win核心编程有讲到远程线程注入那些

没有人么,没有大佬会帮下忙嘛，很难受呀


Question: Digital Roots题目大意将输入的正整数的各个数相加

思路是没问题，但是你没有初始化sum，结果就会错。 简单地说就是 int sum=0; 改一下就好

谢谢，可以了


Question: 一百个人，一杀二然后把刀给三，三杀四然后把刀给五。以此规律往后，最后活着的是几？

#include "stdio.h" #include <conio.h> void main() { 	int z,count;          //遍历从首到尾为一大轮 	int i,j; 	int a[100]; 	int b[50]; 	j=1; 	count=0;            //定义count,为每一轮结束后，累加的总遍历人数  	for(i=1;i<101;i++)  //*给数组a[]赋值从1－100 	{ 		a[i-1]=i; 	}       int max=100;      //*定义max，为每一大轮开始场上剩下的总人，初始为100     int n=0;  	for(j=1;j<=max;j++)         	{	  		if(count%2==0)   //count为双，本轮留下奇数 		{ 			if(j%2!=0) 			{ 			n=n+1; 		    b[n-1]=a[j-1];		 		    printf("该数为：%d\n",b[n-1]); 			} 		}  		if(count%2!=0)    //count为单，本轮留下偶数 		{ 			if(j%2==0) 			{ 			n=n+1; 			b[n-1]=a[j-1];             printf("该数为：%d\n",b[n-1]); 			} 		}    		if(j==max) 		{  			for(z=0;z<n;z++) 			{ 				a[z]=b[z]; 			}   			count=count+max; 			max=n; 			j=0; 			printf("累计%d人次，本轮过后场上还留下%d人。\n",count,max); 			printf("按任意健继续……\n"); 			getch();  			n=0; 			z=0;  		}         if (max==1) 		{  		  break;  		}   	} 	printf("最终留下的数为：%d\n",a[z]); 	printf("Byebye!\n"); }

循环链表

#include "stdio.h" #include "string.h"  #define MAX_SIZE 100  int KillMan(int a[], int n) { 	int q[MAX_SIZE]; 	int front = -1,rear = -1;   	for(int i = 0; i < MAX_SIZE; i++) 		q[++rear] = i;   	while(front != rear -1) 	{  		front = (front+1) % MAX_SIZE; 		int t1 = q[front];   		front = (front+1) % MAX_SIZE; 		int t2 = q[front];   		printf("\n%d", t2);   		rear = (rear+1) % MAX_SIZE; 		q[rear] = t1; 	}  	front = (front+1) % MAX_SIZE; 	return q[front];  }  void main() { 	int a[MAX_SIZE]; 	int n = sizeof(a) / sizeof(int);  	printf("\nrest:%d\n\n", KillMan(a, n)); }

队列的思想还是清晰一点

引用 2 楼 Slzde_sub 的回复:   约瑟夫循环 对，是一样的，只是3个人变两个人

这种问题用数组多捞啊，用个循环链表不好么

这问题搞复杂了，就是个队列问题，每次出队两个，进队一个，当队列长度为1时候的元素是啥


Question: C语言

不需要返回值的时候用

作为返回值或者作为参数，作为返回值时表示没有返回值，作为参数时表示没有参数

不需要返回值或传入参数时，或者用于void *的返回值或参数，主要是不清楚返回值的类型或传入参数的类型时会使用void

不需要返回值的时候就可以

如果xx函数就不需要有返回值，则可用void xx()来声明和定义该函数。

void用处很多啊，可以当返回值，可以当参数。void指针用处更加广泛。很多消息发送，都先转成void*，再转回相应都数据结构

试试说一下，好像是说不用返回值时或无参数时，会用到。 有一种函数，**它是不带参数的函数。没用过。 int rand(void); 还有一种是无返回值的函数如： void copy(char to[], char from[])         //有两个形式参数，用作：目标数组，源数组。 {     int i;      i = 0;          while ((to[i] = from[i]) != '\0')     {         ++i;     } } 这是一个子函数。它的作用就是，复制一个字符数组保存到另外某个字符数组中。**void是显现说明不用返回任何值。 下面这个是有返回值类型，有参数的子函数。以作比较。 int putline(char line[], int abc, int i_end)     //int 是要求类型为整形，函数返回的值要按要求来 { 	while (abc <= i_end) { 		putchar(line[abc]); 		abc++; 	} 	return abc;       //返回值为abc，类型会是int型。 } 这个子函数是有返回值的。打印行，并返回最后一个元素下标的值。


Question: 求教一个多种编码格式的搜索方法

MultiByteToWideChar和WideCharToMultiByte能满足你的要求。指定编码格式就可以了


Question: 怎样获得自己拍的视频的码流

h264 文件比较简单，开头sps pps 然后后面就都是nalu帧。  h265还没接触过。。

引用 1 楼 user-2的回复:使用ffmpeg库，一帧一帧的解。 谢谢您的回复，看来我要学习ffmpeg了

使用ffmpeg库，一帧一帧的解。


Question: STL string类中文问题

中文请使用wstring

为什么 不用wstring呢？

引用 1 楼 user-6 的回复: 字符串比较用strcmp吧。 直接== 怕是不行。我反正没试过string 的== 字符串比较可以用==。strcmp是C的用法吧。 ISO/IEC 14882:2011 21.4.8.2  [string::operator==]   template<class charT, class traits, class Allocator>   bool operator==(const basic_string<charT,traits,Allocator>& lhs,                   const charT* rhs) noexcept;   要求： rhs 指向一个至少包含 traits::length(rhs) + 1 个 chartT 的数组。 返回： lhs.compare(rhs) == 0.

编码问题，需要转码。 可以参考以下文章 https://blog.csdn.net/jcjc918/article/details/52200478?locationNum=7&fps=1

编码问题。。


Question: 请教一个预编译问题 #if #elif #endif

引用 楼主 u010315185 的回复:#define COMM_PC // ---------------------------------------------------------------------------------------------[1] #if defined(COMM_PC)         #define MASTER_COMM_PC                       4  //-----------------------------------------------------[2] #elif defined(MAX3485_COMM_PC)         #define MASTER_COMM_PC                       3 #elif defined(MAX3232_COMM_PC)         #define MASTER_COMM_PC                       1 #else         #define MASTER_COMM_PC                       4  #endif   #if (MASTER_COMM_PC== 1)         #define PTZCOMMPC_USARTx USART1    //--------------------------------------------------------------[3]         #define PTZCOMMPC_NVIC_IRQChannel USART1_IRQn #elif (MASTER_COMM_PC== 4)         #define PTZCOMMPC_USARTx UART4//-------------------------------------------------------------------[3]         #define PTZCOMMPC_NVIC_IRQChannel UART4_IRQn #else         #define PTZCOMMPC_USARTx USART2         #define PTZCOMMPC_NVIC_IRQChannel USART2_IRQn #endif 背景：因为在项目中，使用的接口会有RS232或者RS485接口，所以想通过预编译指令来条件选择          本来是想要的执行顺序是   【1】-->【2】-->【3】          可是编译完成后，Go to Definition “PTZCOMMPC_USARTx”老是执行 绿色的代码【3】；即 【1】-->【2】-->【3】             //if(USART_GetITStatus(PTZCOMMPC_USARTx, USART_IT_RXNE) != RESET)   请问各位大神，这是什么原因？？？？  楼主写的语句问题， 如果想要【1】-->【2】-->【3】[/color]招待，那么#if defined(COMM_PC)改成 #ifdef  COMM_PC就可以了。 你的#define COMM_PC这种写法，只能用#ifdef或者#ifndef来判断， #if defined(COMM_PC)这种写法需要有具体的值，才可以。

搞两个头文件，确保编译顺序

Go to Definition  是不对的, 你实际编译运行后看结果


Question: errror C 2061  语法错误：标识符‘’Nodeptr‘’

如楼上所说，遵循先定义后使用，编译器默认是从上往下搜寻的，所以必须要把声明或者实现放在使用的前面。

int FindPrevious(int nun, NodePtr header); 这一行移到NodePtr 定义之后

你得把函数FindPrevious的声明放到结构体的定义之后。不然NodePtr都还未定义，编译器不认识  #include <stdio.h> #include <stdlib.h>   struct ListNode {     int num;     struct ListNode *next; }; typedef struct ListNode Node; typedef Node *NodePtr;  int FindPrevious(int nun, NodePtr header);  int main() { //... }


Question: 关于c语言中scanf赋值的一个疑问？

作为局部变量a，定义之后你没有显式地给a赋值过，那么a的值应该就是内存中的乱码，应该程序每次运行时a的值都会不一样。如果你每次运行都是a的值都是0，那也许是跟编译器有关了。

您好，我显示的a为0是为什么呢，跟系统有关吗，我用的mac

第一段程序，如果输入的内容与类型不匹配，scanf函数会终止当前输入，并将已经输入的字符'f'退回到缓冲区，此时，缓冲区中仍然留着你输入的f56。而你所说的a的值是乱码，的确，由于没有从scanf获得输入，此时a的值，还是你当时定义的局部变量a，其内存中的乱码的那个值。以下的代码和结果，可以给你参考 #include <stdio.h> int main(void) {     int a;     char ss[100];     printf("plese \n");     printf("a = %d\n",a);     scanf("%d\n", &a);     scanf("%s",ss);     printf("number is %d\n", a);     printf("string is %s\n", ss);     return 0; }   第二段程序也是同样的道理，a的输入由于类型不匹配，a的输入被终止，a的值，那就原来内存里是啥就还是啥。你自己可以检验一下。 #include <stdio.h> int main(void) {    char b[20], c[20];    int a;    printf("a = %d\n",a);    scanf("%d", &a);    scanf("%s", b);    scanf("%s", c);      printf("a=%d, b=%s, c=%s.\n", a, b, c);    return 0; }  当然，此时的缓冲区里还剩下7，你可以自己再增加一个scanf语句来试试看。


Question: 在数据结构中单链表的插入和删除操作?

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

需要，0插入最开始处，是否变更L的值，依据实际情况考虑 如果变更那就更改指向，如果不变更，原始的第一个元素的值和插入值（内存）交换，并后插在头指针后

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

引用 2 楼 沐雨青城的回复:楼主想问的是链表头节点是否放元素的吧，如果链表头不放元素，在初始化链表的时候，需要分配一个空节点，用于存储头节点，后续插入删除都在头节点后面进行，好处就是不需要在动链表的指针了，且操作会简单一点，但会浪费一个节点的内存。如果链表头放元素的话，在删除，添加头节点的时候，需要更新链表头的指针，操作会麻烦一点，但不会浪费内存，这个要不要这个链表头空节点，取决于个人爱好，有没有关系都不大。 此外，楼主提供的代码，貌似有点小问题，首先你的i看起来是从1开始算，如果取0的话，搞个负数是啥意思，且好像没有考虑表头元素修改的问题。 因为有些参考书上给出了这些，我很疑惑，我也感觉位置没有0位置，但是一想会不会凡事要有个意外

引用 2 楼 沐雨青城的回复:楼主想问的是链表头节点是否放元素的吧，如果链表头不放元素，在初始化链表的时候，需要分配一个空节点，用于存储头节点，后续插入删除都在头节点后面进行，好处就是不需要在动链表的指针了，且操作会简单一点，但会浪费一个节点的内存。如果链表头放元素的话，在删除，添加头节点的时候，需要更新链表头的指针，操作会麻烦一点，但不会浪费内存，这个要不要这个链表头空节点，取决于个人爱好，有没有关系都不大。 此外，楼主提供的代码，貌似有点小问题，首先你的i看起来是从1开始算，如果取0的话，搞个负数是啥意思，且好像没有考虑表头元素修改的问题。 代码1和代码2的区别就是有没有考虑到用户输入的位置是0位置，即i=0

引用 2 楼 沐雨青城的回复:楼主想问的是链表头节点是否放元素的吧，如果链表头不放元素，在初始化链表的时候，需要分配一个空节点，用于存储头节点，后续插入删除都在头节点后面进行，好处就是不需要在动链表的指针了，且操作会简单一点，但会浪费一个节点的内存。如果链表头放元素的话，在删除，添加头节点的时候，需要更新链表头的指针，操作会麻烦一点，但不会浪费内存，这个要不要这个链表头空节点，取决于个人爱好，有没有关系都不大。 此外，楼主提供的代码，貌似有点小问题，首先你的i看起来是从1开始算，如果取0的话，搞个负数是啥意思，且好像没有考虑表头元素修改的问题。 我的意思是：在对链表进行插入或删除操作时，需不需要考虑用户输入在0位置的插入和删除操作，若用户输入的是0，那么这个代码的意思就是，寻找0位置进行插入或删除操作，但0位置是没有意义的，即进行操作失败，我表达的应该是这个意思


Question: C# 读取MYSQL数据 列的所有值并且判断

引用 5 楼 Smliling 的回复:我想在MySQL中存取 视频或图片，转化后都报格式错误！请个为大神指教  Mysql 储能图片和视频的地址，读取的时候直接读取地址就行了

我想在MySQL中存取 视频或图片，转化后都报格式错误！请个为大神指教

偷偷告诉你，论坛里面有C#专区

请大神们，指导！！！！

引用 2 楼 lidaoying 的回复:引用 1 楼 jianwen0529 的回复:偷偷告诉你，论坛里面有C#专区  在那里 .Net技术——C#


Question: getchar；与gets（）的读取

自己试了试第二种，结果和第一种情况是一样的，a一样不能输出

scanf是格式化输入，既然是格式化，那么%d就是匹配一个整型，输入abcde因为不匹配，scanf返回0，getchar()是对应的换行符，输入的内容还在输入缓存里，当遇到gets时，就会将"abcde"赋值给a。因此可以正常输出。可以检查一下n，应该是一个随机值。

第一个getchar读的是a 第二个getchar读的是回车

char *a; getchar(); 此处读取掉a  int n, m, t; scanf( "%d", &n ); //此处读取掉换行符，也就是你输入n回车键时候的换行符

但是我scanf后面用了一次getchar啊，不是应该也是读取了第一个字母，gets从第二个开始吗，还是%d有什么特别意义

getchar scanf gets 等等 这些函数都是从stdin获取数据 你输入 abcede\n  缓冲区数据abcede\n 运行getchar 缓冲区数据 bcede\n 后面的gets就读取到b开头的字符串  你用scanf %d %d不处理 abcede\n 缓冲区数据不变  scanf 返回值0 n值不变 你后面gets获取到的字符串是a开头的


Question: 百炼POJ 2807题目为什么超时？

最外层的while(1)是多余的，if(temp==-1) break;也是多余的


Question: 怎样提高clion的警告等级

奇怪，不能上传图片。 点击file/settings/editor/code style/inspections，这时，在目录右侧出现C/C++/Data flow analysis，其中有一个项是“missing return”，点一下这个项，在右侧会出现选择warning或error的选项。 但是若程序中故意注释掉return语句，编译后什么也没有报。

引用 1 楼 jianwen0529 的回复:把option选项和工程配置等浏览一遍，总会找得到的  找到了这个选项，缺少return时，默认是warning，但是将程序中的return注释掉，编译时不出现任何warning。将默认的warning选项更改为error，编译后仍然不报错。 不知怎么回事。。。

把option选项和工程配置等浏览一遍，总会找得到的


Question: 求助

你的代码已经做到了 不过楼上的说反了，因为你用的是#ifndef a  #ifndef a #include "b.h" #else #include "c.h" #endif 这段话的作用就是： 如果前面或预处理定义中没有 #define a 那么就 include "b.h" 如果有，那么就 include "c.h"

前面或预处理定义中有 #define a 那么就选择b，没有就选择c


Question: 宏定义求助

引用 2 楼 zhouchao_0321 的回复:首先你用#define a这种格式，应该是赋不了值的，只有真和假，如果想赋值做判断，有个方法你可以试一下行不行。 #define a 111, 然后如果需要重新定义的话，再#undef a; #define a 123(或其他)，判断的时候，用#if defined(a==123)来做判断。 +1

#define a 1 // 此处1可以改为其他值   #if(a==1) #define b 3 #elif(a==2) #define b 4 #else #endif

#define a   //定义a //define a   //未定义a


Question: c语言关于字模输出函数的问题

从上下文看 w单位是“位”，表示字模的宽度 char *pdata 存放的是字模具体数据，单位是字节，每字节等于8位 所以要w=(w+7)/8*8 算出，每行需要多少字节

保证w/8是整除的，防止小数部分被舍弃，因为int/int得出的是向下取整（对于>=0的情况）

重新计算w，看起来像是为了保证w始终为8的倍数。看起来代码像是每行同时控制8个点的，保证w为8的倍数应该是为了避免出现重复或者遗漏。


Question: 求助

可以编译的时候，添加命令来指定

你想通过scanf输入的a的值动态来判断include哪个头文件，貌似是不行，ifdef是编译时候确定的

#ifdef a==1 #include "b.h" #ifdef a==0 #include "c.h" #endif

#ifndef这类语句主要用在编译选择的时候，通过定义的宏来选择编译的内容，你这个用scanf函数是想根据运行时，来决定include哪个文件，应该是不行的，而且你的scanf("a = %d",&a);中的a是需要指定变量类型的，应该编译都过不了的吧。 不过可以通过在代码里使用#define 和#undef来开关编译选项，来选择#include文件的时机。

ifndef是判断有没有宏定义，而不是a的值是否为0

了解一下代码生成技术。


Question: 求助

是不是应该用C++的编译器编译呢？如果是需要调用C的头文件，建议使用#include <cqueue>

没听说过驱动开发可以调用STL的。

你包含的STL，不是C语言的头文件，用C编译肯定会出错


Question: 小白求教      c函数的参数指针问题

请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？

引用 1 楼 hou09tian 的回复:func()函数的参数本身就是一个一维数组，并不是二维数组，所以ptr+1只能指向该数组的第二个元素。如果把func()的代码修改为 void func(int ptr[2][3]) { 	printf("ptr point is %p\n", ptr); 	printf("*ptr point is %p\n", *ptr); 	printf("*(ptr + 1) point is %p\n", **(ptr + 1)); } 此时，输出为  此时func()函数的参数是一个二维数组，ptr+1指向的是二维数组的第二个元素，即第二个一维数组。 请参考《C++中对数组名的运算》 希望能够帮到你   非常感谢您的回答。   但是难道 *ptr[8]不是由指针构成的数组,而ptr作为数组名是指针，则 ptr 等效为指针的指针？   作为小白，在我的认知里就是 [] 和 *不是可以匹配相等么， 那么* ptr[8] 可以匹配**ptr？ 谢谢帮助

非常感谢你们的回答。   但是难道 *ptr[8]不是由指针构成的数组,而ptr作为数组名是指针，则 ptr 等效为指针的指针？   作为小白，在我的认知里就是 [] 和 *不是可以匹配相等么， 那么* ptr[8] 可以匹配**ptr？ 谢谢帮助

你写的int *ptr[8]不就是一维数组指针么？

你写的就是一位数组啊

数组传参，弱化成指针

引用 5 楼 Eagle_hwei 的回复:[quote=引用 1 楼 hou09tian 的回复:] func()函数的参数本身就是一个一维数组，并不是二维数组，所以ptr+1只能指向该数组的第二个元素。如果把func()的代码修改为 void func(int ptr[2][3]) { 	printf("ptr point is %p\n", ptr); 	printf("*ptr point is %p\n", *ptr); 	printf("*(ptr + 1) point is %p\n", **(ptr + 1)); } 此时，输出为  此时func()函数的参数是一个二维数组，ptr+1指向的是二维数组的第二个元素，即第二个一维数组。 请参考《C++中对数组名的运算》 希望能够帮到你  非常感谢您的回答。   但是难道 *ptr[8]不是由指针构成的数组,而ptr作为数组名是指针，则 ptr 等效为指针的指针？   作为小白，在我的认知里就是 [] 和 *不是可以匹配相等么， 那么* ptr[8] 可以匹配**ptr？ 谢谢帮助[/quote] * ptr[8] 可以匹配**ptr 可以看一下func()函数的声明 void func(int **); func()函数的定义 void func(int *ptr[8]) 这就说明了可以匹配。 但是需要注意的是，在func()函数的定义中，该函数的形参ptr是一个一维数组，该数组中的元素类型是int*。所以ptr+1指向的是该数组中的第二个元素。

void func(int *ptr[8])     {         printf("ptr point is %p\n", ptr);         printf("*ptr point is %p\n", *ptr);         printf("*(ptr + 1) point is %p\n", *(ptr + 1));     } ============= 这一句，void func(int *ptr[8])中的int * ptr[8],是定义了一个有8个元素的int指针数组，这个指针数组里的每一个元素都是一个int指针。  主函数中的int ptr[2][3] = { {8, 7, 3}, {4, 5, 6} };这一句是定义了一个二维数组，作函数参数时，它应该是数组指针，即应该定义为 int (*ptr)[3]，  而楼主的程序写法是将一个二维数组的首地址传给了一个指针数组的首元素，由于C编译器使用线性的方式存放二维数组，子函数中的ptr事实上是分别指向了二维数组的元素(当然，最后2个指针越界了）


Question: 有限条边连接图的问题

引用 2 楼 Scaramouch_ 的回复:[quote=引用 1 楼 adlay 的回复:] 方法一: 如果剩余的边数量 > 剩余未选到的点的数量:      从所有剩余边中选择最大的 否则:      从剩余的点关联的边上选择一条最大的  方法二:    1. 对每一个点, 选择一条和它相连的边种最大的一条    2. 去除重复的边    3. 剩余的按从大到小选取即可 方法二的话 ，这样有可能没有构成一个连通的图[/quote] 嗯, 确实是有这个可能, 看下这样:  1. 初始化已选边为空, 已选的点为空 2. 选择一条最长的边加入到已选的边中, 这条边的两个点加入到已选的点中. 3. 从剩余边中筛选出连接 已选的点 和 剩余的点 的边, 并从中选择最长的一条边出来 4. 将选择的边加入到已选边中, 将这条边上的点加入到已选的点中 5. 重复 3, 4 步, 直到剩余的点为空 6. 从剩余的边中从大到小选择  这样应该可以保证每一次选择出来的边都能和已选择的边构成一个连通图

引用 1 楼 adlay 的回复:方法一: 如果剩余的边数量 > 剩余未选到的点的数量:      从所有剩余边中选择最大的 否则:      从剩余的点关联的边上选择一条最大的  方法二:    1. 对每一个点, 选择一条和它相连的边种最大的一条    2. 去除重复的边    3. 剩余的按从大到小选取即可 方法二的话 ，这样有可能没有构成一个连通的图


Question: 数据结构查找删除操作哪里出错了

ElemType *e1;     int *pos; 把这两个指针换成变量pos和e1，传递进函数ListLocate(&L,4,&pos)和ListDelete_sq(&L,2,&e1)中，就 不会报错了，在这两个函数中，有*pos = i;和 *e=L->slist[i-1];，对这两个指针赋值了，但你还没有对这两个指针分配内存，所以会报访问非法内存的错误。

我想知道为什么指针用了就错

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

我用#CSDN#这个app发现了有技术含量的博客，小伙伴们求同去《C/C++泛型编程实现数据结构之线性表》, 一起来围观吧 https://blog.csdn.net/qq_27180763/article/details/82656677

ElemType *e1 = new int; int *pos = new int; 末尾加上 if(pos) delete pos; if(e1) delete e1; 饭要一口一口吃，你在学习链表的时候，最好先别掺杂上一些影响代码阅读的东西，要分清主次。其次你的命名让人看了很难受（int的重命名没感觉出来有什么必要，反而使代码更加晦涩难懂，带大小写和下划线的命名方法好像有点不太规范。。），我也是小白，共同学习，共同进步吧。


Question: 小白一个， 想问一下函数的参数为二维指针的问题

另外，举个二维数组，正确操作的例子。  #include <stdio.h>                                                                                void lian(int p[][3]); int main(void) {     int shu[2][3] = { {1,2,3}, {4, 5, 6} };     printf("shu point is %p\n", shu);     printf("*shu point is %p\n", *shu);     lian(shu);     return 0; }  void lian(int shu[][3]) {     printf("shu point is %p\n", shu);     printf("*shu point is %d\n", shu[1][1]); }  另外，也可以参考我的博客： https://blog.csdn.net/zxc024000/article/details/78957907

问题的原因在于，有几个： 首选： 对于，二维数组P[10][10]： P代表二维数组首地址，*P代表 P[0][10]的地址，**P代表P[0][0]的值。  对于，一维数据P[10]； P代表一维数组首地址，*P代表P[0]的值。   其次，指针和数组，并不等价。并不是，把数组首地址，赋给指针后。指针就可以当，数组来用。  首选：  lian(shu); 传递给函数的参数，为二维数组的首地址。  然后： void lian(int *shu[8])，将二维数组的首地址（就是个地址值），转为一维数组首地址类型（一维的，指针数组）。  然后： 在 lian 函数中。 printf("shu point is %p\n", shu);  输出的为shu地址值，这个没什么问题，因为即使做了类型转换，首地址的值并没有变。  然后： 在lian函数中。 printf("shu point is %p\n", *shu)，输出的为shu[0]的值。此时，要去shu地址指向的地方，取其值，而这个值，就是1 。  所以，你用%p的方式，输出int型的1，自然为00000001。   补充： void lian(char **);  应该写错了吧，应该是void lian(int **); 而且，这版的代码，只能gcc，g++是编不过的。

变量类型不一样，第一个打印时变量类型是**，第二个打印时变量类型是*

程序写的类型相容没有警告是个好习惯，虽然能运行不可控那就白写了，建议先把类型转换加上~


Question: 做项目遇到个问题，就是图中Vref参考电压要变化，怎么用pic单片机I/O口控制R5悬空和接地来实现？感谢各位解答。

引用 2 楼 qq_32339877的回复:引用 1 楼 user-4 的回复：你这个加个电容用PWM波就可以实现了吧关键没有pwm口 定时器输出到这个IO口，R3对地并一个电容滤波，改变定时器的周期比不就行了吗？

单片机引脚配置为开漏，输出0时r5接地，输出1时r5相当于接高阻，近似断开。

R5和端口之间接一个二极管就可以了

你这个加个电容用PWM波就可以实现了吧


Question: 《C标准库》里实现的clock应该错了吧？

引用 15 楼 weixin_39158150 的回复:老哥，这个只是功能介绍，没有实现的代码啊。它完全可以用各种方式实现比如winapi，它也没说是用time函数的返回值乘以一个值来得出的呀（个人怎么想都觉得秒*数的方式实现不了） 要搞清楚因果关系。并不是clock返回秒乘以一个数，而是计算机计时的时候是按clock计数，返回的秒实际上是clock除以一个频率。 以前dos下用18.2就是因为早期的pc机有个18.2Hz的硬件时钟， 计算机好像有个硬件中断就是以这个频率在一直计数，clock在这个机器上实际就是读取这个计数器的数据，计算机计时需要对这个计数进行除18.2的处理，就是说每有18.2个脉冲过来秒数加1。 后来的计算机速度提高，计时的精度也提高了，所以clock也就被调高了吧

引用 13 楼 Slzde_sub 的回复:[quote=引用 12 楼 weixin_39158150 的回复:] [quote=引用 11 楼 Slzde_sub 的回复:]    没必要扯这么多  去msdn上看看函数定义  函数返回值  函数说明  函数示例   那里是最标准的  请问在msdn里怎么找在里面迷路了都[/quote]   https://msdn.microsoft.com/zh-cn/library/4e2ess30.aspx   有能力尽量看英文原版[/quote]  老哥，这个只是功能介绍，没有实现的代码啊。它完全可以用各种方式实现比如winapi，它也没说是用time函数的返回值乘以一个值来得出的呀（个人怎么想都觉得秒*数的方式实现不了）

引用 11 楼 Slzde_sub 的回复:   没必要扯这么多  去msdn上看看函数定义  函数返回值  函数说明  函数示例   那里是最标准的  请问在msdn里怎么找在里面迷路了都

CLOCKS_PER_SEC依赖于操作系统以及编译器，也就是说不同的环境下可能是不一样的 当然你如果确定自己只用某一个具体的环境，那就可以把它当成一个固定的值 如果想规范，就需要处理CLOCKS_PER_SEC

引用 1 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！ 赵老师，您这段话怕是写在桌面随时复制粘贴吧？

引用 4 楼 hou09tian 的回复:你的这个clock()函数算的是从1900年到现在的时间吧？ 正如楼上所说，clock()函数返回的并不是毫秒。MSDN上的解释是 The elapsed time since the CRT initialization at the start of the process, measured in CLOCKS_PER_SEC units per second.  clock()函数返回的是进程开始时CRT初始化所消耗的时间，以每秒的 CLOCKS_PER_SEC 来测量。 也就是说，clock()函数返回值是秒× CLOCKS_PER_SEC 。CLOCKS_PER_SEC并不是一个固定值。  这样相乘很怪吧，乘起来都是整千整千的，实际使用起来不是这样的啊，实际真的能精确到毫秒啊。

引用 3 楼 ckc 的回复:clock返回的是启动的秒数乘以CLOCKS_PER_SEC CLOCKS_PER_SEC依赖于操作系统以及编译器，并没有规定死是多少 vc6定义的是1000，这样clock返回就是毫秒 linux下定义的是1000000，对应clock是微秒 以前的dos下tubro c2.0定义CLOCKS_PER_SEC是18.2 以上这些都是可以的，并没有违规 所以你这书上直接返回秒也是可以的，这时候CLOCKS_PER_SEC=1这样相乘很怪吧，乘起来都是整千整千的，实际使用起来不是这样的啊，实际真的能精确到毫秒啊。

RETURN VALUE        The  value  returned  is  the CPU time used so far as a clock_t; to get the number of seconds used, divide by CLOCKS_PER_SEC.  If the processor time used is not available or its        value cannot be represented, the function returns the value (clock_t) -1.  没毛病。


Question: c语言怎么实现窗体不激活，以及去除左上角图标文字？

挖窗口style的文档看一下，记得标题栏用风格就能控制的~


Question: 关于链表操作中free函数的问题

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

引用 1 楼 mscf 的回复:node * cj2(node *list, 	node * 	listt) { //思路：在第一个链表中将两个链表中的共同元素去掉，但是每次调用del_num时,free函数会出错 	node *list1 = list; 	for (; list != NULL; list = list->next) {//这里有逻辑问题，list1和list指向的是同一副本，而后续的del_num会操作list指向的副本，导致list变成脏数据，而c语言for循环的特性第三个表达式是本次循环结束后执行的，如果很不幸list指向的首元素刚好被free，在查找它的next时就会发生pe错误，一个低效的改进写法见后面 		if (sea_num(listt, list->value) != NULL) 			list1 = del_num(list1, list->value); 	} 	return list1; }  改进后 node * cj2(node *list, 	node * 	listt) { //思路：在第一个链表中将两个链表中的共同元素去掉，但是每次调用del_num时,free函数会出错 	node *list1 = list; 	for (; list != NULL; list = list->next) { 		if (sea_num(listt, list->value) != NULL) { 			list1 = del_num(list1, list->value); 			list = list1; 		} 	} 	return list1; } 多谢您的指点，我以后会注意逻辑问题的


Question: 中缀表达式转后缀表达式

中缀表达式（如：-A+B-C+D)，求后缀表达式，遇到负数，可以这么处理。 第一种： 遇到“-”时，先判断是负号还是减号： 1. 如果上一个符号是 “（”，那么是负号。 2. 如果上一个符号是“）”，那么是减号。 3. 如果是表达式的第一个符号，那么是负号。 4. 如果上一符号是运算符，那么是负号。 5. 如果上一个符号是数字，那么是减号。  判断后，如果是负号，则连同后面的数字，一并当成数字处理。 特殊情况  -(-A) + B，如果“-”是第一个符号，并且后面是"("，则需要追加处理，继续重复上面的处理。如之前那种情况，最后判断为A（正） 如果是减号，则当成符号处理。  第二种： 这种比较简单啦，像第一种一样判断，是负号还是减号。如果是负号，先插入一个数字0，然后把该负号当成”减号“一样处理即可。   之后，延用后缀表达式的常规求法（这块资料很多了）。

引用 2 楼 a3192048的回复:后缀为：A-B+C-D+ 1）如果遇到数字，我们就直接将其输出。  2）如果遇到操作符，则我们将其放入到栈中，遇到左括号时我们也将其放入栈中。  3）如果遇到一个右括号，则将栈元素弹出，将弹出的操作符输出直到遇到左括号为止。注意，左括号只弹出并不输出。  4）如果遇到任何其他的操作符，如（“+”， “*”，“（”）等，从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后，才将遇到的操作符压入到栈中。有一点需要注意，只有在遇到" ) "的情况下我们才弹出" ( "，其他情况我们都不会弹出" ( "。  5）如果我们读到了输入的末尾，则将栈中所有元素依次弹出。 能细说一下这题关于手工算法的步骤吗

为什么要处理负号，他还是个数啊！


Question: 代码就是运行不对，感觉有部分代码没有运行，大神求教！！

单步跑一遭不就好了。。  总觉得有拼音命名。。那个zongt  真是逼死码农

引用 16 楼 Slzde_sub 的回复:你把abs 。改成  fabs      bu昨晚终于弄好了。。 #include<stdio.h> #include<math.h> int zongt; struct cnc                //用结构体数组定义机床  	{ 		int ready;       //状态判断量，1为正在工作  		int loc;        //位置参数 1-4  		int num;        //CNC加工过的材料数量  		int tr;         //RGV小车上下料时间  		int tq;         //CNC加工材料所需时间  		int t;          //CNC自身携带的计时器       }cnc[9];   struct rgv                 //用结构体定义引导车      {     	int ready;        //状态判断量，1为正在工作      	int loc;          //位置参数 1-4     	int tg;           //RGV洗料的时间   	}rgv;    int max(int x,int y)        //寻找最大值函数  { 	int z=0; 	if(x>y) 	z=x; 	else 	z=y; 	return (z); }  int loc(int r)              //计算rgv用于移动的时间，r为rgv和某个cnc之间的位置参数的差  {  	int t1=20,t2=33,t3=46,u=0;     //t1~t3为对应移动1~3个单位所需要的时间  	switch(r) 	{ 		case 0:u=0;break;  		case 1:u=t1;break; 		case 2:u=t2;break; 		case 3:u=t3;break;  	};  	return (u); }    int main() { 	int loc(int r);                   //声明函数loc()  	int max(int x,int y);             //声明函数max  	int m,q,i,j,p,k,tam,sum=59,ta[9];      	 struct  cnc cnc[9]={{0,0,0,0,0,0},{1,1,0,28,560,296},      //结构体数组cnc参数初始化（人为将表1数据输入）  	  {1,1,0,31,560,268},{1,2,0,28,560,217},                      	  {1,2,0,31,560,189},{1,3,0,28,560,138},{1,3,0,31,560,110}, 	  {1,4,0,28,560,58},{1,4,0,31,560,31}}; 	  struct rgv rgv={0,1,25};             //结构体rgv参数初始化  	  printf("cnc[1]:%d %d %d %d %d %d\ncnc[2]:%d %d %d %d %d %d\ncnc[3]:%d %d %d %d %d %d\ncnc[4]:%d %d %d %d %d %d\ncnc[5]:%d %d %d %d %d %d\ncnc[6]:%d %d %d %d %d %d\ncnc[7]:%d %d %d %d %d %d\ncnc[8]:%d %d %d %d %d %d\n", 			  cnc[1].loc,cnc[1].num,cnc[1].ready,cnc[1].t,cnc[1].tq,cnc[1].tr, 			  cnc[2].loc,cnc[2].num,cnc[2].ready,cnc[2].t,cnc[2].tq,cnc[2].tr, 			  cnc[3].loc,cnc[3].num,cnc[3].ready,cnc[3].t,cnc[3].tq,cnc[3].tr, 			  cnc[4].loc,cnc[4].num,cnc[4].ready,cnc[4].t,cnc[4].tq,cnc[4].tr, 			  cnc[5].loc,cnc[5].num,cnc[5].ready,cnc[5].t,cnc[5].tq,cnc[5].tr, 			  cnc[6].loc,cnc[6].num,cnc[6].ready,cnc[6].t,cnc[6].tq,cnc[6].tr, 			  cnc[7].loc,cnc[7].num,cnc[7].ready,cnc[7].t,cnc[7].tq,cnc[7].tr, 			  cnc[8].loc,cnc[8].num,cnc[8].ready,cnc[8].t,cnc[8].tq,cnc[8].tr);          printf("rgv:%d %d %d\n",rgv.loc,rgv.ready,rgv.tg);  	for(zongt=0;zongt<=28800;) 	{  		for(j=1;j<=8;j++) 		{  		 k=abs(cnc[j].loc-rgv.loc); 		 m=(max(cnc[j].tq-cnc[j].t,loc(k))); 		 ta[j]=(m+cnc[j].tr+rgv.tg); 	     }; 	     tam=ta[1]; 	     p=1; 	    for(i=1;i<=8;i++) 	    { 	    	if(tam>ta[i]) 	    	 { 			  tam=ta[i]; 			  p=i; 		     }; 		}; 		 cnc[p].num++; 	     rgv.loc=cnc[p].loc; 		printf("目标工作台：%d  所需时间：%d s 该工作台已加工数:%d\n",p,tam,cnc[p].num);	 		rgv.ready=1;  	    cnc[p].ready=1; 	    zongt+=tam; 	    for(j=1;j<=8;j++) 	    { 	    	cnc[j].t=tam+cnc[j].t; 	    	if(cnc[j].t>=(cnc[j].tq+cnc[j].tr)) 	      { 	      	cnc[j].t+=tam; 		    cnc[j].ready=0; 		    cnc[j].t=(cnc[j].t-(cnc[j].tq+cnc[j].tr));  		  }; 		}; 		for(j=1;j<=8;j++) 		{  		if(cnc[j].t>=(cnc[j].tq+cnc[j].tr)) 	      { 		    cnc[j].ready=0; 		    cnc[j].t=(cnc[j].t-(cnc[j].tq+cnc[j].tr));  		  }; 	     }; 	}; 	for (j=1;j<=8;j++) 	{ 		sum+=cnc[j].num; 	};  	  printf("总耗时为：%d\n成料总数量：%d\n",zongt,sum);      return 0; }      结果基本过的去吧  万分感谢！！！！

引用 14 楼 Slzde_sub 的回复:草。。知道错误了。。。我顺手把那个error改掉了    c语言里要用fabs   不能用abs额，我之前就是在dev c++ 跑的，出来的结果就是和您一样。。好吧，估计是我算法有问题。。不应该是每次目标工作台都是0的。。所需时间也不对。。每次好像计算的那个ta[j]是一个定值，然后导致输出的就一直是一样的。。。这个问题是不是不属于编程上的问题了。。

引用 9 楼 Slzde_sub 的回复:稍等。。我只能用眼睛看    我只有一台mbp现在。。我的注释可能不全，如果方便的话，我们可以微信或者QQ交流

引用 9 楼 Slzde_sub 的回复:稍等。。我只能用眼睛看    我只有一台mbp现在。。好的，没事，我今晚估计要通宵了。。。时刻等着您！

引用 6 楼 Slzde_sub 的回复:  我身边没有可调试的电脑  你把for循环的zongt<=288...什么的   改成zongt<=1试试  看看最后那句 。总耗时能不能输出  如果可以的话  。。。另说额，还是不能输出那个总耗时。。。

引用 6 楼 Slzde_sub 的回复:  我身边没有可调试的电脑  你把for循环的zongt<=288...什么的   改成zongt<=1试试  看看最后那句 。总耗时能不能输出  如果可以的话  。。。另说好的，不管怎样，先把分给你，多谢啦！！！

引用 3 楼 Slzde_sub 的回复:单步跑一遭不就好了。。  总觉得有拼音命名。。那个zongt  真是逼死码农你好，能给个联系方式，帮下忙吗，我们在做数学建模，跪谢。。

额，我调试的时候就会出现这个

用vc++6.0运行出来的结果是这样的，感觉主函数的循环就没有执行。。。。

在线等，急！！！


Question: 陈越姥姥的数据结构试验指导案例2-3疑问

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

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

不怎么用VS编程，对*_s系列函数不熟，于是我改为原版的scanf, sprintf，运行正常（我指的是没有出错，不过结果估计不是你想要的），代码如下 #include<stdio.h> #include<string.h>  #define MAXN 30 #define MAXSTRING 64  int count; void search(int remainder, int start, char *sTerms);  main() {     char sTerms[MAXSTRING]="";     int n;      scanf("%d", &n);     sprintf(sTerms, "%d=", n);     search(n, 1, sTerms);     if (count % 4 != 0)         printf("\n"); }  void search(int remainder, int start, char *sTerms) {     char sTmp[MAXSTRING];     strcpy(sTmp, sTerms);     for (int i = start; i <= remainder; i++) {         if (remainder - i >= i) {             printf("%d\n", strlen(sTerms));             sprintf(sTmp + strlen(sTerms), "%d+", i);             search(remainder - i, i, sTmp);         }         else {             printf("%d\n", strlen(sTerms));             sprintf(sTmp + strlen(sTerms), "%d", i);             count++;             if (count % 4 != 1)                 printf(";");             printf("%s", sTmp);             if (count % 4 == 0)                 printf("\n");             return;         }     } } 所以我估计问题出在微软的应该是sprintf_s这个函数。在debug时，问题是出现在search函数返回时，我估计是跟你的sprintf_s写法有关，参考一下以下几个百度百科的例子 j = sprintf_s( buffer, 200, " String: %s\n", s ); j += sprintf_s( buffer + j, 200 - j, " Character: %c\n", c ); j += sprintf_s( buffer + j, 200 - j, " Integer: %d\n", i ); j += sprintf_s( buffer + j, 200 - j, " Real: %f\n", fp ); 你就会猜到 sprintf_s(sTmp + strlen(sTerms), MAXSTRING, "%d", i); 这种拷贝的方法，使得sTmp[MAXSTRING]总共长度为MAXSTRING（64）的字符数组，在拷贝的过程中长度变成了MAXSTRING+strlen(sTerms)，肯定越界，不知道是不是search函数调用结束，临时变量sTmp[MAXSTRING]在销毁时，系统发现其越界，所以报错？总之，我的意思是，你把sprintf_s(sTmp + strlen(sTerms), MAXSTRING, "%d+", i);对应的都修改为 sprintf_s(sTmp + strlen(sTerms), MAXSTRING-strlen(sTerms), "%d+", i);保持sTmp 的总长度为MAXSTRING，则程序就能正常运行了。

其实算起来程序本身没有问题，数据溢出，算是外在因素导致的。上面说的

不过MAXSTRING定义了64确实是有点小，如果我输入的值超过30，例如，31就又挂了。  另外 	sprintf_s(sTerms, 3, "%d=", n);这里3也小了，只能输入10以内的数（因为算上'\0'，刚好3位），所以如果输入的数字超过10，这里也要相应调整，如果是两位数的话，这里就至少应该是4，三位数则至少应该是5，以此类推。


Question: MATLAB slice函数的问题

xyzd必须大小相同


Question: 求大神帮忙，多线程下 malloc（） ：memory corruption

查看你的编译器malloc是否线程安全


Question: 关于数学建模

人民币一个亿怎么赚？

你所说的边界值指的是什么？温度高低的极限值吗？说一下具体的需求吧

条件有些欠缺

这个没有上下文，很难说啊。


Question: 求助，if条件判断执行不了，请问那里有问题？3个条件判断。

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

引用 10 楼 zangfong 的回复：unsigned char bufscdy[16]; unsigned char bufscdl[16]; unsigned char bufscdwd[16];改成 unsigned int bufscdy[16]; unsigned int bufscdl[16]; unsigned int bufscdwd[16];试试？意思是定义成16位类型，我晚上试试，谢谢。

看了你的源代码，我觉得应该不是if判断的问题，应该是出在你的get_ad函数里。 你看下，你定义的unsigned char bufscdy[16];那么bufscdy也就1个字节，但你后来还是准备塞2个字节 （bufscdl[l]=ADRESH*256+ADRESL;） 所以我猜会不会是因为这个原因，所以你获得的 bufscdl都没有获取到你想要的结果，所以if判断才只能走else？ unsigned char bufscdl[16]; unsigned char bufscdwd[16]; 也是同理。 引用 6 楼 qq_32339877 的回复:#include <pic.h> __CONFIG(HS&WDTDIS&LVPDIS); #define GONGZUO RD0 #define CHONGDIAN RD1 #define GUANJI RD2 #define JIANGGONGLV RD3 #define JIANGDIBAOHUDIANLIU RD4 void Delay(unsigned int i) {       unsigned int k;       for(k=0;k<i;k++); } void init() {      TRISA=0b11111111;      TRISD=0b00000000;      PORTA=0b00000000;      PORTD=0b00000000;      ADCON1=0b10000000;      ADIE=0; } unsigned int get_ad(unsigned char m) { if(m==0) { unsigned char bufscdy[16]; unsigned char j; unsigned int ADbufscdy; for(j=0;j<16;j++) {      ADCON0=0b00000001;      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      ADGO=1;      while(ADGO) continue;      bufscdy[j]=ADRESH*256+ADRESL; }      ADbufscdy=0;     for(j=0;j<16;j++) {      ADbufscdy+=bufscdy[j]; }      ADbufscdy=ADbufscdy/16;      return(ADbufscdy); } else if(m==1) { unsigned char bufscdl[16]; unsigned char l; unsigned int ADbufscdl; for(l=0;l<16;l++) {      ADCON0=0b00001001;      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      ADGO=1;      while(ADGO) continue;      bufscdl[l]=ADRESH*256+ADRESL; }      ADbufscdl=0;     for(l=0;l<16;l++) {      ADbufscdl+=bufscdl[l]; }      ADbufscdl=ADbufscdl/16;      return(ADbufscdl); } else if(m==2) { unsigned char bufscdwd[16]; unsigned char t; unsigned int ADbufscdwd; for(t=0;t<16;t++) {      ADCON0=0b00010001;      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      asm("NOP");      ADGO=1;      while(ADGO) continue;      bufscdwd[t]=ADRESH*256+ADRESL; }      ADbufscdwd=0;     for(t=0;t<16;t++) {      ADbufscdwd+=bufscdwd[t]; }      ADbufscdwd=ADbufscdwd/16;      return(ADbufscdwd); } } void main(void) {       unsigned int scdy;       unsigned int scdl;       unsigned int wd;      init(); while(1) {      scdy=get_ad(0);          scdl=get_ad(1);      wd=get_ad(2);     if(scdl > 6)     {         if(scdy<=860)         {             if(wd <= 820)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=0;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else if(wd > 909)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=0;                 JIANGGONGLV=1;                 JIANGDIBAOHUDIANLIU=1;             }         }         else         {             if(wd <= 820)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else if(wd > 909)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=1;                 JIANGDIBAOHUDIANLIU=1;             }         }      }     else     {         CHONGDIAN=0;         GONGZUO=1;         GUANJI=0;         JIANGGONGLV=0;         JIANGDIBAOHUDIANLIU=0;     } } } 这是我全部的程序，大致意思是3个AD转换的结果出来，判断，符合什么条件就执行什么语句。我目前是用ISIS仿真软件仿真的，结果都不是想要的结果。各位大神看看我这程序那里要改的。万分感谢。

引用 1 楼 zangfong 的回复：我试了下，你这段代码也可以运行的呀。你自己再调试一下看看。另外，作为强迫症患者，帮你整理了一下，不知道有没有复制粘贴错：     if(scdl > 6)     {         if(scdy<=860)         {             if(wd <= 820)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=0;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else if(wd > 909)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=0;                 JIANGGONGLV=1;                 JIANGDIBAOHUDIANLIU=1;             }         }         else         {             if(wd <= 820)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else if(wd > 909)             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=0;                 JIANGDIBAOHUDIANLIU=1;             }             else             {                 CHONGDIAN=1;                 GONGZUO=0;                 GUANJI=1;                 JIANGGONGLV=1;                 JIANGDIBAOHUDIANLIU=1;             }         }      }     else     {         CHONGDIAN=0;         GONGZUO=1;         GUANJI=0;         JIANGGONGLV=0;         JIANGDIBAOHUDIANLIU=0;     }谢谢，指导，但是我改成你写的还是不执行，每次到if判断就直接跳过，跳到else这里执行里面的语句。

这种写法我也写过，但是我通过ISIS仿真，仿真不出我要的结果。

先不说你的语句有么有问题，我们就先说你的逻辑吧，你设计的逻辑是存在很大的问题的，区分不清楚，在判断的时候多次重复“scdl>6&&scdy>860”，这样会使程序出现不必要的运行，也会使你的思维逻辑出现错误（也就是思维误区），if语句是可以嵌套的， 你可以一个一个区分的，优化代码我帮你整理了，这样的话就可以根据语句的结构来识别思维逻辑。程序是一小部分，思维逻辑是一大部分。 if(scdl>6) 	{ 		if(scdy<=860) 		{ 			if(wd<=820) 			{  			}else if(820<wd&&<=909) 			{ 				CHONGDIAN=1; 				GONGZUO=0; 				GUANJI=0; 				JIANGGONGLV=1; 				JIANGDIBAOHUDIANLIU=1; 			}else 			{ 				CHONGDIAN=1; 				GONGZUO=0; 				GUANJI=1; 				JIANGGONGLV=0; 				JIANGDIBAOHUDIANLIU=1; 			} 		}else 		{ 			if(wd<=820) 			{ 				CHONGDIAN=1; 			    GONGZUO=0; 				GUANJI=1; 				JIANGGONGLV=0; 				JIANGDIBAOHUDIANLIU=1; 			}else if(820<wd&&<=909) 			{ 				CHONGDIAN=1; 				GONGZUO=0; 				GUANJI=1; 				JIANGGONGLV=1; 				JIANGDIBAOHUDIANLIU=1; 			}else 			{ 				CHONGDIAN=1; 				GONGZUO=0; 				GUANJI=1; 				JIANGGONGLV=0; 				JIANGDIBAOHUDIANLIU=1; 			} 		} 	}else 	{ 		CHONGDIAN=0; 		GONGZUO=1; 		GUANJI=0; 		JIANGGONGLV=0; 		JIANGDIBAOHUDIANLIU=0; 	}

建议把数字换成enum或者define，magic number对理解不好。

条件不符合当然不执行 你是想实现如下？ if(scdl>6) {   if(scdy<=860)   {     if(wd...)...   }   else   {     if(wd ...)...   } } else { }


Question: 求该算法题的C语言编程，大佬帮帮忙，写不下去了，要能运行的

先扫描一次，将数据转换成连续D或者连续A的个数： DADDA -> 1121 然后依次从每个点计算最大连续串数 a0：1+1+2=4 a1：1+1=2 a2：2+1=3 a3：1   AAADDAADADA  2 —> 3221111 a0：3+2+2=7 a1：2+2+1=5 a2：2+1+1+1+1=6 a3：1+1+1+1=4 a4：1+1+1=3 a5：1+1=2 a6：1

是最大连续子序列问题。 A D可以简化成 把两种怪物理解为 1  -1 ，改变怪兽的状态可以理解为 初始值或者补偿值。  所以就是 求  1，-1，1，1    中加上初始值（查A为正值 查D为负值）的最大值或者最小值。  核心思想就是 当统计和从负到正 或者从正到负【楼上所说的翻转】，则证明之前统计的和可以舍弃。

嗯嗯，还不是太懂。。。。。

整个算法思想和过程如下：  选取连续的一个序列，当A或者B中一方个数较小=M，那么就暂停。 这种情况，只要反转较小数量的一方那么它们必定是连续相同的。 在此基础上，还需要判断第一个后续是否符合要变的，如果是那么就把它归到序列中，以此类推，直到不符合时停止。 ， 举例 DADDAAD，仅有反转1次。 第一步选取连续的串变为：DADDAAD 第二步，判断第一后续即DAD，D 因为选取的序列中A和D数量相同，不管反转哪一方，都可以，那我就把D归到序列中。但是此刻D较多，即为反转后的一方 继续前进DADD，D满足反转后一方，那么归到序列中 继续前进DADDA，A不符合，停止。  最终序列为DADD，4个数。  下一次循环，从索引1开始检查……直到选取的序列未索引能到达整个序列的末尾  引用 2 楼 hehuiui 的回复:你好，那个你是如何判断M的，就是要修改几个。

看起来像是求最大连续子数列的问题

你好，那个你是如何判断M的，就是要修改几个。

仅供参考 #include <stdio.h> #include <string.h>  int main() {     int N = 0, M = 0;     char buf[1024] = { 0 };     int len;     int maxHP = 0;     int start = 0, end;     int DN = 0, AN = 0;     int tmp;      scanf("%d", &N);     scanf("%d", &M);     if (N < M)     {         printf("Input error.\n");         return 0;     }      scanf("%s", buf);     len = strlen(buf);      if (len != N)     {         printf("Input error.\n");         return 0;     }      tmp = 0;     while (tmp < len)     {         if (buf[tmp] != 'D' && buf[tmp] != 'A')         {             printf("Input error.\n");             return 0;         }         ++tmp;     }      while (start < len)     {         end = start;          DN = 0, AN = 0;         for (; end < len; ++end)         {             if (buf[end] == 'D')                 ++DN; // 统计D个数             else                 ++AN; // 统计A个数             if ((DN > AN ? AN : DN) == M) // 如果连续串中D和A个数最小等于M，那么立即停止                 break;         }          if (DN < AN) // 反转D->A的情况         {             tmp = 'A';         }         else if (DN > AN) // 反转A->D的情况         {             tmp = 'D';         }         else // DN == AN，随便反转的情况         {             tmp = 0;         }          // 统计更后续的字符是否符合情况         while (++end < len)         {             if (tmp == 0 || tmp == buf[end])             {                 tmp = buf[end];             }             else             {                 break;             }         }          if (end - start > maxHP) // 此串更长，更新最大HP值         {             maxHP = end - start;         }          // 如果end已经能查找到最后，终止轮询。（继续轮询无意义，因为查找的值将不可能大于maxHP）         if (end >= len)         {             break;         }          ++start;     }      printf("%d\n", maxHP);      return 0; }


Question: 为什么很多自定义的类型，还要用typedef定义一个 _t的类型别名

原来声明时、需要写struct关键字。现在不需要了。当成class用就可以了。

在之前的c版本中， 定义一个结构体 struct sender 之后，使用的时候 必须要写上 struct sender m_sender，为了简洁易懂，就使用typedef struct sender sender_t; 给他一个别名，用的时候 直接sender_t m_sender就可以了，现在c++中，哪怕你不定义别名，不写struct也可以了，在一个，定义成自己喜欢用起来方便的名字，省很多力气


Question: for循环初始化无效

emmmmmm你少打了个“=”


Question: for循环初始化无效

我调试了下你的代码，你说的奇怪的数字，其实是临时变量kk被声明之后，尚未初始化时从内存中读取的乱码，其后kk就被初始化为0了，但是你的for循环中                             for(int kk=0;kk<c;kk++){                                 arr[i][kk]==0;                             } arr[i][kk]==0;不是赋值，而是比较。结果程序在编译的过程中做了优化，arr[i][kk]==0;这句就优化没了（具体你可以看下汇编代码），所以for循环没有执行体，就直接运行完了，然后就执行后面的代码去了。 你把arr[i][kk]==0;改成arr[i][kk]=0;就可以正常调试了。 你的函数第82行也有这个问题                             for(int j=0;j<r;j++){                                 arr[j][i]==0;                             }


Question: 根据数组顺序进行排序。

基本就是这个意思。这样就有思路了，谢谢了，请问C语言怎么学那，怎么有自己的思维方式。

你的意思是这样？ #include<stdio.h> #include<stdlib.h> #include<string.h>  #define MAX_SIZE 100  char buf[MAX_SIZE];  char ttime[] = "23:00"; char tdate[] = "2018-09-14"; char tweek[] = "FRIDAY";  int order1[3] = {2,3,1}; int order2[3] = {3,1};  void test(int *ord) {     int i;     for(i = 0; i < 3; i++)     {         switch(ord[i]){         case 1:             strcat(buf,tdate);strcat(buf," ");break;         case 2:             strcat(buf,ttime);strcat(buf," ");break;         case 3:             strcat(buf,tweek);strcat(buf," ");break;         default:break;         }     } }   int main() {     memset(buf,0,sizeof(buf));     test(order1);     printf("%s\n",buf);     memset(buf,0,sizeof(buf));     test(order2);     printf("%s\n",buf);     return 0; }

是这个意思，我需要根据order[3]中的顺序对三个字符进行排序，假如order[3] = {3, 1, 2},顺序则是星期  日期 时间， order[3] = {2, 1};则是时间 日期，星期不显示；（为0代表不显示），就是这样的； 还要调用sprintf打印出来； 一个项目中的一个小的需求。


Question: C函数运行时地址

引用 6 楼 zxc024000 的回复:Ubuntun gcc5.4，尝试了一下上述程序。输出的main地址，以及objdump出的地址，都是统一的。  这类东西，应该跟编译器（g++/gcc)自身有关。比如clang和gcc/g++，对c++的优化就有很多差别。  建议看看gcc7列出的改动的地方吧。 https://gcc.gnu.org/gcc-7/changes.html 挺好的，不错可以看看。

引用 6 楼 zxc024000 的回复:Ubuntun gcc5.4，尝试了一下上述程序。输出的main地址，以及objdump出的地址，都是统一的。  这类东西，应该跟编译器（g++/gcc)自身有关。比如clang和gcc/g++，对c++的优化就有很多差别。  建议看看gcc7列出的改动的地方吧。 https://gcc.gnu.org/gcc-7/changes.html附加的链接资源不错

引用 7 楼 DelphiGuy 的回复:跟操作系统有关，较新的操作系统普遍使用一种安全技术，称之为 Address Space Layout Randomization (ASLR)，每次加载可执行文件（.exe、.dll之类的）都放在一个随机起始地址，甚至操作系统核心，每次启动时也加载到随机地址（都是一个范围，不是任意的），而不是固定地址。这样做是为了防止恶意程序针对缺陷代码进行攻击。 addr2line版本没跟上？

引用 7 楼 DelphiGuy 的回复:跟操作系统有关，较新的操作系统普遍使用一种安全技术，称之为 Address Space Layout Randomization (ASLR)，每次加载可执行文件（.exe、.dll之类的）都放在一个随机起始地址，甚至操作系统核心，每次启动时也加载到随机地址（都是一个范围，不是任意的），而不是固定地址。这样做是为了防止恶意程序针对缺陷代码进行攻击。 防君子防不了小人； 防菜鸟防不了大神。

可以了解下虚拟地址

引用 3 楼 misskissC 的回复:[quote=引用 2 楼 misskissC 的回复:] [quote=引用 1 楼 user-6 的回复:] 这种地址是随机的我的疑问： [1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解，问题在于 跟其配套的addr2line没法使用该随机地址。 [2] 期待您给结论附个原因  另外，比如在centos上，就不存在这个问题。 /* gcc version 4.8.5 (Red Hat 4.8.5-28) */ #include <stdio.h>   int main(void) {     return printf("main=%p\n", main); }  gcc main.c -o main ./main 0x40051d  ./main 0x40051d  ./main 0x40051d  objdump -ds main  000000000040051d <main>:  ....  addr2line -e main 0x40051d -f main ??:?  [/quote]  Linux下查看 进程 虚拟地址空间：  #include <stdio.h>  int main(void) {     printf("main=%p\n", main);     while (1);     return 0; }   gcc vaddr.c -o vaddr ./vaddr & main=0x55be8d47264a [1] 1798  cat /proc/1798/maps 55be8d472000-55be8d473000 r-xp 00000000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d672000-55be8d673000 r--p 00000000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d673000-55be8d674000 rw-p 00001000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d963000-55be8d984000 rw-p 00000000 00:00 0                          [heap] 7f1c8e21e000-7f1c8e405000 r-xp 00000000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e405000-7f1c8e605000 ---p 001e7000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e605000-7f1c8e609000 r--p 001e7000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e609000-7f1c8e60b000 rw-p 001eb000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e60b000-7f1c8e60f000 rw-p 00000000 00:00 0 7f1c8e60f000-7f1c8e636000 r-xp 00000000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e822000-7f1c8e824000 rw-p 00000000 00:00 0 7f1c8e836000-7f1c8e837000 r--p 00027000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e837000-7f1c8e838000 rw-p 00028000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e838000-7f1c8e839000 rw-p 00000000 00:00 0 7ffe47da3000-7ffe47dc4000 rw-p 00000000 00:00 0                          [stack] 7ffe47dd7000-7ffe47dda000 r--p 00000000 00:00 0                          [vvar] 7ffe47dda000-7ffe47ddc000 r-xp 00000000 00:00 0                          [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]   killall -9 vaddr[/quote]  自己根据/proc/pid/maps写一个 根据虚拟地址 得到进程  在该地址上函数名吧

引用 2 楼 misskissC 的回复:[quote=引用 1 楼 user-6 的回复:] 这种地址是随机的我的疑问： [1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解，问题在于 跟其配套的addr2line没法使用该随机地址。 [2] 期待您给结论附个原因  另外，比如在centos上，就不存在这个问题。 /* gcc version 4.8.5 (Red Hat 4.8.5-28) */ #include <stdio.h>   int main(void) {     return printf("main=%p\n", main); }  gcc main.c -o main ./main 0x40051d  ./main 0x40051d  ./main 0x40051d  objdump -ds main  000000000040051d <main>:  ....  addr2line -e main 0x40051d -f main ??:?  [/quote]  Linux下查看 进程 虚拟地址空间：  #include <stdio.h>  int main(void) {     printf("main=%p\n", main);     while (1);     return 0; }   gcc vaddr.c -o vaddr ./vaddr & main=0x55be8d47264a [1] 1798  cat /proc/1798/maps 55be8d472000-55be8d473000 r-xp 00000000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d672000-55be8d673000 r--p 00000000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d673000-55be8d674000 rw-p 00001000 08:01 264241                     /home/lgt/workspace/vaddr/vaddr 55be8d963000-55be8d984000 rw-p 00000000 00:00 0                          [heap] 7f1c8e21e000-7f1c8e405000 r-xp 00000000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e405000-7f1c8e605000 ---p 001e7000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e605000-7f1c8e609000 r--p 001e7000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e609000-7f1c8e60b000 rw-p 001eb000 08:01 1185760                    /lib/x86_64-linux-gnu/libc-2.27.so 7f1c8e60b000-7f1c8e60f000 rw-p 00000000 00:00 0 7f1c8e60f000-7f1c8e636000 r-xp 00000000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e822000-7f1c8e824000 rw-p 00000000 00:00 0 7f1c8e836000-7f1c8e837000 r--p 00027000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e837000-7f1c8e838000 rw-p 00028000 08:01 1185732                    /lib/x86_64-linux-gnu/ld-2.27.so 7f1c8e838000-7f1c8e839000 rw-p 00000000 00:00 0 7ffe47da3000-7ffe47dc4000 rw-p 00000000 00:00 0                          [stack] 7ffe47dd7000-7ffe47dda000 r--p 00000000 00:00 0                          [vvar] 7ffe47dda000-7ffe47ddc000 r-xp 00000000 00:00 0                          [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]   killall -9 vaddr

引用 1 楼 user-6 的回复:这种地址是随机的我的疑问： [1] 跟 附 中的内容还是有关系的哈。虚拟地址是随机的完全可以被理解，问题在于 跟其配套的addr2line没法使用该随机地址。 [2] 期待您给结论附个原因  另外，比如在centos上，就不存在这个问题。 /* gcc version 4.8.5 (Red Hat 4.8.5-28) */ #include <stdio.h>   int main(void) {     return printf("main=%p\n", main); }  gcc main.c -o main ./main 0x40051d  ./main 0x40051d  ./main 0x40051d  objdump -ds main  000000000040051d <main>:  ....  addr2line -e main 0x40051d -f main ??:?

这种地址是随机的