Question: 二叉树括号表示法的合法检测

仅供参考：#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: 算法讨论

仅供参考：#include <stdio.h> double A[300][100]; double valuex[300]; double valuey[300]; int i; double fun00(double x,double y) {return x  +   y  ;}; double fun01(double x,double y) {return x*x+ 3*y  ;}; double fun02(double x,double y) {return x  + 2*y*x;}; //...  fun03(double x,double y) {return ...+...   ;}; //... //...  fun98(double x,double y) {return ...+...   ;}; double fun99(double x,double y) {return x/2+20*y  ;}; double (*funNN[100])(double,double)={     fun00,     fun01,     fun02, //  fun03, //  ... //  fun98,     fun99, }; int main() {     double x,y;     int f,FN;      for (i=0;i<300;i++) {         valuex[i]=(double)i;         valuey[i]=(double)i;     }     FN=3;     for (i=0;i<300;i++) {          x=valuex[i];          y=valuey[i];          for (f=0;f<FN;f++) A[i][f]=funNN[f](x,y);     }     for (i=0;i<3;i++) {         for (f=0;f<FN;f++) printf("%lg ",A[i][f]);         printf("\n");     } 	return 0; } //0 0 0 //2 4 3 //4 10 10

引用 2楼ooolinux 的回复:一家签审完后，检查剩余五家签审状态，给其中未签审的发邮件，不就可以了，哪有什么24种。要求写在一封邮件上，要确定收件人，所以有24种


Question: 一个小程序

引用 6 楼 HymanLiuTS的回复:[quote=引用 4 楼 liu545454 的回复:] [quote=引用 1 楼 user-3 的回复:] 后置的++是在你这条语句执行完后才加1，所以你输出的是最开始的那个元素，也就是2 *(p++) p++不是在括号里面吗？不是先加1？[/quote] 因为++运算符的优先级要高于*，所以你加不加小括号都是一样的。你就把后++想像成是一个函数，它先返回一个值得副本，然后再对自身加1[/quote] 明白了 谢谢

引用 4 楼 liu545454 的回复:[quote=引用 1 楼 user-3 的回复:] 后置的++是在你这条语句执行完后才加1，所以你输出的是最开始的那个元素，也就是2 *(p++) p++不是在括号里面吗？不是先加1？[/quote] 因为++运算符的优先级要高于*，所以你加不加小括号都是一样的。你就把后++想像成是一个函数，它先返回一个值得副本，然后再对自身加1

引用 1 楼 user-3 的回复:后置的++是在你这条语句执行完后才加1，所以你输出的是最开始的那个元素，也就是2 这一块有点糊涂

引用 1 楼 user-3 的回复:后置的++是在你这条语句执行完后才加1，所以你输出的是最开始的那个元素，也就是2 *(p++) p++不是在括号里面吗？不是先加1？

引用 2 楼 user-3 的回复:如果你希望输出的是4，写成 *++p 是的

如果你希望输出的是4，写成 *++p


Question: 约瑟夫环的问题，为啥我的代码运行出来结果总是不对呢？大家帮忙看一下哪里错了。

比如DispList函数里的，你的s都没有初始化过，在for循环中就这样用s->next = p->next;？？？？？ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: C语言结构体

for (int i=0;i<12;i++) {  plane[i].number=i+1;  plane[i].mark=0; } “变量赋值”和“变量初始化”不是一回事！ “变量赋值”发生在运行期，其写法遵循赋值语法规定。 “变量初始化”发生在编译期或运行期，其写法遵循初始化列表语法规定。

引用 9 楼 loveqise 的回复:引用 8楼fefe82 的回复:在 C 语言里，全局变量只能用常量初始化。初始化了的结构体不算常量吗 不算。  6.6 Constant expressions Syntax 1 constant-expression:     conditional-expression  Description 2 A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.  Constraints 3 Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated. 4 Each constant expression shall evaluate to a constant that is in the range of representable values for its type.  Semantics 5 An expression that evaluates to a constant is required in several contexts. If a floating expression is evaluated in the translation environment, the arithmetic range and precision shall be at least as great as if the expression were being evaluated in the execution environment.  6 An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, _Alignof expressions, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof or _Alignof operator.  7 More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following: — an arithmetic constant expression, — a null pointer constant, — an address constant, or — an address constant for a complete object type plus or minus an integer constant expression.  8 An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and _Alignof expressions. Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to a sizeof or _Alignof operator.  9 An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly by the use of an expression of array or function type. The array-subscript [] and member-access . and -> operators, the address & and indirection * unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.  10 An implementation may accept other forms of constant expressions.  11 The semantic rules for the evaluation of a constant expression are the same as for nonconstant expressions.

引用 4楼赵4老师 的回复:将name和subname删掉。删掉也提示错误，而且删了结构就不完整了

将name和subname删掉。

引用 1楼paschen 的回复:没见到你plane的定义啊有啊！

没见到你plane的定义啊

在 C 语言里，全局变量只能用常量初始化。

引用 6楼user-4 的回复:你的结构体包含了四个字段，你只给前面两个int类型的字段初始化了，那后面的name和subname呢？结构体不一定全部要初始化啊，只要部分有初始值就行


Question: 二叉链表线索化中序遍历

错误楼上都说清楚了. 参考：http://blog.csdn.net/aspnet_lyc/article/details/14126157

if(!P->lchild); 这句后面也多了分号  另外InThreading函数需要两个参数，你调用的时候只给了一个参数

struct BiThrnode *lchild,*rchild;  改成：  struct BiThrNode *lchild,*rchild;   void InorderThreading(BiThrNode *p); 后面多了一个分号

亲 谢谢 谢谢 第三个问题呢？

typedef struct BiThrNode {    char data;    struct BiThrnode *lchild,*rchild;    int Ltag,Rtag; }BiThrNode;


Question: fatal error C1083: 无法打开包括文件: “bintree.h”: No such file or directory

1.VS的当前路径是在工程所在的目录 2.使用绝对路径试试 3.右键项目--属性--配置属性--C/C++--附加包含目录里添加上bintree.h所在的路径

找不到这个文件，必要时使用绝对路径


Question: 小白出没，求请教。。。

引用 3 楼 zhttty523 的回复:for(i=0;i,m-1;i++) 中间的逗号改为小于就行了是我太粗心了

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

我刚试了一下，程序可以运行成功啊！没有LZ所谓的停止运行

单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

for(i=0;i,m-1;i++) 中间的逗号改为小于就行了

for(i=0;i,m-1;i++) 你中间是逗号，需要分号

建议单步调试一下，看是哪一行出错了  #include<stdio.h>  int leap(int a) {  	if(a%4==0 && a%100!=0 || a%400==0) 		return 1; 	else  		return 0; }  int number(int y,int m,int d) { 	int i,sum=0; 	int a[12]={31,29,31,30,31,30,31,31,30,31,30,31}; 	int b[12]={31,28,31,30,31,30,31,31,30,31,30,31};  	if(leap(y)==1) 		for(i = 0;  i< m-1; i++)                          			sum += a[i]; 	else  		for(i = 0 ;i < m-1; i++) 			sum += b[i]; 	sum += d;  	return sum; } int main(void) { 	int year,month,day,n; 	 	printf("输入年月日\n"); 	scanf("%d%d%d", &year, &month, &day);  	n = number(year, month, day);     printf("%d\n",n);  	return 0; }


Question: c里对函数的循环调用出错，求教

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

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

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

感觉关键就是循环调用那里有问题


Question: 如何实现循环读入结构体数组字段？

谢谢！把fopen那句放在主函数for循环外就成功了。另外不需要指向结构体的指针pst++辅助，删除即可。

因为你每次重新打开文件，每次打开时文件指针都在开头，把你的文件打开放在主函数循环外面

当重新打开文件时，文件的指针指向开头。 把文件打开和关闭放到循环外面。


Question: fscanf函数的使用需要注意的一个地方

fscanf对应的源代码是公开的。楼主不会自行“升级”吗？

%*[^\n] 这个通配符的意思是 跳过所有字符 直到换行符为止。 好像不是这个意思。

fscanf(fp, "%[^\n]%*c", sLineWord);


Question: 为什么程序运行只有个黑框没有任何内容，之前的程序也是这样

哈哈，谢谢，现在已经解决了，应该是sublime的问题

对的，现在在IDE里行了，但是在cmd和直接运行可执行文件就还是黑框没反应

因为你程序一直在死循环里  你的 for(k=1;k<=4;++j)  写错了  改成 for(k=1;k<=4;++k)

for(k...)那里，应该是k++吧，你写错了。


Question: 如何用UE提取 所有带标点符号+文字+字母


Question: 求C语言做出的程序怎么保存数据

创建一个存档文件。存档时写入与当前游戏进程有关的数据，读档时读取文件，还原游戏进程。可以对数据进行简单的加密，就不那么容易被修改了。

引用 2 楼 c_xiaoxiaobai 的回复:[quote=引用 1 楼 user-3 的回复:] 保存到文件， 具体怎么做呢？？我还是个小白 能不能说的具体点内[/quote]  网上搜索读写二进制文件

将你要保存的值写入到文件，下次从文件读取

简单一点可以一个文件一个配置，文件名是key, 文件内容是value

引用 2 楼 c_xiaoxiaobai 的回复:[quote=引用 1 楼 user-3 的回复:] 保存到文件， 具体怎么做呢？？我还是个小白 能不能说的具体点内[/quote] fopen, fprintf, fscanf, fclose

引用 1 楼 user-3 的回复:保存到文件， 具体怎么做呢？？我还是个小白 能不能说的具体点内

保存到文件，


Question: 求C的大牛解答一下菜鸡问题！！

引用 7 楼 qq_15173325 的回复:[quote=引用 6 楼 wh357589873 的回复:] 首先，为啥是同一个数，因为你用的是union,它虽然看起来很大，但是实际的大小和里面最大的元素的大小相等。实际只存一个数。为啥输入字母不行？你看看你那里scanf明明是%d,你应该输入数字的，不然这句是执行失败的。  这些我仔细处理好了 但是又有新问题    [/quote]啥啊？

错误原因分析： 1、union使用有误 union 中所有的数据成员共用一个空间，同一时间只能储存其中一个数据成员，所有的数据成员具有相同的起始地址。 修改如下： struct obj { 	char Nounion[20]; 	union iunion xinxi_shenfen; 	union iunion xinxi_name; 	union iunion xinxi_num; 	union iunion xinxi_sex; 	struct obj *pNext; }; 2、输入有误 编号为数字，不能输入非数字。  完整代码如下：  #include<stdio.h> #include<stdlib.h>  union iunion { 	char info[10]; 	int num; }; struct obj { 	char Nounion[20]; 	union iunion xinxi_shenfen; 	union iunion xinxi_name; 	union iunion xinxi_num; 	union iunion xinxi_sex; 	struct obj *pNext; };  int iCount;  struct obj *Create() { 	struct obj *pHead = NULL; 	struct obj *pEnd, *pNew; 	iCount = 0; 	pEnd = pNew = (struct obj*)malloc(sizeof(struct obj)); 	printf("请输入：1.身份 2.名字 3.编号 4.性别 5.班级或职位\n"); 	scanf("%s", &( (*pNew).xinxi_shenfen.info) ); 	scanf("%s", &( (*pNew).xinxi_name.info) ); 	scanf("%d", &((*pNew).xinxi_num.num)); 	scanf("%s", &((*pNew).xinxi_sex.info));  	scanf("%s", &(*pNew).Nounion); 	printf("身份：%s\n", (*pNew).xinxi_shenfen.info); 	printf("名字：%s\n", (*pNew).xinxi_name.info); 	printf("编号：%d\n", (*pNew).xinxi_num.num); 	printf("性别：%s\n", (*pNew).xinxi_sex.info); 	printf("班级或职位：%s\n", (*pNew).Nounion); 	while (pNew->xinxi_num.num != 0) 	{ 		iCount++; 		if (iCount == 1) 		{ 			pNew->pNext = pHead; 			pEnd = pNew; 			pHead = pNew; 		} 		else 		{ 			pNew->pNext = NULL; 			pEnd->pNext = pNew; 			pEnd = pNew; 		} 		pEnd = pNew = (struct obj*)malloc(sizeof(struct obj)); 		printf("请输入：1.身份 2.名字 3.编号 4.性别 5.班级或职位\n"); 		scanf("%s", &((*pNew).xinxi_shenfen.info)); 		scanf("%s", &((*pNew).xinxi_name.info)); 		scanf("%d", &((*pNew).xinxi_num.num)); 		scanf("%s", &((*pNew).xinxi_sex.info));  		scanf("%s", &(*pNew).Nounion); 		printf("身份：%s\n", (*pNew).xinxi_shenfen.info); 		printf("名字：%s\n", (*pNew).xinxi_name.info); 		printf("编号：%d\n", (*pNew).xinxi_num.num); 		printf("性别：%s\n", (*pNew).xinxi_sex.info); 		printf("班级或职位：%s\n", (*pNew).Nounion); 	} 	free(pNew); 	return pHead; }  void Print(struct obj *pHead) { 	struct obj *pTemp; 	int iIndex = 1; 	pTemp = pHead; 	while (pTemp != NULL) 	{ 		printf("身份：%s\n", pTemp->xinxi_shenfen.info); 		printf("名字：%s\n", pTemp->xinxi_name.info); 		printf("编号：%d\n", pTemp->xinxi_num.info); 		printf("性别：%s\n", pTemp->xinxi_sex.info); 		printf("班级或职位：%s\n", pTemp->Nounion); 	} }  void main() {	struct obj *pHead; 	pHead = Create(); 	Print(pHead); }

引用 5 楼 yanxinrui0027 的回复:把union改成struct结构  这练习规定要用结构体和共用体

引用 6 楼 wh357589873 的回复:首先，为啥是同一个数，因为你用的是union,它虽然看起来很大，但是实际的大小和里面最大的元素的大小相等。实际只存一个数。为啥输入字母不行？你看看你那里scanf明明是%d,你应该输入数字的，不然这句是执行失败的。  这些我仔细处理好了 但是又有新问题

把union改成struct结构

解决了一些问题  那是Print函数进入了死循环，处理ing

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

自己调试，调试方法：把相关变量输出，看从哪开始其值与自己预想的不一样，或从哪开始执行不下去了，这个地方前后仔细检查

惨案


Question: 求教大神：C语言小程序错误

引用 3 楼 paschen 的回复:循环条件是i<=M，当i 等于M时越界了，score[M]的有效索引是0 到 M-1谢了！！

循环次数一样,但是使用的元素不同

不等价, 一个是 i=0  一个是 i=1

数组下标是从0开始。 如果你用这个（i=1;i<=M;i++）那么肯定是写不到第一个元素和最后一个元素。

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

数组下标是0开头

第一个，我不知道你M是不是用的宏，如果用的宏到没问题，没用宏定义M，那你这里就是错的(数组大小定义的时候必须是一个常量)。  第二个，数组的下标是从0到M-1的，所以你的循环应该是从0开始，到M-1。


Question: 如果函数返回类型不确定，最终的值会是什么？

调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx

返回值与return 后面的类型不一致时会隐式转换，但函数返回的类型是一致的，1楼大牛解释地很好了

不存在类型不确定的可能

引用 5 楼 warcraftzhaochen 的回复:[quote=引用 1 楼 user-4 的回复:] 你的函数返回类型是确定的，是 unsingned char 。  C 不会有返回类型不确定的函数。  ===================================== 7.19.6.3 The printf function Synopsis 1 #include <stdio.h> int printf(const char * restrict format, ...); Description 2 The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.  ============================= 7.19.6.1 The fprintf function 8 The conversion specifiers and their meanings are: d,i The int argument is converted to signed decimal in the style [−]dddd. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros. The default precision is 1. The result of converting a zero value with a precision of zero is no characters.  9 If a conversion specification is invalid, the behavior is undefined.239) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.  ====================================== The behavior is undefined  未定义行为       实际问题是这样的 调用fun的和fun不属于同一个文件，且没有引用fun的声明，在vs2008中发现这种现象 unsigned int a = fun();                  //a 不正常 unsigned char b = fun();              //  b正常 但在arm编译器中却都正常 [/quote]  你要问 C99 的话，这应该是一个编译错误。 C99 已经不允许使用未经声明的函数。 =========== C89 的话，这个可以，会有一个默认的声明 int fun() 。注意这里返回值类型也是确定的（int），而不是不确定。  同时，当调用是的声明（int func()）与定义是的声明（unsinged char func()）不一致的时候，依然是一个未定义行为。

引用 1 楼 user-4 的回复:你的函数返回类型是确定的，是 unsingned char 。  C 不会有返回类型不确定的函数。  ===================================== 7.19.6.3 The printf function Synopsis 1 #include <stdio.h> int printf(const char * restrict format, ...); Description 2 The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.  ============================= 7.19.6.1 The fprintf function 8 The conversion specifiers and their meanings are: d,i The int argument is converted to signed decimal in the style [−]dddd. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros. The default precision is 1. The result of converting a zero value with a precision of zero is no characters.  9 If a conversion specification is invalid, the behavior is undefined.239) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.  ====================================== The behavior is undefined  未定义行为       实际问题是这样的 调用fun的和fun不属于同一个文件，且没有引用fun的声明，在vs2008中发现这种现象 unsigned int a = fun();                  //a 不正常 unsigned char b = fun();              //  b正常 但在arm编译器中却都正常


Question: 出现未知问题，求帮助！

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];

#include<stdio.h> int main() {     int a,b;     char zi;     scanf("%d",&a);     scanf("%d",&b);     scanf("%c",&zi);     getchar();     printf("%c",zi);     return 0; } 在scanf后面再加一个getchar就可以了，因为你输入的是字符，而C语言中回车符号就代表两个字符，当你按下回车时字符就已经被scanf读取了。 再加一个getchar就是为了吞噬回车字符


Question: 求助：关于读入文本格式数据并排序问题的思路

感谢大家指点！我学C两周多时间，水平还很低，链表这些都还没开学。这道题是谭浩强第三版作业。待会仔细看看你们的回复。有问题还会请教你们的！

实际应用 比如你有1000个数据 STUDENT  stu[1000];  你有6个字段，你可以定义6个排序，即按每列排序 LIST   *SortHead[6]; LIST   *SortTail[6]; 创建排序如下 for(int x=0;x<6;x++) { 	for(int i=0;i<1000;i++) 	{ 		LIST *p=new LIST; 		p->data=&stu[i]; 		p->prev=NULL; 		p->next=NULL;  		if(SortHead[x]==NULL) 		{ 			SortHead[x]=p; 			SortTail[x]=p; 		} 		else 		{ 			SortTail[x]->next=p; 			p->prev=SortTail[x]; 			SortTail[x]=p; 		} 	} } 然后分别对SortHead[6]的6个链进行排序i计算和节点交换 完成后排序就准备好了  由于你同一时间只能操作一种，你只需要定义一个默认的指针 LIST   *SortNormalHead； LIST   *SortNormalTail； 比如，按第一列排序显示给观众，则SorNormalHead=SortHead[0];  SorNormalTail=SortTail[0], 按第6列排序显示给观众，则SorNormalHead=SortHead[5];  SorNormalTail=SortTail[5],  补充说明： 如果你操作熟练后，你发现stu[1000]是不合理的 因为数据有多有少，所以最后其实数据读取还多出一根绳， 那根绳按不排序的方式挂住数据，排序的绳以不排序绳作为数据构建基础

编程的核心是数据结构+算法 文件是实现数据的保存，和算法无关 排序本身是一种算法，只和数据结构有关，和文件无关  struct student { 	char name[90]; 	int id; 	float mathscore; 	float englishscore; 	float chinesescore; 	float average; }stu[3]; 这东西只是个结构体，并非数据结构，所以你依靠他保存读取文件是挺方便的 但一设计算法，就傻B了，这就是因为对数据结构没有很好认识。 再直接点说，结构体最多是种数据类型，并不是数据结构 而你的这东西连数据类型都算不上 你应该养成如下习惯，先定义数据类型，再去定义变量，思路才会清晰起来 typedef struct tagSTUDENT { 	char name[90]; 	int id; 	float mathscore; 	float englishscore; 	float chinesescore; 	float average; }STUDENT;  STUDENT stu[3];  有了定义好的数据类型，才能在定义变量的同时，方便的定义数据结构 比如链表 typedef struct tagLIST { 	STUDENT *data; 	struct tagLIST *prev; 	struct tagLIST *next; }LIST  数据就好比瓜儿一样吊在STUDENT *data;上 LIST就向线一样链接了所有的瓜 根据data的数据，改变LIST链接的先后顺序，着就是排序 数据本身的大小，位置，都是不变的 因为有了LIST就有了顺藤摸瓜的便利，这才是正道  试想一堆瓜，不是用绳接先后去标记，而是抱着瓜真实的排大小，你不累吗？

fscanf(fp,"%10d%20s%10.2f%10.2f%10.2f%10.2f",temp.id,temp.name,temp.mathscore,temp.englishscore,temp.chineses 少写了取地址符号&。 编译运行成功，但是读的值是0，不知道为什么。

接着上面的话题，我先实现读取结构体数组字段的功能。我写的代码如下：编译通过，可是运行崩溃了。请高手帮忙查找一下错误！ #include <stdio.h> #include <stdlib.h> int count; struct student { 	char name[90]; 	int id; 	float mathscore; 	float englishscore; 	float chinesescore; 	float average; } stu[3],temp;   struct student readfile(void);  int main() { 	for(count=0;count<3;count++) 	{ 	stu[count]=readfile(); 	printf("total is:%f\n",stu[count].mathscore+stu[count].englishscore+stu[count].chinesescore);     }     return 0; }  struct student readfile() { 	FILE *fp; 	if((fp=fopen("stud.dat","r"))==NULL)     {     	fputs("Can't open stud.dat!",stderr);     	exit(1); 	} 	fscanf(fp,"%10d%20s%10.2f%10.2f%10.2f%10.2f",temp.id,temp.name,temp.mathscore,temp.englishscore,temp.chinesescore,temp.average); 	fclose(fp); 	return temp; }

请注意用c语言

#include <stdio.h>  #include <stdlib.h> int count; struct student { 	char name[90]; 	int id; 	float mathscore; 	float englishscore; 	float chinesescore; 	float average; } stu[3];  struct student getinfo(); struct student calculateaverage(struct student); void savedata(struct student); int main() { 	for (count=0;count<3;count++) 	{ 		stu[count]=getinfo(); 		stu[count]=calculateaverage(stu[count]); 		savedata(stu[count]); 	} 	return 0; }  struct student getinfo() { 	struct student temp; 	printf("Input Name:\n"); 	gets(temp.name); 	printf("ID number:\n"); 	scanf("%d",&(temp.id)); 	printf("Math score:\n"); 	scanf("%f",&(temp.mathscore)); 	printf("English score:\n"); 	scanf("%f",&(temp.englishscore)); 	printf("Chinese score:\n"); 	scanf("%f",&(temp.chinesescore)); 	while(getchar()!='\n') 	    continue; 	return temp; }  struct student calculateaverage(struct student stu) { 		struct student temp; 		temp=stu; 		temp.average=(temp.mathscore+temp.englishscore+temp.chinesescore)/3; 		return temp; }  void savedata(struct student stu) { 	FILE *fp; 	if((fp=fopen("stud.dat","a+"))==NULL) 	{ 		fputs("Can't open stud.dat file\n",stderr); 		exit(1);     }    	fprintf(fp,"%10d%20s%10.2f%10.2f%10.2f%10.2f\n",stu.id,stu.name,stu.mathscore,stu.englishscore,stu.chinesescore,stu.average); 	fclose(fp); 	return; 	  } /*希望构建三个函数分别实现读入、排序和输出。对如何排序也是没有头绪。请指导！*/

为什么限定死呢，只要建立 CPP项目  ，或者文件名扩展为 .cpp 就可以 使用 C++的容器和 算法库了  所以，这样处理起来就简单了，不要自己去重复 造 轮子了，先把功能实现取来吧。  你可以贴出 几行样本数据，我可以写一个看看

怎么写的就怎么读，用fscanf,第1，2个参数与fprintf一样，但注意，如果是读double型，要改成%lf  排序C语言只有一个qsort可以用


Question: c语言关于ip定位查询

引用 10楼gldcpp 的回复:用curl吧  自己可以搞定的 就是一个exe 你启动的时候传参数就行 有文档的curl函数怎么调用

引用 6楼赵4老师 的回复:引用 5 楼 qq_36676825 的回复:[quote=引用 2楼赵4老师 的回复:]使用curl调用www.ip138.com能把程序写出来吗 给钱就帮你写。[/quote]那不用了

引用 5 楼 qq_36676825 的回复:引用 2楼赵4老师 的回复:使用curl调用www.ip138.com能把程序写出来吗 给钱就帮你写。

用curl吧  自己可以搞定的 就是一个exe 你启动的时候传参数就行 有文档的

引用 8楼wh357589873 的回复:http://www.jb51.net/article/38231.htm  看这个吧。这种应用性质的就不要用C语言了，C语言不适合做应用性质的。我也不想用c，只是老师的一个要求，不然就用php写了

引用 2楼赵4老师 的回复:使用curl调用www.ip138.com还有别的办法吗

引用 1楼user-4 的回复:可以使用纯真IP数据库,格式介绍的很详细,查找就可以了怎么用小白求教学

可以使用纯真IP数据库,格式介绍的很详细,查找就可以了


Question: 读取文件中有效数据的速度问题

谢谢大家的帮助

找到法子了，直接在open的时候，加上参数O_DIRECT就好了，因为文件中的有效信息很少，系统缓存后反而浪费了时间，这样直接读写反倒是提速了

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

2楼大神已经帮过忙了。

pread函数刚刚也试了一下，也没有提升速度。 倒是不涉及多个文件的读写，我只是从单个文件中，提取有效的数据，有效的数据占比很小，速度上不去的问题；现在应该是虽说我只读取了很小的比例，因为有效数据均匀分布在文件各个位置，但是系统应该把文件分块从硬盘上逐步都缓存到内存了，相当于在内存开辟整个空间，然后缓存了，这样是不是浪费了时间？ mmap的方法也用过了，效果是一样的。 求大神帮忙，不要沉了

使用文件映射方式读取文件

在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快  您是否希望迅速对您频繁使用的文件进行碎片整理？使用 Contig 优化单个的文件，或者创建连续的新文件。http://technet.microsoft.com/zh-cn/sysinternals/bb897428

lseek与read两次系统调用，所以比较慢，你可以试着每次读2560个字节，这样不需要调用了lseek了  还有一个pread函数，不知道你的系统支不支持，它不改变文件指针，速度应该更快


Question: C语言实现RSA解密时的一个问题

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A 仅供参考：void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }

引用 2楼赵4老师 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。很高兴你可以来回答，这个问题我自己解决了，但是新的问题来了，在加解秘中文字符时只能有一部分加解密，其他的全部成乱码了，最后谢谢你宝贵的指点！

for (i = 1;i <= filesize;++i) {     //这里是转字符为整形保存为数组的，其实我觉得没必要 			inside_ol[i] = inside_ol1[i - 1]; 			inside_ol[i] = inside_ol[i]; 			inside_ol2[i] = RSA_encrypt(inside_ol + i, e); int transform(int b, int *a)     //这里是解密的时候的模指运算模块，加密的时候也是这个。 { 	int t, temp = -1; 	while (b>0) { 		t = b % 2; 		++temp; 		a[temp] = t; 		b = b / 2; 	} 	return temp; } int RSA_encrypt(char *inside_ol, int b) { 	int a = *inside_ol; 	int x = 0, back = 1, k, i, s[1000]; 	k = transform(b, s); 	for (i = k;i >= 0;i--) { 		x = 2 * x; 		back = (back*back) % n; 		if (s[i] == 1) { 			x++; 			back = (back*a) % n; 		} 	} 	return back; }


Question: 向文件输出字符，返回值已经显示正常，也没有报错，但是文件中就是没有字符？？

fflush(fp);


Question: 跪求C语言的技术大牛

引用 9 楼 paschen 的回复:[quote=引用 8 楼 qq_15173325 的回复:] [quote=引用 7 楼 paschen 的回复:] [quote=引用 6 楼 qq_15173325 的回复:] [quote=引用 5 楼 paschen 的回复:] scanf("%s",&strs);    你的strs只是一个字符，接收后会导致越界  %s需要的是一个字符串  如果我要strs 是字符串  那我是不是要定义它为指针类型？ [/quote]  char strs[100];[/quote]  还是不是很明白 main()   {           char *str,*num;           char strs[100];           scanf("%s",strs);           str = strs;           printf("复制后：%s\n",str);   }   帮我修改一下  [/quote]  代码没问题啊[/quote]  char strs;         scanf("%s",&strs);         printf("复制后：%s\n",&strs);  strs 获取值后   要输出&strs么？  那strs变成什么了？

C和指针 《深入理解C指针》

引用 8 楼 qq_15173325 的回复:[quote=引用 7 楼 paschen 的回复:] [quote=引用 6 楼 qq_15173325 的回复:] [quote=引用 5 楼 paschen 的回复:] scanf("%s",&strs);    你的strs只是一个字符，接收后会导致越界  %s需要的是一个字符串  如果我要strs 是字符串  那我是不是要定义它为指针类型？ [/quote]  char strs[100];[/quote]  还是不是很明白 main()   {           char *str,*num;           char strs[100];           scanf("%s",strs);           str = strs;           printf("复制后：%s\n",str);   }   帮我修改一下  [/quote]  代码没问题啊

引用 7 楼 paschen 的回复:[quote=引用 6 楼 qq_15173325 的回复:] [quote=引用 5 楼 paschen 的回复:] scanf("%s",&strs);    你的strs只是一个字符，接收后会导致越界  %s需要的是一个字符串  如果我要strs 是字符串  那我是不是要定义它为指针类型？ [/quote]  char strs[100];[/quote]  还是不是很明白 main()   {           char *str,*num;           char strs[100];           scanf("%s",strs);           str = strs;           printf("复制后：%s\n",str);   }   帮我修改一下

引用 6 楼 qq_15173325 的回复:[quote=引用 5 楼 paschen 的回复:] scanf("%s",&strs);    你的strs只是一个字符，接收后会导致越界  %s需要的是一个字符串  如果我要strs 是字符串  那我是不是要定义它为指针类型？ [/quote]  char strs[100];

引用 5 楼 paschen 的回复:scanf("%s",&strs);    你的strs只是一个字符，接收后会导致越界  %s需要的是一个字符串  如果我要strs 是字符串  那我是不是要定义它为指针类型？

引用 2 楼 lzlssg 的回复:用strcpy啊，字符串不能直接赋值啊  我已经删掉strcpy这个函数了，因为这里已经报错了。

引用 1 楼 60 的回复: main()   {           char *str,*num;           char strs[100];           scanf("%s",strs);           str = strs;           printf("复制后：%s\n",str);   }      你没有搞清楚char和char*/char[]的区别。在scanf和printf中，%s适用于 char*/char[]， %c适用于 char。 char* 类型的str，在使用*str得到的是字符串str的第一个字符，是char类型。   比如我输入haha，char strs[100]; 这个变量是不是就是字符串了？  我现在很混乱！！！！

用strcpy啊，字符串不能直接赋值啊


Question: linux 编码 转码

//iconv_linux下字符集编码转换轻松实现 (1) iconv_t iconv_open(const char *tocode, const char *fromcode); //此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。 (2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft); //此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。 (3) int iconv_close(iconv_t cd); //此函数用于关闭转换句柄,释放资源。  //例子1: 用C语言实现的转换示例程序  /* f.c : 代码转换示例C程序 */ #include <iconv.h> #define OUTLEN 255 main() { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  /*unicode码转为gb2312码*/ rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN); printf("unicode-->gb2312 out=%sn",out); //gb2312码转为unicode码  rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN); printf("gb2312-->unicode out=%sn",out); } /*代码转换:从一种编码转为另一种编码*/ int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen) { iconv_t cd; int rc; char **pin = &inbuf; char **pout = &outbuf;  cd = iconv_open(to_charset,from_charset); if (cd==0) return -1; memset(outbuf,0,outlen); if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1; iconv_close(cd); return 0; } /*UNICODE码转为GB2312码*/ int u2g(char *inbuf,int inlen,char *outbuf,int outlen) { return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen); } /*GB2312码转为UNICODE码*/ int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen) { return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen); }  //例子2: 用C++语言实现的转换示例程序  /* f.cpp : 代码转换示例C++程序 */ #include <iconv.h> #include <iostream>  #define OUTLEN 255  using namespace std;  // 代码转换操作类  class CodeConverter {  private: iconv_t cd; public:  // 构造 CodeConverter(const char *from_charset,const char *to_charset) { cd = iconv_open(to_charset,from_charset); }   // 析构 ~CodeConverter() { iconv_close(cd); }   // 转换输出 int convert(char *inbuf,int inlen,char *outbuf,int outlen) { char **pin = &inbuf; char **pout = &outbuf;  memset(outbuf,0,outlen); return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen); } };  int main(int argc, char **argv) { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  // utf-8-->gb2312 CodeConverter cc = CodeConverter("utf-8","gb2312"); cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN); cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;  // gb2312-->utf-8 CodeConverter cc2 = CodeConverter("gb2312","utf-8"); cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN); cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl; }    二、利用iconv命令进行编码转换  iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。  用法： iconv [选项...] [文件...]  有如下选项可用:  输入/输出格式规范： -f, --from-code=名称 原始文本编码 -t, --to-code=名称 输出编码  信息： -l, --list 列举所有已知的字符集  输出控制： -c 从输出中忽略无效的字符 -o, --output=FILE 输出文件 -s, --silent 关闭警告 --verbose 打印进度信息  -?, --help 给出该系统求助列表 --usage 给出简要的用法信息 -V, --version 打印程序版本号  例子: iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt 这个命令读取aaa.txt文件，从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。  小结: Linux为我们提供了强大的编码转换工具,给我们带来了方便。


Question: 怎么在程序开始之前就大概估计一下时间呢？

引用 6 楼 hswshy 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 搜“曳光弹”。 exm?????[/quote] http://www.cnblogs.com/SkyMouse/archive/2011/08/23/2150079.html

这个真心不是单独的一个程序的性能就必然决定的。

运行时间是跟硬件相关的

额...是我现在学的太少了。。。还以为用现在的知识可以解决。。。谢谢大家

你算下时间复杂度啊

引用 3 楼 zhao4zhong1 的回复:搜“曳光弹”。 exm?????

用profiler分析一下，比如intel VTune Amplifier

每次循环计算本次循环的时候，然后估计总时间，不断修改

搜“曳光弹”。


Question: 初始化{0}的问题

int a[5]={0}; 这个是初始化5个元素都是int型 0，即对应asII码值48号0这个元素---对吧  不对，初始化5个元素为0，对应的ASCII值为0。  char  b[5]={0}; 这个是初始化5个元素都chart型 0，即对应asII码值0号‘\0’这个元素对么。。。。  对的。  ===== 以下都是数字0 0 十进制表示 00 八进制表示 0x0 十六进制表示 '\0' ascii code 0 八进制表示 '\x0' ascii code 0 十六进制表示 ===== 以下都是字符'0' 48 '0' ascii code 数值十进制表示 060 '0' ascii code 数值八进制表示 0x30 '0' ascii code 数值十六进制表示 '0' ascii code '\060' ascii code 八进制表示 '\x30' ascii code 十六进制表示

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

第一个 对的  第二个  不等价  '\N'  和 字母N的ascii值等价,是一个固定的数值

都是数字0，不是'0'  对于数字，0是0，48是48. 对于字符，0是'\0'，48是'0'  相同的二进制，你用不同数据类型解释它可能会显示不同的结果

引用C 语言里 '\N' 和 N 是等价的，N 可以是值介于十进制 0~255 之间八进制、十进制、十六进制数。 这句话又怎么理解？？？？？  \ 是引导一个转义字符 '\123' 就相当于 ascii为 123的字符

引用int a[5]={0}; 这个是初始化5个元素都是int型 0，即对应asII码值48号0这个元素---对吧  char  b[5]={0}; 这个是初始化5个元素都chart型 0，即对应asII码值0号‘\0’这个元素对么。。。。  对的，会将这片内存用0填充


Question: 请教下面这段程序要怎么free才能将所有malloc的空间free完。

引用 9 楼 shihengzhen101 的回复:引用 7 楼 dzc_woniu 的回复:[quote=引用 5 楼 shihengzhen101 的回复:] 你再运行一下，看看崩溃在哪一行？   你这一块代码混乱啊，为什么直接置为NULL了   while((_buf1[i][j]=strtok(buf2,"|"))!=NULL)             {                 buf2=NULL;                 if(strcmp(_buf1[i][j],"ZS") == 0)                 {                     _buf1[i][j - 2] = NULL;                     --j;                      fla = 1;                     break;                  }                 _buf1[i][++j] = (char *)malloc(30);             } [/quote]（j-2）置为NULL，是因为前面的两个字符串不要，

引用 7 楼 dzc_woniu 的回复:引用 5 楼 shihengzhen101 的回复:你再运行一下，看看崩溃在哪一行？   你这一块代码混乱啊，为什么直接置为NULL了   while((_buf1[i][j]=strtok(buf2,"|"))!=NULL)             {                 buf2=NULL;                 if(strcmp(_buf1[i][j],"ZS") == 0)                 {                     _buf1[i][j - 2] = NULL;                     --j;                      fla = 1;                     break;                  }                 _buf1[i][++j] = (char *)malloc(30);             }

引用 7 楼 dzc_woniu 的回复:引用 5 楼 shihengzhen101 的回复:你再运行一下，看看崩溃在哪一行？崩溃时查一下x和y的值

没有运行环境，很难调试啊 一般释放内存错误是释放了多次或者堆被破坏了，也就是你放的数据超出了分配的内存，你单步调试一下吧

你再运行一下，看看崩溃在哪一行？

引用 2 楼 xian_wwq 的回复:一个原则， 一次malloc对应一次free 就不会有问题我是按照这个原则free的，就是不知道是不是free的逻辑有问题，，，感觉我陷入死局了，，所以请大家帮我看看，，，哈哈

引用 1 楼 shihengzhen101 的回复:在用完的地方free就行，现在出了什么问题 我是这么free的，但是报错“free(): invalid pointer:” for(y = 0;y < 42;y++) 721     { 722         free(cont[y]); 723     } 724     if(p_fla != NULL) 725     { 726     for(x = 0;x < i;x++) 727     { 728         if(fla == 0) 729         { 730             for(y = 0;y < j;y++) 731             { 732                 free(_buf1[x][y]); 733             } 734         } 735         else 736         { 737             for(y = 0;y < j-1;y++) 738             { 739                 free(_buf1[x][y]); 740             } 741         } 742     } 743     }

一个原则， 一次malloc对应一次free 就不会有问题

在用完的地方free就行，现在出了什么问题

free后将指针设置为NULL，再次free的时候不会出错

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。 判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

引用 10 楼 dzc_woniu 的回复:引用 9 楼 shihengzhen101 的回复:[quote=引用 7 楼 dzc_woniu 的回复:] [quote=引用 5 楼 shihengzhen101 的回复:] 你再运行一下，看看崩溃在哪一行？   你这一块代码混乱啊，为什么直接置为NULL了   while((_buf1[i][j]=strtok(buf2,"|"))!=NULL)             {                 buf2=NULL;                 if(strcmp(_buf1[i][j],"ZS") == 0)                 {                     _buf1[i][j - 2] = NULL;                     --j;                      fla = 1;                     break;                  }                 _buf1[i][++j] = (char *)malloc(30);             } [/quote]（j-2）置为NULL，是因为前面的两个字符串不要，[/quote] 不能理解啊，你这样不就内存泄露了吗？你还没有free，就把指针置为NULL


Question: 关于C语言打开文件的问题

参考： https://msdn.microsoft.com/en-us/library/bb776913.aspx https://msdn.microsoft.com/en-us/library/bb775966.aspx

这个在各个平台的实现是不同的。我目前只知道在 Windows 上你需要： #include <windows.h> #pramga comment(lib, "comdlg32.lib") 调用 GetOpenFileName 或者使用 COM 接口 IFileDialog 来实现。

仅供参考：#pragma comment(lib,"user32") #include <windows.h> #include <conio.h> void main() {     int r;      cprintf("press any key...");     getch();     r=MessageBox(NULL,"Hello!","MsgBox",MB_OKCANCEL|MB_SETFOREGROUND);     cprintf("\r\nr=%d",r); }

FILE *inpt = fopen("D:\123\12.txt","r"); 改成：  FILE *inpt = fopen("D:\\123\\12.txt","r"); //或者： FILE *inpt = fopen("D:/123/12.txt","r");

"D:\123\12.txt"  改成  "D:\\123\\12.txt"  使用 \\  转义字符代替 \

这个是要界面的，建议看看MFC或者Qt的知识。 main函数那个是控制台，做不来的


Question: C 宏连接符 ## 的问题？？？

#include <stdio.h>  #define toString(c) "TL"#c"XY" #define fun(a,b) toString(a##b) int main() {    printf("%s\n",fun(1,2)); }

TLabXY根本就不是变量，无法赋值

等待高手解答。。。。。。。

我刚才试了一下，发现不行，错误如下： Error[Pe137]: expression must be a modifiable lvalue  Error while running C/C++ Compiler   我是做嵌入式开发的，用的IAR开发环境，我已经将开发环境设置为标准的C语言标准，    我实际的应用场景是这样的，  #define  __func(a,b)      (TLabXY = 1)  #define func(a,b)   __func(a,b)  void main(void) {     func(1,2); }  希望在调用中实现   TL12XY = 1

TL ## a ## b ## XY

#define  __func(a,b)      (TL ## a ## b ## XY = 1)  #define func(a,b)   __func(a,b)  void main(void) { 	int TL12XY; 	func(1,2); }

#与##在宏定义中的--宏展开 #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         return 0; } 宏展开时： 如果宏定义以#开头，不展开参数，直接替换。 故g(f(1,2))--->#f(1,2)--->"f(1,2)"； 如果宏定义不以#开头，展开参数，直接替换，由外层向里层，如果碰到的是#开头的宏，不继续往里层展开，往外层展开。 由外层向里层，如果碰到的是以非#开头的宏，继续往里层走，直至最里层，开始一层层往外层展开。 故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。 PS： ##在宏中定义，是字符连接符 如a##b##c 等同于 "abc" #在宏开头出现，是表示宏展开的方式不同 #a 等同于"a" #abc 等同于 "abc" 复杂的: #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         char a = 'a';         cout<<g(a)<<endl; // a         cout<<g(g(a))<<endl; // a         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         printf("%s\n", g(h(f(1,2)))); // h(f(1,2))         printf("%s\n", h(g(f(1,2)))); // "f(1,2)"         printf("%s\n", h(h(f(1,2)))); // "12"         system("pause");         return 0; } 预处理后的：（在编译选项中添加/EP /P后编译生成的.i文件。gcc加-E） int main() {         char a = 'a';         cout<<"a"<<endl;         cout<<"g(a)"<<endl;         printf("%s\n", "12");         printf("%s\n", "f(1,2)");         printf("%s\n", "h(f(1,2))");         printf("%s\n", "\"f(1,2)\"");         printf("%s\n", "\"12\"");         system("pause");         return 0; } --------------------------------------------------- 宏解析 1.       ##操作符 ##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号，它不能出现于宏替代表的开端和末尾。 例： #define concat(s,t) s##t #define AAA ABC concat(A, AA) 将被替换成 ABC 2.       重新扫描和替换 在替换列表中的所有参数替换过之后，预处理器将对结果token序列重新扫描以便对其中的宏再次替换。 当正在替换的宏在其替换列表中发现自身时，就不再对其进行替换。在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换（防止递归）。 例： #define ROOT AAA CCC #define AAA ROOT ROOT 将被替换成 ROOT CCC

要么宏展开时定义 #define func(a,b) int TL ## a ## b ## XY = 1


Question: c语言初学，函数

用VS吧，直接全选对齐下就知道少了个括号了。 http://blog.csdn.net/cometnet/article/details/19551125

while后面少了一个大括号

while少个｝

引用 4 楼 cocoabird的回复:出错信息是啥？看你程序没问题 这个，就是找不到文件

出错信息是啥？看你程序没问题

引用 1 楼 user-4的回复:  找一个好一点的 IDE ，可以风格化代码，然后就可以看清楚了  c-free 如果没有 风格化代码 就不要用了 好的，不过大神用的什么编译软件？


Question: 数列问题?

if(j==4)  printf(“\n”);的话，你一行的最后一个数就和前面4个数分在不同的两行里了  换成这样的话，可以用j==4  {  			printf("%d  ", a[i][j]); 			if (j == 4)  printf("\n"); 		}

引用 2 楼 baidu_33792305 的回复:问题更正： 可以正确运行结果了。 想问一下，为何： if(j= =0)  printf(“\n”); 而不是j==4时换行？  每次输入新的一行时时行换行，当然你要每次输入完一行时换行也行

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


Question: 杭电OJ1002，WA，不知道错在哪了，求指点

您可以试试我的代码。。0+0是没有问题的呢。样例输入也没有问题。自己也想了好多数也没找到问题

比如0+0 仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110

可以详细一点吗

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


Question: 有关C语言的内存布局问题

内存中是连续的按顺序的一块内存,有可能需要字节对其

直接%p打印地址看看？

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


Question: 这个程序中的问题？

单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

楼主可以尝试着每次打印中间结果，因为对于int型整数相除，结果还是得到一个int型的整数，也就是说会产生四舍五入的问题。因此计算结果不正确。

OK，谢谢了！！

这个问题主要是除法的原因。定义成int型，a/b如果是一个分数，那么就相当于是把它变成了一个float型数了，而实际上应该是一个int型的数。

菜鸟求教~~~在线等~~~


Question: Linux调试程序的问题

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

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

注：前面关于end1我也声明了这个变量。。


Question: 定义的结构体，没有声明任何变量，编译时候有什么影响

#2 是对的

1、不存在  2、编译器默认不会链接那些函数，VS里有个/Gy参数（函数级链接）

会降低那么一点编译速度

没有实例化 应该没有了吧  #include  没影像的，只要函数没有，就不会增大代码尺寸


Question: 用PlaySound函数如何做到音乐可以随时停止而不是要等全部播放完

好烦，C语言累死了

老赵难得正经回答一次，还被无视，难怪发飙了~~~

PlaySound The PlaySound function plays a sound specified by the given filename, resource, or system event. (A system event may be associated with a sound in the registry or in the WIN.INI file.)   BOOL PlaySound(   LPCSTR pszSound,     HMODULE hmod,        DWORD fdwSound     );   Parameters pszSound  A string that specifies the sound to play. If this parameter is NULL, any currently playing waveform sound is stopped. To stop a non-waveform sound, specify SND_PURGE in the fdwSound parameter.  Three flags in fdwSound (SND_ALIAS, SND_FILENAME, and SND_RESOURCE) determine whether the name is interpreted as an alias for a system event, a filename, or a resource identifier. If none of these flags are specified, PlaySound searches the registry or the WIN.INI file for an association with the specified sound name. If an association is found, the sound event is played. If no association is found in the registry, the name is interpreted as a filename.   hmod  Handle of the executable file that contains the resource to be loaded. This parameter must be NULL unless SND_RESOURCE is specified in fdwSound.  fdwSound  Flags for playing the sound. The following values are defined:  SND_APPLICATION  The sound is played using an application-specific association.  SND_ALIAS  The pszSound parameter is a system-event alias in the registry or the WIN.INI file. Do not use with either SND_FILENAME or SND_RESOURCE.  SND_ALIAS_ID  The pszSound parameter is a predefined sound identifier.  SND_ASYNC  The sound is played asynchronously and PlaySound returns immediately after beginning the sound. To terminate an asynchronously played waveform sound, call PlaySound with pszSound set to NULL.  SND_FILENAME  The pszSound parameter is a filename.  SND_LOOP  The sound plays repeatedly until PlaySound is called again with the pszSound parameter set to NULL. You must also specify the SND_ASYNC flag to indicate an asynchronous sound event.  SND_MEMORY  A sound event's file is loaded in RAM. The parameter specified by pszSound must point to an image of a sound in memory.  SND_NODEFAULT  No default sound event is used. If the sound cannot be found, PlaySound returns silently without playing the default sound.  SND_NOSTOP  The specified sound event will yield to another sound event that is already playing. If a sound cannot be played because the resource needed to generate that sound is busy playing another sound, the function immediately returns FALSE without playing the requested sound.  If this flag is not specified, PlaySound attempts to stop the currently playing sound so that the device can be used to play the new sound.   SND_NOWAIT  If the driver is busy, return immediately without playing the sound.  SND_PURGE  Sounds are to be stopped for the calling task. If pszSound is not NULL, all instances of the specified sound are stopped. If pszSound is NULL, all sounds that are playing on behalf of the calling task are stopped.  You must also specify the instance handle to stop SND_RESOURCE events.   SND_RESOURCE  The pszSound parameter is a resource identifier; hmod must identify the instance that contains the resource.  SND_SYNC  Synchronous playback of a sound event. PlaySound returns after the sound event completes.  Return Values Returns TRUE if successful or FALSE otherwise.  Remarks The sound specified by pszSound must fit into available physical memory and be playable by an installed waveform-audio device driver. PlaySound searches the following directories for sound files: the current directory; the Windows directory; the Windows system directory; directories listed in the PATH environment variable; and the list of directories mapped in a network. For more information about the directory search order, see the documentation for the OpenFile function.  If it cannot find the specified sound, PlaySound uses the default system event sound entry instead. If the function can find neither the system default entry nor the default sound, it makes no sound and returns FALSE.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in mmsystem.h.   Import Library: Use winmm.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also Waveform Audio Overview, Waveform Functions

2楼已经给出正解了。都瞎吗？！

老赵性情中人。。。。

还有就是音乐随时可以停。。

使用 异步模式来播放。 此时函数立即返回。 好像是使用 NULL 参数停止吧。  kbhit

参考： http://blog.163.com/tab_98/blog/static/1192409720159227278402/


Question: 二进制文件写入失败

if (fp = NULL)应该是if (fp == NULL)


Question: 一种hash算法请指教

搜“暴雪哈希算法”


Question: 关于 Fibonacci数列 取余

没有必要处处取余， 只sum取就够了。  取余也是计算量啊  （a + b ）mod c  = （a mod c） + （b mod c） a*b mod c = (a mod c ) * (b mod c)  a/b mod c 就不行了， 这才有个逆元的说法， 想知道逆元的概念就自己百度吧

a+b = c 因为 进位是从低位进到高位  所以 c的n位的数据 只会被a 和 b 中 n位和低于n位的数据影响  高于n位的数 不会影响n位数据

同余定理 ？


Question: 计算矩阵行列式bug,望解决

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。 判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }


Question: C语言函数qsort中compare详细用法

int compare (const void *p, const void *q) {     /*int x = *(const int *)p;     int y = *(const int *)q;     if (x < y) {         return -1;         如果x<y那么返回-1     } else if (x > y) {         return 1;         如果x>y那么返回1     }     return 0;*/           相等等于0 return (*(int *)p-*(int *)q); } 这个函数就是利用返回值来查看x和y的大小关系 调用compare函数后，如果返回值是 -1那么x<y 1那么x>y 0那么相等。 函数返回值做验证参数

应该说是一样的，这个compare函数就是告诉它两个数的大小关系就行

参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\qsort.c

qsort Performs a quick sort.  void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );  Routine Required Header Compatibility  qsort <stdlib.h> and <search.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  None  Parameters  base  Start of target array  num  Array size in elements  width  Element size in bytes  compare  Comparison function  elem1  Pointer to the key for the search  elem2  Pointer to the array element to be compared with the key  Remarks  The qsort function implements a quick-sort algorithm to sort an array of num elements, each of width bytes. The argument base is a pointer to the base of the array to be sorted. qsort overwrites this array with the sorted elements. The argument compare is a pointer to a user-supplied routine that compares two array elements and returns a value specifying their relationship. qsort calls the compare routine one or more times during the sort, passing pointers to two array elements on each call:  compare( (void *) elem1, (void *) elem2 );  The routine must compare the elements, then return one of the following values:  Return Value Description  < 0 elem1 less than elem2  0 elem1 equivalent to elem2  > 0 elem1 greater than elem2    The array is sorted in increasing order, as defined by the comparison function. To sort an array in decreasing order, reverse the sense of “greater than” and “less than” in the comparison function.  Example  /* QSORT.C: This program reads the command-line  * parameters and uses qsort to sort them. It  * then displays the sorted arguments.  */  #include <stdlib.h> #include <string.h> #include <stdio.h>  int compare( const void *arg1, const void *arg2 );  void main( int argc, char **argv ) {    int i;    /* Eliminate argv[0] from sort: */    argv++;    argc--;     /* Sort remaining args using Quicksort algorithm: */    qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare );     /* Output sorted list: */    for( i = 0; i < argc; ++i )       printf( "%s ", argv[i] );    printf( "\n" ); }  int compare( const void *arg1, const void *arg2 ) {    /* Compare all of both strings: */    return _stricmp( * ( char** ) arg1, * ( char** ) arg2 ); }   Output  [C:\code]qsort every good boy deserves favor boy deserves every favor good   Searching and Sorting Routines  See Also   bsearch, _lsearch


Question: 新人求解！！！！！

fot(i=1;(i<=n);i++)  改成  for(i=1;(i<=n);i++)

你这里边有好多好多错误 1）拼写错误 for 写成fot 2）声明错误 int decide (int n); 应该放到main函数之前 3）逻辑错误 根本看不清你要干嘛 4）调用错误 如果想在decide函数中读取n的或需要传入指针 5）变量重复 n定义了好几遍

你这编码风格不好

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

int decide(int n);这个函数应该不需要传入参数了


Question: 二进制文件读写，结构中带指针。字符串多出乱码

它是直接malloc更大的空间，而不是根据实际输入的字符长度来malloc的

引用 1 楼 jingxingxiaozhang 的回复:我找到问题了。我想后面有乱码肯定是没有\0，没有\0肯定是写入文件的时候，没有写入\0.我将 one.age = 20; one.name_len = strlen(name) +1   one.name = malloc(strlen(name)+1);     //这里开辟内存空间包括了\0 strcpy_s(one.name, strlen(name)+1, name);   //将name复制给noe.name 我给one.name_len 加上了1一个字节。这个输出就正确了。 但是我看视频上，同样的他是这么写的 	struct teacher one; 	char* name = "zhangsan"; 	one.age = 10; 	one.id = 20; 	one.name = malloc(64); 	memest(one.name, 0, 64); 	strcpy(one.name, name); 	one.name_len = strlen(name); 他这个也没有给\0的空间，为什么他最后能正常输出呢？？？？ 他直接先malloc了64个字节

把结构体中的指针写入文件是没用的，你需要写入指针指向的内容，读取时重新创建

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A

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


Question: 求一个编写C语言的软件，谢谢！！！

Pelles C for Windows

visual studio 2013

感觉用vc++顺手啊啊啊啊

DEV——C++  小 好用 编写控制台小程序好了

c-free

谢谢各位大神。

VS2008或者Devc++ CodeBlocks也行

C与C++程序设计学习与实验系统 2013.3 可以不用建立项目（单文件），简单的试验代码甚至不用保存为文件，直接编译运行观察结果，比较方便。 只有几十M大小。

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

没人推荐codeblocks?


Question: 多源代码文件程序的编译,新手求教，急急！！！

通常有个IDE的话直接添加到IDE新建的项目里即可

已经好了，谢谢

类似这样： gcc -g -Wall -o test xx1.c xx2.c xx3.c

1.如果是用的是IDE，比如VS之类的 将文件添加到工程中，然后点运行就行  2.GCC手动编译链接：http://www.cnblogs.com/hdchild/archive/2009/11/07/1598178.html


Question: C语言 八字节浮点数时间戳怎么转

引用 5 楼 qq_15534581 的回复:不是一个人。。。 只是《黑客帝国》中Matrix系统中同一个类的不同实例。

不是一个人。。。

和那个帖主是一个人吗，怎么数据都那么象

多谢  看到里面你说的那句  加31年 瞬间顿悟


Question: linux中scanf无法运行

ss是linux的一个命令。 ss命令用于显示socket状态

./ss  =========

ss是个命令吧。换个执行文件名就好了


Question: 这个函数怎么实现它的功能？

链接发错帖子了

https://msdn.microsoft.com/en-us/library/bb776913.aspx https://msdn.microsoft.com/en-us/library/bb775966.aspx

这是事件机制，当按下键盘某个键时候，就会触发键盘事件，程序会给予响应

#include <conio.h> int main() {     int key;       while(1)     {         key=getch(); //这里         if (key == '\033') //按了ESC键         {             printf("0x%x\n",key);             break;         }         else         {             printf("0x%x\n",key); //*打印出各键对对应的键值         }     }       return 0; }

ESC的ASCII码是27，可以通过检查是不是27判断是否按的是ESC

VS IDE中，在Exit上点鼠标右键，选查找所有引用。

能具体说一下吗，没有听懂……我是新手……

按键消息..


Question: 关于sizeof的浅显理解

sizeof 和 strlen 的关系，就像数值 2 和 "int a" 的 a 一样。

的确理解够浅显

分析的不错啊，不过sizeof的水还是比较深的，慢慢体会吧

谢谢楼主分享

总是把不相关的知识点放在一起讨论。

sizeof  是一个编译期间的运算符, 编译完成后就是一个常数 strlen 是运行的时候要去扫描内存, 是动态计算结果的.

建议楼主闲来无事去看看gcc/g++源代码中sizeof的实现。

sizeof 给出的类型的大小。如果给它一个对象，那么给出的这个对象的类型的大小。  当对象是一个子对象的时候，sizeof 给出的大小可以跟对象的实际大小不一致。


Question: 为什么JAVA的封装函数那么多而C库函数少？

因为C处在底层，从底层到高层是倒金字塔型， 最底层就是高电平低电平两个接口

C发展的比较早（那时候软件开发的规模也要小些），还没有面向对象，也就没有类库，只有一些标准库函数和一些IDE扩充的库函数。 好比诺基亚黑白屏手机，和现在的苹果、安卓手机比。

面向对象 +　设计模式

C只是标准库函数少，基本得用平台库。就看你要不要把平台库看成是C库了。

因为缺少的功能可以自己编

因为C完成很多功能无需库。

实际上JDK中也不过4000多个类，和.net框架、VCL/FMX框架比还差得远，后两者都上万。

C不属于任何一个公司，而java属于oracle

为什么QQ那么便宜Ferrari那么贵？


Question: 获取可变长数组内的无素出现乱码

仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //

1.这种写法只有GCC编译器可以通过编译 scanf("%d%d",&n,&m);  int array[n][m];  2.用malloc或者new动态分配  3.用STL，比如vector什么的

也就是说在程序运行期，可变长数组的长度是不可改变的罗只能使用下面这个方式  #define ROW_MAX 2 #define COLUMN_MAX 3 int a[ROW_MAX][COLUMN]_MAX;  如果需要在程序运行时改变大小，只能利用malloc calloc分配内存进行操作，这样理解没问题吧？还有没其它方法可以实现在程序运行过程中动态改变的？

int array[n][m]; printf("这是一个二维数组遍历的参考例子\n"); printf("请输入二维数组的行和列\n"); scanf("%d%d", &n, &m);  你这样的写法已经定死了数组的两个维度了，是1X1的

//int array[n][m];       printf("这是一个二维数组遍历的参考例子\n");       printf("请输入二维数组的行和列\n");       scanf("%d%d",&n,&m);       int array[n][m];


Question: restrict关键字没有起作用呢？

以下为 C11 对 restrict 的定义：  6.7.3.1 6.7.3.1 Formal definition of restrict 1 Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T. 2 If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of whatever function is called at program startup in a freestanding environment). 3 In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E.137) Note that ‘‘based’’ is defined only for expressions with pointer types. 4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause. If P is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined. 5 Here an execution of B means that portion of the execution of the program that would correspond to the lifetime of an object with scalar type and automatic storage duration associated with B. 6 A translator is free to ignore any or all aliasing implications of uses of restrict. 7 EXAMPLE 1 The file scope declarations int * restrict a; int * restrict b; extern int c[]; assert that if an object is accessed using one of a, b, or c, and that object is modified anywhere in the program, then it is never accessed using either of the other two. 8 EXAMPLE 2 The function parameter declarations in the following example void f(int n, int * restrict p, int * restrict q) { while (n-- > 0) *p++ = *q++; } assert that, during each execution of the function, if an object is accessed through one of the pointer parameters, then it is not also accessed through the other. 9 The benefit of the restrict qualifiers is that they enable a translator to make an effective dependence analysis of function f without examining any of the calls of f in the program. The cost is that the programmer has to examine all of those calls to ensure that none give undefined behavior. For example, the second call of f in g has undefined behavior because each of d[1] through d[49] is accessed through both p and q. void g(void) { extern int d[100]; f(50, d + 50, d); // valid f(50, d + 1, d); // undefined behavior } 10 EXAMPLE 3 The function parameter declarations void h(int n, int * restrict p, int * restrict q, int * restrict r) { int i; for (i = 0; i < n; i++) p[i] = q[i] + r[i]; } illustrate how an unmodified object can be aliased through two restricted pointers. In particular, if a and b are disjoint arrays, a call of the form h(100, a, b, b) has defined behavior, because array b is not modified within function h. 11 EXAMPLE 4 The rule limiting assignments between restricted pointers does not distinguish between a function call and an equivalent nested block. With one exception, only ‘‘outer-to-inner’’ assignments between restricted pointers declared in nested blocks have defined behavior. { int * restrict p1; int * restrict q1; p1 = q1; // undefined behavior { int * restrict p2 = p1; // valid int * restrict q2 = q1; // valid p1 = q2; // undefined behavior p2 = q2; // undefined behavior } } 12 The one exception allows the value of a restricted pointer to be carried out of the block in which it (or, more precisely, the ordinary identifier used to designate it) is declared when that block finishes execution. For example, this permits new_vector to return a vector. typedef struct { int n; float * restrict v; } vector; vector new_vector(int n) { vector t; t.n = n; t.v = malloc(n * sizeof (float)); return t; }  137) In other words, E depends on the value of P itself rather than on the value of an object referenced indirectly through P. For example, if identifier p has type (int **restrict), then the pointer expressions p and p+1 are based on the restricted pointer object designated by p, but the pointer expressions *p and p[1] are not.

违反 restrict 约定的行为是一个 未定义行为。  未定义行为可能产生任何结果，包括但不限于：产生期望的结果，产生未期望的结果，产生随机的结果，产生无法解释的结果，运行错误，随机的运行时错误，编译错误，等等  6.7.3 Type qualifiers 8 An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.135) The intended use of the restrict qualifier (like the register storage class) is to promote optimization, and deleting all instances of the qualifier from all preprocessing translation units composing a conforming program does not change its meaning (i.e., observable behavior).  p3 既然被声明为 restrict ，通过 p4 去修改 p3 指向的（数组的）内容是不对的。

int a[3] = {1,2,3}; 	    int * restrict p1; 	    p1 = a;//这里的赋值不应该错误吗？p1不是访问一个数据对象初始的方式吗？ 	    printf("%d\n",p1[2]);  	    int * restrict p3 = (int *)malloc(10*sizeof(int)); 	    p3[3] = 10; 	    p3[3] += 10; 	    printf("%d\n",p3[3]); 	    p4[3] = 11; 	    p3[3] += 10; 	    printf("%d\n",p3[3]);//这里不应该输出是30吗？p3不是访问那内存的唯一方式吗？p4[3]=11不应该忽略吗？ 	    printf("%d\n",p4[3]);


Question: usb鼠标 绝对坐标

将鼠标换成数字手写板。

就单片机做鼠标连电脑来的

数字化仪支持绝对坐标输入，就是不便宜啊

引用 3 楼 tw2429 的回复:就单片机做鼠标连电脑来的  用单片机感觉有点大材小用，虽然比较万能（通用）。

驱动和操作系统也要配合。

应该要修改硬件的固件（可能是集成的芯片）。


Question: 在.h头文件中宏定义数组元素，但不定义数组，在.c文件中再正式定义数组行吗？

要完全彻底地弄清楚这个问题，我觉得可以试试了解一下gcc源代码中处理宏定义相关片断。

引用 7 楼 xixia07m 的回复:请cyfcsd回答一下我的问题，数组怎么就成为只读的了？为什么不能写AOCC_BSADE[0]=...这样的语句了? 你定义了#define  AOCC_BSADE[0]  one以后程序里的所有AOCC_BSADE[0]都会变成one，one=...这种语句不能通过编译

引用 5 楼 cyfcsd 的回复:[quote=引用 4 楼 xixia07m 的回复:] [quote=引用 1 楼 cyfcsd 的回复:] 宏定义就是纯粹的字符串替换，以后你代码中的AOCC_BSADE[0]都会变成one，这应该不是你想要的吧，还有在.c文件中定义不加extern，声明时才用 你到底是要实现什么功能啊？  这是我想要的。把定义语句改为  char  AOCC_BSADE[AOCC_BSADE_NUM]  是不是就可以了？这个数组要在串口通讯程序中用到，我的问题就是能不能在.h文件中不定义这个数组，而把它定义在串口通讯程序所在的main程序的前面？这样的安排可以吗？[/quote] 这么用那这个数组就成了只读的了，不能写AOCC_BSADE[0]=...这样的语句了，定义可以放到main程序前面，但只能在main函数这个文件里用，不能在别的文件里用[/quote]  为什么就成只读的了？写成AOCC_BSADE[0]=XXX会有什么问题？

引用 4 楼 xixia07m 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 宏定义就是纯粹的字符串替换，以后你代码中的AOCC_BSADE[0]都会变成one，这应该不是你想要的吧，还有在.c文件中定义不加extern，声明时才用 你到底是要实现什么功能啊？  这是我想要的。把定义语句改为  char  AOCC_BSADE[AOCC_BSADE_NUM]  是不是就可以了？这个数组要在串口通讯程序中用到，我的问题就是能不能在.h文件中不定义这个数组，而把它定义在串口通讯程序所在的main程序的前面？这样的安排可以吗？[/quote] 这么用那这个数组就成了只读的了，不能写AOCC_BSADE[0]=...这样的语句了，定义可以放到main程序前面，但只能在main函数这个文件里用，不能在别的文件里用

引用 1 楼 cyfcsd 的回复:宏定义就是纯粹的字符串替换，以后你代码中的AOCC_BSADE[0]都会变成one，这应该不是你想要的吧，还有在.c文件中定义不加extern，声明时才用 你到底是要实现什么功能啊？  这是我想要的。把定义语句改为  char  AOCC_BSADE[AOCC_BSADE_NUM]  是不是就可以了？这个数组要在串口通讯程序中用到，我的问题就是能不能在.h文件中不定义这个数组，而把它定义在串口通讯程序所在的main程序的前面？这样的安排可以吗？

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

要实现啥目的呢？


Question: printf()参数列表类型的问题

与 %s 匹配的本身就是 char* 指针，而输出的内容就是字符串，而不是指针的值  要输出指针的值，用的是%p

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

与%s匹配的应该是指针

下面是百度到的，好像明白了。 “具体说就是用char *p="abcqer12345";这种方法定义字符串是不能通过指针改变内容的，原因是这个定义确定了abcqer12345是字符串常量——因为char *p="abcqer12345";被编译器解释为“创建一个字符串常量abcqer12345，并把它的首地址(就是a的地址)赋给char *型指针p”——既然是“常量”，自然就不能更改。”

char *first;表示的是指向一个字符串的指针，不是代表指向一个字符的指针。 你用%c去输出treas.first当然有警告

#include <stdio.h> int main(void) {     struct pnames{     	char *first;     	char *last; 	}; 	struct pnames treas={'n','m'}; 	printf("%c\n",treas.first); 	system("pause"); 	return 0;	 } 为什么会报错？8	9	D:\CPP\TestStruc.c	[Warning] initialization makes pointer from integer without a cast

char* first;   // 是一指针 指向了常量 "Brad";  和 char * str="Brad";的道理;  #include <stdio.h> int main(void) {     struct pnames {         char* first;         char* last;     };     struct pnames treas = {"Brad", "Fallingjaw"};     char* str = "Brad";      printf("%s\t%d\n", treas.first, &treas.first);     printf("%s\t%d\n", str, &str);     return 0; }  //    输出 //    Brad    2686744 //    Brad    2686740


Question: DEV C++改完配置之后可以调试，但重新打开出现问题是怎么回事？

Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt  关闭UAC、防火墙、杀毒软件、……

DEV C++ 默认只带 32位编译器吧 你改成使用 64 位编译器设置，但是实际没有 64位的吧


Question: 为什么fgets没有读取到\n

不要妄下结论。 fgets, fgetws Get a string from a stream.  char *fgets( char *string, int n, FILE *stream );  wchar_t *fgetws( wchar_t *string, int n, FILE *stream );  Function Required Header Compatibility  fgets <stdio.h> ANSI, Win 95, Win NT  fgetws <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns string. NULL is returned to indicate an error or an end-of-file condition. Use feof or ferror to determine whether an error occurred.  Parameters  string  Storage location for data  n  Maximum number of characters to read  stream  Pointer to FILE structure  Remarks  The fgets function reads a string from the input stream argument and stores it in string. fgets reads characters from the current stream position to and including the first newline character, to the end of the stream, or until the number of characters read is equal to n – 1, whichever comes first. The result stored in string is appended with a null character. The newline character, if read, is included in the string.   fgets is similar to the gets function; however, gets replaces the newline character with NULL. fgetws is a wide-character version of fgets.   fgetws reads the wide-character argument string as a multibyte-character string or a wide-character string according to whether stream is opened in text mode or binary mode, respectively. For more information about using text and binary modes in Unicode and multibyte stream-I/O, see Text and Binary Mode File I/O and Unicode Stream I/O in Text and Binary Modes.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _fgetts fgets fgets fgetws    Example  /* FGETS.C: This program uses fgets to display  * a line from a file on the screen.  */  #include <stdio.h>  void main( void ) {    FILE *stream;    char line[100];     if( (stream = fopen( "fgets.c", "r" )) != NULL )    {       if( fgets( line, 100, stream ) == NULL)          printf( "fgets error\n" );       else          printf( "%s", line);       fclose( stream );    } }   Output  /* FGETS.C: This program uses fgets to display     Stream I/O Routines  See Also   fputs, gets, puts

你可以试着从文件读，就可以读到换行符了

因为被控制台吃了，控制台通过换行符判断一次输入结束


Question: 初学求教，hangman游戏

找不到那两个函数的实现，需要将相关库文件或者cpp文件添加到项目中

少必要的cpp文件。


Question: 求给定精度的简单交错序列部分和

#include<stdio.h> int main() { 	double a,b,d,sum=0; 	int i,c=1; 	scanf("%lf",&a); 	for(i=1;c!=0;i=i+3) 	{ 		b=1.000/i; 		if(i%2!=0) 			sum=sum+b; 		else 			sum=sum-b; 		if(b<=a) 			c=0; 	} 	printf("sum = %lf",sum); 	return 0; }

看一下while的循环条件，应该是while(fabs(k)>eps)

首先“ }while(fabs(k)>=eps);”改成“ }while(fabs(k)>eps);”，满足题目中不大于的条件； 其次将   if (fabs(k)<eps)  break; 改成    if (fabs(k)<eps) { s=1.0; break; } 这样是保证当输入esp的值大于1时，输出的值为1.

题目中说不大于， 这里改成    }while(fabs(k)>eps);  看下是否可以

printf("sum = %.15lg\n",s); ？


Question: 关于链表

非常感谢两位

link 相当于Node * link l; 相当于 Node *l; typedef是取别名的意思，不是定义变量

前面有typedef, link是定义一个类型，相当于node *


Question: 归并排序为什么for循环不从第一个数字开始输出

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

是你的控制台输出的行数有限。 点击窗口左上角的那个小图标，选择“默认值”，然后在“布局”选项卡中增大缓冲区的高度。


Question: 数据结构二叉树问题

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

单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 数据结构二叉树问题

修改发的错误                  void leaf1(BiTree root) { if(root!=NULL) { leaf(root->LChild); leaf(root->RChild); if(root->LChild==NULL&&root->RChild!=NULL)   LeafCount1++; if(root->LChild!=NULL&&root->RChild==NULL)   LeafCount1++; }	 }


Question: 关于文件remove函数的操作

嗯 删除文件

你说的是删除文件？？？？

写保护？ 关闭UAC、防火墙、杀毒软件、……  Change the current working directory. int _chdir( const char *dirname );


Question: 高手求教，为什么swap函数没能交换两指针变量本身的地址。。

swap（）函数用void空类型，并不会改变*p1和*p2的值啊，这两个值只会在函数内改变，并不会把主程序中的*p1和*p2改掉，而且函数内的变量用完就自动删掉了，并没有什么用。你可以把*p1和*p2改为全局变量，这样就可以在执行函数的时候改动变量的值了。注意swap括号里的东西要删掉。

你传地址应该改内容啊 改成这样试试   #include <stdio.h> void swap(int *p1,int *p2){ int p; p=*p1,*p1=*p2,*p2=p; } void main(){ int a,b; int *t1=&a,*t2=&b; printf("请输入a和b的值\n"); scanf("%d,%d",&a,&b); if(a<b){ swap(t1,t2); } printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d",*t1,*t2); }

仅供参考：#include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2

例3： #include <stdio.h>  void change(int *, int *); int main (void) {     int x = 3, y = 5;      change(&x,&y);     printf("x = %d, y = %d",x, y);     return 0; } void change(int * a, int * b) {     int t;     t = *a;     *a = *b;     *b = t; }  结果：x = 5, y = 3 分析：交换成功！把地址传过去，直接改地址里的值。

#include <stdio.h>  void change(int *, int *); int main (void) {     int x = 3, y = 5;      change(&x,&y);     printf("x = %d, y = %d",x, y);     return 0; } void change(int * a, int * b) {     printf("a = %d, b = %d\n",*a, *b);     int * t;     t = a;     a = b;     b = t;     printf("a = %d, b = %d\n",*a, *b); }  结果： a = 3, b = 5 a = 5, b = 3 x = 3, y = 5 分析：没有交换！把地址传过去，但是是把地址传给了新定义的两个指针变量，然后两个指针变量的值的给交换啦，所以两个新定义的指针变量所指向的对象交换啦，但是原先的两个整型变量值并没有改！ 易错点：C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。不能通过执行调用函数（change）来改变实参指针变量(&x,&y)的值，但是可以改变实参指针变量所指变量的值。


Question: 用代码实现算法

您好，感谢您的帮助，但是当把数据读取进去后为什么会出现语法错误，显示是语法错误：“常量”

您好，您的这个怎么读取txt内容

#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>  void printBinStr(const void* buf , size_t size); void printHexStr(const void* buf , size_t size);  int main(int argc, char* argv[]) {     char arr[100];     for (int i = 0; i != 100  ; ++i) {         arr[i] = i+ '1';     }     printBinStr(arr , sizeof(arr));      putchar('\n'); // 打印文件     const char* filename =  "main.cpp";     if (argc == 2)         filename = argv[1];      FILE *f = fopen(filename, "rb");     if (!f) {         std::cerr << "Error: Cannot open File "<< std::endl;         return -1;     }         // Get file size:     fseek(f, 0, SEEK_END);     const long N = ftell(f);     fclose(f);      f = fopen(filename, "rb");     char* buf = new char[N+1];     fread(buf,1,N,f);     buf[N]= '\0';      printHexStr(buf , N);        return 0; }  void printBinStr(const void* buf , size_t size) {     unsigned char* str = (unsigned char*)buf;     char line[512] = {0};     const size_t lineLength = 6; // 每行6个字符     char text[24] = {0};     char sbin[10] = {0};     char* pc;     int textLength = lineLength;       for (size_t ix = 0 ; ix < size ; ix += lineLength) {         sprintf(line, "%.8xh: ", ix); // 打印二进制         for (size_t jx = 0 ; jx != lineLength ; jx++) {          itoa(* (str + ix + jx),   sbin,   2);       //转换成字符串，进制基数为2              if (ix + jx >= size) {                 sprintf(line + (11 + jx * 9), "         "); // 处理最后一行空白                 if (ix + jx == size)                     textLength = jx;  // 处理最后一行文本截断             } else                 sprintf(line + (11 + jx * 9), "%08s ", sbin);         } // 打印字符串         {             memcpy(text, str + ix, lineLength);             pc = text;             while (pc != text + lineLength) {                 if ((unsigned char)*pc < 0x20) // 空格之前为控制码                     *pc = '.';                 // 控制码转成'.'显示                 pc++;             }             text[textLength] = '\0';             sprintf(line + (11 + lineLength * 9), "; %s", text);         }          printf("%s\n", line);     } }  void printHexStr(const void* buf , size_t size) {     unsigned char* str = (unsigned char*)buf;     char line[512] = {0};     const size_t lineLength = 16; // 8或者32     char text[24] = {0};     char* pc;     int textLength = lineLength;      for (size_t ix = 0 ; ix < size ; ix += lineLength) {         sprintf(line, "%.8xh: ", ix); // 打印16进制         for (size_t jx = 0 ; jx != lineLength ; jx++) {             if (ix + jx >= size) {                 sprintf(line + (11 + jx * 3), "   "); // 处理最后一行空白                 if (ix + jx == size)                     textLength = jx;  // 处理最后一行文本截断             } else                 sprintf(line + (11 + jx * 3), "%.2X ", * (str + ix + jx));         } // 打印字符串         {             memcpy(text, str + ix, lineLength);             pc = text;             while (pc != text + lineLength) {                 if ((unsigned char)*pc < 0x20) // 空格之前为控制码                     *pc = '.';                 // 控制码转成'.'显示                 pc++;             }             text[textLength] = '\0';             sprintf(line + (11 + lineLength * 3), "; %s", text);         }          printf("%s\n", line);     } }


Question: 关闭文件必须要检查文件指针吗？

if (tp = NULL)  ----->  if (tp == NULL)

if (tp = NULL)你这个弄的 保险点是要判断是否为nul的，不然出现段错误


Question: 用scanf函数输入值越界

在调试的时候又发现了一个问题，就是下一步如果多个方向都可以走的话怎么选的问题。 程序里 MarkMap(map, position, location);   //标记可以通过的位置 			e.passnum = location; 			e.location = position; 			e.direction = 0;                    //向东探索 			Push(S, e); 是直接向右探索的，假设迷宫的出入口分布为（1，1）、（8，8） 探索方向应该是向右下方进行的，如何能让下一步探索综合向右和向下的结果呢

你输入数据"1，1 "时，是不是汉字下的逗号啊？？？

之前是因为输入了汉子的逗号 谢谢各位大侠

你用空格分开，输入时也是用空格

上面的回复：不是汉字逗号

没问题啊，只要你输入的不是汉字括号，scanf我这里运行可以通过的。没有异常。赋值也是正确。

输入的时候，两个数字用英文下的逗号分隔

好的 蟹蟹大侠！ #include<stdio.h> #include<string.h> #include<malloc.h> #include<stdlib.h>  #define ERR_NOMEMRROY -1  #define ERR_INVALIDPARAM -2 #define ERR_OVERFLOW -3 #define ERR_ILLEGALINDEX -4 #define ERR_EMPTYRESULT -5  #define MAZE_MAXSIZE 100     //迷宫最大行数和列数  typedef struct{ 	int x; 	int y; }position;                //记录迷宫的行和列  typedef struct { 	int passnum;          //路径块的序号 	position location;    //路径块在迷宫中的位置	 	int direction;		 //从当前路径走向下一路径块的方向 0东1西2南3北 }datatype;  typedef struct node { 	datatype data; 	struct node* next;	 }StackNode,*LinkStack;  int InitStack(LinkStack *top) { 	StackNode *t = NULL;   	if (!top)return ERR_INVALIDPARAM;  	//分配内存空间 	t = (StackNode*)malloc(sizeof(StackNode)); 	if (!t)return ERR_NOMEMRROY;  	t->next = NULL; 	(*top) = t; 	return 0; }  int Push(LinkStack top, datatype e) { 	StackNode *p = NULL; 	if (!top)return ERR_INVALIDPARAM;  	p = (StackNode*)malloc(sizeof(StackNode)); 	if (!p)return ERR_NOMEMRROY; 	 	p->data = e; 	p->next = top->next; 	top->next = p; 	return 0; }  int Pop(LinkStack top, datatype *e) { 	StackNode *p = NULL; 	if (!p)return ERR_INVALIDPARAM; 	if (!p->next)return ERR_EMPTYRESULT;  	p = top->next; 	top->next = p->next; 	*e = p->data; 	free(p); 	return 0; } int DestoryStack(LinkStack top) { 	StackNode *p = NULL; 	if (!top) return ERR_INVALIDPARAM;  	while (top) 	{ 		p = top; 		top = top->next; 		free(p); 	} 	return 0; } int StackEmpty(LinkStack top) { 	if (!top)return ERR_INVALIDPARAM; 	return(top->next == NULL); }  int Peek(LinkStack top, datatype *e) { 	if (!top)return ERR_INVALIDPARAM; 	if (!top->next)return ERR_EMPTYRESULT; 	 	*e = top->next->data; 	return 0; }  int CanPass(int map[][MAZE_MAXSIZE], position pos) //0表示可以以通过 { 	return (map[pos.x][pos.y] == 0); }  int MarkMap(int map[][MAZE_MAXSIZE], position pos, int mark) //用mark标记迷宫中的pos位置 { 	map[pos.x][pos.y] = mark; 	return 0; } int NextPos(int map[][MAZE_MAXSIZE], int dir, position *pos) //根据当前位置及移动方向，求得下一方向 为什么要用*pos { 	position d[4] = { {0,1},{1,0},{0,-1},{-1,0} }; 	(*pos).x += d[dir].x; 	(*pos).y += d[dir].y; 	return 0;  } /*计算迷宫入口到出口的路径*/ int MazePath(int map[][MAZE_MAXSIZE], position entry, position exit) { 	int location = 1; 	position position = entry; 	datatype e; 	//初始化链栈 	LinkStack S; 	InitStack(&S);  	do 	{ 		if (CanPass(map, position)) 		{ 			MarkMap(map, position, location);   //标记可以通过的位置 			e.passnum = location; 			e.location = position; 			e.direction = 0;                    //向东探索 			Push(S, e);  			if (position.x == exit.x&&position.y == exit.y) 				return location;  			location++; 			NextPos(map, e.direction, &position); 		} 		else  //当前位置不能通过  		{ 			if (!StackEmpty(S)) 			{ 				Pop(S, &e); 				location--;  				 				if (e.direction<3) 				{ 					e.direction++;   //寻找方向 					Push(S, e);		//入栈该位置的下一个方向 					location++;		 					position = e.location; //确定当前位置 					NextPos(map, e.direction, &position);//确定下一个位置  				} 				while (e.direction == 3 && !StackEmpty(S))  //direction=3说明四个方向都走不通，退回到上一步 				{ 					MarkMap(map, e.location, 0);  //标记位置不通 					Pop(S,&e); 					location--; 				} 			}	 		} 	} while (!StackEmpty(S)); 	DestoryStack(S); 	return 0; }  void PrintMaze(int map[][MAZE_MAXSIZE], int row, int col) { 	int i, j;  	//打印列号 	printf("\n   "); 	for (i = 0; i < row; i++) 		printf("%3d",i); 	printf("\n");  	//打印行号 	for (i = 0; i < row; i++) 	{ 		printf("%3d", i); 		for (j = 0; j < col; j++) 		{ 			if (map[i][j] == 0)printf("   ");  //非障碍物打印空格 			else if (map[i][j] == 1)printf("  #");     //障碍物打印# 			else printf("%3d", map[i][j]); 		} 		printf("\n"); 	} 	printf("\n"); }  int main() { 	int steps = 0; 	position entry, exit; 	int maze[MAZE_MAXSIZE][MAZE_MAXSIZE] = { 	{ 1,1,1,1,1,1,1,1,1,1 }, 	{ 1,0,0,1,0,0,0,1,0,1 }, 	{ 1,0,0,1,0,1,0,1,0,1 }, 	{ 1,0,0,0,0,1,1,0,0,1 }, 	{ 1,0,1,1,1,0,0,0,1,1 }, 	{ 1,0,0,0,1,0,0,0,0,1 }, 	{ 1,0,1,0,0,0,1,0,0,1 }, 	{ 1,0,1,1,1,0,1,1,0,1 }, 	{ 1,1,0,0,0,0,0,0,0,1 }, 	{ 1,1,1,1,1,1,1,1,1,1 }, 	};  	printf("迷宫的结构如下：\n"); 	PrintMaze(maze, 10, 10);  	printf("请输入入口的行和列（row,col）："); 	scanf_s("%d,%d", &entry.x, &entry.y);  	printf("%d,%d", entry.x, entry.y); 	system("pause");  	printf("请输入出口的行和列（row,col）："); 	scanf_s("%d,%d", &exit.x, &exit.y);  	steps = MazePath(maze, entry, exit); 	if (steps == 0)printf("迷宫没有从入口到出口的路径\n"); 	else printf("从入口到出口需要%2d步\n", steps);  	PrintMaze(maze, 10, 10);  	getch(); 	return 0;   }

把完整代码贴上来，我给你调试

不是的，我试过不加逗号了，而且scanf里也写逗号了


Question: F:\C语言程序\链表.cpp(197) : error C2601: 'Convert' : local function definitions are i

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

这代码哪来的？ 各种编译错误和逻辑错误。 帮你把编译的错误都改了，但还有很多别的错误，建议自己单步调试。 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  #include<stdio.h> #include<stdlib.h> typedef int datatype; typedef struct node { 	datatype data; 	struct node *next;//结构体指针用作结构体成员 }lnode;    lnode *createlinklist(); lnode *get_linklist(lnode *head, int i); void print(lnode *head);//函数声明后面记得一定有一个分号； lnode *locate_linklist(lnode *head, int x); void insert_linklist(lnode *head, int i, int x); int del_linklist(lnode *head, int i, int n); void del_linklist_key(lnode *head, int x); void convert(lnode *head); lnode *fuzhi_linklist(lnode *head); void del_jishudatalinklist(lnode *head);  void main() { 	lnode *head, *found1, *found2; 	int i, x; 	head = createlinklist(); 	printf("请输入查找序号"); 	scanf("%d", &i); 	found1 = get_linklist(head, i); 	printf("请输入查找值"); 	scanf("%d", &x); 	found2 = locate_linklist(head, x); 	insert_linklist(head, i, x); 	del_linklist_key(head, x);//删除值相同的多与节点 	print(head); }    lnode *createlinklist() { 	lnode *head, *p, *q;//p为定位指针 	int x, n, i; 	if ((head = (lnode*)malloc(sizeof(lnode))) == NULL) 	{ 		printf("链表申请失败\n"); 		return NULL; 	}  	else 		head->next = NULL; 	printf("请输入链表的节点数:"); 	scanf("%d", &n); 	printf("请输入数据:");   	for (i = 0; i < n; i++) 	{ 		scanf("%d", &x); 		p = head; 		if (i == 0) 			head->data = n;//头结点数据域中放结点个数   		if ((q = (lnode*)malloc(sizeof(lnode))) == NULL) 		{ 			printf("新节点申请失败\n"); 			break; 			return NULL; 		} 		else 		{ 			q->data = x; 			q->next = head->next; 			head->next = q; 			p = q; 			printf("\n请输入数据:"); 		}  	}  	return head;//返回头指针 }  lnode *get_linklist(lnode *head, int i) { 	lnode *p = head->next;//从第一个结点开始查找；p为查找指针 	int j = 1;//计数器  	while (p != NULL&&j < i) 	{ 		p = p->next;//查找指针后移 		j++;//计数器加一 	}  	if (p != NULL) 		return p;//返回第i个结点的指针值，找不到则返回空值 	else 		return NULL; }  lnode *locate_linklist(lnode *head, int x) { 	lnode *p = head->next;//从第一个结点开始查找；p为查找指针  	while (p != NULL && (p->data != x)) 		p = p->next;//指针后移 	return p;//返回值为x的结点的指针值，找不到则返回空值  }   void insert_linklist(lnode *head, int i, int x)//在单链表head的第i个位置插入值x { 	lnode *p, *q;//从第一个结点开始查找；,q为待插指针 	p = get_linklist(head, i - 1);  	if (p == NULL) 		printf("error\n");  	else 	{ 		q = (lnode*)malloc(sizeof(lnode));//申请结点空间 		q->data = x; 		q->next = p->next; 		p->next = q; 	}  }   int del_linklist(lnode *head, int i, int n)//n为节点个数 { 	lnode *p, *q; 	int *x = new int, m;//m保存结点个数 	p = get_linklist(head, i - 1);//p指向第i-1个指针 	if (p == NULL) 		printf("第i-1结点不存在"); 	else 	if (p->next == NULL) 		printf("第i结点不存在"); 	else 	{ 		q = p->next;//q指向第i个指针 		*x = q->data;//备份i的数据 		p->next = q->next; 		free(q);//回第i个指针收地址 		n--; 		m = n; 	} 	return m; }   void print(lnode *head) { 	lnode *p;//p为定位指针 	int i = 0;//i输出节点的个数 	p = head->next; 	while (p != NULL) 	{ 		i++; 		printf("第%d个数据: %d\n", i, p->data); 		p = p->next; 		printf("线性表的表长为: %d\n", i); 	}  }   void del_linklist_key(lnode *head, int x) { 	lnode *p = NULL, *q, *ptr, *m; 	m = locate_linklist(head, x);  	while (p != NULL)//检查表中x以后的所有节点 	{ 		q = m; 		ptr = m->next; 		while (ptr != NULL)//检查节点p后面所有的后继结点ptr 		{ 			if (ptr->data == p->data) 			{ 				q->next = ptr->next; 				ptr = q->next; 				free(ptr); 			} 			else 			{ 				q = ptr; 				ptr = ptr->next; 			} 			p = p->next; 		}  	} } void Convert(lnode *head)//实现单链表 的逆置 { 	lnode *p, *q; 	p = head->next;//指针p指向剩余结点中的第一个数据结点 	head->next = NULL; 	while (p != NULL) 	{ 		q = p; 		p = p->next; 		q->next = head->next; 		head->next = q; 	}  }   lnode *fuzhi_linklist(lnode *head)//将一个单链表中的元素复制到另一个单链表中 { 	lnode *head1, *p1, *p, *weij;  	if ((head1 = (lnode *)malloc(sizeof(lnode))) != NULL) 	{ 		printf("内存分配成功\n"); 		p = head->next; 		p1 = head1->next;//p1指针指向head1的第一个节点 		while (p != NULL) 		{ 			if (((p->data) % 2) == 0) 			{ 				if ((weij = (lnode *)malloc(sizeof(lnode))) != NULL) 				{ 					p1->next = weij; 					p1 = weij; 					weij->data = p->data;  				} 				else 					break; 			} 			else 				p = p->next;  		} 		return head1;  	}  	else 		return NULL;  }   void del_jishudatalinklist(lnode *head)//删除其中的奇数节点的值 { 	lnode *p = head->next, *q = NULL;//p指针指向第一个节点 	while (p != NULL)//循环保证所有的节点的指针不为空 	{ 		if (((p->data) % 2) != 0) 		{ 			q->next = p->next; 			free(p); 			p = q->next; 		} 		else 		{ 			q = p; 			p = p->next; 		} 	} }

Convert函数定义前面的那个函数，是不是少了一个右大括号？

\C语言程序\链表.cpp(197) : error C2601: 'Convert' : local function definitions are illegal F:\C语言程序\链表.cpp(213) : error C2601: 'fuzhi_linklist' : local function definitions are illegal F:\C语言程序\链表.cpp(250) : error C2601: 'del_jishudatalinklist' : local function definitions are illegal F:\C语言程序\链表.cpp(267) : fatal error C1004: unexpected end of file found 执行 cl.exe 时出错.  链表.obj - 1 error(s), 0 warning(s)    怎么改，请问各位


Question: 关于使用Visual Studio 2013运行c程序的问题

引用 10 楼 hdj_cz_forever 的回复:[quote=引用 4 楼 wenpinglaoyao 的回复:] [quote=引用 2 楼 wenpinglaoyao 的回复:] 楼主，首先，你上传的是图片，这样不利于大家帮您找问题，您应该上传源代码，我们复制粘贴以后在自己的平台上运行一下，会更容易找问题。其次，楼上正解，scanf_s不同于老版的scanf，如果给它传递字符数组，需要传递一个数组大小的，说是为了scanf函数的安全着想【怕溢出攻击】  改成这样【scanf_s("%s", name, 40);】[/quote] 请问，scanf_s("%f",&weight);  这条语句中，变量weight没有上述要求了吧？[/quote]  嗯是的，因为变量weight只是一个单个int变量，函数不需要知道它的内存大小，但字符数组不同。

引用 4 楼 wenpinglaoyao 的回复:[quote=引用 2 楼 wenpinglaoyao 的回复:] 楼主，首先，你上传的是图片，这样不利于大家帮您找问题，您应该上传源代码，我们复制粘贴以后在自己的平台上运行一下，会更容易找问题。其次，楼上正解，scanf_s不同于老版的scanf，如果给它传递字符数组，需要传递一个数组大小的，说是为了scanf函数的安全着想【怕溢出攻击】  改成这样【scanf_s("%s", name, 40);】[/quote] 请问，scanf_s("%f",&weight);  这条语句中，变量weight没有上述要求了吧？

引用 7 楼 qq423399099 的回复:scanf_s读取%c和%s的时候必须多传一个参数来指定读入的字符长度 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 受教了，谢谢~

引用 5 楼 shihengzhen101 的回复:楼主，你不要用中文的文件名啊，虽然这里不是这个问题，但是尽量不要用中文命名文件名和路径名 好的，谢谢提醒~

单步跟踪程序运行，观察分析原因，看是在哪一步出了问题

引用 2 楼 wenpinglaoyao 的回复:楼主，首先，你上传的是图片，这样不利于大家帮您找问题，您应该上传源代码，我们复制粘贴以后在自己的平台上运行一下，会更容易找问题。其次，楼上正解，scanf_s不同于老版的scanf，如果给它传递字符数组，需要传递一个数组大小的，说是为了scanf函数的安全着想【怕溢出攻击】  改成这样【scanf_s("%s", name, 40);】

顺带说一句，我也是自学，大家以后互相鼓励啊亲！

scanf_s函数少一个参数，40， 所以运行时读不到这个参数，内存访问不了就报错了


Question: 求大佬帮我看看，哪里有错。自己写的还有头结点的链式队列

单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  #include <stdio.h> #include <malloc.h> #include <stdlib.h> typedef struct node { 	int date; 	struct node* next; }*Node, NODE; typedef struct { 	Node front, rear; }SeqQueue, *Queue; Queue init_Queue(); void in_Queue(Queue, int); void out_Queue(Queue, int*); int empty_Queue(Queue); int main(void) { 	Queue ps = init_Queue(); 	int i, val; 	printf("入队元素："); 	for (i = 0; i<3; i++) 	{ 		printf("%3d", i); 		in_Queue(ps, i); 	} 	printf("\n"); 	printf("出对列的元素："); 	while (empty_Queue(ps)) 	{ 		out_Queue(ps, &val); 		printf("%3d", val); 	} 	printf("\n"); 	return 0; } Queue init_Queue() { 	Queue ps; 	Node p = (Node)malloc(sizeof(NODE));//建立一个头结点 	ps = (Queue)malloc(sizeof(SeqQueue)); 	if (ps == NULL) 		exit(0); 	else 	{ 		p->next = NULL; 		ps->rear = ps->front = p; 	} 	return ps; } void in_Queue(Queue ps, int val) { 	Node p = (Node)malloc(sizeof(NODE));//生成新节点 	p->date = val; 	p->next = NULL; 	ps->rear->next = p;//当前节点的尾指针指向下一个新的节点 	ps->rear = p;//尾指针指向新节点 	return; } void out_Queue(Queue ps, int*val)//FIFO.首节点出队列 { 	Node p; 	if (empty_Queue(ps)) 	{ 		p = ps->front->next;//用p指针来保存新节点。 		*val = p->date; 		ps->front->next = p->next; 		free(p); 	} 	else 	{ 		printf("dui列为空,出队列失败！\n"); 		return; 	} 	if (ps->front->next == NULL) 		ps->rear = ps->front; 	return; } int empty_Queue(Queue ps) { 	if (ps->front == ps->rear) 		return 0; 	else 		return 1; }

if(ps->front->next=NULL)  改成  if(ps->front->next==NULL)