Question: 八皇后问题中出现的一个bug，传值调用后实参发生了变化？？？！！求解

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，掰手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

仅供参考：#include <stdio.h> int d[8][8]; int n; void queen8(int L) {     int x,y;      if (8==L) {         n++;         printf("%d\n",n);         for (y=0;y<8;y++) {             for (x=0;x<8;x++) { //              printf("%d",d[y][x]);                 if (d[y][x]) printf("■");                 else         printf("□");             }             printf("\n");         }         return;     }     for (x=0;x<8;x++) {         for (y=0;y<L;y++) {             if  (              d[y][x      ]              || (x-(L-y)>=0 && d[y][x-(L-y)])              || (x+(L-y)< 8 && d[y][x+(L-y)]))                 break;         }         if (y>=L) {             d[L][x]=1;             queen8(L+1);             d[L][x]=0;         }     } } int main() {     int y,x;     for (y=0;y<8;y++) {         for (x=0;x<8;x++) {             d[y][x]=0;         }     }     queen8(0);     return 0; }

i一点也不是随机值啊，就是最高字节变1，显然是越界设出来的

八皇后问题，定义的二维数组是8行8列，那么处理函数里看，是越界了。因为下标只能从0~7

引用 2 楼 Chancy_cx 的回复:square定义的是[8][8]的数组  void Changeflag(Board* board, int iQueen, int jQueen,bool flg) { 	int i = iQueen, j = 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		j++; 	}  	i = 1, j = jQueen; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++; 	}  	i = iQueen + 1, j = jQueen + 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++, j++; 	}  	i = iQueen - 1, j = jQueen - 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i--, j--; 	}  	i = iQueen + 1, j = jQueen - 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++, j--; 	}  	i = iQueen - 1, j = jQueen + 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i--, j++; 	} }  大佬 能帮忙看下吗  已经非常明显了啊，你定义的 [8][8] 的数组，下标最大应该是 7 你里面访问到 8 了 数组下标是从 0 开始的， 不是 1

引用 7 楼 Chancy_cx 的回复:[quote=引用 5 楼 cfjtaishan 的回复:] 在调用Changeflag之前，先看一下i的值是多少。这儿怀疑i是一个随机值。 544494427我的qq[/quote] 这个问题，你查看调用之前i的值了吗？

引用 5 楼 cfjtaishan 的回复:在调用Changeflag之前，先看一下i的值是多少。这儿怀疑i是一个随机值。 544494427我的qq

引用 5 楼 cfjtaishan 的回复:在调用Changeflag之前，先看一下i的值是多少。这儿怀疑i是一个随机值。 大佬 方便加个微信或者qq聊吗，现在很头疼这个问题

在调用Changeflag之前，先看一下i的值是多少。这儿怀疑i是一个随机值。

引用 2 楼 Chancy_cx 的回复:square定义的是[8][8]的数组  void Changeflag(Board* board, int iQueen, int jQueen,bool flg) { 	int i = iQueen, j = 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		j++; 	}  	i = 1, j = jQueen; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++; 	}  	i = iQueen + 1, j = jQueen + 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++, j++; 	}  	i = iQueen - 1, j = jQueen - 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i--, j--; 	}  	i = iQueen + 1, j = jQueen - 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i++, j--; 	}  	i = iQueen - 1, j = jQueen + 1; 	while (i >= 1 && i <= 8 && j >= 1 && j <= 8) 	{ 		board->square[i][j].flag = flg; 		i--, j++; 	} }  大佬 能帮忙看下吗 在调用这个函数之前，建议你先打印一下i,j，这儿怀疑变量i是一个随机值。

很明显, Changeflag 函数里面写入 board.squre 数组时发生了越界


Question: C语言除错最后一行error:expected declaration or statement at end of input谢谢

引用 2 楼 wxf2012301351 的回复: 1、问题： 以下函数前少了“}”,即main函数少了“}”  void NextPos(unsigned *x, unsigned *y, short di) /* 定位下一个位置 */ 	{ 		switch (di) { 		case 1:++(*x); break; 		case 2:++(*y); break; 		case 3:--(*x); break; 		case 4:--(*y); break; 		default: 			break; 		} 	}   2、加上“}”后的代码：  #include <stdio.h> #include <stdlib.h> typedef struct { 	unsigned ord, x, y;/*通道块在路径上的序号和在迷宫中的坐标位置*/ 	short di; /* 从此通道块走向下一通道块的“方向” */ }Elemtype; typedef struct Node { /* 定义单链表 */ 	Elemtype data; 	struct Node* next; } Node, *LinkList; typedef struct {       /* 定义链栈结构 */ 	LinkList top;      /* 栈顶指针 */ 	unsigned length;   /* 栈中元素个数 */ } LStack; void DestroyStack(LStack *S) /* 销毁栈 */ { 	LinkList q; 	while (S->top) { 		q = S->top; 		S->top = S->top->next; /* 修改栈顶指针 */ 		free(q);/* 释放被删除的结点空间 */ 	} 	S->length = 0; } void InitStack(LStack *S) /* 构造空栈 */ { 	S->top = NULL;  /* 栈顶指针初值为空 */ 	S->length = 0;   /* 空栈中元素个数为 0 */ } int Pop(LStack *s, Elemtype *e) {   /* 若栈不空，则删除 S 的栈顶元素，用 e 返回栈顶元素的值。*/ 	LinkList q; 	if (!s->top){ 		return 0; 	} 	*e = s->top->data; /* 返回栈顶元素 */ 	q = s->top; 	s->top = s->top->next; /* 修改栈顶指针 */ 	--s->length;/* 栈的长度减1 */ 	free(q);/* 释放被删除的结点空间 */ 	return 1; } int Push(LStack *S, Elemtype e) {  /* 在栈顶之上插入元素 e 为新的栈顶元素 */ 	LinkList p = (LinkList)malloc(sizeof *p); /* 建新的结点 */ 	if (!p) { 		return 0; /* 存储分配失败 */ 	} 	p->data = e; 	p->next = S->top; /* 链接到原来的栈顶 */ 	S->top = p;       /* 移动栈顶指针 */ 	++S->length;      /* 栈的长度增1 */ 	return 1; } void NextPos(unsigned *x, unsigned *y, short di); /* 定位下一个位置 */ int main(void) { 	LStack S, T; 	unsigned x, y, curstep, i = 0;/* 迷宫坐标，探索步数 */ 	Elemtype e; 	char maze[10][10] = { 		{ '#', ' ', '#', '#', '#', '#', '#', '#', '#', '#' }, 		{ '#', ' ', ' ', '#', ' ', ' ', ' ', '#', ' ', '#' }, 		{ '#', ' ', ' ', '#', ' ', ' ', ' ', '#', ' ', '#' }, 		{ '#', ' ', ' ', ' ', ' ', '#', '#', ' ', ' ', '#' }, 		{ '#', ' ', '#', '#', '#', ' ', ' ', ' ', ' ', '#' }, 		{ '#', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#' }, 		{ '#', ' ', '#', ' ', ' ', ' ', '#', ' ', ' ', '#' }, 		{ '#', ' ', '#', '#', '#', '#', '#', '#', ' ', '#' }, 		{ '#', '#', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '#' }, 		{ '#', '#', '#', '#', '#', '#', '#', '#', ' ', '#' }, 	}; 	InitStack(&S); 	InitStack(&T); 	printf("迷宫图形,#号代表墙壁,空格代表通路:\n"); 	for (x = 0; x < 10; x++) { 		for (y = 0; y < 10; y++) 			printf("%c", maze[x][y]); 		printf("\n"); 	} 	x = 1; /*迷宫起点*/ 	y = 0; 	curstep = 1; /* 探索第一步 */ 	do {  /* 进入迷宫 */ 		if (maze[y][x] == ' ') { /* 如果当前位置可以通过 */ 			maze[y][x] = '1';/* 留下足迹 */ 			e.x = x; 			e.y = y; 			e.di = 1; 			e.ord = curstep; 			if (!Push(&S, e)) { /* 加入路径，即压栈 */ 				fprintf(stderr, "内存不足。\n"); 			} 			if (x == 8 && y == 9) { /* 到达终点 */ 				break; 			} 			NextPos(&x, &y, 1); /* 下一位置是当前位置的东邻 */ 			curstep++;  		} 		else { /* 如果当前位置不能通过 */ 			if (S.length != 0) { 				Pop(&S, &e); 				while (e.di == 4 && S.length != 0) { 					maze[e.y][e.x] = '0'; /* 留下不能通过足迹 */ 					Pop(&S, &e); /* 退回一步，即出栈 */ 				} 				if (e.di < 4) { 					e.di++; 					if (!Push(&S, e)) { /* 加入路径，即压栈 */ 						fprintf(stderr, "内存不足。\n"); 					} 					x = e.x; /* 重置坐标 */ 					y = e.y; 					NextPos(&x, &y, e.di); /* 寻找下一位置 */ 				} 			} 		} 	} while (S.length != 0); 	printf("走出迷宫路线，1代表走过的路，0代表试探过的路径\n"); 	for (x = 0; x < 10; x++) { 		for (y = 0; y < 10; y++) { 			printf("%c", maze[x][y]); 			if (maze[x][y] == '1') 				i++; 		} 		printf("\n"); 		for (x = 0; x < i; x++) 		{ 			Pop(&S, &e); 			Push(&T, e); 		} 		printf("出迷宫顺序，（X坐标，Y坐标，前进方向）：\n"); 		while (T.length != 0) 		{ 			printf("(%d，%d，%d)\t", T.top->data.x, T.top->data.y, T.top->data.di); 			Pop(&T, &e); 		} 		DestroyStack(&S); 		getchar(); 		return 0; 	} } 	void NextPos(unsigned *x, unsigned *y, short di) /* 定位下一个位置 */ 	{ 		switch (di) { 		case 1:++(*x); break; 		case 2:++(*y); break; 		case 3:--(*x); break; 		case 4:--(*y); break; 		default: 			break; 		} 	}     运行结果：

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

调通了谢谢了

int main( void ) {     LStack S,T;     unsigned x,y,curstep,i=0;/* 迷宫坐标，探索步数 */     Elemtype e;     char maze[10][10] = {         {'#',' ','#','#','#','#','#','#','#','#'},         {'#',' ',' ','#',' ',' ',' ','#',' ','#'},         {'#',' ',' ','#',' ',' ',' ','#',' ','#'},         {'#',' ',' ',' ',' ','#','#',' ',' ','#'},         {'#',' ','#','#','#',' ',' ',' ',' ','#'},         {'#',' ',' ',' ','#',' ',' ',' ',' ','#'},         {'#',' ','#',' ',' ',' ','#',' ',' ','#'},         {'#',' ','#','#','#','#','#','#',' ','#'},         {'#','#',' ',' ',' ',' ',' ',' ',' ','#'},         {'#','#','#','#','#','#','#','#',' ','#'},     };     InitStack(&S);     InitStack(&T);      printf("迷宫图形,#号代表墙壁,空格代表通路:\n");     for ( x = 0;x < 10;x++) {         for ( y = 0;y < 10;y++ )             printf("%c", maze[x][y]);         printf("\n");     }     x = 1; /*迷宫起点*/     y = 0;     curstep = 1; /* 探索第一步 */     do {  /* 进入迷宫 */         if ( maze[y][x] == ' ' ) { /* 如果当前位置可以通过 */             maze[y][x] = '1';/* 留下足迹 */             e.x = x;             e.y = y;             e.di = 1;             e.ord = curstep;             if (!Push(&S,e) ) { /* 加入路径，即压栈 */                 fprintf( stderr,"内存不足。\n" );             }             if ( x == 8 && y == 9 ) { /* 到达终点 */                 break;             }             NextPos(&x, &y, 1); /* 下一位置是当前位置的东邻 */             curstep++;          }         else { /* 如果当前位置不能通过 */             if (S.length!=0) {                 Pop(&S,&e);                 while (e.di == 4 && S.length!=0) {                     maze[e.y][e.x] = '0'; /* 留下不能通过足迹 */                     Pop(&S, &e); /* 退回一步，即出栈 */                 }                 if (e.di < 4) {                     e.di++;                     if (!Push(&S,e) ) { /* 加入路径，即压栈 */                         fprintf( stderr,"内存不足。\n" );                     }                     x = e.x; /* 重置坐标 */                     y = e.y;                     NextPos(&x,&y,e.di); /* 寻找下一位置 */                 }             }         }     } while (S.length!=0);     printf("走出迷宫路线，1代表走过的路，0代表试探过的路径\n");     for ( x = 0;x < 10;x++ ) {         for ( y = 0;y < 10;y++ ) {             printf("%c",maze[x][y]);             if(maze[x][y]=='1')                 i++;         }         printf("\n");     }     for(x=0;x<i;x++)     { Pop(&S,&e);         Push(&T,e);     }     printf("出迷宫顺序，（X坐标，Y坐标，前进方向）：\n");     while(T.length!=0) {         printf("(%d，%d，%d)\t",T.top->data.x,T.top->data.y,T.top->data.di);         Pop(&T,&e);     }     DestroyStack(&S);     getchar();     return 0; } main函数里缺少一个右大括号。如果没有理解错的话，是这个循环的右大括号少了。 for ( x = 0;x < 10;x++ ) {         for ( y = 0;y < 10;y++ ) {             printf("%c",maze[x][y]);             if(maze[x][y]=='1')                 i++;         }         printf("\n");     } 在printf("\n");后面少了一个}


Question: C语言关于数组问题

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\limits.h /*** *limits.h - implementation dependent values * *       Copyright (c) Microsoft Corporation.  All rights reserved. * *Purpose: *       Contains defines for a number of implementation dependent values *       which are commonly used in C programs. *       [ANSI] * *       [Public] * ****/  #pragma once  #include <crtdefs.h>  #ifndef _INC_LIMITS #define _INC_LIMITS  #ifndef _CRTBLD /* This version of the header files is NOT for user programs.  * It is intended for use when building the C runtimes ONLY.  * The version intended for public use will not have this message.  */ #error ERROR: Use of C runtime library internal header file. #endif  /* _CRTBLD */  #define CHAR_BIT      8         /* number of bits in a char */ #define SCHAR_MIN   (-128)      /* minimum signed char value */ #define SCHAR_MAX     127       /* maximum signed char value */ #define UCHAR_MAX     0xff      /* maximum unsigned char value */  #ifndef _CHAR_UNSIGNED #define CHAR_MIN    SCHAR_MIN   /* mimimum char value */ #define CHAR_MAX    SCHAR_MAX   /* maximum char value */ #else  /* _CHAR_UNSIGNED */ #define CHAR_MIN      0 #define CHAR_MAX    UCHAR_MAX #endif  /* _CHAR_UNSIGNED */  #define MB_LEN_MAX    5             /* max. # bytes in multibyte char */ #define SHRT_MIN    (-32768)        /* minimum (signed) short value */ #define SHRT_MAX      32767         /* maximum (signed) short value */ #define USHRT_MAX     0xffff        /* maximum unsigned short value */ #define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */ #define INT_MAX       2147483647    /* maximum (signed) int value */ #define UINT_MAX      0xffffffff    /* maximum unsigned int value */ #define LONG_MIN    (-2147483647L - 1) /* minimum (signed) long value */ #define LONG_MAX      2147483647L   /* maximum (signed) long value */ #define ULONG_MAX     0xffffffffUL  /* maximum unsigned long value */ #define LLONG_MAX     9223372036854775807i64       /* maximum signed long long int value */ #define LLONG_MIN   (-9223372036854775807i64 - 1)  /* minimum signed long long int value */ #define ULLONG_MAX    0xffffffffffffffffui64       /* maximum unsigned long long int value */  #define _I8_MIN     (-127i8 - 1)    /* minimum signed 8 bit value */ #define _I8_MAX       127i8         /* maximum signed 8 bit value */ #define _UI8_MAX      0xffui8       /* maximum unsigned 8 bit value */  #define _I16_MIN    (-32767i16 - 1) /* minimum signed 16 bit value */ #define _I16_MAX      32767i16      /* maximum signed 16 bit value */ #define _UI16_MAX     0xffffui16    /* maximum unsigned 16 bit value */  #define _I32_MIN    (-2147483647i32 - 1) /* minimum signed 32 bit value */ #define _I32_MAX      2147483647i32 /* maximum signed 32 bit value */ #define _UI32_MAX     0xffffffffui32 /* maximum unsigned 32 bit value */  /* minimum signed 64 bit value */ #define _I64_MIN    (-9223372036854775807i64 - 1) /* maximum signed 64 bit value */ #define _I64_MAX      9223372036854775807i64 /* maximum unsigned 64 bit value */ #define _UI64_MAX     0xffffffffffffffffui64  #if _INTEGRAL_MAX_BITS >= 128 /* minimum signed 128 bit value */ #define _I128_MIN   (-170141183460469231731687303715884105727i128 - 1) /* maximum signed 128 bit value */ #define _I128_MAX     170141183460469231731687303715884105727i128 /* maximum unsigned 128 bit value */ #define _UI128_MAX    0xffffffffffffffffffffffffffffffffui128 #endif  /* _INTEGRAL_MAX_BITS >= 128 */  #ifndef SIZE_MAX #ifdef _WIN64 #define SIZE_MAX _UI64_MAX #else  /* _WIN64 */ #define SIZE_MAX UINT_MAX #endif  /* _WIN64 */ #endif  /* SIZE_MAX */  #if __STDC_WANT_SECURE_LIB__ /* While waiting to the C standard committee to finalize the decision on RSIZE_MAX and rsize_t,  * we define RSIZE_MAX as SIZE_MAX  */ #ifndef RSIZE_MAX #define RSIZE_MAX SIZE_MAX #endif  /* RSIZE_MAX */ #endif  /* __STDC_WANT_SECURE_LIB__ */   #endif  /* _INC_LIMITS */

元素大小和你类型的是一样的，比如你可以sizeof(int)看看

你数组是int类型的，那里面所有元素都是int能表示的范围  你数组是long long into类型的，那里面所有元素都是long long int 能表示的范围  同理其他类型

每个元素的存储范围由数组类型决定。 比如int arr[10];  那么数组中的每一个元素都是int类型的，其存储范围也就是int的存储范围，具体数值大小，看一下limits.h更准确一些。  可以定义long  long int a[10]; 类型的数组，每个元素都是long long int 类型的，但定义数组的不可丢掉数组长度。

引用 3 楼 zj19941201 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] 定义的数组，数组中每个元素存放的值的范围跟该数组元素的类型有关，数组元素的类型决定了存放的值的范围； C语言中定义的数组需要指定其长度，因此定义long long int a[]是缺少长度的，定义不合法。  我想要问的问题你没弄清呢，我不是说数组的长度，我说的是数组的成员所能存放的数值范围[/quote] 嗯？我说了，是由其数组类型决定其存放的值的范围。

为什么不打开include\limits.h亲自看一看呢？

引用 2 楼 user-6 的回复:可以，你定义什么类型的数组，它的成员就是什么类型。  哦哦，明白了，我试试看。

引用 1 楼 cfjtaishan 的回复:定义的数组，数组中每个元素存放的值的范围跟该数组元素的类型有关，数组元素的类型决定了存放的值的范围； C语言中定义的数组需要指定其长度，因此定义long long int a[]是缺少长度的，定义不合法。  我想要问的问题你没弄清呢，我不是说数组的长度，我说的是数组的成员所能存放的数值范围

可以，你定义什么类型的数组，它的成员就是什么类型。


Question: 知道函数的功能，那么函数参数该如何定义？

引用 3 楼 g62r83t27 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 参考Google Protobuf源代码。 我只想问一个函数接口，你却让我看一个工程。。。。。。 使坏啊，赵老师[/quote] 斩草要除根！

引用 4 楼 g62r83t27 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 需要定义两个函数吧，一个是处理协议B的函数，一个是解析协议A的，解析协议B的函数由解析函数A的调用。 函数的传入参数，对于函数A，传递的是包含协议A和B的缓存数据，还有就是缓存数据的长度。函数B传入参数那应该是协议B数据开始的位置（地址）和数据的长度 B是被A包含的，我需要一个处理A的，把A 中的B分离出来，给DealB，把不属于B的A给DealA， 现在我要写的是SearchA(。。。。。。)，SearchA中不能调用DealA，也不能调用DealB，只能通过参数和返回值告诉你什么情况下调用DealA且传给DealA什么数据，和什么情况下调用DealB和传递给DealB什么数据。。。 [/quote] 那就通过searchA函数的返回值来确定是调用A还是调用B，通过参数的传出参数来确定buffer开始的多少个字节开始是A协议或者B协议开头； 如果还想知道B协议的长度，那么再用一个传出参数得到协议的长度。

引用 2 楼 cfjtaishan 的回复:需要定义两个函数吧，一个是处理协议B的函数，一个是解析协议A的，解析协议B的函数由解析函数A的调用。 函数的传入参数，对于函数A，传递的是包含协议A和B的缓存数据，还有就是缓存数据的长度。函数B传入参数那应该是协议B数据开始的位置（地址）和数据的长度 B是被A包含的，我需要一个处理A的，把A 中的B分离出来，给DealB，把不属于B的A给DealA， 现在我要写的是SearchA(。。。。。。)，SearchA中不能调用DealA，也不能调用DealB，只能通过参数和返回值告诉你什么情况下调用DealA且传给DealA什么数据，和什么情况下调用DealB和传递给DealB什么数据。。。

引用 1 楼 zhao4zhong1 的回复:参考Google Protobuf源代码。 我只想问一个函数接口，你却让我看一个工程。。。。。。 使坏啊，赵老师

参考Google Protobuf源代码。


Question: 用结构体数组编写学生信息管理系统其中学科成绩等运用二分查找和顺序查找！！！求大神帮忙改一下！！！

#include <stdio.h> #include <stdlib.h> #include <string.h> struct node {     int code;     char name[20];     char type;     int age;     int chinese;     int math;     int total; }stud[100]; struct node temp; void menu(); int input(); void find(int); void insert(int); void deletel(int); void print(int); void sort(int);  int main() {     int n,c=0,d=0;     while(1)     {         menu();         scanf("%d",&n);         switch(n)         {             case 1:system("cls");d=input();c+=d;break;             case 2:system("cls");find(c);break;             case 3:system("cls");insert(c);++c;break;             case 4:system("cls");deletel(c);--c;break;             case 5:system("cls");print(c);break;             case 6:system("cls");sort(c);break;             case 7:exit(0);break;             default:                    printf("输入错误，请输入(1-7):\n");                    printf("按回车键继续...\n");                    getchar();         }     }      return 0; } void menu(void) {     system("cls");     printf("\t\t学生信息管理系统\n");     printf("\t\t***************\n");     printf("\t\t**  欢迎使用  **\n");     printf("\t\t*[1]输入数据*\n");     printf("\t\t*[2]查找数据*\n");     printf("\t\t*[3]插入数据*\n");     printf("\t\t*[4]删除数据*\n");     printf("\t\t*[5]打印数据*\n");     printf("\t\t*[6]排序数据*\n");     printf("\t\t*[7]退出*\n");     printf("\t\t**  欢迎使用 **\n");     printf("\t\t***************\n");     printf("\t\t请输入你的选项(1-7):"); } int input() {     int i,n;     printf("请输入要插入几位学生信息:\n");     scanf("%d",&n);     for(i=0;i<n;i++)     {         printf("请输入第%d个学生学号:",i+1);         scanf("%d",&stud[i].code);         printf("第%d个学生姓名:",i+1);         scanf("%s", stud[i].name);         getchar();         printf("第%d个学生性别F/M:",i+1);         scanf("%c",&stud[i].type);         printf("第%d个学生年龄:",i+1);         scanf("%d",&stud[i].age);         printf("第%d个学生语文成绩:",i+1);         scanf("%d",&stud[i].chinese);         printf("第%d个学生数学成绩:",i+1);         scanf("%d",&stud[i].math);         stud[i].total = stud[i].chinese + stud[i].math;     }     return n; } void find(int c) {     int n,m,i,j,l;     char k[20];     system("cls");     printf("输入1学号查找\n输入2按姓名查找\n");     printf("请选择:");     scanf("%d",&n);     if(n==1)     {         printf("请输入学生学号:");         scanf("%d",&m);         for(i=0;i<c;i++)         {             if(stud[i].code==m)             {                 printf("**********************\n");                 printf("学号:%d\n",stud[i].code);                 printf("姓名:%s\n",stud[i].name);                 printf("性别:%c\n",stud[i].type);                 printf("年龄:%d\n",stud[i].age);                 printf("语文成绩:%d\n",stud[i].chinese);                 printf("数学成绩:%d\n",stud[i].math);                 printf("总分:%d\n",stud[i].total);                 printf("**********************\n");                 printf("回车键返回\n");                 getchar();                 getchar();             }         }     }     else         if(n==2)         {             getchar();             printf("请输入姓名:");             fgets(k,20,stdin);             l=strlen(k);             k[l-1]='\0';             for(j=0;j<c;j++)             {                 if(strcmp(k,stud[j].name)==0)                 {                     printf("**********************\n");                     printf("学号:%d\n",stud[j].code);                     printf("姓名:%s\n",stud[j].name);                     printf("性别:%c\n",stud[j].type);                     printf("年龄:%d\n",stud[j].age);                     printf("语文成绩:%d\n",stud[j].chinese);                     printf("数学成绩:%d\n",stud[j].math);                     printf("总分:%d\n",stud[j].total);                     printf("**********************\n");                     printf("回车键返回\n");                     getchar();                     getchar();                 }             }         }         else         {             getchar();             getchar();         } } void insert(int c) {     int i,j;     system("cls");     printf("请输入要插入学生的信息:\n");     printf("请输入学号:");     scanf("%d",&temp.code);     printf("请输入姓名:");     scanf("%s", temp.name);     getchar();     printf("请输入性别F/M:");     scanf("%c",&temp.type);     printf("请输入年龄:");     scanf("%d",&temp.age);     printf("请输入语文成绩:");     scanf("%d",&temp.chinese);     printf("请输入数学成绩:");     scanf("%d",&temp.math);     temp.total=temp.chinese+temp.math;     for(i=0;i<c;i++)     {         if(temp.code<stud[i].code)         {             for(j=c;j>i;j--)             {                 stud[j].code=stud[j-1].code;                 strcpy(stud[j].name,stud[j-1].name);                 stud[j].type=stud[j-1].type;                 stud[j].age=stud[j-1].age;                 stud[j].chinese=stud[j-1].chinese;                 stud[j].math=stud[j-1].math;                 stud[j].total=stud[j-1].total;             }             stud[j].code=temp.code;             strcpy(stud[j].name,temp.name);             stud[j].type=temp.type;             stud[j].age=temp.age;             stud[j].chinese=temp.chinese;             stud[j].math=temp.math;             stud[j].total=temp.total;             break;         }     }     if(i>=c)     {         stud[i].code=temp.code;         strcpy(stud[i].name,temp.name);         stud[i].type=temp.type;         stud[i].age=temp.age;         stud[i].chinese=temp.chinese;         stud[i].math=temp.math;         stud[i].total=temp.total;     } } void deletel(int c) {     int i,j,n;     printf("请输入要删除的学号:\n");     scanf("%d",&n);     for(i=0;i<c;i++)     {         if(stud[i].code==n)         {             c=c-1;             for(j=i;j<c;j++)             {                 stud[j].code=stud[j+1].code;                 strcpy(stud[j].name,stud[j+1].name);                 stud[j].type=stud[j+1].type;                 stud[j].age=stud[j+1].age;                 stud[j].chinese=stud[j+1].chinese;                 stud[j].math=stud[j+1].math;                 stud[j].total=stud[j+1].total;             }         }     }     getchar();     printf("按回车键继续...\n");     getchar(); } void print(int c) {     int i;     system("cls");     for(i=0;i<c;i++)     {         printf("********************\n");         printf("学号:%d\n",stud[i].code);         printf("姓名:%s\n",stud[i].name);         printf("性别:%c\n",stud[i].type);         printf("年龄:%d\n",stud[i].age);         printf("语文成绩:%d\n",stud[i].chinese);         printf("数学成绩:%d\n",stud[i].math);         printf("总分:%d\n",stud[i].total);         printf("**********************\n");     }     printf("按回车键继续...\n");     getchar();     getchar(); } void sort(int c) {     int i,j,n;     printf("学号排序\n");     for(i=c-1;i>0;i--)         for(j=0;j<i;j++)             if(stud[j].code>stud[j+1].code)             {                 temp      = stud[j];                 stud[j]   = stud[j+1];                 stud[j+1] = temp;                 /*                 temp.code=stud[j].code;                 strcpy(temp.name,stud[j].name);                 temp.type=stud[j].type;                 temp.age=stud[j].age;                 temp.chinese=stud[j].chinese;                 temp.math=stud[j].math;                 temp.total=stud[j].total;                 stud[j].code=stud[j+1].code;                 strcpy(stud[j].name,stud[j+1].name);                 stud[j].type=stud[j+1].type;                 stud[j].age=stud[j+1].age;                 stud[j].chinese=stud[j+1].chinese;                 stud[j].math=stud[j+1].math;                 stud[j].total=stud[j+1].total;                 stud[j+1].code=temp.code;                 strcpy(stud[j+1].name,temp.name);                 stud[j+1].type=temp.type;                 stud[j+1].age=temp.age;                 stud[j+1].chinese=temp.chinese;                 stud[j+1].math=temp.math;                 stud[j+1].total=temp.total;                 */             }     getchar();     getchar(); }  两处错误，scanf输入name时，去掉前面的&；另外，排序时，不需要将结构体中的所有元素分别交换，直接给结构体赋值即可。详见上面的代码； 另外，二分查找需要先将程序执行一下排序（可以使用回调函数和函数指针），然后在使用折半查找。顺序查找不需要。


Question: 求每个选项解释一次和静态变量会怎样

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

这个程序考察的是变量的声明周期： 全局变量,static静态变量，是在内存的数据段申请的空间，其生命周期是整个程序开始到程序的结束； 局部变量，即在函数内或语句体内定义的变量，其作用域函数或语句体内有效，其生命周期是函数的创建开始到函数调用结束； 另外，需要注意的是当局部变量名和全局变量名同名时，局部变量会屏蔽全局变量，即在函数内全局变量无效。

这个是考变量作用域与优先级 1, 在fun中定义了k,  局部变量优先, 所以全局变量k被隐藏,就像没有一样. fun函数中全部都是使用的局部变量k 回到main中后, 仍然是全局变量k 2. fun 中使用的也是全局变量k,   这就不用解释了  3. 首先 fun中的k也是一个局部 变量,局部优先,所以在fun中仍然会隐藏掉全局的k.   只是它是static的,  在函数内部的static变量只被会定义一次, 以后的调用就使用的都是同一个, 不会像普通变量那样, 每次都重新分配. 比如第一个调用fun, k++后变成2, 第二次调用fun, 再k++就变成3了.   回到main中printf时, 跟1相同, 是使用全局的k  4. 跟2是一样的, 只是少了每次fun中初始化为1.

2和4就是改变全局变量的值 3，static延长函数生命周期，自己查下他的作用，还有是怎么实现的

1.一个函数执行时，从栈里分配局部变量的空间，函数执行结束时会回收栈里分配的空间。


Question: C语言 万年历 一行输出两个月

引用 5 楼 棉猴 的回复： #include "stdafx.h" #include <stdio.h>  int year(int y) { 	if ((y % 4 == 0) && (y % 100 != 0) || y % 400 == 0) 		return 366; 	else 		return 365; }   int main() { 	int y; 	int i, j, sum = 0, t = 0; 	int begin, week; 	int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };  	scanf_s("%d", &y); 	for (i = 1; i<y; i++) 		sum += year(i);  	week = (sum + 1) % 7;     //表示该年1月1日为星期几 	int next_begin, next_week; 	 	if (year(y) == 366) 		days[1] = 29;  	printf("\n%d年日历如下：\n\n", y); 	int week_num, next_week_num, max_week_num;//本月和下一个月包含的星期数 	char two_monthes_week[200] = { 0 }; 	for (i = 0; i<12; i = i + 2) 	{ 		printf("       %d月                       %d月                \n", i + 1, i+2); 		printf("  7  1  2  3  4  5  6      7  1  2  3  4  5  6  \n "); 		printf("=======================  =======================\n"); 		begin = 1; 		next_begin = 1; 		int temp_sum = sum; 		for (int j = 0; j < i; ++j) 		{ 			temp_sum = (temp_sum +days[j]); 		} 		week = (temp_sum + 1) % 7;//当前月的1号是星期几 		next_week = (days[i] + week) % 7;//下一个月的1号是星期几 		//获取两个月中包含的星期数的最大值 		//第一个月包含的星期数 		if (week + days[i] % 7 == 0) 		{ 			week_num = (week + days[i]) / 7; 		} 		else 		{ 			week_num = ((week + days[i]) / 7) + 1; 		} 		//第二个月包含的星期数 		if (next_week + days[i+1] % 7 == 0) 		{ 			next_week_num = (next_week + days[i+1]) / 7; 		} 		else 		{ 			next_week_num = ((next_week + days[i+1]) / 7) + 1; 		} 		//取两个月星期数的最大值 		if (week_num >= next_week_num) 		{ 			max_week_num = week_num; 		} 		else 		{ 			max_week_num = next_week_num; 		} 		//循环，每个循环为一个星期 		bool is_first_week = true; 		int length = 0; 		for (int j = 0; j < max_week_num; ++j)//遍历每个星期 		{  			while ((week % 7 != 0) || (week == 0))//一个星期是否结束 			{ 				if (is_first_week)//如果是第一个星期，，则需要输出空格 				{ 					for (int k = 0; k < week; ++k)//输出空格 					{ 						length += sprintf_s(two_monthes_week + length, 200 - length, "%s", "   "); 					} 					is_first_week = false;//只需要第一个星期输出 				} 				if (begin <= days[i])//如果超出了这个月的日期，则输出空格 				{ 					length += sprintf_s(two_monthes_week + length, 200 - length, "%3d", begin); 				} 				else 				{ 					length += sprintf_s(two_monthes_week + length, 200 - length, "%s", "   "); 				} 				week++; 				begin++; 			} 			//输出下一个月 			is_first_week = true; 			length += sprintf_s(two_monthes_week + length, 200 - length, "%s", "    "); 			while ((next_week % 7 != 0) || (next_week == 0))//一个星期是否结束 			{ 				if (is_first_week)//如果是第一个星期，，则需要输出空格 				{ 					for (int k = 0; k < next_week; ++k) 					{ 						length += sprintf_s(two_monthes_week + length, 200 - length, "%s", "   "); 					} 					is_first_week = false; 				} 				if (next_begin <= days[i + 1]) 				{ 					length += sprintf_s(two_monthes_week + length, 200 - length, "%3d", next_begin); 				} 				else 				{ 					length += sprintf_s(two_monthes_week + length, 200 - length, "%s", "   "); 				} 				next_week++; 				next_begin++; 			} 			printf(two_monthes_week); 			printf("\n"); 			week = 0; 			next_week = 0; 			length = 0; 		} 	}      return 0; }   能发送一下代码嘛，不能复制

写了两篇关于万年历的小文章，请多指教 http://blog.csdn.net/hou09tian/article/details/73928669 http://blog.csdn.net/hou09tian/article/details/73928712

百度搜相关关键字。

怎么做到一行输出两个月？

引用 1 楼 qq_37560806 的回复:怎么做到一行输出两个月？  sprintf到一个字符数组 int len=sprintf(buffer,"。。。"); len=sprintf(buffer+len,"。。。");


Question: 本人新手  求大神帮助

仅供参考：#include <conio.h> #include <windows.h>  void ConPrintAt(int x, int y, char *CharBuffer, int len) {    DWORD count;    COORD coord = {x, y};    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleCursorPosition(hStdOut, coord);    WriteConsole(hStdOut, CharBuffer, len, &count, NULL); } void HideTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = FALSE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } }  void ShowTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = TRUE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } } void GetWH(int *w,int *h) {     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     CONSOLE_SCREEN_BUFFER_INFO csbi;     if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {         *w=csbi.srWindow.Right;         *h=csbi.srWindow.Bottom;     } else {         *w=80;         *h=25;     } } void ClearConsole() {    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //   not used but we need to capture this since it will be    //   written anyway (passing NULL causes an access violation).    DWORD count;    //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  int main() {     unsigned short k;     int x,y,w,h;     char d;      SetConsoleOutputCP(437);     ClearConsole();     GetWH(&w,&h);     x=w/2;y=h/2;     HideTheCursor();     ConPrintAt(x,y,"O",1);     d='o';     while (1) {         Sleep(50);         if (kbhit()) {             k=getch();             if (27==k) break;//按Esc键退出             if (0==k||0xe0==k) k|=getch()<<8;//非字符键             switch (k) {                 case 0x48e0:case 0x04800://上                     d='u';                     if (y>0) {                         ConPrintAt(x,y," ",1);                         y--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x50e0:case 0x05000://下                     d='d';                     if (y<h) {                         ConPrintAt(x,y," ",1);                         y++;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x4be0:case 0x04b00://左                     d='l';                     if (x>0) {                         ConPrintAt(x,y," ",1);                         x--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 0x4de0:case 0x04d00://右                     d='r';                     if (x<w-1) {                         ConPrintAt(x,y," ",1);                         x++;                         ConPrintAt(x,y,"O",1);                     }                 break;             } //          cprintf("%04x pressed.\r\n",k);         } else {             switch (d) {                 case 'u':                     if (y>0) {                         ConPrintAt(x,y," ",1);                         y--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'd':                     if (y<h) {                         ConPrintAt(x,y," ",1);                         y++;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'l':                     if (x>0) {                         ConPrintAt(x,y," ",1);                         x--;                         ConPrintAt(x,y,"O",1);                     }                 break;                 case 'r':                     if (x<w-1) {                         ConPrintAt(x,y," ",1);                         x++;                         ConPrintAt(x,y,"O",1);                     }                 break;             }         }     }     ClearConsole();     ShowTheCursor();     return 0; }


Question: 数据存储问题

出现乱码是正常的，因为x是int类型的，以fputc是按字节写入的，那么很有肯定是有乱码的。 建议改成fprintf(fp, "%d\n", x[i][j]);  void save(int(*x)[M]) {     FILE *fp;     printf("输入存放的文件名：");     char filename[10];     scanf("%s", filename);     if ((fp = fopen(filename, "w")) == NULL)     {             printf("无法打开此文件\n");             exit(0);         }     int i, j;     for (i = 0; i < N; i++)     {             for (j = 0; j < M; j++)             {                 fprintf(fp, "%d\n", x[i][j]);                     }         }     fclose(fp); }

引用 1 楼 user-3 的回复:“w” 改成 “wt” fputc 改成 fprintf 谢谢，完成了， fprintf(fp,"%d",*(*(x + i) + j)); 			fputs("\n", fp);

这里存的是数字1，2，3等对应的字符当然是乱码，不是存的的'1'，'2'

“w” 改成 “wt” fputc 改成 fprintf


Question: 有没有大神帮我解密一下

完全不知道BF语句是什么, 百度都搜不到


Question: restrict 关键字 的作用

明白啦～十分感谢上面的回复～受到帮助真是太感动啦~

restrict 只是告诉编译器，以便于优化  而并不是用于确保地址不重叠

restrict的定义是 ( restrict type qualifier )： During each execution of a block in which a restricted pointer P is declared (typically each execution of a function body in which P is a function parameter), if some object that is accessible through P (directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P (directly or indirectly), otherwise the behavior is undefined.  也就是说，restrict是程序员告诉编译器额外的信息：在restric所修饰指针P所生存的作用域内，程序员保证只有指针P是指向P所指向的这片内存的，没有‘别人’可以修改这个指针指向的这片内存，所有修改都得通过这个指针来。这就有助于编译器优化代码，如果程序员违反这个约定，则行为时未定义的。  举个栗子  int fun(int *a, int *b) {     *a = 5;     *b = 6;     return *a + *b;    //不一定返回11 }  如果指针a和指针b指向同一个对象，*b = 6会导致 *a为6，返回12.所以编译器在做return *a + *b 的时候需要重新读取*a 的值。  fun:     movl $5,(%rdi)    #存储5到*a     movl $6,(%rsi)    #存储6到*b     movl (%rdi),%eax    #重新读取*a     addl $6,%eax      #加上6     ret  如果我们确保两个指针不会指向同一个对象，则可以使用restrict修饰指针变量  int rfun(int *restrict a, int *restrict b) {     *a = 5;     *b = 6;     return *a + *b;  }  编译器可以根据这个信息做优化  rfun:     movl $11,%eax   #在编译期就可以计算出11     movl $5,(%rdi)    #存储5到*a     movl $6,(%rsi)    #存储6到*b     ret  总而言之，restrict是为了告诉编译器指针独享指针所指向的内存，从而编译器能生成更优化的机器码。编译器是无法检测指针是否独享指针指向内存的，所以如果程序员使用restrict，那么程序员也需要遵守相应的契约保证才能得出正确的代码，否则，行为是未定义的。

restrict的定义是 ( restrict type qualifier )： During each execution of a block in which a restricted pointer P is declared (typically each execution of a function body in which P is a function parameter), if some object that is accessible through P (directly or indirectly) is modified, by any means, then all accesses to that object (both reads and writes) in that block must occur through P (directly or indirectly), otherwise the behavior is undefined.  也就是说，restrict是程序员告诉编译器额外的信息：在restric所修饰指针P所生存的作用域内，程序员保证只有指针P是指向P所指向的这片内存的，没有‘别人’可以修改这个指针指向的这片内存，所有修改都得通过这个指针来。这就有助于编译器优化代码，如果程序员违反这个约定，则行为时未定义的。  举个栗子  int fun(int *a, int *b) {     *a = 5;     *b = 6;     return *a + *b;    //不一定返回11 }  如果指针a和指针b指向同一个对象，*b = 6会导致 *a为6，返回12.所以编译器在做return *a + *b 的时候需要重新读取*a 的值。  fun:     movl $5,(%rdi)    #存储5到*a     movl $6,(%rsi)    #存储6到*b     movl (%rdi),%eax    #重新读取*a     addl $6,%eax      #加上6     ret  如果我们确保两个指针不会指向同一个对象，则可以使用restrict修饰指针变量  int rfun(int *restrict a, int *restrict b) {     *a = 5;     *b = 6;     return *a + *b;  }  编译器可以根据这个信息做优化  rfun:     movl $11,%eax   #在编译期就可以计算出11     movl $5,(%rdi)    #存储5到*a     movl $6,(%rsi)    #存储6到*b     ret  总而言之，restrict是为了告诉编译器指针独享指针所指向的内存，从而编译器能生成更优化的机器码。编译器是无法检测指针是否独享指针指向内存的，所以如果程序员使用restrict，那么程序员也需要遵守相应的契约保证才能得出正确的代码，否则，行为时未定义的。


Question: 明明文件已经建立了，为什么文件里什么内容都没有

引用 2 楼 zuoside__lord 的回复:引用 1 楼 ipqtjmqj 的回复:用w会将原文件清空，可是我要写进去啊，不用w用什么， 用a,append

用w会将原文件清空

单步跟踪程序运行，检查是否执行到写操作，同时在fclose后再查看文件中的内容


Question: 怎么才能让第一行的“*”从1个开始  而不是2个

int main() {     int i,j;     for (i = 0; i < 10; i++) {         for (j = 0; j <=i ; j++) {             printf("*");         }         printf("\n");     } }

j <= i + 1  去掉 +1 或者去掉 = 都行

#include <stdio.h>  int main() {     int i,j;     for (i = 0; i < 10; i++) {         for (j = 0; j <= i + 1; j++) {             printf("*");         }         printf("\n");     } }


Question: 结构体内不同的变量要怎么输入？

%s并不是按逗号进行分割  你可以分成多个scanf，各输入间用回车分隔

我的印象中输入时scanf是认空格和回车为数据分隔符的

引用 2 楼 xian_wwq 的回复:输入字符串之间用空格分割, 可以实现scanf函数连续输入多个字符串。 例如：  char s1[100],s2[100],s3[100]; scanf("%s%s%s",s1,s2,s3);  如果输入it is bad回车，s1中将存放it, s2中存放is, s3中存放bad。   scanf("%d,%s,%s,%d",&p1->number,p1->name,p1->sex,&p1->age);   中的”,'最好去掉，否则输入的时候就要加上”,“ 如果要输入有空格的字符串该怎么写呢

题目中的现象是正常的。 用%s，会将之后对应的输入都视为字符串接收。  解决办法是对四个成员分别输入：         printf("input number:\n"); 	scanf("%d", &p1->number); 	printf("input name:\n"); 	scanf("%s", p1->name); 	printf("input sex:\n"); 	scanf("%s", p1->sex); 	printf("input age:\n"); 	scanf("%d", &p1->age); 用心回答每个问题，如果对您有帮助，请采纳答案好吗，谢谢！


Question: 新手C语言入门，求助！

虽然是个很简单的问题，却困扰了我一下午，谢谢！

char *q = (char*)malloc(strlen(s) - strlen(p) + 1);  //q分配了 5 - 3 + 1 = 3个字符 	int i; 	for (i = 0; i < strlen(s) - strlen(p); i++) {  //循环体中只处理了前2个字符 		printf("%d\n", i); 		q[i] = s[i]; 		printf("%c\n", q[i]);  	} 	q[i] = '\0';   //第3个字符需赋值为字符串结束符，否则q[3]是不确定值，就会出现题目中的现象 用心回答每个问题，如果对您有帮助，请采纳答案好吗，谢谢！


Question: 求各位大神帮我修改一下本图书管理系统的BUG，本人万分感谢

感谢各位帮助了。我改一下试试看。意见好多啊，不过我也受教了。蟹蟹！

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0];  “多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，掰手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

//#include"stdafx.h" #include<stdio.h> #include<stdlib.h> #include<string.h>  typedef struct node {     int num;//书号     char title[50];//书名     char author[50];//著作者     int num1;//现存量     int num2;//库存量     char name[50];//借阅者姓名     int idnum;//学生证号     struct node *link; }linklist;  linklist* creatnull(linklist *l)//申请单链表的空间 {     l = (linklist*)malloc(sizeof(linklist));//申请空间     l->link = NULL;//尾结点置空     return l; } void creat(linklist **l)//采编入库 {     int i,n;     linklist *p,*tail,*q;     tail = *l;     if((*l)->link!=NULL)//判断：下一结点不为空         q= (*l)->link;//q指针指向下一个结点     else q = *l;//输入数据读入     while(tail->link!=NULL)     {         tail=tail->link;     };     printf("\n请输入入库图书的数量:");     scanf("%d",&n);     for(i=1;i<=n;i++)     {         p=(linklist*)malloc(sizeof(linklist));         printf("\n请输入入库图书的书号:");         scanf("%d",&p->num);         while(q->num!=p->num&&q->link!=NULL)//输入的书名重复         {             q=q->link;         }         if(q->num==p->num)         {             q->num1=q->num1+1;             q->num2=q->num2+1;             printf("\n该图书已在图书库存在，已自动增加图书数量");}         else         {             printf("\n请输入入库图书的书名:");             scanf("%s", p->title);//传入数据至单链表数据域             printf("\n请输入入库图书的著作者:");             scanf("%s", p->author);             printf("\n请输入入库图书的现存量:");             scanf("%d",&p->num1);             printf("\n请输入入库图书的库存量:");             scanf("%d",&p->num2);             strcpy(p->name,"NULL");             tail->link=p;             tail=p;             tail->link=NULL;//尾结点置空          };     }  } void print(linklist *l)//输出所有图书的信息 {     linklist *p;     p=l->link;     printf("\n输出所有图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");     while(p)//单链表没读完     {         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         p=p->link;     } }  void locat(linklist *l,int i)//根据书号查找图书    i是输入的书号 {     int count=0;     linklist *p;     p=l->link;     while(p->link!=NULL)     {         if(p->num!=i)         {             p=p->link;//下移一个结点         }         else         {             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);             p=p->link;             count++;   //同书号的有多少个         }     };     if(p->num==i)     {         printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         count++;     }     if(count==0)         printf("该图书不在此书库！"); }  void locat1(linklist *l,int j)//根据学号查询 {     int count=0;     linklist *p;     p=l->link;     while(p->link!=NULL)     {         if(p->idnum!=j)         {             p=p->link;         }         else         {             printf("\n输出学生的信息:\n学号\t借阅者姓名\t书号\t书名\t著作者");             printf("\n%d\t%s\t\t%d\t%s\t%s\n",p->idnum,p->name,p->num,p->title,p->author);             p=p->link;             count++;         }     };     if(p->idnum==j)     {         printf("\n输出学生的信息:\n学号\t借阅者姓名\t书号\t书名\t著作者");         printf("\n%d\t%s\t\t%d\t%s\t%s\n",p->idnum,p->name,p->num,p->title,p->author);         p=p->link;         count++;     }     if(count==0)         printf("该学生未借阅！"); }  void borrowbook(linklist *l)//借阅 {     linklist *p;     int i;     int count=0;     printf("\n借阅的图书书号:");     scanf("%d", &i);     p = l->link;      printf("bookno = %d\n", i);     while(p != NULL)     {         if(p->num != i)         {             p=p->link;         }         else         {             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);             //p = p->link;             break;             count++;         }     }     if(p != NULL && p->num == i)     {         printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");         printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         count++;     }     if(count == 0)     {         printf("该图书不在此书库！");     }     else     {         if(p->num1<=0)         {             printf("\n该书库存不足,读者无法借阅.");         }         else         {             p->num1=p->num1-1;             printf("\n请输入借阅者的姓名:");             scanf("%s", p->name);             printf("\n请输入借阅者的学生证号:");             scanf("%d",&p->idnum);             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量\t借阅者姓名\t学生证号");             printf("\n%d\t%s\t%s\t%d\t%d\t%s\t\t%d\n",p->num,p->title,p->author,p->num1,p->num2,p->name,p->idnum);         }     } }  void returnbook(linklist *l)//归还 {     linklist *p;int i,a;     int count=0;     int counta=0;     printf("\n请输入归还图书的书号:");     scanf("%d",&i);     p = l->link;      while(p != NULL)     {         if(p->num!=i){p=p->link;}         else         {             break;         }     };     if(p->num==i){         count++;     }     if(count==0)     {         printf("该图书不在此书库！");     }     else     {         printf("\n请输入学生证号:");         scanf("%d",&a);         p = l->link;         while(p)         {             if(p->idnum!=a){                 p=p->link;             }             else             {                 break;             }         }         if(p && p->idnum==a) {             counta++;         }         if(counta==0)         {             printf("该学生未借阅图书！");         }         else         {             p->num1=p->num1+1;             strcpy(p->name,"NULL");             printf("\n输出图书的信息:\n书号\t书名\t著作者\t现存量\t库存量");             printf("\n%d\t%s\t%s\t%d\t%d\n",p->num,p->title,p->author,p->num1,p->num2);         }     } } int main() {     linklist l,*head;//初始化单链表头结点     head=creatnull(&l);     printf("                 *********************************\n");     printf("                       欢迎使用图书管理系统       \n");     printf("                 *********************************\n");     printf("\n");     int flag=1,a;     while(flag)     {         printf("               *************************************\n");         printf("                          1:馆藏图书信息            \n");         printf("                          2:采编入库                \n");         printf("                          3:图书查询                \n");         printf("                          4:学号查询                \n");         printf("                          5:读者借阅                \n");         printf("                          6:读者归还                \n");         printf("                          7:退出图书管理系统        \n");         printf("               *************************************\n");         printf("                            请输入您的选项：");         scanf("%d",&a);         switch(a)         {              case 7:flag=0;                    printf("                 *********************************\n");                    printf("                       成功退出图书管理系统       \n");                    printf("                 *********************************\n");                    break;             case 1:flag=1;                    print(head);                    printf("\n\n\n");                    break;             case 2:flag=1;                    creat(&head);                    printf("\n\n\n");                    break;             case 3:flag=1;                    int number;//书号                    printf("\n请输入要查找的图书书号:");                    scanf("%d",&number);                    locat(head,number);                    printf("\n\n\n");                    break;             case 4:flag=1;                    int idnumber;//学号                    printf("\n请输入要查找的学号:");                    scanf("%d",&idnumber);                    locat1(head,idnumber);                    printf("\n\n\n");                    break;             case 5:                    flag=1;                      borrowbook(head);                    printf("\n\n\n");                    break;             case 6:flag=1;                    returnbook(head);                    printf("\n\n\n");                    break;         }     }     system("pause");     return 1; } 除了scanf处输入有若干错误；主要是scanf以%s输入时，不需要加前面的&，因为数组名本身就是地址。 借书和还书还有问题，逻辑上还存在问题。链表遍历时，不能遍历到最后一个节点，所以改成while (p)形式判断。另外，若找到节点，不应该再执行p = p->link，而是直接跳出循环。 以上改动，详见代码！

示例(部分代码) 	printf("    21点\n"); 	printf("1.开始游戏\n"); 	printf("2.操作设置\n"); 	printf("3.难度设置\n"); 	printf("4.查看排名\n"); 	printf("5.操作帮助\n"); 	printf("6.退出游戏\n");  	printf("\n选择菜单: "); 	scanf("%d",&menu);  	while( menu<=0 || menu>=7) 	{ 		if(menu<-10000) 		{ 			getchar(); 			printf("\n好端端的,干嘛输入字母!\n"); 			printf("请重新选择菜单: "); 			scanf("%d",&menu); 		}else 		{ 			printf("\n菜单选择错误!\n请重新选择菜单: "); 			scanf("%d",&menu); 		} 	}  这里解释下,我在这里判断menu的值看是否输入了字母.因为定义menu时,没给值,它会随机地被赋予一个很大的负数. 通过判断不是很大的负数默认来确定有没有成功地获取用户输入的数据. 但这方法不够""判断sanf返回值来确定有没有成功地获取用户输入的数据"好

引用 4 楼 ghxujei 的回复:其实我也希望直接写一个函数，然后每次从键盘输入的时候都调用一下判定是否为数字，这样的话所有的地方就都不会出问题了。但是我确实是不会写。真的不知道从何入手。 可以这样实现,用%s读取用户输入的数据并存到数组str 然后遍历str,若存在0-9为外的字符,返回false

解决方法:         出错时,加条语句来清空缓冲区       方法一:scanf("%s", s);        方法二: scanf(“%*[^\n]%*c”): 出错原因:       用scanf("d",&n);只会从缓冲区获取数字,就是说,输入了字母的话,他就获取不了缓冲区的字符!       如果是循环获取的话,就永远卡死,因为scanf("d",&n);永远获取不到应有的数字.       所以,你该把字母读走然后再scanf("d",&n);       所以,你也可以用读把n声明为char类型,这样的话就不会出现这样的问题(要读取数字,却有字符阻拦着)了!  其次,你还可以通过sanf的返回值去判断,是否读到了字符,没有的话就用清空缓冲区  关于缓冲区的问题,你也可以看看我博客中初学c常见问题,里面有提到过缓冲区的

是这样。  while(tail->link!=NULL)     {         tail=tail->link;     };     printf("\n请输入入库图书的数量:");     scanf("%d",&n);  当我在提示之后输入字母，他会出错。我想在程序中加上一段代码，可以检测我输入的是否为数字，如果不是数字，就提示请正确输入数字，然后重新输入。如果是数字的话，才进行下一步。

printf("               *************************************\n"); 		printf("                          1:馆藏图书信息            \n"); 		printf("                          2:采编入库                \n"); 		printf("                          3:图书查询                \n"); 		printf("                          4:学号查询                \n"); 		printf("                          5:读者借阅                \n"); 		printf("                          6:读者归还                \n"); 		printf("                          7:退出图书管理系统        \n"); 		printf("               *************************************\n");  		printf("                            请输入您的选项：");                      		scanf("%d",&a); 这个要求程序属于一个数字，且要求是1-7，如果是其他数字或字符，程序就会进入死循环。

printf("\n请输入入库图书的现存量:");                 scanf("%d",&p->num1);                 printf("\n请输入入库图书的库存量:");                 scanf("%d",&p->num2);  你是说的这两个吗？输入非数字的时候你们的程序还能运行？ 如果是这里，把控制台输入当成字符串，读入字符串后判断字符串是不是全数字，不是全数字提示错误 信息，让用户重新输入，知道输入你们认为合法的值。 建议，应该用界面的方式进行录入。还有最后的书籍不应该保存在内存中。最好能用数据库保存。 以上建议仅供参考。


Question: 指针在子函数里面赋值为什么回到主函数又变回原来的值，求解答

指针指向地址，不是赋值，地址不是值

只是改变了形参的指向

因为你的指针是按值传递的，函数中的形参只是实参的复制品，你在函数中修改的也只是一个复制品，不会影响外面的实参  如果要在函数中修改指针，需要传递指针的地址

楼主可以利用指针写一个swap交换两个整数的函数，在main中：输出两个数，调用swap交换两个数，再输出两个数。 然后改写成交换两个指针变量的值，就容易理解为什么形参要用指针的指针了。

你这个问题，是没考虑局部变量的作用域问题。局部变量，只在函数内存在，函数结束后就会消失。就是说你传进去一个地址，被调用函数中改变了这个地址，但是被调用函数结束后，这个地址是会消失的。所以，主函数中打印地址，肯定是不会改变的。另外，我感觉你有个指针的用法，你弄糊涂了。传递指针是为了在被调用函数中改变这个指针所指向的内容，这个指针的地址是没办法改变的。因为C语言的变元传递是值传递！传递指针说白了就是传递一个地址的值，但可以在被调用函数中改变这个指针所指向内容的值，而不是改变这个指针的指向！同时希望多交流，我也是C刚看完！QQ：1010256995。


Question: c语言基础问题。求指点

我也想知道啊

请你弄明白，我现在大一学习c语言，还没进入IT行业，这只是我碰到的一道题，还没到代码编程程度，更还没到面试什么的，请不要说那些话语，不想回答我没强迫你，我请教的是别人

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

逗号运算符的使用，建议写个main函数，把这几条语句加进去测试一下。

在C语言中，多个表达式可以用逗号分开，其中用逗号分开的表达式的值分别结算（从左向右计算），但整个表达式的值是最后一个表达式的值。

考察的是逗号运算符和逗号表达式 逗号表达式的一般形式为 　 表达式1，表达式2 逗号表达式的求解过程是：先求解表达式1，再求解表达式2。整个逗号表达式的值是表达式2的值。 1. 6 2. 30 3. 12 4. 12

这些奇技淫巧只适用于得瑟

其实这些语法不用去深究，要弄懂调试一下就行了。 现实项目中用这些语法，我保证你会被打死！

你这么写， 能过面试算我输。


Question: 初学C语言，这是什么意思呢。

malloc申请的是堆上的空间，堆上的空间是手动申请需要手动释放，否则会导致内存溢出（死循环操作，会导致内存空间逐步被申请完），和堆上的空间枯竭。堆上的内存都快用完了，颠倒怎么还能运行流畅呢

引用 1 楼 wanggui2015的回复:无线循环申请内存，你的电脑应该会秒死机。。。 哇，突然觉得要是C语言没学好，好可怕啊，

无线循环申请内存，你的电脑应该会秒死机。。。


Question: hash表的数组初始化问题

引用 1 楼 自信男孩的回复:hash表数组中的元素是每个链表的头，即数组的个数就是链表的个数。通过hash的值先找到对应的链表头，然后再遍历链表找到对应的节点。 Hash的值应该是作为数组的索引吧，但是用链表实现的话，链表的地址不是分散的吗，那为什么可以做到O(1)的查找时间

基础是数组， 数组的每一个元素是一个结构体，结构体里有链表

因为hash会有碰撞，即几个不同的key用同样的hash算法 得到相同的 hash值。 用这个hash值当作数组索引，那么就出现了多对一的情况，所以相同hash值的元素用一条链表串起来， 当计算出hash值时，还要比较一下到底是哪一个key。  hash值得范围越大越浪费空间，但是多对一的情况就会越少， O(1) 只是理解值


Question: 这是怎么搞的，上面都没错，到要完了都错了。

再供参考：//不带表头结点的单向链表 #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-> //

仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*q1,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将整个链表逆序     if (head->next!=NULL && head->next->next!=NULL) {         p=head->next;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head->next=p;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //84->28->20->23->96->19->59->97->29->41-> //84->28->05->20->23->96->19->59->97->29->41-> //84->28->05->20->96->19->59->97->29->41-> //05->19->20->28->29->41->59->84->96->97-> //97->96->84->59->41->29->28->20->19->05-> //41->29->28->20->19->05->97->96->84->59-> //

链表排序，join是结点，pa是指向待插入链表的指针。

这个要实现什么？join，pa是怎么定义的？


Question: 求纠正翻译一段c语言的crc8算法

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

注，所有数都为16位数值=？


Question: NotifyIME 什么时候被调用？

换个别的开源输入法参考之？

引用 8 楼 zhao4zhong1 的回复:那个 别的输入法可以打标点符号，就这个开源输入法的打不出来。有补丁呢？

那个

你哪个微软的PPT没准需要打最新的补丁。

引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 u012403370 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 换个输入法再试试。 我在开发输入法呢[/quote] 参考这方面的开源项目？[/quote] 嗯，用了开源项目。好像是在微软的PPT上打不上标点符号，我写了日志文件发现的。这个函数没什么反应。

引用 4 楼 u012403370 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 换个输入法再试试。 我在开发输入法呢[/quote] 参考这方面的开源项目？

引用 2 楼 zhao4zhong1 的回复:换个输入法再试试。 我在开发输入法呢

我在开发输入法呢

换个输入法再试试。


Question: C语言代码求助

calval函数的y没有赋值，虽然用y做加减乘除

仅供参考：//运用C语言开发一个“小学生算术四则运算测试系统”。该系统是让计算机充当一位给小学生布置作业的算术老师，为学生出题并阅卷。该系统要求实现下列功能： //①为小学生出题（分别进行+、-、*、/等不同运算）。 //②学生做题后，进行评阅。学生每做一题后，评阅给出“答题正确，很好”或“答题错误，重做”等信息。 //③加、减、乘、除运算功能可以自由选择实现。 //④运算数值可控制在两位数的四则运算范围内。 #include <stdio.h> #include <stdlib.h> #include <time.h> int c,a,b,r,ri; void main() {     srand( (unsigned)time( NULL ) );     system("cls");     printf("小学生算术四则运算测试系统\n");     while (1) {         printf("1加法 2减法 3乘法 4除法 0退出:");fflush(stdout);         rewind(stdin);         scanf("%d",&c);         if (0==c) break;         switch (c) {         case 1:             a=rand()%100;             b=rand()%100;             r=a+b;             while (1) {                 printf("%d+%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 2:             a=1+rand()%99;             b=rand()%a;             r=a-b;             while (1) {                 printf("%d-%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 3:             a=rand()%99;             b=rand()%99;             r=a*b;             while (1) {                 printf("%d*%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         case 4:             a=2+rand()%998;             b=1+rand()%(a/2);             while (1) {                 if (0==a%b) break;                 b--;             }             r=a/b;             while (1) {                 printf("%d/%d=?",a,b);fflush(stdout);                 rewind(stdin);                 scanf("%d",&ri);                 if (ri==r) {                     printf("答题正确，很好！\n");                     break;                 } else {                     printf("答题错误，请重做。\n");                 }             }         break;         }     } }

我的代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 30 //定义最大30个测试用例 char a[N][50]; //定义每个测试用例可以有50个字符 char comp[10][6] = {"zero","one","two","three","four","five","six","seven","eight","nine"}; int  val[N];  void StringBracket(char *str)//删除空格 { 	int i,j,len;  	len=strlen(str); 	j=0; 	for(i=0; i<len; i++) 	{ 		if(str[i]!=' ') 		{ 			str[j]=str[i]; 			j=j+1; 		} 	} 	str[j]='\0'; }  char calval(char *str)  //计算每个表达式的值 { 	int i,j,len,y; 	int a1=0,a2=-1,b1=0,b2=-1;//每个表达式最多有4个整数 	char str1[20],str2[20];//分解为两个字符串 	char stra1[10],stra2[10]={0},strb1[10],strb2[10]={0};//每个字符串最多分解为两个子串  	len=strlen(str); 	for(i=0; i<len; i++) 	{ 		str1[i]=str[i]; 		if(str[i]=='+'|| str[i]=='-'|| str[i]=='*'|| str[i]=='/'|| str[i]=='%') 		{ 			str1[i]='\0'; 			for(j=i+1; j<len; j++)  				str2[j-i-1]=str[j]; 				str2[len-i-2]='\0'; 				break;  		} 	}    	len=strlen(str1); 	for(i=0; i<len; i++) 	{ 		stra1[i]=str1[i]; 		if(i>1 && str1[i]==' ') 		{ 			stra1[i]='\0'; 			for(j=i+1; j<len; j++)  				stra2[j-i-1]=str1[j]; 				stra2[len-i-1]='\0'; 				break;  		} 	} 	len=strlen(str2); 	for(i=0; i<len; i++) 	{ 		strb1[i]=str2[i]; 		if(i>1 && str2[i]==' ') //i>1表示不考虑前面的空格 		{ 			strb1[i]='\0'; 			for(j=i+1; j<len; j++)  				strb2[j-i-1]=str2[j]; 				strb2[len-i-1]='\0'; 				break;  		} 	}     StringBracket(stra1);     StringBracket(stra2);     StringBracket(strb1);     StringBracket(strb2);     for(i=0; i<10; i++)     {     	if(strcmp(stra1,comp[i])==0)	a1=i;     	if(strcmp(stra2,comp[i])==0)	a2=i;     	if(strcmp(strb1,comp[i])==0)	b1=i;     	if(strcmp(strb2,comp[i])==0)	b2=i;      }      if(a2>=0) a1=a1*10+a2; //a2初始化为-1，>=0表示为两位数      if(b2>=0) b1=b1*10+b2; 	switch(y) 	{ 		case 1: 			return a1+b1;             break; 		case 2:              return a1-b1;             break; 		case 3:              return a1*b1;             break; 		case 4:              return a1/b1;             break;   		case 0:             return a1%b1; 			break; 		default:             printf("    输入错误,请重新输入\n"); 	} }    int main()  {     	int i,j,n=0; 	int y; 	char str[10]; 	printf("|--------------------------------|\n"); 	printf("|         英文算数计算系统       |\n"); 	printf("|                1--加法运算     |\n"); 	printf("|                2--减法运算     |\n"); 	printf("|                3--乘法运算     |\n"); 	printf("|                4--除法运算     |\n"); 	printf("|                0--相除取余运算 |\n"); 	printf("|--------------------------------|\n\n"); 	printf("|你想要进行哪一种运算（0-4）     |\n");          	scanf("%d",&y); 	system("pause"); 	system("cls");    	printf("Please input numbers:\n"); 	while(1) 	{ 		gets(a[n]); 		val[n]=calval(a[n]); 		if(val[n]==0)   			break; 			n++;  		if(n>=N)  			break;  	} 	printf("Output:\n"); 	for(i=0;i<n;i++) 	{ 		if (val[i]>0) 		{ 			itoa(val[i], str, 10);//整数转换为字符串 			printf("%s ",a[i]);//输出原表达式 			for(j=0;j<strlen(str);j++) 			{ 				printf("%s ",comp[str[j]-0x30]); 			} 		} 		printf("\n"); 	}  	return 0; }

/* 英文算数计算系统 从键盘输入两个小于100的整数A和B，计算A与B两数的基本算数运算。需要注意的是：A和B的每一位数位上的数字由对应的英文单词给出。 系统要求： （1）系统由菜单做导航，给出输入数据功能、退出程序功能、数据输入功能并能够循环输入执行运算等。 （2）在数据运算输入功能菜单下分别给出A与B的相加运算、A与B的相乘运算、A与B的相减运算、A与B的相除运算、A与B的相除取于运算等功能。 （3）当A输入为zero，同时B输入为zero时自动返回菜单上一级。 输入样例： one + two = three four + five six = zero seven + eight nine = zero + zero = 输出样例： one + two = three three four + five six = nine zero zero seven + eight nine = nine six  */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 30 //定义最大30个测试用例 char a[N][50]; //定义每个测试用例可以有50个字符 char comp[10][6] = {"zero","one","two","three","four","five","six","seven","eight","nine"}; int  val[N];  void StringBracket(char *str)//删除空格 { 	int i,j,len;  	len=strlen(str); 	j=0; 	for(i=0; i<len; i++) 	{ 		if(str[i]!=' ') 		{ 			str[j]=str[i]; 			j=j+1; 		} 	} 	str[j]='\0'; }  char calval(char *str)  //计算每个表达式的值 { 	int i,j,len,y; 	int a1=0,a2=-1,b1=0,b2=-1;//每个表达式最多有4个整数 	char str1[20],str2[20];//分解为两个字符串 	char stra1[10],stra2[10]={0},strb1[10],strb2[10]={0};//每个字符串最多分解为两个子串  	len=strlen(str); 	for(i=0; i<len; i++) 	{ 		str1[i]=str[i]; 		if(str[i]=='+'|| str[i]=='-'|| str[i]=='*'|| str[i]=='/'|| str[i]=='%') 		{ 			str1[i]='\0'; 			for(j=i+1; j<len; j++)  				str2[j-i-1]=str[j]; 				str2[len-i-2]='\0'; 				break;  		} 	}    	len=strlen(str1); 	for(i=0; i<len; i++) 	{ 		stra1[i]=str1[i]; 		if(i>1 && str1[i]==' ') 		{ 			stra1[i]='\0'; 			for(j=i+1; j<len; j++)  				stra2[j-i-1]=str1[j]; 				stra2[len-i-1]='\0'; 				break;  		} 	} 	len=strlen(str2); 	for(i=0; i<len; i++) 	{ 		strb1[i]=str2[i]; 		if(i>1 && str2[i]==' ') //i>1表示不考虑前面的空格 		{ 			strb1[i]='\0'; 			for(j=i+1; j<len; j++)  				strb2[j-i-1]=str2[j]; 				strb2[len-i-1]='\0'; 				break;  		} 	}     StringBracket(stra1);     StringBracket(stra2);     StringBracket(strb1);     StringBracket(strb2);     for(i=0; i<10; i++)     {     	if(strcmp(stra1,comp[i])==0)	a1=i;     	if(strcmp(stra2,comp[i])==0)	a2=i;     	if(strcmp(strb1,comp[i])==0)	b1=i;     	if(strcmp(strb2,comp[i])==0)	b2=i;      }      if(a2>=0) a1=a1*10+a2; //a2初始化为-1，>=0表示为两位数      if(b2>=0) b1=b1*10+b2; 	switch(y) 	{ 		case 1: 			return a1+b1;             break; 		case 2:              return a1-b1;             break; 		case 3:              return a1*b1;             break; 		case 4:              return a1/b1;             break;   		case 0:             return a1%b1; 			break; 		default:             printf("    输入错误,请重新输入\n"); 	} }    int main()  {     	int i,j,n=0; 	int y; 	char str[10]; 	printf("|--------------------------------|\n"); 	printf("|         英文算数计算系统       |\n"); 	printf("|                1--加法运算     |\n"); 	printf("|                2--减法运算     |\n"); 	printf("|                3--乘法运算     |\n"); 	printf("|                4--除法运算     |\n"); 	printf("|                0--相除取余运算 |\n"); 	printf("|--------------------------------|\n\n"); 	printf("|你想要进行哪一种运算（0-4）     |\n");          	scanf("%d",&y); 	system("pause"); 	system("cls");    	printf("Please input numbers:\n"); 	while(1) 	{ 		gets(a[n]); 		val[n]=calval(a[n]); 		if(val[n]==0)   			break; 			n++;  		if(n>=N)  			break;  	} 	printf("Output:\n"); 	for(i=0;i<n;i++) 	{ 		if (val[i]>0) 		{ 			itoa(val[i], str, 10);//整数转换为字符串 			printf("%s ",a[i]);//输出原表达式 			for(j=0;j<strlen(str);j++) 			{ 				printf("%s ",comp[str[j]-0x30]); 			} 		} 		printf("\n"); 	}  	return 0; }


Question: 关于C语言函数的的一些疑惑

现在回头看，发现条理挺清晰的，可能那时候心比较乱，看得比较艰难，谢谢各位大牛

而且这和我平时的风格有点不一样，我平时是这么写的，当时写这个为了验证循环链表是否正确，因为从链表到循环链表我就用了一条语句，总觉得怪怪的。 ps：回复太长了只能分段发 #include <stdio.h>   #include <stdlib.h>       typedef int ElemType;       /* 定义结点类型 */      typedef struct Node   {       ElemType data;       /* 定义数据域 */     struct Node *next;   /* 定义指针域 */ }Node,*LoopLinkList;            /* 循环单链表的创建,采用尾插法建立单链表 */   Node *LinkListCreatT()   {       Node *head,*r,*p;       head = (Node *)malloc (sizeof(Node));  /* 初始化链表 */ 	if(head == NULL) 	{ 		printf("地址分配失败！\n");	 	}     r = head ;  /* 中间变量 */     ElemType x;   	printf("请输入循环链表的元素(以非数字结束,如e):");     while(scanf("%d",&x) == 1)  /* 输入数字时scanf返回1 */     {           p = (Node *)malloc(sizeof(Node));   		         p->data = x;   		         p->next = r->next;           r->next = p;           r = p;  /*  钩链，新创建的结点总是作为最后一个结点  */     }       r->next = head;  /* 设置为循环链表 */     return head;    }    int main()   {       LoopLinkList list,start;        list = LinkListCreatT();        for(start = list->next ;start != list;start = start->next) 	{ 		if(start->next == list)   /* 判断尾节点的指针域是否为头结点 */ 			printf("循环链表的最后一个元素:%d",start->data);   	}     printf("\n");       return 0;   }

非常感谢各位大牛的回答，这个问题是我在写循环链表的时候提出的，因为我参照了网上的例子，但是发现效率低得吓人，比自己写的还要慢（例子代码有注释），之前都没有遇到这样的问题，而且代码改动的难度也很大，与自己的思路不太一样。我发代码出来想问问可读性怎么样？因为阅读的时候有点费解，修改更难。  /*******************************************************************************/ #include <stdio.h> #include <stdlib.h> /*******************************************************************************/ int InPut();  ////集合元素输入 int Action(); ////选择操作函数 int IN_SET(struct Set* head);  ////测试集合元素子函数 void Check(struct Set* head);  ////测试集合元素主函数 void OutPut(struct Set* head); ////集合元素输出 void DeleteAll(struct Set* head);//释放内存空间 void aa(struct Set* head);     ////输出集合A void bb(struct Set* head);     ////输出集合B void cc(struct Set* head1, struct Set* head2); ////输出交集C void dd(struct Set* head1, struct Set* head2); ////输出并集D void ee(struct Set* head1, struct Set* head2); ////输出对称差E struct Set* JiaoJi(struct Set* head1, struct Set* head2); ////求交集C struct Set* BingJi(struct Set* head1, struct Set* head2); ////求并集D struct Set* DCC(struct Set* head1 , struct Set* head2);   ////求对称差E struct Set* INSERT_SET(struct Set* head);                 ////插入集合元素 struct Set* DeleteNode(struct Set* head, int data);       ////删除节点 struct Set* Sort(struct Set* head, struct Set* newnode);  ////按非递减方式排序 /*******************************************************************************/ struct Set  { 	int data; 	struct Set *next; }; /***主函数**********************************************************************/ int main()  { 	return Action(); } /***选择操作函数****************************************************************/ int Action() {     int choice,c; 	struct Set *a = NULL; 	struct Set *b = NULL; 	while(1) 	{ 		printf("   1 :   向集合A添加新元素\n"); 		printf("   2 :   向集合B添加新元素\n"); 		printf("   3 :   测试集合A的元素\n"); 		printf("   4 :   测试集合B的元素\n"); 		printf("   5 :   输出集合A的元素\n"); 		printf("   6 :   输出集合B的元素\n"); 		printf("   7 :   求A、B集合的交集并输出\n"); 		printf("   8 :   求A、B集合的并集并输出\n"); 		printf("   9 :   求A、B集合的对称差并输出\n"); 		printf("  10 :   退出\n\n\n\n请选择您的操作：");  		if(scanf("%d", &choice) == 1) 		{ 			switch(choice) 			{ 			case 1:   a = INSERT_SET(a); break; 			case 2:   b = INSERT_SET(b); break; 			case 3:   Check(a);          break; 			case 4:   Check(b);          break;      		case 5:   aa(a);             break;  			case 6:   bb(b);             break;  		 	case 7:   cc(a,b);           break; 			case 8:   dd(a,b);           break; 		    case 9:   ee(a,b);           break; 			case 10:  DeleteAll(a); DeleteAll(b); return 0;  /* 释放内存空间 */ 			default:  printf("您输入的数据不正确,请输入自然数(1～10)\n"); 			} 		} 		else               /* 输入异常处理，此处输入的数据为字符串，不能正常读取数据 */ 		{ 			printf("您输入的数据不正确!请输入整形数据!\n"); 		} 	    printf("\n\n\n"); 		system("pause");   /* 停顿 */ 		fflush(stdin);     /* 清除输入缓冲区,防止不合法数据录入,此函数只是C标准的扩充， */ 	    //while ( (c = getchar()) != '\n' && c != EOF ) ; 		system("cls");     /* 调用系统函数实现清屏 */  	}/*end of while*/ } /***函数功能：输入集合元素(集合元素唯一且以非递减方式储存到单链表中)********************/ struct Set *INSERT_SET(struct Set *head) { 	int NewData; 	char enter; 	printf("请输入集合的元素："); 	do                      /* 利用循环实现多个集合元素一起读入 */   	{ 		int i=0; 		NewData = InPut();  /* 调用集合元素输入函数 */ 	    scanf("%c",&enter); /* 利用输入缓冲区的回车键字符来控制循环 */ 		struct Set *p=NULL, *pr=head;   		p = (struct Set *)malloc(sizeof(struct Set));  		if(p == NULL) 		{ 			printf("内存不足！\n"); 			return head; 		} 		p->next = NULL;       /* 置新节点的指针域赋为空 */		 		p->data = NewData; 		while (pr != NULL)    /* 遍历链表,保证元素的唯一性 */ 		{ 			if(pr->data == NewData) 			{ 				printf("%d已经存在集合中,不再重复记录数据！\n",pr->data); 				i=1; 				break; 			} 			pr = pr->next; 		}	 		if(i==0)               /* 表示新输入的元素不在原集合中，数据添加成功        */ 		{ 			head=Sort(head,p); /* head为表头，p为新插入节点，调用非递减方式排序函数 */ 		} 	} while(enter!='\n'); 	return head; } /***函数功能：集合元素输入**************************************************************/ int InPut() { 	int NewData; 	while(1)            /* 此循环保证数据类型的合法性 */ 	{ 		if(scanf("%d", &NewData)==1) 		{ 			return NewData; 		} 	    char w;         /* 防止死循环，影响函数一次性读入多个集合元素的功能      */ 		scanf("%c",&w); /* 若这个数据不合法，去掉这个数据，再循环读入下一个数据  */ 	} } /***函数功能：以非递减方式排序**********************************************************/ struct Set *Sort(struct Set *head, struct Set *newnode) { 		struct Set *pr=head, *temp=NULL; 		if (head == NULL)       /* 链表表头为空 */ 			return newnode;     /* 返回新的表头 */ 		while (pr->data < newnode->data && pr->next != NULL)   		{ 			temp = pr;        			pr = pr->next;    		} 		if (pr->data > newnode->data ) 		{ 			if (pr == head)  /* 在首节点前插入新节点 */ 			{ 				newnode->next = head; 				head = newnode; 			} 			else             /* 在链表中间插入 */ 			{ 				newnode->next = temp->next; 				temp->next = newnode; 			} 		} 		else                /* 在表尾插入新节点 */ 		{ 			pr->next = newnode; 		} 		return head; } /***函数功能：测试集合元素主函数********************************************************/ void Check(struct Set *head) { 	char i;     printf("请输入您要测试的集合元素："); 	do                    /* 循环控制，实现多个集合元素一次性测试 */ 	{ 		int j=IN_SET(head); 		if(j==0)          /* 调用测试集合元素子函数 */ 			printf("已经在集合中!\n");   		else if(j==1) 			printf("不在集合中!\n"); 		scanf("%c",&i);  /* 回车表示输入结束 */ 	}while(i!='\n'); } /***函数功能：测试集合元素子函数(集合元素已经在集合中返回0，否则返回1)******************/ int IN_SET(struct Set *head) { 	int data; 	if(head == NULL) 	{ 		printf("\n对不起,该链表没有有数据!\n"); 		return 3; 	}		 	data = InPut();  /* 调用数据输入函数 */     while(head != NULL)     {  		if(head->data == data) 		{ 			printf("元素%d",data); 			return 0; 		} 		head = head->next;        } 	printf("元素%d",data);      return 1;      /* 测试的数据不在集合中 */ } /***函数功能：输出集合A*****************************************************************/ void aa(struct Set *head) { 	if (head == NULL) 	{ 		printf("集合A为空集!"); 		return; 	} 	else 	   printf("集合A={"); 	OutPut(head); 	printf("}"); } /***函数功能：输出集合B***************************************************************/ void bb(struct Set *head) { 	if (head == NULL) 	{ 		printf("集合B为空集!"); 		return; 	} 	else 	   printf("集合B={"); 	OutPut(head); 	printf("}"); } /***函数功能：输出交集C*****************************************************************/ void cc(struct Set* head1, struct Set* head2) { 	 head1=JiaoJi(head1,head2); /* 调用求交集函数 */ 	 if (head1 == NULL) 	 { 		printf("交集C为空集!"); 		return; 	 } 	 else 	    printf("交集C={"); 	 OutPut(head1);    /* 调用集合元素输出函数 */  	 printf("}"); 	 DeleteAll(head1); /* 释放整个链表的内存空间 */ } /***函数功能：输出并集D***************************************************************/ void dd(struct Set* head1, struct Set* head2) { 	 head1=BingJi(head1, head2); /* 调用求并集函数 */ 	 if (head1 == NULL)  	 { 		 printf("并集D为空集!"); 		 return; 	 } 	 else 	    printf("并集D={"); 	 OutPut(head1);     /* 调用集合元素输出函数   */  	 printf("}"); 	 DeleteAll(head1);  /* 释放整个链表的内存空间 */ } /***函数功能：输出对称差E*************************************************************/ void ee(struct Set* head1, struct Set* head2) { 	head1=DCC(head1, head2); /* 调用求对称差函数 */ 	if (head1 == NULL) 	{ 		printf("对称差E为空集!"); 		return; 	} 	else 	   printf("对称差E={"); 	OutPut(head1);    /* 调用集合元素输出函数    */ 	printf("}"); 	DeleteAll(head1); /* 释放整个链表的内存空间  */ } /***函数功能：输出集合元素(集合元素以非递增的方式输出)********************************/ void OutPut(struct Set *head) { 	if (head->next != NULL) 	{ 		OutPut(head->next);       /* 递归算法 */ 	} 	if (head->next == NULL)        /* 控制输出的第一个元素后面不能再跟逗号"," */ 		printf("%d",head->data); 	else 	    printf(",%d",head->data); /* 每输出一个元素前面加一个逗号","	      */ } /***函数功能：求集合A和集合B的交集C，并以非递减方式存储********************************/ struct Set *JiaoJi(struct Set *head1, struct Set *head2) { 	 struct Set *pr=head1,*p=head2,*c,*head,*temp; 	 head=c=(struct Set*)malloc(sizeof(struct Set)); 	 head->next = NULL; 	 while(pr!=NULL)     /* 以非递减方式遍历整个集合A,找出交集C并存储到链表C */ 	 { 		  p=head2;       /* 每次都要从表头开始,q为集合B表头                  */ 		  while(p!=NULL) /* 内循环遍历集合B                                  */ 		  { 			   if(pr->data==p->data) 			   { 				temp = (struct Set *)malloc(sizeof(struct Set)); 				temp->data = pr->data;  				temp->next = NULL; 				c->next = temp; 				c = temp;   				break; 			   } 			   p=p->next; 		  } 	      pr=pr->next; 	 } 	 head = head->next;     return head; } /***函数功能：求集合A和集合B的并集D******************************************************/ struct Set *BingJi(struct Set *head1, struct Set *head2)  { 	 struct Set *pr=head1,*p,*q=head2,*head,*d,*temp; /* head表示D链表表头 */ 	 head=d=(struct Set*)malloc(sizeof(struct Set)); 	 head->next = NULL; 	 while(q!=NULL) /* 以集合B来初始化并集D */   	 { 		 temp=(struct Set*)malloc(sizeof(struct Set)); 		 temp->data=q->data; 		 temp->next=NULL; 		 d->next=temp; 		 d=temp; 		 q=q->next; 	 } 	 head = head->next;   	 while(pr!=NULL)    /* 遍历整个集合A,使集合A中每个元素都与集合B中所有元素比较一下 */ 	 { 	     int i=0;       /* 标记作用                                                   */ 		 p=head2;       /* 每次都要从表头开始遍历链表，p集合B的表头                   */ 		 while(p!=NULL) /* 内循环遍历集合B,找出两个集合公共部分元素                   */   		 {  			 if(pr->data==p->data)   			 { 			     i=1; 				 break; 			 } 			 p=p->next; 		 } 		 if(i==0) 		 { 			 temp=(struct Set*)malloc(sizeof(struct Set)); 			 temp->data=pr->data; 			 temp->next=NULL; 			 head=Sort(head,temp); /*以集合B为基础，找出集合A中独有的元素，调用排序函数*/ 		 } 		 pr=pr->next; 	 } 	 return head; } /***函数功能：求集合A和集合B的对称差E***************************************************/ struct Set* DCC(struct Set * head1 , struct Set * head2) { 	struct Set *a=NULL, *b=NULL;  	a=JiaoJi(head1, head2); /* 求交集 */ 	b=BingJi(head1, head2); /* 求并集 */ 	while(a != NULL)  	{			 		b=DeleteNode(b,a->data); /* 调用删除节点函数 */ 		a=a->next; 	}     return b; } /***函数功能：删除节点函数**************************************************************/ struct Set* DeleteNode(struct Set* head, int data) { 	struct Set *p=head, *pr=head; 	while(data != p->data) 	{ 		pr = p; 		p = p->next; 	} 	if(p==head) 		head = p->next; 	else 		pr->next = p->next;			 	free(p); /* 释放已删除节点分配的内存 */ 	return head; } /***函数功能：释放内存空间**************************************************************/ void DeleteAll(struct Set* head) {  	struct Set* pr=NULL; 	while(head!=NULL) 	{   		pr=head->next; 		free(head);  /* 释放已申请的内存空间 */ 		head=pr; 	} }

函数原层级调用非常多. 一般重复的代码尽量写成函数.

引用 4 楼 hdt 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] 这个不好说，根据实际情况来定吧；如果A，B两个功能函数是平级的，或者类似的。比如学生管理系统，查询和创建应该是平级的，都放到main函数里调用比较好；如果A，B两个功能是实现同一个功能，那么肯定是调用关系比较好； 函数定义和调用，还要考虑代码可读性，符合逻辑的使用，至于那种方式好，除了考虑上面的情况，还要考虑你的框架设计，接口设计，函数细分的程度。因此，还得具体问题具体分析！ 请举个例子，那个比较大的软件，是如你所说。所有函数彼此正交。互不调用。 [/quote] 函数的主要用途有两个，缺一不可。一个十分割功能。一个就是复用。 前一个目的降低软件的复杂度。 第二个增加代码编写效率。 还是上边那一句话，缺一不可。 而且你所说的增删改，应该不是函数。而是功能。或者叫模块。

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

引用 4 楼 hdt 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] 这个不好说，根据实际情况来定吧；如果A，B两个功能函数是平级的，或者类似的。比如学生管理系统，查询和创建应该是平级的，都放到main函数里调用比较好；如果A，B两个功能是实现同一个功能，那么肯定是调用关系比较好； 函数定义和调用，还要考虑代码可读性，符合逻辑的使用，至于那种方式好，除了考虑上面的情况，还要考虑你的框架设计，接口设计，函数细分的程度。因此，还得具体问题具体分析！ 请举个例子，那个比较大的软件，是如你所说。所有函数彼此正交。互不调用。 [/quote] 我们平时写的学生管理系统，如果用链表做，查询和创建学生表都是对链表的操作，但是这两个接口函数还要做交集，这样逻辑上是不是就不很好理解（做交集调用是可以，没问题，因为函数调用没有限制彼此不能调用）；这两个功能同时被main调用或者再定义一个函数，但是对于这两个函数之间最好不要有调用吧。

引用 3 楼 cfjtaishan 的回复:这个不好说，根据实际情况来定吧；如果A，B两个功能函数是平级的，或者类似的。比如学生管理系统，查询和创建应该是平级的，都放到main函数里调用比较好；如果A，B两个功能是实现同一个功能，那么肯定是调用关系比较好； 函数定义和调用，还要考虑代码可读性，符合逻辑的使用，至于那种方式好，除了考虑上面的情况，还要考虑你的框架设计，接口设计，函数细分的程度。因此，还得具体问题具体分析！ 请举个例子，那个比较大的软件，是如你所说。所有函数彼此正交。互不调用。

函数的功能就是把一些共有的功能抽象出来，达到一个复用的目的。节省时间。清晰功能。比如排序。 很多地方都会需要。所以把它抽象出来，避免重复。 所以你的第二个想法是错误的。 另外，你的第一个看法。问题在于，你不会看函数。一个函数如果他编写的没有问题，为什么要进入他呢。 我只要考虑他的输入，输出就可以了。只有当输出不符合我的要求的时候，也就是说它内部有问题的时候，我才要跟踪进去。

都独立出来，相当于所有的函数是平级的，各个功能彼此是独立的。这做的到吗？


Question: 函数返回值与参数指针的区别

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

一个是值拷贝，一个是直接对指定变量地址操作。

引用 3 楼 paschen 的回复:b = function1(); 之后b的值也会变成-0.003698的  但是，把这条语句写去主函数里，而不是在全局范围 如果不写在main函数里，或者其他函数里，楼主肯定不会编译通过，更不用说结果不一样了。

引用 6 楼 g62r83t27 的回复:这个函数返回值赋值，也只在特定文件里面赋值才会出问题，在有的文件里面不出问题。。。。  函数返回值获得函数的值和通过传入传出参数得到值都是一样的，是两种获得函数返回值的方式；  对于浮点数，要考虑它的精度问题。建议你使用int类型作为返回值和函数传出参数的类型，将a,b,c也定义成int类型，然后在看两种方式的结果是否一致。

引用 4 楼 g62r83t27 的回复:[quote=引用 3 楼 paschen 的回复:] b = function1(); 之后b的值也会变成-0.003698的  但是，把这条语句写去主函数里，而不是在全局范围[/quote]  应该不会这样，你可以再看下生成的汇编代码

引用 1 楼 user-6 的回复:值是一样的，你是怎么看的结果 debug http://www.hanxinxin.com/pic/pic1.png http://www.hanxinxin.com/pic/pic2.png

值是一样的，你是怎么看的结果

引用 9 楼 qwqwqw408 的回复:你那个extYcValue是不是在多个c文件里面定义了，你说的函数返回赋值和指针赋值结果不一样的情况，应该不可能会出现。你把完整代码贴出来看看 代码无法贴出来，太多了，我只能大概描述我所能描述的东西  1， extYcValue属于extYcValue.c文件的的全局变量，其他地方无定义 2， aiDcAdGet为aiDcAd.c的实现函数，其他地方无同名函数的实现，两个.c文件，不在同一个目录里面  3， 其中，aiDcAd.c中也存在调用返回类型为float的函数，不过调用的是同文件里面的函数，这时候赋值正常。。


Question: C语言结构组问题，对指定字符和学号尾数进行比较

不用拷贝，直接比较或者直接用strstr查看输入的尾号是不是学号的子串  #include <stdio.h> #include <string.h>  #define N 16  typedef struct {     char num[10];     int s; } STREC;  int fun(STREC a[],char studno[],int n ) {     //--ksstart（注释不能删除）—     //考生代码从此开始编写     //--ksend---     int i;      for (i = 0; i < n; i++) {         if (strstr(a[i].num, studno)) {             a[i].s += 10;             break;         }     }      return i; }  int main() {     STREC s[N] = { {"GA005",85},{"GA003",76},{"GA002",69},{"GA004",85},         {"GA001",96},{"GA007",72},{"GA008",64},{"GA006",87},         {"GA015",85},{"GA013",94},{"GA012",64},{"GA014",91},     {"GA011",90},{"GA017",64},{"GA018",64},{"GA016",72}};     int i, n = 0;     n = fun(s, "001", N);     printf("%d\n",n);      for(i = 0; i < N; i++) {         printf("%s %4d\n",s[i].num,s[i].s);     }     printf("\n");      return 0; }

用strcpy拷贝，strcmp比较

怎么拷贝啊。。。。我只知道怎么拷贝一个字符不会写拷贝字符串。。。。

你把学号尾部对应位数的字符串拷贝出来，然后跟指定字符串比较一下，如果相等就加分


Question: 形参为数组形式的函数该如何调用？

数组名或指针均可,都代表一个地址

传递对应元素类型的数组或者指针

int main(void) {     char src[] = "helloworld";     char dst[32];      copy_n(dst, src, 5);     puts(dst); }  按照对应的参数传递实参就可以了。

是的，对应的是指针

数组形参会退化成指针，传的也是指针。


Question: 有哪位大神知道怎么在freeradius中增加access-challenge?网上搜到的不行

还不如说说具体你用什么编译环境，怎么编译不过的，编译出错提示信息是啥。

你处理过freeradius的挑战应答吗，帮帮忙呗


Question: 建立二叉树，输出其各种遍历结果

http://blog.csdn.net/u010810428/article/details/47947555 可以参考一下这位博主的博客

for(i=0;i<64;i++)                             {                                 layer1[i]=layer2[i];                             } 这个操作肯定会把layer1的值都覆盖，包括左右子树指针内容。

#include <iostream> #include<string.h> #include<stack> #include <stdio.h> #include <stdio.h> #include <stdlib.h> using namespace std;  typedef struct node {     char data;     struct node *lchild,*rchild; }BinTree;  typedef struct node1 {     BinTree *btnode;     bool isFirst; }BTNode;   void creatBinTree(char *s,BinTree *&root)  //创建二叉树，s为形如A(B,C(D,E))形式的字符串  {     int i;     bool isRight=false;     stack<BinTree*> s1;          //存放结点      stack<char> s2;              //存放分隔符     BinTree *p,*temp;     root->data=s[0];     root->lchild=NULL;     root->rchild=NULL;     s1.push(root);     i=1;     while(i<strlen(s))     {         if(s[i]=='(')         {             s2.push(s[i]);             isRight=false;         }             else if(s[i]==',')             {             isRight=true;         }         else if(s[i]==')')         {             s1.pop();             s2.pop();         }         else if(isalpha(s[i]))         {             p=(BinTree *)malloc(sizeof(BinTree));             p->data=s[i];             p->lchild=NULL;             p->rchild=NULL;             temp=s1.top();             if(isRight==true)                 {                 temp->rchild=p;                 cout<<temp->data<<"的右孩子是"<<s[i]<<endl;             }             else             {                 temp->lchild=p;                 cout<<temp->data<<"的左孩子是"<<s[i]<<endl;             }             if(s[i+1]=='(')                 s1.push(p);         }         i++;     }     }  void display(BinTree *root)        //显示树形结构  {     if(root!=NULL)     {         cout<<root->data;         if(root->lchild!=NULL)         {             cout<<'(';             display(root->lchild);         }         if(root->rchild!=NULL)         {             cout<<',';             display(root->rchild);             cout<<')';         }     } }  void preOrder1(BinTree *root)     //递归前序遍历  {     if(root!=NULL)     {         cout<<root->data<<" ";         preOrder1(root->lchild);         preOrder1(root->rchild);     } }  void inOrder1(BinTree *root)      //递归中序遍历 {     if(root!=NULL)     {         inOrder1(root->lchild);         cout<<root->data<<" ";         inOrder1(root->rchild);     } }   void postOrder1(BinTree *root)    //递归后序遍历 {     if(root!=NULL)     {         postOrder1(root->lchild);         postOrder1(root->rchild);         cout<<root->data<<" ";     }     }   void preOrder2(BinTree *root)     //非递归前序遍历  {     stack<BinTree*> s;     BinTree *p=root;     while(p!=NULL||!s.empty())     {         while(p!=NULL)         {             cout<<p->data<<" ";             s.push(p);             p=p->lchild;         }         if(!s.empty())         {             p=s.top();             s.pop();             p=p->rchild;         }     } }  void inOrder2(BinTree *root)      //非递归中序遍历 {     stack<BinTree*> s;     BinTree *p=root;     while(p!=NULL||!s.empty())     {         while(p!=NULL)         {             s.push(p);             p=p->lchild;         }         if(!s.empty())         {             p=s.top();             cout<<p->data<<" ";             s.pop();             p=p->rchild;         }     }     }   void postOrder2(BinTree *root)    //非递归后序遍历 {     stack<BTNode*> s;     BinTree *p=root;     BTNode *temp;     while(p!=NULL||!s.empty())     {         while(p!=NULL)              //沿左子树一直往下搜索，直至出现没有左子树的结点           {             BTNode *btn=(BTNode *)malloc(sizeof(BTNode));             btn->btnode=p;             btn->isFirst=true;             s.push(btn);             p=p->lchild;         }         if(!s.empty())         {             temp=s.top();             s.pop();             if(temp->isFirst==true)     //表示是第一次出现在栈顶               {                 temp->isFirst=false;                 s.push(temp);                 p=temp->btnode->rchild;                 }             else                        //第二次出现在栈顶               {                 cout<<temp->btnode->data<<" ";                 p=NULL;             }         }     }     }   void postOrder3(BinTree *root)     //非递归后序遍历 {     stack<BinTree*> s;     BinTree *cur;                      //当前结点      BinTree *pre=NULL;                 //前一次访问的结点      s.push(root);     while(!s.empty())     {         cur=s.top();         if((cur->lchild==NULL&&cur->rchild==NULL)||            (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))         {             cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过                s.pop();             pre=cur;          }         else         {             if(cur->rchild!=NULL)                 s.push(cur->rchild);             if(cur->lchild!=NULL)                     s.push(cur->lchild);         }     }     }   int main(int argc, char *argv[]) {     char s[100];     while(scanf("%s",s)==1)     {         BinTree *root=(BinTree *)malloc(sizeof(BinTree));         creatBinTree(s,root);         display(root);         cout<<endl;         preOrder2(root);         cout<<endl;          inOrder2(root);         cout<<endl;         postOrder2(root);         cout<<endl;         postOrder3(root);         cout<<endl;     }     return 0; }

仅供参考：#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


Question: const void*指针返回类型数据使用问题求解

请问问题解决了，我也遇到了相同的问题，请教一下大神！谢谢！674186676@qq.com

引用 10 楼 wanggui2015 的回复:http://bbs.elecfans.com/jishu_1133384_1_4.html  这个里面说用32位无符号整型替代void*  多谢大神，我研究一下，回复你，因为有个疑问，如果用32位无符号整型代替void*,那么应该返回的是数据的首地址吧，通过这个地址LabVIEW怎么获得真正的数据哪？

我还是觉得这种方法不科学的啊，你那个LabView针对返回指针类型肯定有其他解决方法的吧？

引用 7 楼 wanggui2015 的回复:你写个生成dll的工程，里面函数这样写：   int MyQTTSAudioGet(void** ppAudioData, const char* sessionID, unsigned int* audioLen, int* synthStatus, int* errorCode) { 	*ppAudioData = QTTSAudioGet(sessionID, audioLen, synthStatus, errorCode); 	return *ppAudioData == NULL ? -1 : 0; }   然后把这些函数导出，生成一个dll不就行了么。  我先试试，不过一个*的void*的参数有没有办法？貌似两个*的LabVIEW也不支持

跪求大神回复

引用 3 楼 wanggui2015 的回复:[quote=引用 2 楼 paranet 的回复:] 是讯飞的语音合成接口。大侠不用知道怎么使用LabVIEW，我只想知道在C中怎么调用标准接口函数，将返回值的const void*挪到参数列表  额，你是想把qtts这个库再封装一层接口，这个接口唯一的改变就是把返回值放到参数列表里是吧？  是的是的！

LabVIEW上支持的C函数返回值类型少的可怜

是讯飞的语音合成接口。大侠不用知道怎么使用LabVIEW，我只想知道在C中怎么调用标准接口函数，将返回值的const void*挪到参数列表   引用 1 楼 wanggui2015 的回复:讯飞语音云合成接口啊，LabVIEW没用过没法帮你，不过如果有接口调用方面的问题可以找我。

这个应用的目的是把大片的文字转化为语音，官方的例子语音数据是使用while循环成块生成，流盘到文件，依照大神的意思，我可以直接将范例程序打个dll包，LabVIEW中调用这个dll的同时，另一个线程直接检测文件大小有没有变化，有变化就读文件，对吗？ 这倒绝对是一个可行的办法

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！  聊聊磁盘I/O那些事 http://www.sohu.com/a/148649739_683048

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

//		const void* data = QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret); 		const char* data = (const char*)QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret); 第一行是原来的代码，我用第二行代替后，在C中没有报错，而且得到的文件和原来的一模一样， 于是我做了下面的动态库 _declspec(dllexport) const char* QTTSAudioGet_LV(const char* sessionID, unsigned int* audio_len, int* synth_status, int* errorCode) { 	const char* pAudioData; 	pAudioData = (const char*)QTTSAudioGet(sessionID, audio_len, synth_status, errorCode); 	return pAudioData; }  LabVIEW给我返回了个空字符串，但是没有报错，只是数据没返回来，是不是因为没有给字符串分配内存？


Question: 请问有没有将C语言新标准C11的书籍或资料？推荐一下。

李忠，标准C语言指南，电子工业出版社

http://baike.baidu.com/link?url=OPjBPDYyMClIhvwNcXkI1M4vzE0Qfwe88Nxd2N83DHsL2tJTIIhtf4PMotZ6aw8zDhe7pdqBm7p-fYD8B4Ix6K 网上应该比较多一些吧

网上搜一下C11概览就行,增加的基本都是高级功能,一般也用不到, 能用到也最好不用,因为没有移植性. 目前工作中是不会使用C11的,最新的gcc默认 使用-std=gnu11, c11版本还有许多bug和功能未完善

个人觉得C11不如把C++当C用。


Question: alsps驱动问题

搜了，说了一个寄存器问题，但是改了也没反应

百度搜相关关键字。