Question: 这样申明函数，请问怎么区分两个参数

这不是声明，声明可以不要参数名。但定义函数体需要参数名。

函数原型（声明）可以不写参数名，只写参数类型。 定义函数体的时候要写全，不然你怎么使用参数（相当于局部变量）。

定义的时候，如果不使用函数参数，可以不定义参数名。 但是，需要使用的时候，必须定义参数名。

声明的时候应该可以省略，但是定义的时候不能省略吧!

省2个变量名，并不能显得代码有多高端和简洁

不使用的话可以你不用声明，如果使用必须声明变量名

C Function Definitions A function definition specifies the name of the function, the types and number of parameters it expects to receive, and its return type. A function definition also includes a function body with the declarations of its local variables, and the statements that determine what the function does.   Syntax  translation-unit :  external-declaration translation-unit external-declaration  external-declaration : /* Allowed only at external (file) scope */  function-definition declaration  function-definition : /* Declarator here is the function declarator */  declaration-specifiersopt attribute-seqopt declarator declaration-listopt compound-statement  /* attribute-seq is Microsoft Specific */  Prototype parameters are:  declaration-specifiers :  storage-class-specifier declaration-specifiers opt  type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt  declaration-list :  declaration declaration-list declaration  declarator :  pointeropt direct-declarator  direct-declarator : /* A function declarator */   direct-declarator ( parameter-type-list ) /* New-style declarator */ direct-declarator ( identifier-list opt ) /* Obsolete-style declarator */  The parameter list in a definition uses this syntax:   parameter-type-list : /* The parameter list */  parameter-list parameter-list , ...  parameter-list :  parameter-declaration parameter-list , parameter-declaration  parameter-declaration :  declaration-specifiers declarator declaration-specifiers abstract-declarator opt  The parameter list in an old-style function definition uses this syntax:  identifier-list : /* Used in obsolete-style function definitions and declarations */  identifier identifier-list , identifier  The syntax for the function body is:  compound-statement : /* The function body */   { declaration-list opt statement-list opt }  The only storage-class specifiers that can modify a function declaration are extern and static. The extern specifier signifies that the function can be referenced from other files; that is, the function name is exported to the linker. The static specifier signifies that the function cannot be referenced from other files; that is, the name is not exported by the linker. If no storage class appears in a function definition, extern is assumed. In any case, the function is always visible from the definition point to the end of the file.   The optional declaration-specifiers and mandatory declarator together specify the function’s return type and name. The declarator is a combination of the identifier that names the function and the parentheses following the function name. The optional attribute-seq nonterminal is a Microsoft-specific feature defined in Function Attributes.   The direct-declarator (in the declarator syntax) specifies the name of the function being defined and the identifiers of its parameters. If the direct-declarator includes a parameter-type-list, the list specifies the types of all the parameters. Such a declarator also serves as a function prototype for later calls to the function.   A declaration in the declaration-list in function definitions cannot contain a storage-class-specifier other than register. The type-specifier in the declaration-specifiers syntax can be omitted only if the register storage class is specified for a value of int type.   The compound-statement is the function body containing local variable declarations, references to externally declared items, and statements.   The sections Function Attributes, Storage Class, Return Type, Parameters, and Function Body describe the components of the function definition in detail.

Function Prototypes A function declaration precedes the function definition and specifies the name, return type, storage class, and other attributes of a function. To be a prototype, the function declaration must also establish types and identifiers for the function’s arguments.   Syntax  declaration :  declaration-specifiers attribute-seq opt init-declarator-list opt ;  /* attribute-seqopt is Microsoft Specific */   declaration-specifiers :  storage-class-specifier declaration-specifiers opt type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt  init-declarator-list :  init-declarator init-declarator-list , init-declarator  init-declarator :  declarator declarator = initializer  declarator :  pointer opt direct-declarator  direct-declarator : /* A function declarator */   direct-declarator ( parameter-type-list )      /* New-style declarator */ direct-declarator ( identifier-list opt )    /* Obsolete-style declarator */  The prototype has the same form as the function definition, except that it is terminated by a semicolon immediately following the closing parenthesis and therefore has no body. In either case, the return type must agree with the return type specified in the function definition.   Function prototypes have the following important uses:   They establish the return type for functions that return types other than int. Although functions that return int values do not require prototypes, prototypes are recommended.   Without complete prototypes, standard conversions are made, but no attempt is made to check the type or number of arguments with the number of parameters.   Prototypes are used to initialize pointers to functions before those functions are defined.    The parameter list is used for checking the correspondence of arguments in the function call with the parameters in the function definition.  The converted type of each parameter determines the interpretation of the arguments that the function call places on the stack. A type mismatch between an argument and a parameter may cause the arguments on the stack to be misinterpreted. For example, on a 16-bit computer, if a 16-bit pointer is passed as an argument, then declared as a long parameter, the first 32 bits on the stack are interpreted as a long parameter. This error creates problems not only with the long parameter, but with any parameters that follow it. You can detect errors of this kind by declaring complete function prototypes for all functions.  A prototype establishes the attributes of a function so that calls to the function that precede its definition (or occur in other source files) can be checked for argument-type and return-type mismatches. For example, if you specify the static storage-class specifier in a prototype, you must also specify the static storage class in the function definition.   Complete parameter declarations (int a) can be mixed with abstract declarators (int) in the same declaration. For example, the following declaration is legal:    int add( int a, int );  The prototype can include both the type of, and an identifier for, each expression that is passed as an argument. However, such identifiers have scope only until the end of the declaration. The prototype can also reflect the fact that the number of arguments is variable, or that no arguments are passed. Without such a list, mismatches may not be revealed, so the compiler cannot generate diagnostic messages concerning them. See Arguments for more information on type checking.  Prototype scope in the Microsoft C compiler is now ANSI-compliant when compiling with the /Za compiler option. This means that if you declare a struct or union tag within a prototype, the tag is entered at that scope rather than at global scope. For example, when compiling with /Za for ANSI compliance, you can never call this function without getting a type mismatch error:  void func1( struct S * );  To correct your code, define or declare the struct or union at global scope before the function prototype:  struct S; void func1( struct S * );  Under /Ze, the tag is still entered at global scope.

也可以老式K&R风格的声明： int func(a, b) {   return a + b; }

函数声明可以省略变量名，只需要写出类型就可以了。但是在函数定义中必须把类型和形参名都写出来。

函数实现时如果省略了参数名，那么表示函数中不引用参数的对象，如果函数中要使用参数，需要指定参数名

这不是声明，是原型。


Question: 计算三维数组并输出txt文件崩溃

引用 12 楼 qq_36738327 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] static  double u[Nx][Ny][Nt]={0},v; 在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。 #11亲测有效，学习了，非常感谢[/quote] Who am I！

引用 11 楼 zhao4zhong1 的回复:static  double u[Nx][Ny][Nt]={0},v; 在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。 #11亲测有效，学习了，非常感谢

没找到回复功能。。。只好直接引用楼号 #2：那个不好意思，我上过的C课程讲得比较初级，不了解栈溢出 #4#5：非常感谢，我会尝试一下 #6：这个是我的疏忽，拷贝matlab代码修改时不小心删多了，那个其实是Nx/2 #7：这个是我改代码时的问题，之前一直用matlab，下标是从1开始的，改成C时只考虑了前面的下标对后面没考虑充足 非常感谢以上几位的帮助，下面附上修改过错误的代码，我会尝试#4#5提供的方法是否能使程序崩溃情况消失。  #include<stdio.h> #include<math.h> #define xp 400 #define y1 100 #define y2 200 #define yp y1+y2 #define v1 200 #define v2 400 #define tp 0.75 #define dx 1 #define dy 1 #define dt 0.001 #define Nx 400 #define Ny 300 #define Nt 750 #define f 50 #define pi 3.14159 #define a v*dt/dx #define b dt*v #define Ric (1-2*(pi*f*k*dt)*(pi*f*k*dt))*exp(-(pi*f*k*dt)*(pi*f*k*dt)) void main() { 	int i,j,k; 	double u[Nx][Ny][Nt]={0},v; 	for(k=1;k<Nt-1;k++) 	{ 		for(j=1;j<Ny-1;j++) 		{ 			for(i=1;i<Nx-1;i++) 			{ 				if((i==Nx/2)&&(j==1)) 				{ 					if(j<=(y1/dy)) 					{ 						v=v1; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]+b*b*Ric; 					} 					else 					{ 						v=v2; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]+b*b*Ric; 					 					} 				} 				else 				{ 					if(j<=(y1/dy)) 					{ 						v=v1; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]; 					} 					else 					{ 						v=v2; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]; 					 					}  				} 			} 		} 	} 	FILE *fp; 	fp=fopen("D:\\u.txt","w"); 	for(i=0;i<Nx;i++) 	{ 		for(j=0;j<Ny;j++) 		{ 			for(k=0;k<Nt;k++) 			{ 				fprintf(fp,"%f ",u[i][j][k]); 			} 		} 	} 	fclose(fp); }

引用 8 楼 zhao4zhong1 的回复:5楼请注意，这是C语言论坛。new不属于C语言。  没注意这个，非要用纯C语言的话，那楼主就用malloc或者calloc吧。

5楼请注意，这是C语言论坛。new不属于C语言。

if(j<=(y1/dy)) 					{ 						v=v1; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]; 					} 					else 					{ 						v=v2; 						u[i][j][k+1]=a*a*(u[i+1][j][k]+u[i-1][j][k]+u[i][j+1][k]+u[i][j-1][k])+2*(1-2*a*a)*u[i][j][k]-u[i][j][k-1]; 					 					}  再有一个隐患就是： 循环里用k+1做下标，循环还用for(k=1;k<Nt;k++)，一旦k=Nt-1时，k+1就是Nt，u[i][j][Nt]，这不是数组越界吗？  这是运行隐患。在用循环变量在循环中做线性增减时，务必判断线性增长的值是否还在数组下标范围内。  楼主还要多多练习啊。代码经历还是太年轻。

for(i=1;i<Nx;i++) { 	if((i==Nx)&&(j==1))  再有你写的一个废话代码： 你代码里的这句永远不会是true，你的i永远小于Nx，怎么可能还会有i==Nx的机会呢？ i刚等于Nx时，立刻被i<Nx;条件判断出，从而退出循环。

//动态定义三维数组：   double *** u;   u = new double**[Nx] ;   for( i = 0 ; i < Nx ; i ++ )   { 	u[i] = new double*[Ny] ; } for( i = 0 ; i < Nx ; i ++ )   { 	for( j = 0 ; j < Ny ; j ++ )   	{ 		u[i][j] = new double[Nt] ; 	} } //输入三维数组值：   for(i = 0 ; i < Nx ; i ++ )   { 	for(j = 0 ; j < Ny ; j ++ )   	{ 		for( k = 0 ; k < Nt ; k ++)   		{ 			u[i][j][k] = 0.f; 		} 	} }

仅供参考：//在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------

单步调试下.

开这么大数组，栈溢出了，不知道吗？ 3维，400*300*750，超出了栈内存的大小。

1>------ 已启动生成: 项目: Ric, 配置: Debug Win32 ------ 1>  test01.c 1>e:\vc test\ric\ric\test01.c(85): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1>  c:\program files (x86)\windows kits\10\include\10.0.10240.0\ucrt\stdio.h(205): note: 参见“fopen”的声明 1>  Ric.vcxproj -> E:\vc test\Ric\Debug\Ric.exe 1>  Ric.vcxproj -> E:\vc test\Ric\Debug\Ric.pdb (Full PDB) ========== 生成: 成功 1 个，失败 0 个，最新 0 个，跳过 0 个 ==========


Question: c语言怎么求110度正切值?

包含math.h  然后可以使用里面的tan函数，不过参数是弧度制的

头文件:#include<math.h> 函数:tan(弧度值) 返回:x的正切值


Question: 宏定义的理解

引用 6 楼 qq_18310569 的回复:[quote=引用 3 楼 paschen 的回复:] 引用这一句的 (*(ADC_COFIN *)MN_BUFFER)是什么意思？  把MN_BUFFER这块buffer按ADC_COFIN 类型去解析得到的那个结构体  adc_stCofIn 就代表 (*(ADC_COFIN *)MN_BUFFER) (ADC_COFIN *)和   *(ADC_COFIN *)分别是什么意思呢？[/quote]  ADC_COFIN就是表示那个结构体，这不是宏，了解typedef用法  *(ADC_COFIN *)就是转换成ADC_COFIN *再解引

引用 3 楼 paschen 的回复:引用这一句的 (*(ADC_COFIN *)MN_BUFFER)是什么意思？  把MN_BUFFER这块buffer按ADC_COFIN 类型去解析得到的那个结构体  adc_stCofIn 就代表 (*(ADC_COFIN *)MN_BUFFER) (ADC_COFIN *)和   *(ADC_COFIN *)分别是什么意思呢？

这样不见得多好，万一MN_BUFFER空间不够，就会有越界的风险！想了解宏定义用法，推荐你看windows系统里各种库的头文件！

引用 2 楼 qq_18310569 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 理解和讨论之前请先学会如何观察！  VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898 能简单说一下嘛？[/quote] 很多时候，使用的工具越先进，人越笨；得到得越轻松，人越懒。

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


Question: 跪求大佬帮忙看一下这个代码 判断线性方程是否有唯一解，有什么不对？

边界条件 输入输出格式 ……

OJ有时候就是这样的，可以参考下别人AC的代码，然后看看区别。 多试一些测试用例，特别是边界条件

修改后提交，oj评分60。。。。。似乎是算法错误  #include<stdio.h> #include<stdlib.h> #include<string.h> void exchange_(double *a, double*b, const int n); double beishu(double a,const double b); void xiaoqu(double *a, double *b, double k, int n);  int main() { 	int n; 	int a, b; 	double ** p; 	scanf("%d", &n); 	p = (double**)malloc(sizeof(double*) * n);//为二维数组分配n行 	for (a = 0; a < n; a++) //为每行分配n+1个大小空间 	{ 		p[a] = (double*)malloc(sizeof(double) * n + 1); 	} 	for (a = 0; a < n; a++) 	{ 		for (b = 0; b < n + 1; b++) 		{ 			scanf("%lf", &p[a][b]); 			printf("\n"); 		} 	}//输入数组成功  	int i, j,t=0;//主元定位下标 	for (i = 0, j = 0; i < n - 1; i++, j++) 	{ 		a = i; 		while (p[a][j] == 0 && a < n) 		{ 			a = a + 1; 		} 		exchange_(p[a], p[i], n);//选出主元 		if (p[i][j] == 0) 		{ 			t=1; 			break;//存在自由变量 		} 		for (a = i + 1; a < n; a++)//分别处理主元下各行 		{ 			double k; 			if (p[a][j] == 0) 				continue; 			k = beishu(p[i][j], p[a][j]); 			xiaoqu(p[i], p[a], k, n); 		} 	}//化简完成 	if(t==1) 		printf("NO"); 	else { 		if (p[n - 1][n - 1] == 0) 			printf("NO"); 		else 		printf("YES"); 	} 	getchar(); 	getchar(); 	return 0; } void exchange_(double *a, double*b, const int n)//交换两行 { 	double  p; 	for (int i = 0; i < n + 1; i++) 	{ 		p = a[i]; 		a[i] = b[i]; 		b[i] = p; 	} }

if ... if 要改为 if ... else if ...

代码逻辑问题帮不到你，建议你在必要的地方设置断点，然后单步跟踪程序运行，观察每一步结果与你期望的是否一致

你的具体算法，我不了解哈，我不是数学家 但是如果看代码的话，你看看下面这一部分 if (p[n - 1][n - 1] == 0) printf("NO"); printf("YES");  当p[n - 1][n - 1] == 0时，先是打印“NO”，之后，不管什么条件又打印出来一个"YES"，这明显悖论啊！！！  最好在每一个if选择分支加上{。。。。}大括号进行区分  从代码51到58行，你自己好好想想。


Question: 求助：C函数字符串反转

有的系统把字符串常量存到设置为只读属性的内存段中

char *string = "abcdef"; 改成 char string[] = "abcdef";


Question: 如何从已有文件中读出数据，并且格式保持不变，用C语言编写的，大家给点意见呗

可以了结果是这样：  姓名	学号	语文	数学	英语 张明明 1.000000 67.000000 78.000000 82.000000 李成友 2.000000 78.000000 91.000000 88.000000   谢谢大神了，哈哈

谢谢，不过我试了一下还是不对。运行后是这样的结果：  姓名	学号	语文	数学	英语 张明明    0 1072693248    0 1079033856 李成友    0 1073741824    0 1079214080

你的studentID和3个score都是float的，应该用%f才对 fscanf(fp1,"%s%4d%4d%4d%4d",&S1[i].name, &S1[i].studentID, &S1[i].score.chinese,//按指定格式读出文件中数据 &S1[i].score.math, &S1[i].score.english);	 改成：  fscanf(fp1, "%s%4f%4f%4f%4f", &S1[i].name, 			&S1[i].studentID, 			&S1[i].score.chinese,//按指定格式读出文件中数据 			&S1[i].score.math, 			&S1[i].score.english);


Question: 文件输入输出。哪里错了？谢谢

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

你的文件不对。 改成这样：（不要带注释） 2 1 7  9 8

FILE *fin； 后面的分号你用成全角的，要英文下的


Question: 新手求指点---单链表，大家帮忙找一下漏洞

《Visual C++ 游戏开发经典案例详解》？

仅供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=v;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=v;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

引用 4 楼 zhao4zhong1 的回复:[quote=引用 3 楼 qq_26368707 的回复:] [quote=引用 2 楼 user-2的回复:]建议单步跟踪程序运行，观察每一步与你期望的结果是否一致，然后分析原因 谢谢，结果没问题，我只是想问问有没有地方需要优化，或者是对编程的风格有什么建议[/quote] 请自行参悟我的代码。[/quote]请教一下，有什么c语言小项目适合我这种没做过项目的人来扎实基础吗

引用 3 楼 qq_26368707 的回复:[quote=引用 2 楼 user-2的回复:]建议单步跟踪程序运行，观察每一步与你期望的结果是否一致，然后分析原因 谢谢，结果没问题，我只是想问问有没有地方需要优化，或者是对编程的风格有什么建议[/quote] 请自行参悟我的代码。

引用 2 楼 user-2的回复:建议单步跟踪程序运行，观察每一步与你期望的结果是否一致，然后分析原因 谢谢，结果没问题，我只是想问问有没有地方需要优化，或者是对编程的风格有什么建议

建议单步跟踪程序运行，观察每一步与你期望的结果是否一致，然后分析原因


Question: 关于非阻塞打开文件的问题


Question: c问题求助

strcpy( gread[i],"优");  printf("%d个同学成绩等级%s",i+1,gread[i]);

谢谢大家 终于弄出来了

#include "stdio.h" #define N 10 int main() {   char gread[N][8];   int i,score[N];    for(i=0;i<10;i++)  {   printf("请输入第%d个人的成绩:",i+1);	   scanf("%d",&score[i]);   if(score[i]>=90)   gread[i]="优";   else  if(score[i]>=80)   gread[i]="良";   else  if(score[i]>=70)   gread[i]="中";   else  if(score[i]>=60)   gread[i]="及格";   else  gread[i]="不及格"; }  	   for(i=0;i>10;i++)   printf("%d个同学成绩等级%c",i+1,gread[i]);	 }  这样为啥还是不行

或者用两个单独的数组，一个数组存成绩，一个数组存等级。

用一个结构体，包括成绩和等级两个成员。 用一个数组，数组成员是结构体。

是的，但是我不知道该怎么用

是想让你用二维数组吗？


Question: 我这里有一窜代码，希望大家能够帮我看看，我想把我输入的一个字符串变为一个4*4的数组，数组必须两个以上

楼上说了几个问题。 还有就是str[len] = '0';应该是str[len] = '\0';   （'0'是字符0，和'\0'是有区别的）  单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

另外你main函数中间有个return 0;  导致后面的代码将没有机会执行了

if(k=1)  改成  if(k==1)


Question: c新人求助/

C++ Integer Constants Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.  Syntax  integer-constant :  decimal-constant integer-suffixopt octal-constant integer-suffixopt hexadecimal-constant integer-suffixopt 'c-char-sequence'  decimal-constant :  nonzero-digit decimal-constant digit  octal-constant :  0 octal-constant octal-digit  hexadecimal-constant :  0x hexadecimal-digit 0X hexadecimal-digit hexadecimal-constant hexadecimal-digit  nonzero-digit : one of  1 2 3 4 5 6 7 8 9  octal-digit : one of  0 1 2 3 4 5 6 7  hexadecimal-digit : one of  0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F  integer-suffix :  unsigned-suffix long-suffixopt long-suffix unsigned-suffixopt  unsigned-suffix : one of  u U  long-suffix : one of  l L  64-bit integer-suffix :  i64  To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.  To specify a decimal constant, begin the specification with a nonzero digit. For example:  int i = 157;   // Decimal constant int j = 0198;  // Not a decimal number; erroneous octal constant int k = 0365;  // Leading zero specifies octal constant, not decimal  To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:  int i = 0377;   // Octal constant int j = 0397;   // Error: 9 is not an octal digit  To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the “x” does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:  int i = 0x3fff;   // Hexadecimal constant int j = 0X3FFF;   // Equal to i  To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:  unsigned uVal = 328u;             // Unsigned value long lVal = 0x7FFFFFL;            // Long value specified                                    //  as hex constant unsigned long ulVal = 0776745ul;  // Unsigned long value

多补4个0看着舒服点 http://blog.csdn.net/self001/article/details/8060407

原本想帮忙看看来，作为新手的我。发现前辈们以及完美解决，那我能怎么办呢水水水。

引用 2 楼 PKnotnull 的回复:[quote=引用 1 楼 user-5 的回复:] 0x代表这是16进制 我知道16进制0x61是a，0x62是b 为什么前面要加4个零？还有输出的时候是先输出b结果是ba，为什么不是ab？[/quote]  前面的0可以忽略，通常只是为了补齐到8位  顺序反了是因为字节充通常是以小端存储方式，小端怎么存储可以在网上搜索

引用 4 楼 user-5 的回复:(ー_ー)!!我昨天才学到共用体，楼主不要打我 看了下例题，明白了- -！

引用 4 楼 user-5 的回复:(ー_ー)!!我昨天才学到共用体，楼主不要打我 共用同一个内存空间我知道，输出顺序还是不懂 - -！

引用 2 楼 PKnotnull的回复:[quote=引用 1 楼 user-5 的回复:] 0x代表这是16进制 我知道16进制0x61是a，0x62是b 为什么前面要加4个零？还有输出的时候是先输出b结果是ba，为什么不是ab？[/quote] 共用体int i与char用的是同一个内存空间，你输出i的值看下

引用 1 楼 user-5 的回复:0x代表这是16进制 我知道16进制0x61是a，0x62是b 为什么前面要加4个零？还有输出的时候是先输出b结果是ba，为什么不是ab？

0x代表这是16进制


Question: 学习郭天祥第十课，根据他视频上讲写的，写到键盘扫描时，随着按下键的次数，显示时秒的后三位有轻微闪烁，但光标地址实际在走，希望大神指点

按键需要防抖？


Question: 位运算

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

引用 2 楼 loveqise 的回复:[quote=引用 1楼user-4 的回复:]1. 在 C 语言里，01 是一个八进制整型常量，值为 1，类型为 int  2. 在计算 01 & n 之前，会发生Usual arithmetic conversions，将两者转换为同一类型。n 也为 int ，那个两者都被转换为 int (不变）；如果 n 为 long long int ，那个 01 也会被转换为 long long int 类型的 1 。谢谢，Usual arthimetic conversions的转换规则是什么？1、是进行位运算时才会转换，还是所有运算都会转换2、同类型，如int是短整型转为长整型吗？3、不同类型，如int和char等怎么转换[/quote]  1、是的，会进行隐式转换 2、int在不同平台上可能是短/长整型，但同一个平台上不会同时是两种 3、char类型变量会转换成一个int的临时变量

隐式类型转化，在进行运算时，以表达式中最长类型为主，将其他类型位据均转换成该类型

引用 1楼user-4 的回复:1. 在 C 语言里，01 是一个八进制整型常量，值为 1，类型为 int  2. 在计算 01 & n 之前，会发生Usual arithmetic conversions，将两者转换为同一类型。n 也为 int ，那个两者都被转换为 int (不变）；如果 n 为 long long int ，那个 01 也会被转换为 long long int 类型的 1 。谢谢，Usual arthimetic conversions的转换规则是什么？1、是进行位运算时才会转换，还是所有运算都会转换2、同类型，如int是短整型转为长整型吗？3、不同类型，如int和char等怎么转换


Question: 简单程序问题

嵌套循环呗  你只有一层循环，那只能交换一次相邻位置的元素，最小的未定已经到了最前，最大的未必到了最后  好好理解一下冒泡排序...

不加i和j怎么进行排序呢？ 而且你这个排序的内存j循环不需要循环那么多次。 http://blog.csdn.net/hguisu/article/details/7776068

其实就是个冒泡排序。http://blog.csdn.net/qq_25371579/article/details/50763111?locationNum=2&fps=1

按分数由大到小排序？？？，好像还写得有点冗余

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


Question: 用dvc++怎么对二叉树的遍历进行单步调试

1. 编译通过(ctrl+F9)  2. 设置断点(ctrl+F5)  3. 调试(F8)  4. 增加观察变量（在左边的debug观察窗口右键增加或者F4）  5. 单步调试：F7  6. 结束调试：ctrl+alt+f2

你可以直接在csdn上搜dev c++的单步调试的博客，上面讲的很清楚。


Question: VS2015/2013编译C程序提示找不到指定文件

你的项目里有多个源文件中，存在多个main方法。  解决方法：将所有其它的main方法给为与源文件同名，如 void mian_source03（），只留一个你需要调试、运行的那个main方法。、当你需要调试、运行另一个源文件中的mian方法时，再进行改名。

项目里面还有个 Source03.cpp。 从项目中去掉这个文件。

cpp file

关闭UAC、防火墙、杀毒软件、……

引用 2 楼 user-6 的回复:链接失败，你是不是包含了其他源文件，里面也定义了main  没有呀

引用 3 楼 qq423399099 的回复:重新建个win32控制台项目试试。   win32控制台可以

重新建个win32控制台项目试试。

链接失败，你是不是包含了其他源文件，里面也定义了main

最简单的HelloWorld都不行


Question: const应该如何定义

引用 4 楼 sunyongliang118 的回复:char*  const zpDataBasePathIngoreCharArr = "~.\\/*";  1年后回过头看，你的回答才是正确的 。

int* const zpDataBasePathIngoreCharArr 呢

引用 4 楼 sunyongliang118 的回复:char*  const zpDataBasePathIngoreCharArr = "~.\\/*";  我已经改的差不多了

引用 2 楼 sdghchj 的回复:跟const没关系，是你的类型初始化错误。 一个char*指针，却用一个初始化列表来初始化，且列表中的各个值都还是字符类型不是指针类型。 初始化列表是用来对数组初始化的。  谢谢你哈

引用 2 楼 sdghchj 的回复:跟const没关系，是你的类型初始化错误。 一个char*指针，却用一个初始化列表来初始化，且列表中的各个值都还是字符类型不是指针类型。 初始化列表是用来对数组初始化的。 表示完全同意。


Question: 关于指针

理解和讨论之前请先学会如何观察！  仅供参考：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

返回值void应该改成int *

楼主似乎晕了，void fun怎么会有返回值，而且你这里就算是有返回值，那返回的确实是n的地址，要想返回n的地址，得解引，既return *n。

这样的写法有些编译器都过不了编译。

楼上很正确啊，*n是指向的内存区的值，而n里面才是地址

return n;是返回指针n所指向的内存区域的地址。 return *n;是返回指针n所指向的内存区域里的值。 完全不知道2#在解释什么。 PS：而且你既然将n作为参数传进来了，那么根本不需要return n;

return n; 和return *n;有什么区别呢

引用 5 楼 u010165006 的回复:《C语言点滴》  发错了，楼主可以参考： 《深入理解C指针》

《C语言点滴》

明明是返回类型为void的函数，return n; 什么意思


Question: 跪求大神帮我

换了才开始学忘了换了不小心，改为int了但还是不行无法调试

输出是%f不是%d，浮点型

还是不行

通过了，但还是是无法调试  改了一下还是这么显示

不知道编译通过了没有？ 转意字符换行是'\n'不是'/n', sum是float型，为什么用整形输出？ 不妨把文本格式代码贴出来。


Question: 散分＋推荐阅读“没学过C语言的代价”

又百度搜来的相关关键字啊?

哈哈哈   请讲

赵4老师，你好，我刚刚写了一篇文章，有空的时候还望能够给个回复，感谢。         帖子： 【话题：工作生活】电信诈骗--一次难得的人生经历

西电离我们吉祥村特别近噢！

我觉得本科教的C太浅

赵四老师,大三学生基础很差还有救吗

学习还是有必要的，当然精通，作为小白，不敢多说！

个人兴趣吧.还有看到底有没有需要

原来赵老师也是西电人呀

老赵不但是西电人，而且是80年代上的西电，十分了得（不只是年纪）。

mark

来晚了吗

在结帖时平分300分

还差两贴就可以再结帖时平分300分了。

引用 34 楼 wenpinglaoyao 的回复:敢问赵老师对《深度探索c++对象模型》一书怎么看？我感觉里面的错误（疏忽式）不少 挑错虽然也是看书的一种方法，但不是从书中学习作者先进思想的最好办法。 空杯心态还是要有的。

果然我算数不及格啊！ http://bbs.csdn.net/topics/392052283

赶快结帖吧

先来一贴...


Question: 新手求救~~c 中能否加密word、pdf、图片等格式文件？

如果文件较大，不需要一次性全部读进内存中进行加密，可以分块读取、加密、保存。   我以前做加密时，加密接口只接收 16个字节的二进制数据（AES为16个字节，DES为8个字节），如果需要加密更长的数据，那么要多次调用我的加密接口。

估计是没使用binary 模式读取

仅供参考：#include <stdio.h> #include <string.h> #include <conio.h> FILE *fi,*fo; int i; int main(int argc,char **argv) {     if (argc<3) {         printf("Usage:%s src des\n",argv[0]);         return 1;     }     if (0==stricmp(argv[1],argv[2])) {         printf("Src and des is same!\n");         return 2;     }     fo=fopen(argv[2],"wb");     if (NULL==fo) {         printf("Can not create file %s\n",argv[2]);         return 3;     }     fi=fopen(argv[1],"rb");     if (NULL==fi) {         fclose(fo);         printf("Can not find file %s\n",argv[1]);         return 4;     } 	i=0;     fseek(fi,-1L,SEEK_END);     while (1) {         fputc(fgetc(fi)^0x5A,fo); 		i++; 		if (i%1000000==0) cprintf("\r%dKB",i/1000);         if (fseek(fi,-2,SEEK_CUR)) break;     }     fclose(fi);     fclose(fo); 	cprintf("\r%dKB OK.\r\n",i/1000);     return 0; }

感谢user-4版主回复，我的程序里的明文接口是一个十六进制数组，我试过直接读取.doc文件，会报错。

可以啊，加密算法又不区分文件格式


Question: 函数指针

引用 14 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！ 赵4老师跟赵四小姐是什么关系?

理解和讨论之前请先学会如何观察！

引用 10 楼 qq_28743877 的回复:赵4老师正解!!!

引用 3 楼 qq423399099 的回复:通过函数指针调用函数不需要加星号  这个好像有一点不同，加与不加含义是不同的，我在调试的时候发现，如果不加p显示为一个变量，如果加上*p显示为一个函数，结果是一样的，但是这种情况仅仅出现在费成语痷函数的指针上，如果是成员函数的指针，结果又不一样了

引用 15 楼 u010312274 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] 理解和讨论之前请先学会如何观察！ 赵4老师跟赵四小姐是什么关系?[/quote] 就是普通老师跟小姐的关系。

引用 4楼paschen 的回复:函数指针解引了还是本身，所以你可以对函数指针一直解引，也可以不解引就直接调用函数什么是解引

引用 3楼小灸舞 的回复:通过函数指针调用函数不需要加星号不加*就不是指针了啊

引用 9 楼 user-7 的回复:[quote=引用 4 楼 paschen 的回复:] 函数指针解引了还是本身，所以你可以对函数指针一直解引，也可以不解引就直接调用函数  函数指针和函数还是不是一回事的。函数只是会自动转换成函数指针而已，所以可以一直解引用。  碰到不会转换的地方，比如 sizeof, typeid, template, ... ，就会发现他们的不同。[/quote]  嗯嗯，是我说的不准确，是函数可以一直转换成函数指针  而且指向成员函数的指针就不是这样了

通过函数指针调用函数不需要加星号

本来就是这样理解，有什么问题吗。 而且target[i] = (*p)(source[i]); 还可以省略*，写成target[i]=p(source[i]);

函数指针指p向返回值类型为double并且接受一个double类型参数的的函数

赵4老师正解!!!

引用 4 楼 paschen 的回复:函数指针解引了还是本身，所以你可以对函数指针一直解引，也可以不解引就直接调用函数  函数指针和函数还是不是一回事的。函数只是会自动转换成函数指针而已，所以可以一直解引用。  碰到不会转换的地方，比如 sizeof, typeid, template, ... ，就会发现他们的不同。

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

仅供参考：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]


Question: 调用system()，在vs中运行正常，当直接运行生成的文件时system()好像被阻塞？

如果能方便地提升权限，那还设置权限干啥？

请判断每个函数调用的返回值。 权限问题？ 参考RunAs命令？

使用 shutdown 的系统全路径就可以任意命名了。

你在 VS 里面能运行，表示和其他的没有任何关系，包括权限等。 难道你的 VS 能够提权吗？  VS 直接运行的是全路径的 .exe 文件。 此时的 工作目录是源代码目录。 而这个目录里面没有 shutdown .  而你直接运行的话，工作目录就是生成目录。 这个目录下面有 shutdown 。 system 运行 shutdown 的话会递归的。

引用 6 楼 zhao4zhong1 的回复:system("runas /user:mydomain\\administrator \"cmd /c shutdown ...\"");   恩，这样是可以了。应该就是新进程权限问题。 我又查了一下，有人说 “在开启 UAC 的情况下，Administrators 组成员运行 RUNAS 命令（runas /user:administrator cmd.exe）提升管理员权限必须要启用 administrator 帐户，并且为其指定密码（因为系统默认禁止空密码登陆）。”  如果我登录的就是管理员账户，并且没有密码，那这样是不是就不行了。那如何方便的在代码中提升system的新进程权限，或者继承，system有没有附加参数使新进程继承父进程的权限？好像system是从环境变量中确定的。 或者说，在c中执行shell命令，用哪个方法可以在这些方面轻松地调控。

system("runas /user:mydomain\administrator \"cmd /c shutdown ...\"");

引用 3 楼 zhao4zhong1 的回复:请判断每个函数调用的返回值。 权限问题？ 参考RunAs命令？   我把system("shutdown -a")的返回值输出到文件中发现返回值是-1； 百度了一下发现：        1、如果 system()在调用/bin/sh 时失败则返回127, 其他失败原因返回-1.。 　　2、若参数string 为空指针(NULL), 则返回非零值. 　　3、如果system()调用成功则最后会返回执行shell 命令后的返回值, 但是此返回值也有可能为system()调用/bin/sh 失败所返回的127, 因此最好能再检查errno 来确认执行成功.  这个其他失败原因是什么情况啊， shutdown -a:1116                               //这是d,r两种版本下在vs中，无计划任务时，取消指令的返回值 shutdown -a:1116  shutdown /s /t:0                                //这是在vs中，设置计划的返回值 shutdown -a:0                                   //这是vs中紧接着取消计划的返回值  shutdown -a:-1                                   //直接运行时，无论哪个命令，都是返回-1.。 shutdown /s /t:-1  会不会是这样，哪怕我以管理员身份运行，当调用system时，创建的子进程并没有继承管理员权限。 那为什么vs中就可以呢，这是我最好奇的一点，为什么调试程序时是好的，使用时便不一样了。涉及到些什么的程序还会出现这种调试和使用不一样的现象

引用 1 楼 user-2 的回复:你的生成的程序修改一下。 不要使用shutdown.  谢谢，不过我想知道的是如果shutdown不行，但是不管什么版本，在vs中和直接运行为什么会不一样，更远的可以说为什么我调试一切正常，在同样的环境下为什么不能有想要的效果。

你的生成的程序修改一下。 不要使用shutdown.


Question: Yacc构建语法树

百度搜相关关键字。


Question: asm 内嵌汇编的使用

谢谢大家，找到原因了 "movl $0,  %%ecx \n\t"  要改为"movl %0,  %%ecx \n\t"

asm("":::) 啥的 只是 AT&T 格式汇编的规定,  懒得记的时候还是单独写成个汇编文件方便些,  用 nasm/yasm 啥的你就不用为 M$ Win, Linux啥的写两套代码...  第一个:后是输出参数, 比如写 "=a"(result)  就自动在汇编后加上  result = eax 的指令.  第二个:后是输入参数, 编译器会在生成汇编指令时先填上合适的值,  a b c d D S 分别代表  (E/R)ax, bx, cx, dx, di,si .   或者用 m v  r  啥的指定类型,  在汇编里用 %0 %1 %2 引用....   比如上面我代码里就指定设置 eax 的值为 4 (__NR__write),  ebx = 1 (stdout),  ecx = "Hello world!\n",  edx = 13(strlen("Hello...")) ...  第三个:后是受影响的寄存器, 内存指示啥的 ,  比如 __asm__ ("":::"memory");   表示一个 memory barrier, 阻止编译器跨越这条代码重排指令, 如果你啥多线程跑出很古怪的结果就可能是少了这个, 如果你汇编里修改了内存的值, 通常应该加上这个...

你这几句就是 edx = 13,  ecx = 0, ebx = 0, eax = "Hello World!"  ... 缺了 syscall , 并且看起来参数也不对, 应该是这样子...  int main() {         __asm__ __volatile__("int $0x80\n\t"::"a"(4),"b"(1),"c"((long)"Hello World!\n"),"d"(13));         return 0; }

6.45.2 Extended Asm - Assembler Instructions with C Expression Operands


Question: 简单C程序错误分析

引用 3 楼 paschen 的回复:b[i][j]=a[j][i] 时a[j][i] 可能还未初始化，里面元素的值不确定   确实可能有这个问题。。。那么输出的错误数列的相关元素的值确实可能是随机出现的吗？

确实可能有这个问题。。。那么输出的数列的值可能是随机出现的吗？

引用 6 楼 baidu_33792305 的回复:有大神可以解答一下吗？错误输出的矩阵中的“24”和“1558”两个数是如何出现的，是随机的吗？~~ 楼主你这里出现的数字是随机给的。没有初始化就进行使用，有的编译器是不准通过的，这个问题你得注意一下。

二维数组都没初始化你就开始a[i][j]=a[j][i]，不明白你想干吗。如果你是想转置矩阵的话，可以先进行循环输入，但是别a[i][j]=a[j][i]，等你的输入完了之后，再转置（注意，只需要转置矩阵的一个半三角就可以）。

你是在用turbo C，我已开始也用这个，太古老了

最好贴代码，而不是截图。 有点不明白你scanf输入以后在干嘛，换过去又换回来？ 确实要执行3*3次？ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 关于文件的删除操作 实在是找不出问题所在

引用 2 楼 vectorindex 的回复:还是不行 郁闷啊 啊啊啊啊 不一定和你的问题有关系，这一句代码有问题：   if(strlen(x) >= 10)  x只有10个元素，存储字符串最大9个字符。  另外，实在是奇怪的问题的话，对于VC来说还有可能是你链接的库设置不好，修改为链接静态库试试。  Multi-threaded (/MT)

下一次使用时会不会在tc中遇到上个文件的eof，本人是小白，随便猜猜，看看就好

不清楚，暂时发现，每次重新使用tc时，是不是要zeromemry或者memset

还是不行 郁闷啊 啊啊啊啊

1. 首先，close, remove这些调用，应该在返回值判断之后，再看errno, 这样代码就比较稳当。 2. 如果删除错误为13, 可能是外部程序打开了文件。因为你说单步调试没有问题，所以我推测是杀毒程序在扫描。 3. 避免这种问题，不妨在errno=13之后，暂停几秒重试一下。


Question: getchar返回值到底是int型还是char型？？

返回的是int型，如果你用char接收，会隐式转换成char型，也就是对应的字符

你可以直接到stdio.h文件中看到getchar的函数声明

返回的是int, 发生是隐式类型转换

返回的不是char类型的字符，而是你打印的时候，是以字符的形式打印的。

getc, getwc, getchar, getwchar Read a character from a stream (getc, getwc), or get a character from stdin (getchar, getwchar).  int getc( FILE *stream );  wint_t getwc( FILE *stream );  int getchar( void );  wint_t getwchar( void );  Routine Required Header Compatibility  getc <stdio.h> ANSI, Win 95, Win NT  getwc <stdio.h> or <wchar.h> ANSI, Win 95, Win NT  getchar <stdio.h> ANSI, Win 95, Win NT  getwchar <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns the character read. To indicate an read error or end-of-file condition, getc and getchar return EOF, and getwc and getwchar return WEOF. For getc and getchar, use ferror or feof to check for an error or for end of file.  Parameter  stream  Input stream  Remarks  Each of these routines reads a single character from a file at the current position and increments the associated file pointer (if defined) to point to the next character. In the case of getc and getwc, the file is associated with stream (see Choosing Between Functions and Macros). Routine-specific remarks follow.  Routine Remarks  getc Same as fgetc, but implemented as a function and as a macro.  getwc Wide-character version of getc. Reads a multibyte character or a wide character according to whether stream is opened in text mode or binary mode.   getchar Same as _fgetchar, but implemented as a function and as a macro.  getwchar Wide-character version of getchar. Reads a multibyte character or a wide character according to whether stream is opened in text mode or binary mode.    Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _gettc getc getc getwc  _gettchar getchar getchar getwchar    Example  /* GETC.C: This program uses getchar to read a single line  * of input from stdin, places this input in buffer, then  * terminates the string before printing it to the screen.  */  #include <stdio.h>  void main( void ) {    char buffer[81];    int i, ch;     printf( "Enter a line: " );     /* Read in single line from "stdin": */    for( i = 0; (i < 80) &&  ((ch = getchar()) != EOF)                          && (ch != '\n'); i++ )       buffer[i] = (char)ch;     /* Terminate string with null character: */    buffer[i] = '\0';    printf( "%s\n", buffer ); }   Output  Enter a line: This is a test This is a test   Stream I/O Routines  See Also   fgetc, _getch, putc, ungetc

正常返回值是int，如果赋值给char会自动转换


Question: 这样判断有缺陷吗？

#include <stdio.h> #include <locale.h> int HZwtail(char *hz,int p) {//返回0：非汉字|1：汉字前半个字节|2：汉字后半个字节     int s,i;     unsigned int c;      if (p<1) return 0;     s=0;     for (i=0;i<=p;i++) {         c=(unsigned)(hz[i]);         if (c==0) return 0;         switch (s) {         case 0:             if (c>0x80u)                 s=1;             else                 s=0;             break;         case 1:             if (c>=0x40u)                 s=2;             else                 s=0;             break;         case 2:             if (c>0x80u)                 s=1;             else                 s=0;             break;         }     }     return s;    //GBK汉字内码范围    //81-A0, 40-7E 80-FE    //AA-AF, 40-7E 80-A0    //B0-D6, 40-7E 80-FE    //D7   , 40-7E 80-F9    //D8-F7, 40-7E 80-FE    //F8-FE, 40-7E 80-A0  //if((((0x81u<=q && q<=0xA0u) || (0xB0u<=q && q<=0xD6u) || (0xD8u<=q && q<=0xF7u)) && ((0x40u<=w && w<=0x7Eu) || (0x80u<=w && w<=0xFEu)))  //|| (((0xAAu<=q && q<=0xAFu) || (0xF8u<=q && q<=0xFEu))                           && ((0x40u<=w && w<=0x7Eu) || (0x80u<=w && w<=0xA0u)))  //|| (              q==0xD7u                                                       && ((0x40u<=w && w<=0x7Eu) || (0x80u<=w && w<=0xF9u)))) //  if (q>0x80u && w>=0x40u) //      i=i+2; //  else //      i=i+1; } int main() {     setlocale(LC_ALL,"chs");     char hzstr[]="a汉字0啊12";     int i;     printf("%s\n",hzstr);     for (i=0;i<11;i++) {         printf("%d",HZwtail(hzstr,i));     }     printf("\n");     return 0; } //a汉字0啊12 //01212012000 //

更准确的话应该需要是第第一个字节为 0xA0-0xFF 这一部分

不可以的。 需要判断第一个连续的汉字的起始位置，然后从偶数截断。 碰到非汉字字符，重置起始位置。 你还需要考虑显示边界的问题，如果显示 80 列字符，那么只能从 80或者79 截断。 不能让汉字显示半边的。   我们早年做的是从网络接受字符串，显示在点阵的液晶屏上，可以一个一个的判断。

char 的取值范围是 -127~+127,不可能出现 0x80. 应该这样比较，使用 unsigned char 。    if(（（unsigned char） *(data + 15) ）> 0x80)   这种方式，可以比较、查找 GB2312 编码的汉字，这种编码的汉字，使用两个字节都，大于0x80,这样的汉字有5、6千个。  更多、更大范围的汉字，使用GBK编码（兼容GB2312），这样的汉字有几万个，这样的汉字，一个字节有可能小于0x80.  所有判断是否为汉字，不是这么简单的一句与 0x80进行比较的，要同时考虑多个字节。

lz是打算将 data 第15个字符之后的所有汉字都拷贝到 buf 中么？

引用 7 楼 zhao4zhong1 的回复:仅供参考：integer proc HZwtail(integer p)     integer s,i,c      if p<1         return(0)     endif     s=0     for i=1 to p         c=CurrChar(i)         case s         when 0             if c>0x80                 s=1             else                 s=0             endif         when 1             if c>=0x40                 s=2             else                 s=0             endif         when 2             if c>0x80                 s=1             else                 s=0             endif         endcase     endfor     return(s)    //GBK汉字内码范围    //81-A0, 40-7E 80-FE    //AA-AF, 40-7E 80-A0    //B0-D6, 40-7E 80-FE    //D7   , 40-7E 80-F9    //D8-F7, 40-7E 80-FE    //F8-FE, 40-7E 80-A0  //if (((0x81<=q and q<=0xA0) or (0xB0<=q and q<=0xD6) or (0xD8<=q and q<=0xF7)) and ((0x40<=w and w<=0x7E) or (0x80<=w and w<=0xFE)))  //or (((0xAA<=q and q<=0xAF) or (0xF8<=q and q<=0xFE))                          and ((0x40<=w and w<=0x7E) or (0x80<=w and w<=0xA0)))  //or (              q==0xD7                                                     and ((0x40<=w and w<=0x7E) or (0x80<=w and w<=0xF9))) //  if (q>0x80 and w>=0x40) //      i=i+2 //  else //      i=i+1 //  endif end 如何判断第一个字节和第二个字节的？老师。

参考维基百科GBK条目

没看懂，你写程序的目的是什么

应该用IsDBCSLeadByte


Question: 加不加*，都可以怎么回事？ 函数指针

加不加*都是一样的。 http://blog.csdn.net/shiliangsl0115/article/details/6152188

函数指针可以不用加*，也可以加多个*  ........


Question: 在头文件中定义函数并封装为Dll的问题

头文件包含的是否正确一般只影响编，程序运行错误可能是由于你代码哪里的问题

多谢楼上2位指点 @paschen 我再看看他的代码，估计指针用的有问题 @zhao4zhong1 现在用的delphi程序调用，没有源码。等我写个调用程序调试下看

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


Question: 插入顺序表，提交遇到小问题

边界条件 输入输出格式 ……


Question: 字符 'A' 如何转换为十六进制 '0x0A'

让他们减去( 'A'-0x0A)  ‘A’ - ( 'A'-0x0A) ‘B’ - ( 'A'-0x0A)

#include <stdio.h> unsigned char buf_1[2] = {'A', 'B'}; unsigned char buf_2[2]; int v0,v1; int main() {     sscanf((const char *)buf_1,"%1X%1X",&v0,&v1);     buf_2[0]=v0;     buf_2[1]=v1;     printf("0x%02X,0x%02X\n",buf_2[0],buf_2[1]);     return 0; } //0x0A,0x0B //

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

计算机只认二进制，十六进制和十进制都是对人的理解来说的。无论写成unsigned char buf_2[2] = {0x0A, 0x0B}; 还是unsigned char buf_2[2] = {10, 11};  在内存中保存的值是一样的。

0x0A只是写法是十六进制而已，实际是二进制存储的 要转换，先把字符放到字符串中，然后调用sscanf或strtoul

引用 4 楼 halloworldd 的回复:[quote=引用 1 楼 user-7 的回复:] 0x0A跟'0x0A'是两个东西，一个是代码里的数字的表示方法，一个是字符串。 buf_2[i] = buf_1[i]-'A' + 10  是转化成十六进制数0x0A，不是字符串“0x0A”  unsigned char buf_1[2] = {'A', 'B'};  //转化为下面的十六进制 unsigned char buf_2[2] = {0x0A, 0x0B}[/quote] 在内存里面0x0A就是10， unsigned char buf_2[2] = {0x0A, 0x0B}跟unsigned char buf_2[2] = {10, 11}是一样的。 0x0A只是数字的另一种代码表达方式

引用 1 楼 user-7 的回复:0x0A跟'0x0A'是两个东西，一个是代码里的数字的表示方法，一个是字符串。 buf_2[i] = buf_1[i]-'A' + 10  是转化成十六进制数0x0A，不是字符串“0x0A”  unsigned char buf_1[2] = {'A', 'B'};  //转化为下面的十六进制 unsigned char buf_2[2] = {0x0A, 0x0B}

引用 1 楼 user-7 的回复:0x0A跟'0x0A'是两个东西，一个是代码里的数字的表示方法，一个是字符串。 buf_2[i] = buf_1[i]-'A' + 10  不好意思没说清楚，是转化成十六进制数，0x0A，不是字符串“0x0A”

说错，'0x0A'是什么鬼，字符串是双引号


Question: Qt中使用QProcess启动.exe程序

QProcess proc;   QStringList arguments;   proc.start(" e:\\abc\\a.exe ", arguments);


Question: 新手求助

“was not declared in this scope”是一个错误信息，在编译的时候会遇到。其含义为标识符在其出现的地方是未被定义的。 出现该错误的时候，会同时把未定义的变量名显示出来。比如如下程序： int main() {     printf("%d",i);//这个i是没定义的。 } 就会显示一个'i' was not declared in this scope或者类似的错误信息出来。 对于变量和函数，如果未定义都会出现这个错误。 该错误出现时，需要根据出现该错误的行号及名称，查找对应名称变量或函数的作用，一般有如下几种可能： 1 忘记定义。写代码的时候疏忽了，导致一些变量直接使用但没有定义。只要对应定义相应的函数或变量即可。 2 拼写错误。写代码的时候，敲错了字符。比如sum敲成了Sum, average敲成averge等。对应修改即可。 3 作用域不正确。在超出变量和函数的作用域部分使用了该变量或函数。需要通过定义位置，或增加声明的手段，加大变量的作用域使其包含引用位置。

没见到你avsco  avcour1 fali2 good 这些函数的定义啊

第7行和第9行。 char course[5][10], *pcou; printf("Input course :\n"); pcou = course[0];  pcou = course[0];course[0]的类型是 char *，所以pcou的定义应该是 char **pcou？ 我是菜鸟，代码格式有点乱逻辑不太好看，所以就看了前几行。  建议题主提问题用标准代码格式和多写些注释，这样可以更快得到其他大神回复。


Question: 关于* argv[]指针数组在printf函数中的引用问题

第一个应要用*argv  另外char *argv[] 参数其实是 char**类型

又被谭浩强坑了……

答案很简单，第一个错了

我感觉第一的是错的，我自己敲了一遍确实有问题


Question: 【新手求助】关于ICCAVR编程

把这些文件都添加到工程，然后就都会进行编译了

在右边窗口中的files上点鼠标右键，添加……


Question: 如何定义二维数组的指针数组

int a[10][4]; 	int b[8][4]; 	int (*p[2])[4] = {a,b};

引用 2 楼 qq423399099 的回复:http://blog.csdn.net/haihuanjack/article/details/8065974  这个很不错  int   a[3][6];  int **p=a;        像这样定义是错误的  因为a代表着除了第一列以外的列数的维数大小，如a+1的地址就是a[1]的地址，也就是a[1][0]的地址，而p仅是整形指针的指针，没跨越一次就是4字节，因此他们的大小是不匹配的，所以这样子直接等于号是不正确的。  要真正的定义方式应概是定义指向n维数组的指针，n就是除第一维的另外维度，  如上面的指针定义应该为  int  (*p)[6];  p=a;  这样子就 可以就可以通过p以下标形式来访问数组。

仅供参考：//在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------

int     a[10][4]={{1}},  b[8][4]={{2}}; int     (*p[2])[4] = {a, b};


Question: 程序问题

谢谢两位大神！

你循环只需要交换时只需要遍历到一半  否则你第一个和最后一个交换，最后一个再和第一个交换就相当于没交换了

因为你第二个for循环写错了。 循环的次数应该是for(i = 0; i < 5/2; i++){......} 你循环5次，相当于换过去又换回来了


Question: 指向函数的指针

float (*function[4])(float x, float y);  float func(float x, float y) { 	//......... }  void main() { 	float x=0.0f, y=0.0f; 	function[0] = func; 	(*function)(x, y); }

改成：   float func(float x, float y) {    //......... }

光标的地方报错


Question: 求大神帮看看这段c代码有啥问题

int a=3; // test

你遍历的函数呢？ 感觉没什么问题啊，比如输入：ab..c.. 结构就是：    a  /   \ b    c

仅供参考：#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G

引用 1 楼 user-4 的回复: *bt=NULL;  这一句不行啊。老实地把每个指针赋值为NULL. 而且你这程序还有一个问题，叶子节点都是 废的，其中左右孩子为空，里面的ch也没有用。 抱歉写错了，是data也没有用


Question: C语言简单问题求解

一定要注意初始化，指针要预防野指针

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

1.total没有初始化 2.你的switch (scanf("%d", &a))这些用法都是不对的。scanf的返回值并不是a的值，而是成功接收到赋值的个数（你程序里是1） 根本进入不了别的case分支  单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

静下心来自己一步一步的检查

你的total变量没有初始化就使用了

哪里不行，编译出错，运行出错？ float total; 变量没有初始化，改为float total = 0.0f;


Question: 完成输入一个数组逆序输出功能

#include<stdio.h>#include<windows.h>  改成  #include<stdio.h> #include<windows.h>

你这代码贴的反人类。。。

有什么提示？


Question: 二叉树

int count1(node *r) {     if (r->left && r->right)         return count1(left) + count1(right);     else if (r->left)         return 1 + count1(r-left);     else if (r->right)         return 1 + count1(r->right);     else         return 0; }

用一个全局变量做计数器，遍历，判断度，计数器加一。或者用静态变量，声明在遍历函数内部。


Question: 自学数据结构时遇到一些问题，自己看了一下午还没发现，愿不吝赐教，谢谢

谢谢赵老师，谢谢版主大人，还有那个大哥，我弄懂了非常感谢

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

1.你应该把printf("请输入相应的数据(*表示置空):");这句放到函数外，不然每次递归都会调用到 2.你的输入也是不对的，应该输入类似:SA**D**这样的才行  #include <stdio.h> #include <stdlib.h> #include <conio.h> typedef char ElementType; typedef struct BiTreeNode { 	ElementType data; 	struct BiTreeNode *lchild; 	struct BiTreeNode *rchild; }BiTreeNode, *BiTree; BiTree Initate() { 	BiTreeNode *p; 	p = NULL; 	return p; } void CreateBiTree(BiTree &T) { 	ElementType data; 	 	data = getchar(); 	if (data == '*') 		T = NULL; 	else 	{ 		T = (BiTreeNode *)malloc(sizeof(BiTreeNode)); 		if (T == NULL) 			return; 		T->data = data; 		CreateBiTree(T->lchild); 		CreateBiTree(T->rchild); 	} } void InOrderTraverse(BiTree &T) { 	if (T) 	{ 		InOrderTraverse(T->lchild); 		printf("%c", T->data); 		InOrderTraverse(T->rchild); 	} } BiTree SearchNode(BiTree &T, ElementType data) { 	BiTree p; 	if (T) 	{ 		if (T->data == data) 			return T; 		if (T->lchild) 		{ 			p = SearchNode(T->lchild, data); 			if (p) 				return p; 		} 		if (T->rchild) 		{ 			p = SearchNode(T->rchild, data); 			if (p) 				return p; 		} 	} 	return NULL; } int InsertNode(BiTree &T, ElementType data) { 	BiTree p, q; 	p = SearchNode(T, data); 	if (p) 		return 1; 	else 	{ 		q = (BiTreeNode *)malloc(sizeof(BiTreeNode)); 		if (q == NULL) 			return -1; 		q->data = data; 		q->lchild = NULL; 		q->rchild = NULL; 		if (p == NULL) 			T = q; 		else if (p->lchild == NULL) 			p->lchild = q; 		else 		{ 			q->lchild = p->lchild; 			p->lchild = q->lchild; 		} 	} } int DeleteNode(BiTree &T, ElementType data) { 	BiTree p, q; 	p = SearchNode(T, data); 	if (p == NULL) 		return -1; 	q = p; 	p = NULL; 	free(q); } void DestroyBiTree(BiTree &T) { 	if (T) 	{ 		DestroyBiTree(T->lchild); 		DestroyBiTree(T->rchild); 		T = NULL; 	} } int main(void) { 	BiTree T; 	T = Initate(); 	int a; 	ElementType data; 	do 	{ 		printf("二叉树的基本操作:\n"); 		printf("1.建立二叉树\n2.输出二叉树\n3.查找结点\n4.插入结点\n5.删除结点\n6.销毁二叉树\n0.退出\n"); 		printf("请选择对应的功能:\n"); 		scanf("%d", &a); 		getchar(); 		if (a == 0) 			break; 		switch (a) 		{ 		case 1: 			printf("请输入相应的数据(*表示置空):"); 			CreateBiTree(T); 			break; 		case 2: 			InOrderTraverse(T); 			break; 		case 3: 			printf("请输入结点的数据值:\n"); 			scanf("%c", &data); 			SearchNode(T, data); 			break; 		case 4: 			printf("请输入结点的数据值:\n"); 			scanf("%c", &data); 			InsertNode(T, data); 			break; 		case 5: 			printf("请输入结点的数据值:\n"); 			scanf("%c:", &data); 			DeleteNode(T, data); 			break; 		case 6: 			DestroyBiTree(T); 			break; 		} 	} while (a != 0); 	return 0; }

我觉得你出现问题的最主要的原因在于这两句： printf("请输入相应的数据(*表示置空):");     data=getchar();  这两句代码应该在函数外面，因为你要递归这个函数，放到这每次递归都会打印这句话； 而且使用getchar当你当前的输入结束时，在递归过程中标准输入的字符被读完时会发生阻塞，最好的办法是使用fgets获取整个字符串在递归中进行循环读取。  没有细调，仅供参考。

http://study.163.com/course/introduction/468002.htm#/courseDetail 数据结构教学 感觉还不错

谢谢版主大大，不过这个问题改了还是出错，我上传一张图片看看

InsertNode 函数中：  q->lchild==NULL; q->rchild==NULL;  == 改成 =


Question: 算数表达式求值出问题了，问题出现在EvaluateExpression(char inputs[])，小弟不明白，望大神赐家，谢谢

仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; }


Question: c语言数组传参

数组名作为实参，就是把数组的首元素的地址作为实参传给了函数，实际上它还是一个指针，因此你在定义函数的时候，形参既可以 写成数组形式，也可以写成指针形式； 第二个问题你没有表述清楚啊。a[10]指一个数组或者数组的元素，要看它出现的位置。如果在声明中出现，它就是一个数组，在使用过程中出现，那就是数组中的一个元素。a[10]并不能表示指针。

1.如果数组名作为实参，形参应该写成数组形式或指针变量； 例如：aver=average(score);   //数组名score作实参            float score[10];    //定义数组           ........           float average(float array[10]);   //定义函数，数组作为形参  2.(int *) a[10]是指针，指向包含10个整型元素的一维数组；    int *a[10]是数组，包含10个指向整型元素的指针；

a[10] 表示与 *(a+10)等效  也就是数组中第10个元素，但并不一定是偏移10字节大小的位置

int*p 与 int a[] 是一样的，都相当于int*p  因为数组名作为参数或者返回值已经退化为了指针

（形式）参数定义里，int *p 和 int p[] 是等价的。


Question: 关于求子串的算法，我写了代码，为什么运行是这样的？

建议单步跟踪程序运行，观察每一步所得结果是否与你期望一致

谢谢大家了！

引用 11 楼 lzhui1987 的回复: typedef struct node { 	char ch; 	struct node *next; }STRNODE;                      //串的链式存储结构表示  int str_len(STRNODE *s)            //串的长度计算函数/ { 	return s->ch; }  void str_input(STRNODE *s)          //串的输入函数/ { 	int i=0; 	char ch; 	STRNODE *p,*q; 	p=s; 	q=s->next; 	s->ch=0; 	while((ch=getchar())!='\n')         //通过循环，从键盘输入一串字符串 	{ 		q=(STRNODE *)malloc(sizeof(STRNODE)); 		q->ch=ch; 		q->next=NULL; 		p->next=q; 		p=q; 		s->ch++; 	} } STRNODE *str_sub(STRNODE *sub,STRNODE *s,int pos,int len) {//将串s第pos个字符开始的长度为len的字符序列复制到串sub中 	STRNODE *q,*p,*temp; 	int i=0,t=0; 	p=s->next; 	q=(STRNODE *)malloc(sizeof(STRNODE)); 	//q=sub->next; 	while(p!=NULL&&i!=pos) 	{ 		i++; 		p=p->next; 	} 	while(p!=NULL&&t!=len) 	{ 		q->ch=p->ch; 		temp=(STRNODE *)malloc(sizeof(STRNODE)); 		q->next=temp; 		p=p->next; 		 		//sub->ch=t; 		if(t==0) 			sub=q; 		 		t++; 		if(t!=len) 			q=q->next; 		else 			q->next=NULL; 			 	} 	return sub; } void str_print(STRNODE *s) {//字符串输出显示 	int i; 	STRNODE *p; 	p=s; 	for(i=0;i<s->ch;i++) 	{ 		putchar(p->ch); 		p=p->next; 	} 	printf("\n"); } int _tmain() { 	int position,length,no; 	STRNODE str,str1,str2; 	str.ch=0; 	str1.ch=0,str2.ch=0; 	printf("请输入一串字符："); 	fflush(stdin); 	str_input(&str1); 	printf("请输入取子串的位置和长度："); 	scanf("%d%d",&position,&length); 	str=*(str_sub(&str,&str1,position,length)); 	printf("子串为："); 	str_print(&str); }  和你的比较下，哪里不同，我这个运行正常。 恩，谢谢你的程序，不过我运行后是这样的，不知道是不是编译软件的缘故。 然后在你的想法帮助下，我改了一点点，可以运行了，我改动后的程序这样的，你可以看下。 最后还是要谢谢你，帮我解决了这些天一来的问题。

#include <stdio.h> #include <stdlib.h> #include <string.h>  #define N 100   typedef struct node { 	char ch; 	struct node *next; }Lnode,*linklist;  int main () { 	int i=1,len,pos,len1; 	char a[N]={0},b[N]={0}; 	linklist s,p; 	Lnode *q,*L; 	 	printf("请输入一段字符串:"); 	scanf("%s",a); 	printf("%s\n",a); 	if(a[0]==NULL) 		return 0; 	len=strlen(a); 	printf("%d\n",len);  	L=(Lnode *)malloc(sizeof(Lnode)); 	q=(Lnode *)malloc(sizeof(Lnode)); 	q->ch=a[0]; 	q->next=NULL; 	L->next=q; 	L->ch=len; 	s=q; 	p=L; 	   	while (i<len)      	{ 		q=(Lnode *)malloc(sizeof(Lnode)); 		q->ch=a[i]; 		q->next=NULL; 		s->next=q; 		s=q; 		i++; 	} 	printf("请输入插入的位置及长度："); 	scanf("%d%d",&pos,&len1); 	 	for(int j=0;j<pos;p=p->next,j++); 	for(i=0;i<len1;i++) 	{ 		b[i]=p->ch; 		p=p->next; 	} 	printf("%s",b); 	return 0; }

引用 8 楼 小灸舞的回复:你这个str_sub函数里，最后的while循环里while (p != NULL&&t != len) 你一直让q->ch = p->ch;有什么用？q不需要移动？ 想在定位后，将len长度的字符赋给新的链sub，应该怎么做啊

引用 5 楼 qq_36409192 的回复:[quote=引用 4 楼 unxglwy 的回复:] [quote=引用 2 楼 qq_36409192 的回复:] 程序有点混乱，看出了这么几个问题： 1.getchar的用法问题，getchar的返回值是一个int型的值，而不是char型。 2.你的i,t没初始化，然后你就直接自增了。 3.你的s的next为空，然后你又q=s->next。 4.结点中声明了一个char ch,然后你又在str_input里面又声明了同样的char ch。  ps:比较急，可能还有的问题没看出来。 谢谢你的意见，但是光从问题来说，我还是不知道从哪里去改[/quote] 你这个程序得大改，问题有点多，建议你重新写一下。[/quote] 现在把代码改成这样，但是还是运行不了，帮忙看下 #include<stdio.h> #include<stdlib.h> //#define NULL 0 typedef struct node { 	char ch; 	int len; 	struct node *next; }STRNODE;                 //串的链式存储结构表示 int str_len(STRNODE *s) {     return s->len; } void str_input(STRNODE *s) {     char ch;     STRNODE *p,*q;     p=s;     q=s->next;     s->len=0;     while((ch=getchar())!='\n')     {         q=(STRNODE*)malloc(sizeof(STRNODE));         q->ch=ch;         q->next=NULL;         p->next=q;         p=q;         s->len++;     } } void str_sub(STRNODE *sub,STRNODE *s,int pos,int len) {     STRNODE *p,*q;     int i=0,t=0;     p=s->next;     q=sub;     while(p!=NULL&&i!=pos)     {         i++;         p=p->next;     }     while(p!=NULL&&t!=len)     {         q->ch=p->ch;         p=p->next;         q->len++;         t++;     } } void str_output(STRNODE *s) {     STRNODE *p;     p=s->next;     int i;     for(i=0;i<str_len(s);i++)     {         putchar(p->ch);         p=p->next;     }     printf("\n"); } int main() {     STRNODE str,str1;     int pos,len;     printf("请输入一段字符串:");     str_input(&str1);     printf("请输入插入的位置及长度：");     scanf("%d %d",&pos,&len);     str_sub(&str,&str1,pos,len);     printf("子串为：");     str_output(&str);     return ; }

引用 4 楼 unxglwy 的回复:[quote=引用 2 楼 qq_36409192 的回复:] 程序有点混乱，看出了这么几个问题： 1.getchar的用法问题，getchar的返回值是一个int型的值，而不是char型。 2.你的i,t没初始化，然后你就直接自增了。 3.你的s的next为空，然后你又q=s->next。 4.结点中声明了一个char ch,然后你又在str_input里面又声明了同样的char ch。  ps:比较急，可能还有的问题没看出来。 谢谢你的意见，但是光从问题来说，我还是不知道从哪里去改[/quote] 你这个程序得大改，问题有点多，建议你重新写一下。

引用 2 楼 qq_36409192 的回复:程序有点混乱，看出了这么几个问题： 1.getchar的用法问题，getchar的返回值是一个int型的值，而不是char型。 2.你的i,t没初始化，然后你就直接自增了。 3.你的s的next为空，然后你又q=s->next。 4.结点中声明了一个char ch,然后你又在str_input里面又声明了同样的char ch。  ps:比较急，可能还有的问题没看出来。 谢谢你的意见，但是光从问题来说，我还是不知道从哪里去改

引用 1 楼 paschen 的回复:你str_sub函数中的变量 i 和 t 没有初始化就使用了 sorry啊，初始化后还是运行不了。不过也很谢谢你的提醒

你str_sub函数中的变量 i 和 t 没有初始化就使用了


Question: 高分求教，在线等。。。

仅供参考：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef _MSC_VER     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX; CRITICAL_SECTION cs_BBB; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int main() { #ifdef _MSC_VER     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX);     InitializeCriticalSection(&cs_BBB); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef _MSC_VER     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef _MSC_VER     DeleteCriticalSection(&cs_BBB);     DeleteCriticalSection(&cs_HEX);     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

定义一个int类型标志，线程1每次运行前都有检查这个标志，如果为0就暂停线程的运行，如果为1就继续运行，而线程2负责改变这个标志的值，这是实现控制； 定义一个char型的数组buff，线程1负责写buff，线程2负责打印buff，buff的读写要使用mutex控制以保证写完才能读，这是实现线程2的循环打印

linux系统

什么系统啊，linux吗？还是windows？


Question: 怎么实现文件中字符串查找替换功能

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

仅供参考：#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXN  40 #define MAX2N 80 FILE *fi,*fo; char sn[_MAX_PATH],dn[_MAX_PATH],f[MAX2N],bw[MAXN],bf[MAXN+sizeof(int)-1],bx[MAXN],br[MAXN+sizeof(int)-1],bb[MAXN]; char *ag[MAXN]; int L,i,j,k,lenf,lenr,find,match; __int64 off; void FR() {     printf("\n");     printf("Src : %s\n",sn);     if (find==0) {         printf("Dest: %s\n",dn);     }     for (i=0;i<lenf;i++) {         bb[i]=fgetc(fi);     }     off=0i64;     while (1) {         match=1;         for (j=0;j<lenf;j++) {             if (bw[j]==0&&bf[j]==bb[j]) continue;             if (bw[j]==1) continue;             match=0;             break;//         }         if (match==1) {             printf("%016I64X\n",off);             if (find==0) {                 for (j=0;j<lenf;j++) {                     if (bx[j]==0) fputc(br[j],fo);                     else fputc(bb[j],fo);                 }             }             for (i=0;i<lenf;i++) {                 bb[i]=fgetc(fi);                 if (feof(fi)) break;//             }             if (feof(fi)&&find==0) {                 for (j=0;j<i;j++) fputc(bb[j],fo);                 break;//             }             if (feof(fi)) break;//             else off+=(__int64)lenf;         } else {             if (find==0) {                 fputc(bb[0],fo);             }             memmove(bb,bb+1,lenf-1);             bb[lenf-1]=fgetc(fi);             off++;             if (feof(fi)) {                 if (find==0) {                     for (j=0;j<lenf-1;j++) fputc(bb[j],fo);                 }                 break;//             }         }     } } int main() {     while (1) {         printf("Find & Replace, designed by zhao4zhong1@163.com\n");         printf("Src  file name:");         fflush(stdout);         fgets(sn,_MAX_PATH,stdin);         if ('\n'==sn[0]) break;//         L=strlen(sn);if ('\n'==sn[L-1]) sn[L-1]=0;         if ((fi=fopen(sn,"rb"))==NULL) {             printf("Can not open %s!",sn);             break;//         }         while (1) {             printf("Dest file name:");             fflush(stdout);             fgets(dn,_MAX_PATH,stdin);             if ('\n'==dn[0]) break;//             L=strlen(dn);if ('\n'==dn[L-1]) dn[L-1]=0;             if (strcmpi(sn,dn)==0) printf("Error: Src file name[%s] == Dest file name[%s]!\n",sn,dn);             else if ((fo=fopen(dn,"rb"))!=NULL) {                 fclose(fo);                 printf("Error: Dest file already exists!\n");             } else break;//         }         printf("Find   :");         fflush(stdout);         fgets(f,MAX2N,stdin);         L=strlen(f);if ('\n'==f[L-1]) f[L-1]=0;         if (f[0]=='\'') {             lenf=strlen(f)-1;             for (j=0;j<lenf;j++) {                 if (f[j+1]=='?') bw[j]=1;                 else {                     bw[j]=0;                     bf[j]=f[j+1];                 }             }         } else {             i=0;             for (j=0;j<MAXN;j++) {                 if (f[i]==0x0D||f[i]==0x0A||f[i]==0x1A||f[i]==0) {                     f[i]=0;                     break;//                 }                 while (f[i]==' '||f[i]==9) {                     f[i]=0;                     i++;                 }                 ag[j]=f+i;                 while (f[i]!=9&&f[i]!=' '&&f[i]!=0x0D&&f[i]!=0x0A&&f[i]!=0x00) i++;             }             lenf=j;             for (i=0;i<lenf;i++) {                 if (isxdigit(ag[i][0])) {                     bw[i]=0;                     sscanf(ag[i],"%2x",&bf[i]);                 } else {                     bw[i]=1;                 }             }         }         printf("Replace:");         fflush(stdout);         fgets(f,MAX2N,stdin);         L=strlen(f);if ('\n'==f[L-1]) f[L-1]=0;         if (f[0]==0 || '\n'==dn[0]) find=1;         else {             if (f[0]=='\'') {                 lenr=strlen(f)-1;                 if (lenr!=lenf) {                     printf("Error: Find len != Replace len");                     fclose(fi);                     break;//                 }                 find=0;                 fo=fopen(dn,"wb");                 for (j=0;j<lenr;j++) {                     if (f[j+1]=='?') bx[j]=1;                     else {                         bx[j]=0;                         br[j]=f[j+1];                     }                 }             } else {                 i=0;                 for (j=0;j<MAXN;j++) {                     if (f[i]==0x0D||f[i]==0x0A||f[i]==0x1A||f[i]==0) {                         f[i]=0;                         break;//                     }                     while (f[i]==' '||f[i]==9) {                         f[i]=0;                         i++;                     }                     ag[j]=f+i;                     while (f[i]!=9&&f[i]!=' '&&f[i]!=0x0D&&f[i]!=0x0A&&f[i]!=0x00) i++;                 }                 lenr=j;                 if (lenr!=lenf) {                     printf("Error: Find len != Replace len");                     fclose(fi);                     break;//                 }                 find=0;                 fo=fopen(dn,"wb");                 for (i=0;i<lenr;i++) {                     if (isxdigit(ag[i][0])) {                         bx[i]=0;                         sscanf(ag[i],"%2x",&br[i]);                     } else {                         bx[i]=1;                     }                 }             }         }         if (lenf<=0) break;//         FR();         fcloseall();     }     return 0; }

替换字符串中的特定字符串  void Substitute(char *pInput, char *pOutput, char *pSrc, char *pDst)   {     char    *pi, *po, *p;     int     nSrcLen, nDstLen, nLen;        // 指向输入字符串的游动指针.     pi = pInput;         // 指向输出字符串的游动指针.     po = pOutput;     // 计算被替换串和替换串的长度.     nSrcLen = strlen(pSrc);     nDstLen = strlen(pDst);        // 查找pi指向字符串中第一次出现替换串的位置,并返回指针(找不到则返回null).        p = strstr(pi, pSrc);     if(p)     {             // 找到.         while(p)         {             //计算被替换串前边字符串的长度.             nLen = (int)(p - pi);             // 复制到输出字符串.             memcpy(po, pi, nLen);             memcpy(po + nLen, pDst, nDstLen);             // 跳过被替换串.             pi = p + nSrcLen;             // 调整指向输出串的指针位置.             po = po + nLen + nDstLen;             // 继续查找.             p = strstr(pi, pSrc);         }         // 复制剩余字符串.         strcpy(po, pi);     }     else     {         // 没有找到则原样复制.         strcpy(po, pi);     }   }     测试程序：   int main()   {          FILE *fpSrc,*fpDes;       char filename1[20]="ding1.txt";       char filename2[20]="ding2.txt";       //要求查找的字符串，替换的字符串；       char ps[]="computer";           char pd[]="basketballs";       //求取所查找和替换的字符串的长度；           int len_src=strlen(ps);       int len_des=strlen(pd);       //定义存储字符串缓冲区；很奇怪的一点是，fgets函数不能将字符串写入动态分配的内存中       /*char* Src_buf=(char*)(sizeof(char)*MAXSIZES);       char* Cpy_buf=(char*)(sizeof(char)*MAXSIZES);           char* Des_buf=(char*)(sizeof(char)*MAXSIZES);*/       char Src_buf[MAXSIZES];       char Cpy_buf[MAXSIZES];           char Des_buf[MAXSIZES];           //打开文件       if((fpSrc=fopen(filename1,"r+"))==NULL)       {           printf("fail to open the file1 !\n");          exit(1);        }       if((fpDes=fopen(filename2,"a+"))==NULL)       {           printf("fail to open the file2 !\n");           exit(1);       }       //进行循环读取       while(!feof(fpSrc))//判断文件是否已结束；!feof(fpSrc)       {           fgets(Src_buf,MAXSIZES,fpSrc);           Substitute(Src_buf,Des_buf,ps,pd);           fputs(Des_buf,fpDes);           printf("%s",Des_buf);       }       fclose(fpSrc);       fclose(fpDes);          system("pause");       return 0;   }


Question: c语言数组基础

1. 并不是一定会改变 2. 如果改变了，realloc 会负责拷贝已存在的值。


Question: 关于两头文件调用问题

什么叫不管用，上代码说清楚了。 c++ include 都是文本替换，然后才当程序编译呢。 上面两个说因为头文件 A 已经编译过了，真是难以置信，在 c++ 里，头文件压根不是编译单元，合来编译过了之说。

引用 1 楼 user-3的回复:如果其他源文件也包含了那个头文件，编译时可能先编译了那个源文件，而你的main编译时由于已经编译过那个头文件了，所以不再编译 那肿么办，才能实现那样

引用 2 楼 wh357589873的回复:对，A文件先编译。编译的时候没发现define。等后续的main定义的时候。A已经编译过了。 那怎么办 o(╥﹏╥)o


Question: 循环之后  循环体内有一条语句未执行

getchar 会把你上一次接收后留在缓冲区中换行 符\n接收了，可能通过判断接收的字符是否为\n如果是，就再次getchar()

在 p = getchar() 后面再加一个getchar().


Question: C语言%的用法

%号在C语言中就是一个整数模运算取余作用，楼主那个应该是特例数字吧。

小心整数溢出

使用位运算实现取模会更方便且高效


Question: 请求大神帮助

引用 1 楼 fefe82 的回复:break 在哪?  另：http://en.cppreference.com/w/cpp/numeric/random/rand ； rand 不对，rand 没有参数。 srand 才需要一个参数。 break在逃跑成功后面，rand我一直加参数都是对的诶 。

if(c==2)                 printf("逃跑成功\n");break;                 else                 printf("逃跑失败\n");  语法错误 要大括号~~~~