Question: 判断C语言数组内元素相等，下面程序为什么不行？

问题是求相反数还是相同数

if(a[i]==a[j])\\这里的写法无法实现，但是写成（(a[i]+a[j])==0）就能实现\\    printf("相反数对数为 %d\n",count);           a[i] == a[j]   是相反数吗？

程序可以呀，只是注意你的main函数是void型的，后面return 0应去掉，还有注释符号不是 \\ ，是 // 。

思路有问题。i和j都应该是全循环，而不是固定的i排除最后一个，j排除第一个，因为每次要排除的位置并不固定。 i和j都全循环的情况下，只要判断a[i]==a[j] && i!=j就行了。 你说的换成加法能实现，估计也是巧合而已。


Question: 数据结构与算法 头插法创建单链表

上面的链表创建都会有内存泄露的问题。  #include <stdio.h> #include <stdlib.h>  typedef struct node {     int data;     struct node *next; }Node, *LinkList;  LinkList CreateList(LinkList *L); void PrintList(LinkList L);  int main(void) {     LinkList phead = NULL;      CreateList(&phead);      PrintList(phead);      return 0;  }   LinkList CreateList(LinkList *L) {     if (!L)         return NULL;     LinkList p, s;     int i, len, data;      *L = (LinkList)malloc(sizeof(Node));     p = *L;     p->next = NULL;      scanf("%d", &len);      for (i = 0; i < len; i++) {         s = (LinkList)malloc(sizeof(Node));         scanf("%d", &data);         s->data = data;         s->next = p->next;         p->next = s;     }      return *L;  }  void PrintList(LinkList L) {     LinkList p = L->next;      while (p) {         printf("%d ", p->data);         p = p->next;     }     putchar(10); }    带哨兵的头插法创建链表demo。

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

他这个只是头为空的时候赋值一下而已 你要是不用头节点可以不赋值 但是建议不要使用野指针


Question: 关于 线性表 数据结构 问题

优先级应该跟链表排序有关 随机生成一个链表，类似链表的创建； 随机插入一个节点，那就是链表的插入操作， 随机删除，就是随机删除链表中的某个节点。

每个元素除了关键字外，还有一个优先级。 关键字指的是？？

我只学习了c语言，数据结构就看了链表，百度了优先队列看不大懂。好多都是用二叉树实现的，可以用数组，结构之类实现吗，由于题目要求只能用顺序存储结构的链表实现（静态链表是吧）


Question: 合并两个线性表，这个代码错在哪里，求大神指点。

你怎么知道错了？

写代码建议还是注意理解逻辑，Traverse函数是既有创建又有输出，所以对于lc线性表就不需要输入了，而是输出。 merge时，注意更新lc的length

#include <iostream> //#include<algorithm>  #include<stdio.h> #include <stdlib.h>  #define maxsize 100  using namespace std; struct List {     int *elem;     int length; };  void Init_list(List &l) {     l.elem = new int[maxsize];     if(l.elem==NULL) {         cout<<"动态分配失败"<<endl;         exit(1);     }     l.length = 0; } void Sort_list(List &l) {     for(int i=0; i<l.length; i++)         for(int j=0; j<l.length-i-1; j++)             if(l.elem[j]>l.elem[j+1])             {                 int temp;                 temp=l.elem[j];                 l.elem[j]=l.elem[j+1];                 l.elem[j+1]=temp;             } }  void Traverse_list(List &l) {     int n;     while(scanf("%d",&n) != EOF && l.length <= maxsize)    /*为了保证不越界，需要判断是否大于maxsize*/         l.elem[l.length++] = n;     Sort_list(l);     for(int i=0; i<l.length; i++)         cout<<l.elem[i]<<" ";     cout<<endl;     cout<<"该线性表的长度为："<<l.length<<endl; } void Merge_list(List la,List lb,List &lc) {     int *pa,*pb,*pc;     int *pa_last,*pb_last;      pa=la.elem;     pb=lb.elem;     pa_last = la.elem+la.length-1;     pb_last = lb.elem+lb.length-1;     pc = lc.elem;   /*初始化pc */     while(pa<=pa_last&&pb<=pb_last)     {         if(*pa <= *pb) {             *pc++=*pa++;             lc.length++;    /*增加lc的长度值*/         }         else {             *pc++=*pb++;             lc.length++;    /*增加lc的长度值*/         }     }     while(pa <= pa_last) {         *pc++=*pa++;         lc.length++;    /*增加lc的长度值*/     }     while(pb <= pb_last) {         *pc++ = *pb++;         lc.length++;    /*增加lc的长度值*/     } } int main() {     List l,la,lb,lc;     Init_list(l);     Traverse_list(l);     Init_list(la);     Traverse_list(la);     Init_list(lb);     Traverse_list(lb);     Init_list(lc);     Merge_list(la,lb,lc);     //Traverse_list(lc);     /*输出lc */     for(int i=0; i < lc.length; i++)         cout<<lc.elem[i]<<" ";     cout<<endl;      return 0; } 参考一下上面修改的代码吧。


Question: static作用消失了？

static 变量存在堆上       只初始化一次，，并没有释放掉

第二个程序，a是局部变量，并且未初始化，这样做前置加加应该是随机值加1；所以不会是1，1，1 但是，这个随机值是上次程序留下的，每次调用foo函数，都会去上次的函数栈地址申请函数栈，所以上次的a是1，那么后面调用foo时也可能都是1了，这个不是一定的，是随机或者未定义的。

static 效果还是有的。 初始化一下吧。

初始化之后，重新编译试一下。

static修饰的局部变量在bss 或者date段，不初始化数据为0；不初始化的局部变量的值是不确定的

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……

static的作用是初始化函数之外的变量，也就是全局变量，你这样写本身就有问题

不知道你是什么编译器 我的编译器会报错 不能使用为初始化的变量

不会啊，我在TC3.0中运行，每次都是815（a未初始化，所以a的值不定）

初始化……static会零初始化，正常的局部变量可不会。


Question: c语言合并排序算法

未找到merge的定义，需要在main函数之前声明一下，或者将merge函数声明放在一个自定义头文件里，然后再main函数所在源文件引入一下，（include）

各种排序算法动画演示http://www.webhek.com/misc/comparison-sort/

引用 7 楼 zh19921107 的回复:#include <stdlib.h> #include <stdio.h>  // 声明应该放到函数调用处之前，其实头文件中也就是包含的声明 void merge_sort(int A[], int n); void merge(int array[], int lo, int mid, int hi);  void main() {     int A[] = { 8,5,3,9,11,6,4,1,10,7,2 };     int length;     length = sizeof(A) / sizeof(A[0]);     printf("排序前的数组为：\n");     for (int i = 0;i <length;i++)     {         printf("%d ", A[i]);     }     printf("\n");      merge_sort(A, length);     printf("排序后的数组为：\n");     for (int j = 0;j < length;j++)     {         printf("%d ", A[j]);     }     printf("\n"); }  void merge_sort(int A[], int n) {     int i, s, t = 1;     while (t < n)     {         s = t;t = 2 * s;i = 0;         while (i + t < n)         {             // 此处的merge函数没有找到定义             merge(A, i, i + s - 1, i + t - 1);             i = i + t;         }         if (i + s < n)         {             // 此处的merge函数没有找到定义             merge(A, i, i + s - 1, n - 1);         }     } }  void merge(int array[], int lo, int mid, int hi) {     // 辅助数组     static int aux[100] = {0};     int i = lo, j = mid + 1;     //把元素拷贝到辅助数组中     for (int k = lo; k <= hi; k++)     {         aux[k] = array[k];     }     //然后按照规则将数据从辅助数组中拷贝回原始的array中     for (int k = lo; k <= hi; k++)     {         //如果左边元素没了， 直接将右边的剩余元素都合并到到原数组中         if (i > mid)         {             array[k] = aux[j++];         }//如果右边元素没有了，直接将所有左边剩余元素都合并到原数组中         else if (j > hi)         {             array[k] = aux[i++];         }//如果左边比右边小，则将左边的元素拷贝到原数组中         else if (aux[i]<(aux[j]))         {             array[k] = aux[i++];         }         else         {             array[k] = aux[j++];         }     } }  修改了代码 ： 1.添加头文件<stdio.h> 2.函数声明放到头文件后 3.网上找来一个merge函数加入，参考http://www.cnblogs.com/yangecnu/p/Introduce-Merge-Sort.html  忘了贴结果： 排序前的数组为： 8 5 3 9 11 6 4 1 10 7 2 排序后的数组为： 1 2 3 4 5 6 7 8 9 10 11

main函数最好写在整个函数的最后面，不然就要在函数里声明要调用的函数，

函数声明是在main之前，，，

void merge_sort(int A[], int n); 应该在main（）函数前，本人初学者，声明在函数前才会在该函数调用时找到调用的函数

c语言的合并排序算法应该是一个递归函数：这里参数s和e代表将数组a［］从下标s到下标e进行排序。 void MergeSort(int a[],int s,int e,int tmp[])  { if( s < e)  { int m = s + (e-s)/2;  MergeSort(a,s,m,tmp);  MergeSort(a,m+1,e,tmp);  Merge(a,s,m,e,tmp); }  } 将一个数组进行对半分，不停的继续下去，直到数组里面的元素个数是1，然后再合并成2个元素数组，4个元素数组，直到将原来的数组整个进行排序。 PS：记得给分啊。


Question: vs2010，c语言中的复数定义和使用1

别用vs

C99提供complex.h #include <complex.h>试试

引用 2 楼 赵4老师 的回复:#include <complex>  这是c++ 的，不是c的。  我也碰到了， 可能得自己写

#include <complex>


Question: C语言给单链表p加头节点报段错误，怎么解决？

#include <stdio.h> #include <stdlib.h>  struct LNode {     char data;     struct LNode *next; };  //创建链表,count为创建的链表的节点数目 struct LNode *create(int count,char cdata[]) {     int i=0;     struct LNode *pNode = NULL;     struct LNode *pNewNode = NULL;     struct LNode *head = NULL;     //struct LNode *p=NULL;       //head->data = cdata[0]; /* 此处会导致段错误*/      for(i =0;i <count;i++)     {         pNewNode = (struct LNode*)malloc(sizeof(struct LNode));//分配节点空间         pNewNode->data = cdata[i];          if(head == NULL)    //指定头结点         {             head = pNewNode;             pNode = pNewNode;         }         else         {             pNode->next = pNewNode;             pNode = pNewNode;         }     }     pNode->next = NULL;       //head->next = p; //加了这句话就报错。注释掉就没问题了      return head; } head 指向NULL，那么这句/head->data = cdata[0];一定会导致段错误；那么head->next = p；也会出现段错误，我想在前面已经导致段错误，不会执行到这句； 以上是修改后的代码，可以参考一下；

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

head 若不malloc ，则只有4个字节    ，，，  你定义的结构体字节超过4 ，，，所以head无法存放过多东西

head 需要malloc一下才能用！


Question: 最短路径C语言编程小白，望大佬帮我找找错误

最短路径算法—Dijkstra(迪杰斯特拉)算法分析与实现(C/C++) http://www.wutianqi.com/?p=1890


Question: 这个是socke网络聊天的服务端 存储客户端发来的信息和操作。没有报错 但是运行stuSeek用姓名查询这里出行了问题，弄了好久，到底是什么问题 求大神们帮个忙

if(pTemp=NULL) { break; } stuSeek中的这句改一下，if中的表达式是赋值表达式，而不是判断表达式； 改成如下：  if(pTemp==NULL) { break; }


Question: free()函数错误 求修改

我的天…… 谢谢；了

修改完函数名运行一切正常

函数名后面有没有3。函数名错误


Question: c/c++中%s的问题，只能打印第一个字符。。 不是因为\0吧， 求帮助！！！！！！！

s是输出字符串 你是int类型的line  不搭  int是四位 可能它误判成结束符了吧 不太懂 既然是输入字符为什么不用char

int是四个字节 char是一个字节

自己先顶下，在线等，挺急的。。。。


Question: 大佬们帮我找找这个链表中关于查找元素的地方的错误！！

#include<stdio.h> #include<malloc.h> #include <string.h> #include<stdlib.h>  #define ok 1    /* delete ;*/ #define size 100    /* delete ; */ typedef char elemtype;  typedef struct Lnode {     elemtype data;     struct Lnode *next; }linklist;  void creatlist(linklist *&head,elemtype a[],int n)//尾插法建立线性表 {     linklist *p, *r;     int i;      head = (linklist*)malloc(sizeof(linklist));     r = head;     for(i=0;i<n;i++)     {         p = (linklist*)malloc(sizeof(linklist));         p->data = a[i];         r->next = p;         r = p;     }     r->next = NULL; } int locatedelem(linklist *&head, int i, elemtype &n)/* 缺少 &*/ {     int j = 1;     linklist *s;     s=head->next;     while(s&&j<i)     {         s=s->next;         j++;     }     n = s->data;     return 1; } int listinsert(linklist *&head,int z,elemtype e)//插入节点 {     int j=0;     linklist *p=head,*s;     while(j<z-1&&p!=NULL)     {         j++;p=p->next;     }     if(p==NULL)return 0;     else     {         s=(linklist *)malloc(sizeof(linklist));         s->data=e; s->next=p->next; p->next=s;         return 1;     } } int deleteelem(linklist *&head ,int j)//删除结点 {     int q=0;     linklist *p=head,*s;     while(q<j-1&&p!=NULL)     {         q++;         p=p->next;     }     if(p==NULL)return 0;     else {         s=p->next;         p->next=s->next;         free(s);         s=NULL;         return 1;     } } void DispList(linklist *head)   //输出线性表 {     linklist *p = head->next;     while(p) {         printf("%c",p->data);         p = p->next;     }     putchar(10); }  int converse(linklist *&head)//将链表就地逆序 {     linklist *p,*q;     p=head->next;     head->next=NULL;     while(p)     {         q=p;         p=p->next;         q->next=head->next;         head->next=q;     }      return ok; }  int main(void) {     int i,j,z;     char e;     char a[10];     printf("请输入要创建的链表：\n");     scanf("%s",a);     linklist *s;     creatlist(s, a, strlen(a));    /*第三个参数应该是实际输入的字符长度 */     printf("创建的链表为：\n");     DispList(s);     printf("\n");     printf("查找i号元素并输出,请输入I的值：\n");     scanf("%d",&i);     printf("第i号元素的数值是；\n");     locatedelem(s, i, e);    /*用e，而不要用n类型不匹配, 查找不正确主要是形参n前缺少& */     printf("%c\n", e);     printf("请输入要在z号位置前插入元素,并输入E的值，以空格隔开\n");     scanf("%d %c",&z,&e);     listinsert(s,z,e);     printf("现在的链表为：\n");     DispList(s);     printf("\n");     printf("请输入要删除的j号节点\n");     scanf("%d",&j);     deleteelem(s,j);     printf("现在的链表为：\n");     DispList(s);     printf("\n");     printf("逆序后的链表为：\n");     converse(s);     DispList(s);     return 0; } 宏定义不能加分号; 查找不正确，主要是形参n前缺少& 其他修改详见代码注释

n是int 你应该传char类型的吧 你想让值改变用引用传递


Question: 这是一段自己定义字符串函数strtok的代码，代码里面加粗的两行for循环里面的＊start这个判断条件去掉后好像有问题，求解答

如果取消 *start 判断，在处理最后一个"you!"时，局部变量情况如下： start: "you!" q: " ,._" 此时下面的这个循环结束后将会导致start指向一个“不合适”的位置！(不一定非法，但并不是程序希望的位置。) for(;!strchr(q,*start);start++); 因为在start指向的"you!"范围内，都没有q对应的内容，所以函数strchr()在这个范围内都会返回NULL，然后start+++++++++就不知道加到哪里去了！ 如果加了*start的条件，就会在"you!"后面紧接着的'\0'处停下。


Question: 正则表达式匹配

是不是说在C语言下，pcre库已经是最快， 会不会因为pcre作为一个通用库，比一些小型库速度慢， 我在github上也看了一些小型的regex engine ，，有没有可能从中找到更快的，，，

使用release版


Question: VS2013使用C编译数据类型，输入数据时出现的错误

引用 4 楼 xian_wwq 的回复:[quote=引用 楼主 GGlance 的回复:]  中断设置在这里 执行以下操作，进行逐行调试 为什么在执行第一次输入循环以后就停止了？求大佬解答 #include<stdio.h> struct student { 	int num[5]; 	char name[10]; 	int score; }stu[5]; int main() { 	int i, j, k, l; 	//printf("input the number of the student\n"); 	//scanf_s("%d\n",&n); 	printf("input the  students's num,name,score\n"); 	for (l = 0; l < 5; l++) 	{ 		printf("input the  students's num:"); 		scanf_s("%5d", stu[l].num); 		printf("input the  students's name:"); 		scanf_s("%s",stu[l].name,10); 		printf("input the  students's score:"); 		scanf_s("%5d", stu[l].score,5); 		printf("\n"); 	} 	struct student temp; 	for (i = 0; i < 4; i++) 	{ 		k = i; 		for (j = 0; j < 5; j++) 		if (stu[j].score>stu[k].score) 			k = j; 		temp = stu[k]; stu[k] = stu[j]; stu[j] = temp; 	} 	for (i = 0; i < 5; i++) 		printf("%6d,%10s,%5f\n", stu[i].num, stu[i].name, stu[i].score); 	printf("\n"); 	return 0; }  scanf_s用法不对哦，  scanf_s("%5d", &stu[l].num);  注意这个“&”[/quote]  看得仔细

引用 2 楼 自信男孩的回复:#include<stdio.h> struct student {     char num[5];   /*建议使用char类型*/     char name[10];     int score; }stu[5];  int main() {     int i, j, k, l;     //printf("input the number of the student\n");     //scanf_s("%d\n",&n);     printf("input the  students's num,name,score\n");     for (l = 0; l < 5; l++)     {         printf("input the  students's num:");         scanf_s("%s", stu[l].num, 5);    /*改一下，用%s*/         printf("input the  students's name:");         scanf_s("%s",stu[l].name,10);         printf("input the  students's score:");         scanf_s("%5d", stu[l].score,5);         printf("\n");     }     struct student temp;     for (i = 0; i < 4; i++)     {         k = i;         for (j = 0; j < 5; j++)             if (stu[j].score>stu[k].score)                 k = j;         if (k != i) {    /*当k != i时才要交换*/             temp = stu[k];             stu[k] = stu[i];             stu[i] = temp;         }     }     for (i = 0; i < 5; i++)         printf("%6s, %10s, %5d\n", stu[i].num, stu[i].name, stu[i].score);     printf("\n");      return 0; } 改了一下你的程序，排序有点问题。另外，num应该用char类型。 谢谢您的评论，我回去好好看看

引用 2 楼 自信男孩的回复:#include<stdio.h> struct student {     char num[5];   /*建议使用char类型*/     char name[10];     int score; }stu[5];  int main() {     int i, j, k, l;     //printf("input the number of the student\n");     //scanf_s("%d\n",&n);     printf("input the  students's num,name,score\n");     for (l = 0; l < 5; l++)     {         printf("input the  students's num:");         scanf_s("%s", stu[l].num, 5);    /*改一下，用%s*/         printf("input the  students's name:");         scanf_s("%s",stu[l].name,10);         printf("input the  students's score:");         scanf_s("%5d", stu[l].score,5);         printf("\n");     }     struct student temp;     for (i = 0; i < 4; i++)     {         k = i;         for (j = 0; j < 5; j++)             if (stu[j].score>stu[k].score)                 k = j;         if (k != i) {    /*当k != i时才要交换*/             temp = stu[k];             stu[k] = stu[i];             stu[i] = temp;         }     }     for (i = 0; i < 5; i++)         printf("%6s, %10s, %5d\n", stu[i].num, stu[i].name, stu[i].score);     printf("\n");      return 0; } 改了一下你的程序，排序有点问题。另外，num应该用char类型。 谢谢大佬，我回去多看看算法，自己刚开始学，太笨了

引用 1 楼 赵4老师的回复:崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。 谢谢您，记住了。以后我多加注意

引用 楼主 GGlance 的回复: 中断设置在这里 执行以下操作，进行逐行调试 为什么在执行第一次输入循环以后就停止了？求大佬解答 #include<stdio.h> struct student { 	int num[5]; 	char name[10]; 	int score; }stu[5]; int main() { 	int i, j, k, l; 	//printf("input the number of the student\n"); 	//scanf_s("%d\n",&n); 	printf("input the  students's num,name,score\n"); 	for (l = 0; l < 5; l++) 	{ 		printf("input the  students's num:"); 		scanf_s("%5d", stu[l].num); 		printf("input the  students's name:"); 		scanf_s("%s",stu[l].name,10); 		printf("input the  students's score:"); 		scanf_s("%5d", stu[l].score,5); 		printf("\n"); 	} 	struct student temp; 	for (i = 0; i < 4; i++) 	{ 		k = i; 		for (j = 0; j < 5; j++) 		if (stu[j].score>stu[k].score) 			k = j; 		temp = stu[k]; stu[k] = stu[j]; stu[j] = temp; 	} 	for (i = 0; i < 5; i++) 		printf("%6d,%10s,%5f\n", stu[i].num, stu[i].name, stu[i].score); 	printf("\n"); 	return 0; }  scanf_s用法不对哦，  scanf_s("%5d", &stu[l].num);  注意这个“&”


Question: 函数定义

void sum(int a, int b) {     printf(" %d ",  a + b);          return; }

int sum(int a, int b) {     int total;     total = a + b;     return total; } 这是函数定义。你代码中还有其他问题，先尝试着自己找，这样学起来效果更好


Question: 使用已经释放的指针变量问题

不是“使用已经释放的指针变量问题”，而是“使用已经释放的内存问题”。 如果 free(w) 之后，又给w赋值了，w指向有效可用的内存区域，则 *w 就是可用的，没问题；否则就是问题

非常感谢两位的讲解

引用 2 楼 nanohappy1 的回复:本人菜鸟一枚，还请解释一下原理， 这个语句并没有 返回（return ）啊 我说的是有可能，条件是x是不等于0；因为w指向堆上的空间，free(w)；就是将堆上的空间释放掉，即空间不可用，使用free之后的空间是未定义行为，因为释放之后就是其他变量或者程序可以申请这部分空间，可以对这部分空间进行赋值等操作，那么再通过w使用这部分空间就会导致读到的数据是其他程序或者变量的值，如果通过w写，那么它会修改其他变量或者程序里变量的值。

本人菜鸟一枚，还请解释一下原理， 这个语句并没有 返回（return ）啊

有可能会返回已经释放的指针，因为： if(x){     free(w);    q = p; } 这儿有可能释放w


Question: VS2013 报错0x50D3134E (msvcr120d.dll) (ConsoleApplication16.exe 中)处有未经处理的异常:  0xC0

引用 4 楼 GGlance 的回复:谢谢大神，你的方法是对的，用了你的方法就能输入，但是只输入一次，就卡了。有什么这方面的课程或者书籍推荐么？还是用不习惯VS2013@cfjtaishan 如果想继续学习C语言，可以看一些电子书<<C prime plus>>找一下这本书的最新版本看看，主要是多写，多调试，多思考。然后多做总结。

我一般用  while(scanf("%d", &num) == 0){  //处理  }   进行读取

scanf_s("%5d", &stu[l].score);红字的是一个数值，而不是指针，而scanf_s要求那是一个指针，所以需要加入&

首先谢谢大佬们回答，确实是输入name时出现的问题，但是name是数组名，可以直接用啊，缺少参数是什么意思？不是很理解@cfjtaishan

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

for (i = 0; i <= 5; i++)  和 for (j = 0; j <= 5; j++) 数组已经越界了。 去掉=试试。 scanf_s("%s", stu[i].name, 10); 输入name缺少参数；


Question: c语言循环输入的时候，第一组数据和第二组数据一起输入了，但是最终显示出的数据顺序是对的，求大神指教！！！

#include<stdio.h> #include<string.h>  struct students {     char name[10];     char number[10];     int score;     struct students *next; };  int main() {     int i,j,k;     struct students stu[5],*head,*p;     char n[10],no[10];      for(i=0;i<5;i++)     {         printf("input the information of %dth student:\n",i+1);         scanf("%s%s%d",n,no,&stu[i].score);    /* delete \n*/         strcpy(stu[i].name,n);         strcpy(stu[i].number,no);     }     head=&stu[0];     stu[4].next = NULL;     for(i=0;i<4;i++)     {         stu[i].next=&stu[i+1];     }     p=head;     printf("students list:\n");     while(p!=NULL)     {         printf("%s\t%s\t%d\n",p->name,p->number,p->score);         p=p->next;     } } 去掉scanf中的回车符；

输入的东西，只要没有被scanf取走（扫描后符合%所对应的格式），也没有被清空（flush），还是要被下一次的scanf扫描的


Question: 递归的函数使用

如果楼主能够将递归函数的原理理解了，这个问题就好结局了。  递归函数是不停的建立函数栈，根据栈的特性：先进后出； 那么先计算出来的是低位，然后逐步算出高位，先进后厨那么高位的0和1先出，低位的0和1后出。所以结果是楼主看到的现象。

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

通俗点跟你说吧。 因为递归是在一个函数里面不断调用本函数，直到满足条件后调用的函数才返回。 一个函数调用另一个函数时，本函数会挂起在函数表中，执行调用函数直到遇到返回，本函数就继续。 所以你写的程序知道遇到n<2时才开始返回，返回前输出，所以是从个位数开始。  记得给分。


Question: 线性同余法生成随机数，摘自国外论文

在http://www.codeproject.com搜“Random Number Generation Methods”

引用 10 楼 peyton_tang 的回复:谢谢，刚刚改了一下，发现seed只变了第一次值，后面就没发生变化了哈哈

引用 8 楼 peyton_tang 的回复:[quote=引用 7 楼 zjq9931 的回复:] [quote=引用 3 楼 peyton_tang 的回复:] 谢谢，这个方法我看过了，主要我是想运用上面我从论文摘出的方法，目前来说，我是发现了自己一部分问题，但是还是有问题，不过有一个疑问，我这里面用个的这个seed1是个初始值，我用了指针变量想使seed得原值在每次运算后改变，不知道我的方法是对的么？自己现在这个貌似有点不一样，但是结果并没有紧接着下一个随机 #include<iostream.h> #include<math.h> #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014                      #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791                       #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) static long seed1=25; static long seed2=66; static long seed3=60; double ran2(long *idum) { int j; long k;                                                   static long idum2=123456789;  static long iy=0; static long iv[NTAB] ; float temp; if (*idum<=0)  /* 初始化 */ { if (-(*idum)<1) *idum=1; else *idum=-(*idum); idum2=(*idum); for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */ { k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)   *idum+=IM1; if (j<NTAB)  iv[j]=*idum;  } iy=iv[0]; }                                                           k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)  {*idum+=IM1; k=idum2/IQ2 ; idum2=IA2*(idum2-k*IQ2)-k*IR2;} if (idum2<0) {idum2+=IM2; j=iy/NDIV; iy=iv[j]-idum2; iv[j]=*idum;} if (iy<1) {iy+=IMM1;} if ((temp=AM*iy)>RNMX) return RNMX; else return temp; }      void main() { int j,k; double rndx[30][30]; double rndy[30][30]; double rndz[30][30]; long *a1; long *a2; long *a3; a1=&seed1; a2=&seed2; a3=&seed3; for(j=0;j<30;j++) {for(k=0;k<30;k++) {rndx[j][k]=ran2(a1); rndy[j][k]=ran2(a1); rndz[j][k]=ran2(a1); } } for(j=0;j<10;j++) {for(k=0;k<30;k++) {cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";}}}  应当是对的，每次计算后要做更改。[/quote]也就是说我这里的seed已经发生了改变了是吧，谢谢[/quote] 其实我个人对这个算法一知半解，我自己都不确定我说的是否正确，最好是等高手来看看。

引用 3 楼 peyton_tang 的回复:谢谢，这个方法我看过了，主要我是想运用上面我从论文摘出的方法，目前来说，我是发现了自己一部分问题，但是还是有问题，不过有一个疑问，我这里面用个的这个seed1是个初始值，我用了指针变量想使seed得原值在每次运算后改变，不知道我的方法是对的么？自己现在这个貌似有点不一样，但是结果并没有紧接着下一个随机 #include<iostream.h> #include<math.h> #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014                      #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791                       #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) static long seed1=25; static long seed2=66; static long seed3=60; double ran2(long *idum) { int j; long k;                                                   static long idum2=123456789;  static long iy=0; static long iv[NTAB] ; float temp; if (*idum<=0)  /* 初始化 */ { if (-(*idum)<1) *idum=1; else *idum=-(*idum); idum2=(*idum); for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */ { k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)   *idum+=IM1; if (j<NTAB)  iv[j]=*idum;  } iy=iv[0]; }                                                           k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)  {*idum+=IM1; k=idum2/IQ2 ; idum2=IA2*(idum2-k*IQ2)-k*IR2;} if (idum2<0) {idum2+=IM2; j=iy/NDIV; iy=iv[j]-idum2; iv[j]=*idum;} if (iy<1) {iy+=IMM1;} if ((temp=AM*iy)>RNMX) return RNMX; else return temp; }      void main() { int j,k; double rndx[30][30]; double rndy[30][30]; double rndz[30][30]; long *a1; long *a2; long *a3; a1=&seed1; a2=&seed2; a3=&seed3; for(j=0;j<30;j++) {for(k=0;k<30;k++) {rndx[j][k]=ran2(a1); rndy[j][k]=ran2(a1); rndz[j][k]=ran2(a1); } } for(j=0;j<10;j++) {for(k=0;k<30;k++) {cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";}}}  应当是对的，每次计算后要做更改。

引用 3 楼 peyton_tang 的回复:谢谢，这个方法我看过了，主要我是想运用上面我从论文摘出的方法，目前来说，我是发现了自己一部分问题，但是还是有问题，不过有一个疑问，我这里面用个的这个seed1是个初始值，我用了指针变量想使seed得原值在每次运算后改变，不知道我的方法是对的么？自己现在这个貌似有点不一样，但是结果并没有紧接着下一个随机 #include<iostream.h> #include<math.h> #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014                      #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791                       #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) static long seed1=25; static long seed2=66; static long seed3=60; double ran2(long *idum) { int j; long k;                                                   static long idum2=123456789;  static long iy=0; static long iv[NTAB] ; float temp; if (*idum<=0)  /* 初始化 */ { if (-(*idum)<1) *idum=1; else *idum=-(*idum); idum2=(*idum); for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */ { k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)   *idum+=IM1; if (j<NTAB)  iv[j]=*idum;  } iy=iv[0]; }                                                           k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)  {*idum+=IM1; k=idum2/IQ2 ; idum2=IA2*(idum2-k*IQ2)-k*IR2;} if (idum2<0) {idum2+=IM2; j=iy/NDIV; iy=iv[j]-idum2; iv[j]=*idum;} if (iy<1) {iy+=IMM1;} if ((temp=AM*iy)>RNMX) return RNMX; else return temp; }      void main() { int j,k; double rndx[30][30]; double rndy[30][30]; double rndz[30][30]; long *a1; long *a2; long *a3; a1=&seed1; a2=&seed2; a3=&seed3; for(j=0;j<30;j++) {for(k=0;k<30;k++) {rndx[j][k]=ran2(a1); rndy[j][k]=ran2(a1); rndz[j][k]=ran2(a1); } } for(j=0;j<10;j++) {for(k=0;k<30;k++) {cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";}}}  种子我一般是以时间来取。具体的还真不知道了。。

引用 9 楼 zjq9931 的回复:[quote=引用 8 楼 peyton_tang 的回复:] [quote=引用 7 楼 zjq9931 的回复:] [quote=引用 3 楼 peyton_tang 的回复:] 谢谢，这个方法我看过了，主要我是想运用上面我从论文摘出的方法，目前来说，我是发现了自己一部分问题，但是还是有问题，不过有一个疑问，我这里面用个的这个seed1是个初始值，我用了指针变量想使seed得原值在每次运算后改变，不知道我的方法是对的么？自己现在这个貌似有点不一样，但是结果并没有紧接着下一个随机 #include<iostream.h> #include<math.h> #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014                      #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791                       #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) static long seed1=25; static long seed2=66; static long seed3=60; double ran2(long *idum) { int j; long k;                                                   static long idum2=123456789;  static long iy=0; static long iv[NTAB] ; float temp; if (*idum<=0)  /* 初始化 */ { if (-(*idum)<1) *idum=1; else *idum=-(*idum); idum2=(*idum); for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */ { k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)   *idum+=IM1; if (j<NTAB)  iv[j]=*idum;  } iy=iv[0]; }                                                           k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)  {*idum+=IM1; k=idum2/IQ2 ; idum2=IA2*(idum2-k*IQ2)-k*IR2;} if (idum2<0) {idum2+=IM2; j=iy/NDIV; iy=iv[j]-idum2; iv[j]=*idum;} if (iy<1) {iy+=IMM1;} if ((temp=AM*iy)>RNMX) return RNMX; else return temp; }      void main() { int j,k; double rndx[30][30]; double rndy[30][30]; double rndz[30][30]; long *a1; long *a2; long *a3; a1=&seed1; a2=&seed2; a3=&seed3; for(j=0;j<30;j++) {for(k=0;k<30;k++) {rndx[j][k]=ran2(a1); rndy[j][k]=ran2(a1); rndz[j][k]=ran2(a1); } } for(j=0;j<10;j++) {for(k=0;k<30;k++) {cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";}}}  应当是对的，每次计算后要做更改。[/quote]也就是说我这里的seed已经发生了改变了是吧，谢谢[/quote] 其实我个人对这个算法一知半解，我自己都不确定我说的是否正确，最好是等高手来看看。[/quote]谢谢，刚刚改了一下，发现seed只变了第一次值，后面就没发生变化了哈哈

引用 7 楼 zjq9931 的回复:[quote=引用 3 楼 peyton_tang 的回复:] 谢谢，这个方法我看过了，主要我是想运用上面我从论文摘出的方法，目前来说，我是发现了自己一部分问题，但是还是有问题，不过有一个疑问，我这里面用个的这个seed1是个初始值，我用了指针变量想使seed得原值在每次运算后改变，不知道我的方法是对的么？自己现在这个貌似有点不一样，但是结果并没有紧接着下一个随机 #include<iostream.h> #include<math.h> #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014                      #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791                       #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS) static long seed1=25; static long seed2=66; static long seed3=60; double ran2(long *idum) { int j; long k;                                                   static long idum2=123456789;  static long iy=0; static long iv[NTAB] ; float temp; if (*idum<=0)  /* 初始化 */ { if (-(*idum)<1) *idum=1; else *idum=-(*idum); idum2=(*idum); for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */ { k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)   *idum+=IM1; if (j<NTAB)  iv[j]=*idum;  } iy=iv[0]; }                                                           k=(*idum)/IQ1; *idum=IA1*(*idum-k*IQ1)-k*IR1; if (*idum<0)  {*idum+=IM1; k=idum2/IQ2 ; idum2=IA2*(idum2-k*IQ2)-k*IR2;} if (idum2<0) {idum2+=IM2; j=iy/NDIV; iy=iv[j]-idum2; iv[j]=*idum;} if (iy<1) {iy+=IMM1;} if ((temp=AM*iy)>RNMX) return RNMX; else return temp; }      void main() { int j,k; double rndx[30][30]; double rndy[30][30]; double rndz[30][30]; long *a1; long *a2; long *a3; a1=&seed1; a2=&seed2; a3=&seed3; for(j=0;j<30;j++) {for(k=0;k<30;k++) {rndx[j][k]=ran2(a1); rndy[j][k]=ran2(a1); rndz[j][k]=ran2(a1); } } for(j=0;j<10;j++) {for(k=0;k<30;k++) {cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";}}}  应当是对的，每次计算后要做更改。[/quote]也就是说我这里的seed已经发生了改变了是吧，谢谢

引用 1 楼 cfjtaishan 的回复:#include<iostream> #include<math.h>  using namespace std;  #define IM1 2147483563 #define IM2 2147483399 #define AM (1.0/IM1) #define IMM1 (IM1-1) #define IA1 40014 #define IA2 40692 #define IQ1 53668 #define IQ2 52774 #define IR1 12211 #define IR2 3791 #define NTAB 32 #define NDIV (1+IMM1/NTAB) #define EPS 1.2e-7 #define RNMX (1.0-EPS)  static long seed1=25; static long seed2=12; static long seed3=60;  long ran2(long *idum) {     int j;     long k;     static long idum2=123456789;     long *p=&idum2;     static long iy=0;     static long iv[NTAB] ;     long temp;      if (*idum<=0)  /* 初始化 */     {         if (-(*idum)<1) *idum=1;         else *idum=-(*idum);         *p=(*idum);         for (j=NTAB+7;j>=0;j--) /* 负荷转移表，载入洗牌表 */         {             k=(*idum)/IQ1;             *idum=IA1*(*idum-k*IQ1)-k*IR1;             if (*idum<0)             {*idum+=IM1;}             if (j<NTAB)             {iv[j]=*idum;}         }         iy=iv[0];     }     k=(*idum)/IQ1;     *idum=IA1*(*idum-k*IQ1)-k*IR1;     if (*idum<0)     {*idum+=IM1;         k=idum2/IQ2 ;         idum2=IA2*(idum2-k*IQ2)-k*IR2;}     if (idum2<0) {idum2+=IM2;         j=iy/NDIV;         iy=iv[j]-idum2;         iv[j]=*idum;}     if (iy<1) {iy+=IMM1;}     if ((temp=AM*iy)>RNMX)         return RNMX;     else return temp; }  long rnd_gen2(long *seed) {int p;     long sum=0;     for (p=0;p<12;p++)     {         sum+=ran2(seed);      }     sum-=ran2(seed);     return sum;  }  int main(void) {     int j,k;     long rndx[5][8];     long rndy[5][8];     long rndz[5][8];     long *a1;     long *a2;     long *a3;     a1=&seed1;     a2=&seed2;     a3=&seed3;     for(j=0;j<5;j++)     {         for(k=0;k<8;k++)         {             rndx[j][k]=rnd_gen2(a1);             rndy[j][k]=rnd_gen2(a1);             rndz[j][k]=rnd_gen2(a1);             cout<<j<<','<<k<<' '<<rndx[j][k]<<','<<rndy[j][k]<<','<<rndz[j][k]<<"\n";         }     }      return 0; } 运行结果：  0,0 0,0,0 0,1 0,0,0 0,2 0,0,0 0,3 0,0,0 0,4 0,0,0 0,5 0,0,0 0,6 0,0,0 0,7 0,0,0 1,0 0,0,0 1,1 0,0,0 1,2 0,0,0 1,3 0,0,0 1,4 0,0,0 1,5 0,0,0 1,6 0,0,0 1,7 0,0,0 2,0 0,0,0 2,1 0,0,0 2,2 0,0,0 2,3 0,0,0 2,4 0,0,0 2,5 0,0,0 2,6 0,0,0 2,7 0,0,0 3,0 0,0,0 3,1 0,0,0 3,2 0,0,0 3,3 0,0,0 3,4 0,0,0 3,5 0,0,0 3,6 0,0,0 3,7 0,0,0 4,0 0,0,0 4,1 0,0,0 4,2 0,0,0 4,3 0,0,0 4,4 0,0,0 4,5 0,0,0 4,6 0,0,0 4,7 0,0,0   麻烦您看一下我四楼的更改，我改了一下数据类型，但是依然没有很好的随机

引用 2 楼 zjq9931 的回复:不太懂，不过这里有一个方法：  http://blog.csdn.net/memray/article/details/8932518 麻烦你。看一下我三楼的回复谢谢


Question: 求助C语言关于定义变量的一个问题，多谢各位！

Linklist  &L是引用

百度一下指针和引用的区别，相信比我们回答的更专业清晰

引用 9 楼 Steven_Lenny 的回复:[quote=引用 5 楼 cfjtaishan 的回复:] 这个是C++里的语法功能：引用，在C语言的编译器里是不支持的，编译的时候会报错； 如果想写成C语言识别的接口，可以改一下： void Initlist(Linklist *L, int n) {     *L = (Linklist)malloc(sizeof(Node));     (*L)->next = NULL; } 我试了一下，可是为什么这样编译不通过呢？[/quote] 用这样初始化还会提示和上次有一样的编译错误吗？ 注意，这样该形参，你的实参也要跟着改的，不然会提示类型不匹配。

引用 7 楼 qq_29846883 的回复:百度一下指针和引用的区别，相信比我们回答的更专业清晰 嗯呐，多谢啦

引用 8 楼 sdghchj 的回复:[quote=引用 6 楼 Steven_Lenny 的回复:] [quote=引用 3 楼 sdghchj 的回复:] 在C++语言里，类型后面跟&表示后面声明的是变量的引用，也就是说传递实参变量本身而不是传拷贝。 C语言里没有引用，所以你的代码是c++语言。 也就是说在这种用法下，在函数里面就可以改变main函数中定义的变量，而不需要用传递地址的方式吗[/quote] 嗯是的，但是是C++语法[/quote] 嗯嗯！多谢啦

引用 5 楼 cfjtaishan 的回复:这个是C++里的语法功能：引用，在C语言的编译器里是不支持的，编译的时候会报错； 如果想写成C语言识别的接口，可以改一下： void Initlist(Linklist *L, int n) {     *L = (Linklist)malloc(sizeof(Node));     (*L)->next = NULL; } 我试了一下，可是为什么这样编译不通过呢？

引用 6 楼 Steven_Lenny 的回复:[quote=引用 3 楼 sdghchj 的回复:] 在C++语言里，类型后面跟&表示后面声明的是变量的引用，也就是说传递实参变量本身而不是传拷贝。 C语言里没有引用，所以你的代码是c++语言。 也就是说在这种用法下，在函数里面就可以改变main函数中定义的变量，而不需要用传递地址的方式吗[/quote] 嗯是的，但是是C++语法

引用 3 楼 sdghchj 的回复:在C++语言里，类型后面跟&表示后面声明的是变量的引用，也就是说传递实参变量本身而不是传拷贝。 C语言里没有引用，所以你的代码是c++语言。 也就是说在这种用法下，在函数里面就可以改变main函数中定义的变量，而不需要用传递地址的方式吗

引用 1 楼 zhao4zhong1 的回复:引用  指针即地址 引用即别名  请问这样的情况下L是一个值，相当于通常情况下的*p，而&L是一个指针吗

补充一下……在函数形参里面可以这么写，但是在函数里面再写 Linklist &p; 就发现报错，这是为什么呢？

引用  指针即地址 引用即别名


Question: 为什么此题的答案为C,而不是D,哪位大神能给解释一下吗？

scanf返回值表示的是成功接收的参数个数，返回给str[i]肯定不对

D选项厉害了，scanf有没有返回值我不知道，不过这种写法我也是第一次见，str[i] 也不是地址吧 不过就算这种写法是正确的，那也不可能是正确答案，很明显这个需要一个字符一个字符的输入，不可能输入字符串吧 我咋感觉压根不能运行呢

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

另外，D选项还有语法错误！

因为gets是读取一行，即遇到回车符结束；并将除回车符以外的字符刷到缓存str中，并加上字符串结束'\0‘。（gets不会检查输入的数据会不会导致str越界） scanf是格式化读写，遇到空格就认为是一种格式的结束（但是%c比较特殊），所以scanf只输入了zhang，后面的没存放到str中 B选项能将'\n'放到str缓存中，并且没有加字符串结束标记。 D选项就是死循环，无法结束循环；


Question: C语言指针输出问题

为什么理解C的指针还必须学习汇编呢，我是先学的C后学的汇编，对于地址的理解也没有感觉超级费劲，虽然没有写过经典的大程序，感觉学习C可以懂点硬件的知识比较有用，你再连基本的内存都不明白，那也是搞笑了啊。至于说C的优势就是指针，可能这也是C与很多其他程序的区别吧，但是有了指针确实对C有了很大的帮助。

引用 10 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  仅供参考：//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]   《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！ 意思是说： 我的想法是错的么？

引用 11 楼 zhao4zhong1 的回复:http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组 反汇编， 我还不懂， 自学，不知道该学些啥， 就是一阵乱学。 谢谢老师指点。 哈哈哈哈哈哈哈哈

引用 3 楼 wang0635 的回复:关键问题 int *p = x;    <==== p与x类型不同！哪能这么简单地用p操纵x中的元素 我始终觉得可以啊， 二维数组在计算机里的存储也是线性的， 在一维数组里： 数组名能代表一维数组的首元素地址， 那么 在二维数组里： 每一行的数组名，如x[0]是第一行的 组名， 这里就把x[0]组看成了一维数组， 那么由上 x[0]也可以是看成是  &x[0][0] 而&x[0][0]又是二维数组的首元素地址， 同理：  x 等价于 x[0] 表示二维数组第一行的行首地址， 那么 x 也能代表二维数组首元素地址。 个人经过很多实验的观点。 不知道对不对，哈哈

引用 6 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495  老师， 每次都是这些， 但是确实是这样， 你的很有用。 我是这样做的。 昨天调试了一晚上， 没出来，今天下午才跑来问的。 谢谢

谢谢大家，我找到问题了， 只是把i*3写成了i*2了， 抱歉，昨天晚上练习，可能脑子有点昏。  #include<stdio.h> int main() { 	int x[2][3]; 	int *p = x; 	for (; p < x+2; p++) 	{ 		scanf("%d", p); 		printf("%3d", *p); 	}putchar(10); 	putchar(10); 	int i, j; 	p = x; 	for (i = 0; i < 2; i++) 	{ 		for (j = 0; j < 3; j++) 		{ 			printf("%3d", *(p + i *3  + j));//这里把i*3写成了i*2，每行三个元素 		}putchar(10); 	} 	putchar(10); 	return 0; }

引用 4 楼 jtidni 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] #include<stdio.h>  int main() {     int x[2][3];     int *p = &x[0][0];     for (; p < &x[0][0] + 2 * 3; p++)    /*行数乘以列数*/     {         scanf("%d", p);         printf("%3d\n", *p);     }     putchar(10);     putchar(10);      int i, j;     p = &x[0][0];     for (i = 0; i < 2; i++)     {         for (j = 0; j < 3; j++)         {             printf("%3d", *(p + i * 3 + j));   /*i是行，一行有3列*/         }         putchar(10);     }     putchar(10);      return 0; } 参考一下吧； 指针p是一重指针，但是x是二维数组，类型就不匹配。指针p可以指向二位数组的第一个元素，然后通过p++分别遍历，这样就是把二维数组当成一维数组使用；只是数组的长度是行数乘以列数；  #include<stdio.h> int main() { 	int a[2][3]; 	//int *p = a;		 	int i, j; 	int *ps = a; 	for (i = 0; i < 2; i++) 	for (j = 0; j < 3; j++) 	{ 		scanf("%d", ps + i * 3 + j); 		printf("%5d", *(ps + i * 3 + j)); 	} 	putchar(10); 	return 0; }  那么这个怎么解释？ 之前我都是输出对的，就不知道为什么这里突然不能这么用了。 [/quote]

引用 1 楼 cfjtaishan 的回复:#include<stdio.h>  int main() {     int x[2][3];     int *p = &x[0][0];     for (; p < &x[0][0] + 2 * 3; p++)    /*行数乘以列数*/     {         scanf("%d", p);         printf("%3d\n", *p);     }     putchar(10);     putchar(10);      int i, j;     p = &x[0][0];     for (i = 0; i < 2; i++)     {         for (j = 0; j < 3; j++)         {             printf("%3d", *(p + i * 3 + j));   /*i是行，一行有3列*/         }         putchar(10);     }     putchar(10);      return 0; } 参考一下吧； 指针p是一重指针，但是x是二维数组，类型就不匹配。指针p可以指向二位数组的第一个元素，然后通过p++分别遍历，这样就是把二维数组当成一维数组使用；只是数组的长度是行数乘以列数； #include<stdio.h> int main() { 	int a[2][3]; 	//int *p = a;		 	int i, j; 	int *ps = a; 	for (i = 0; i < 2; i++) 	for (j = 0; j < 3; j++) 	{ 		scanf("%d", ps + i * 3 + j); 		printf("%5d", *(ps + i * 3 + j)); 	} 	putchar(10); 	return 0; } 那么这个怎么解释？ 之前我都是输出对的，就不知道为什么这里突然不能这么用了。

error: cannot convert 'int (*)[3]' to 'int*' in initialization   int *p = x;            ^ error: comparison between distinct pointer types 'int*' and 'int (*)[3]' lacks a cast [-fpermissive]   for (; p < x+2; p++)                ^ error: cannot convert 'int [2][3]' to 'int*' in assignment   p = x;     ^


Question: 求大佬们帮忙看一下哪里有错

原来如此，卡了我2个多小时真是快要死了，多谢指点！

#include<stdio.h> #include <stdlib.h> //#include<malloc.h>  typedef int ElemType;  typedef struct LNode {     ElemType data;     struct LNode *next; }LinkNode; //定义单链表  void CreateListF(LinkNode *&L,ElemType a[],int n) //建立单链表 {     LinkNode *s;     L=(LinkNode *)malloc(sizeof(LinkNode));     L->next=NULL;      for(int i=0;i<n;i++)     {         s=(LinkNode *)malloc(sizeof(LinkNode));         s->data=a[i];         s->next=L->next;         L->next=s;     } }  void InitList(LinkNode *&L) //初始化 {     L=(LinkNode *)malloc(sizeof(LinkNode));     L->next=NULL; }  void DestroyList(LinkNode *&L) //销毁 {     LinkNode *pre=L,*p=L->next;     while(p)     {         free(pre);         pre=p;         p=pre->next;     }     free(pre); }  void DispList(LinkNode *L) //输出 {     LinkNode *p=L->next;     while(p)     {         printf("%d",p->data);         p=p->next;     }     printf("\n"); }  int LocateElem(LinkNode *L, ElemType e) //按元素查找 {     int i = 1;     LinkNode *p = L->next;     while(p && p->data != e)     {         p = p->next;         i++;     }     if(!p)         return(0);     else         return(i); }  bool ListInsert(LinkNode *&L,int i, ElemType e) //插入数据元素 {     int j=0;     LinkNode *p = L, *s;     if(i <= 0)         return false;     while(j < i - 1 && p) {         j++;    /* 改成j++*/         p = p->next;     }     if(!p)         return false;     else     {         s = (LinkNode *)malloc(sizeof(LinkNode));         s->data = e;         s->next = p->next;         p->next = s;         return true;     } }  void sort(LinkNode *&L) //排序 {     LinkNode *p,*pre,*q;     p=L->next->next;     L->next->next=NULL;     while(p!=NULL)     {         q=p->next;         pre=L;         while(pre->next!=NULL && pre->next->data<p->data)             pre=pre->next;         p->next=pre->next;         pre->next=p;         p = q;     } }  void Bing(LinkNode *a,LinkNode *b,LinkNode *&c) //并 {     InitList(c);     LinkNode *p=a->next;     LinkNode *q=b->next;     int i=0;     while(p && q)     {         if(p->data < q->data)         {             ListInsert(c,i+1,p->data);             p=p->next;             i++;         }         else if(p->data==q->data)         {             ListInsert(c,i+1,p->data);             p=p->next;             q=q->next;             i++;         }         else         {             ListInsert(c,i+1,q->data);             q=q->next;             i++;         }     }     while (q) {         ListInsert(c, i+1, q->data);         q=q->next;         i++;     }     while (p) {         ListInsert(c, i+1, q->data);         p = p->next;         i++;     } }  void Jiao(LinkNode *a,LinkNode *b,LinkNode *&c) //交 {     DestroyList(c);     InitList(c);     LinkNode *p=a->next;     int i=0;     while(p)     {         if(LocateElem(b,p->data))             ListInsert(c,++i,p->data);         p = p->next;     } }  void  Cha(LinkNode *a,LinkNode *b,LinkNode *&c) //差 c前少个& {     DestroyList(c);     InitList(c);     LinkNode *p = a->next;     int i = 0;     while(p)     {         if(LocateElem(b, p->data) == 0) {             ListInsert(c, ++i, p->data);             //printf("%d\n", p->data);         }         p = p->next;     }  }  int main(void) {     LinkNode *ha,*hb,*hc;     ElemType a[4] = {2,4,1,3};     ElemType b[4] = {3,1,5,6};     CreateListF(ha,a,4);     CreateListF(hb,b,4);     printf("原ha表:    ");     DispList(ha);     printf("原hb表:    ");     DispList(hb);     sort(ha);     sort(hb);     printf("排序后ha表:    ");     DispList(ha);     printf("排序后hb表:    ");     DispList(hb);     printf("并:   ");     Bing(ha,hb,hc);     DispList(hc);     printf("交:   ");     Jiao(ha,hb,hc);     DispList(hc);     printf("差:   ");     Cha(ha,hb,hc);     DispList(hc); }  两个地方改一下就好了； 第一处：插入一个节点的地方，将i++改成j++; 第二处：求差集时，需要将形参c前加上&. 以上两处都有注释； 另外，对你的代码做了部分风格修改，建议对比你的代码看一下


Question: vc6.00能运行的C语言程序在VS2017中得不到结果

程序没问题，应该是编译器输出时需要处理一下。在Linux下不做修改也可以输出数据。

或者像1楼说的那样，在main()函数的最后田间 system("pause"); 并且在源文件的起始位置处添加 #include <stdlib.h>

没有VS2017，在VS2015上调试的。主要把scanf改为scanf_s,把printf()中表示宽度的数字进行了修改 void inputstu(struct student stu[]) { 	int i, j; 	for (i = 0; i<N; i++) 	{ 		printf("\n please input %d of %d\n", i + 1, N); 		printf("num:"); 		scanf_s("%s", stu[i].num, 6); 		printf("name:"); 		scanf_s("%s", stu[i].name, 8); 		for (j = 0; j<3; j++) 		{ 			printf("score %d", j + 1); 			scanf_s("%d", &stu[i].score[j]); 		} 		printf("\n"); 	} }   void printstu(struct student stu[]) { 	int i, j; 	printf("\nNo.Name Sco1 Sco2 Sco3\n"); 	for (i = 0; i<N; i++) 	{ 		printf("%3s%5s", stu[i].num, stu[i].name); 		for (j = 0; j<3; j++) 			printf("%-4d", stu[i].score[j]); 		printf("\n");  	} }

在最末尾加一个system("pause");  可能要加头文件#include <process.h>


Question: 关于getchar（）函数的问题，求大神帮忙

貌似scanf是会自动跳过换行符的吧

如果用getchar();换成scanf("%c", &ch);那么你预想的情况就会出现。 getchar()；  引用 2 楼 a645328869 的回复:的确吃掉了。但是换行的ASCII是10，10-64=-54，不满足循环，没做什么事情。你在for循环外面写一个输出语句就看到变化了。 赞同，建议楼主在f=getchar();这句后面加上一句调试语句printf("%d\n", f); 你会发现会输出10（输出两行，但是其中一行是10）就是回车符；

可以用getch来获取。 或者getchar后用fflush(stdiin)清理一下缓冲区。


Question: ping www.baidu.com都用到了哪些协议

首先将域名转成ip地址，要做DNS解析，那么走TCP或者UDP的53端口（DNS协议）；TCP或者UDP下面是IP。 然后是ping的ICMP。 所以最基本的就是这里的DNS协议，TCP/UDP/IP协议，ICMP协议。  如果还往局域网考虑，那么根据接的有线还是无线，可以有802.3和ARP；也可以是802.11协议簇。 如果往广域网考虑，那么可以有PPP，HDLC，ATM，X.25……。 如果是蜂窝网接入（手机3G/4G），那么还有移动网络的协议，这块不熟。

引用 2 楼 cfjtaishan 的回复:[quote=引用 1 楼 zjq9931 的回复:] TCP IP的 UDP协议啊。 DNS将域名转换成IP地址。 然后UDP协议发送数据接收数据。 我怎么记得ping包是ICMP协议呢，从底层向上一次为MAC, 数据链路层， IP层,ICMP协议层 www.baidu.com需要解析成IP地址，所以需要DNS协议[/quote] 确实我说的不对。这里看到了详细的过程。 http://blog.csdn.net/guoweimelon/article/details/50865642

引用 1 楼 zjq9931 的回复:TCP IP的 UDP协议啊。 DNS将域名转换成IP地址。 然后UDP协议发送数据接收数据。 我怎么记得ping包是ICMP协议呢，从底层向上一次为MAC, 数据链路层， IP层,ICMP协议层 www.baidu.com需要解析成IP地址，所以需要DNS协议

理解和讨论之前请先学会如何观察！  学会使用抓包软件比如wireshark

百度搜相关关键字。


Question: 关于编译器无法识别字符串中十六进制转议字符(\xff)和普通字符的问题

“标准规定的”，这种回答我没有理由不接受。我也不质疑标准的权威。 我现在只想知道，为什么"\x05five"不定义成'\x05'加上"five"，而"\005five"可以？ 如果\ooo可以固定长度为3个八进制数，那为什么\xhh为什么就不能固定长度为2个十六进制数？ 这其中有什么故事吗？

引用 5 楼 ccssddnn218 的回复:你们都试验过"\0x0051"能行？在我的测试里表现并不是你们说的那样呢，还是“翻译”成了'Q'。引用 4 楼 ForestDB 的回复:LZ给的链接中https://msdn.microsoft.com/zh-cn/library/edsza5ck.aspx不是写得很清楚么：\xhhh，是3个数字，不是2个数字，既然0、5、1都是合法的h，那么自然是凑到一起来当作Q被识别。链接中也给出了"\x05""1"这样的技巧。感觉"\x0051"这样比较符合LZ的审美。引用 3 楼 paschen 的回复:1楼正解，"\x05""1"; 要分隔开，否则会连在一起判断，再或者写成："\x0051"  "\x0051"可以，前面要多两个0

老赵的资料表示就是这样定义的： octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit                 // \ooo最多三个oct  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit                // \xhh是个递归的定义，多长都可以  所以： 1、使用""连接 2、使用\ooo的方式

是我错了，我试了下，如果是\x打头的话，那么只要是个小于0xff的合法的hex数的话，前面有多少0都是无所谓的。那么只有用""连接的方式了。  然后\ooo是有长度限制的，最多就3个合法的oct。

C++ String Literals A string literal consists of zero or more characters from the source character set surrounded by double quotation marks ("). A string literal represents a sequence of characters that, taken together, form a null-terminated string.  Syntax  string-literal :  "s-char-sequenceopt" L"s-char-sequenceopt"  s-char-sequence :  s-char s-char-sequence s-char  s-char :  any member of the source character set except the double quotation mark ("), backslash (\), or newline character escape-sequence  C++ strings have these types:   Array of char[n], where n is the length of the string (in characters) plus 1 for the terminating '\0' that marks the end of the string   Array of wchar_t, for wide-character strings  The result of modifying a string constant is undefined. For example:  char *szStr = "1234"; szStr[2] = 'A';      // Results undefined  Microsoft Specific   In some cases, identical string literals can be “pooled” to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal. The/Gf compiler option enables string pooling.  END Microsoft Specific  When specifying string literals, adjacent strings are concatenated. Therefore, this declaration:  char szStr[] = "12" "34";  is identical to this declaration:  char szStr[] = "1234";  This concatenation of adjacent strings makes it easy to specify long strings across multiple lines:  cout << "Four score and seven years "         "ago, our forefathers brought forth "         "upon this continent a new nation.";  In the preceding example, the entire string Four score and seven years ago, our forefathers brought forth upon this continent a new nation. is spliced together. This string can also be specified using line splicing as follows:  cout << "Four score and seven years \ ago, our forefathers brought forth \ upon this continent a new nation.";  After all adjacent strings in the constant have been concatenated, the NULL character, '\0', is appended to provide an end-of-string marker for C string-handling functions.  When the first string contains an escape character, string concatenation can yield surprising results. Consider the following two declarations:  char szStr1[] = "\01" "23"; char szStr2[] = "\0123";  Although it is natural to assume that szStr1 and szStr2 contain the same values, the values they actually contain are shown in Figure 1.1.  Figure 1.1   Escapes and String Concatenation    Microsoft Specific   The maximum length of a string literal is approximately 2,048 bytes. This limit applies to strings of type char[] and wchar_t[]. If a string literal consists of parts enclosed in double quotation marks, the preprocessor concatenates the parts into a single string, and for each line concatenated, it adds an extra byte to the total number of bytes.   For example, suppose a string consists of 40 lines with 50 characters per line (2,000 characters), and one line with 7 characters, and each line is surrounded by double quotation marks. This adds up to 2,007 bytes plus one byte for the terminating null character, for a total of 2,008 bytes. On concatenation, an extra character is added to the total number of bytes for each of the first 40 lines. This makes a total of 2,048 bytes. (The extra characters are not actually written to the string.) Note, however, that if line continuations (\) are used instead of double quotation marks, the preprocessor does not add an extra character for each line.  END Microsoft Specific  Determine the size of string objects by counting the number of characters and adding 1 for the terminating '\0' or 2 for type wchar_t.  Because the double quotation mark (") encloses strings, use the escape sequence (\") to represent enclosed double quotation marks. The single quotation mark (') can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a string, you must type two backslashes (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)  To specify a string of type wide-character (wchar_t[]), precede the opening double quotation mark with the character L. For example:  wchar_t wszStr[] = L"1a1g";  All normal escape codes listed in Character Constants are valid in string constants. For example:  cout << "First line\nSecond line"; cout << "Error! Take corrective action\a";  Because the escape code terminates at the first character that is not a hexadecimal digit, specification of string constants with embedded hexadecimal escape codes can cause unexpected results. The following example is intended to create a string literal containing ASCII 5, followed by the characters five:  \x05five"  The actual result is a hexadecimal 5F, which is the ASCII code for an underscore, followed by the characters ive. The following example produces the desired results:   "\005five"     // Use octal constant. "\x05" "five"  // Use string splicing.

查MSDN是Windows程序员必须掌握的技能之一。  C++ Character Constants Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.  Microsoft Specific   For Microsoft C++, the source and execution character sets are both ASCII.  END Microsoft Specific  There are three kinds of character constants:   Normal character constants   Multicharacter constants   Wide-character constants  Note   Use wide-character constants in place of multicharacter constants to ensure portability.  Character constants are specified as one or more characters enclosed in single quotation marks. For example:  char ch = 'x';          // Specify normal character constant. int mbch = 'ab';        // Specify system-dependent                         //  multicharacter constant. wchar_t wcch = L'ab';   // Specify wide-character constant.  Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  any member of the source character set except the single quotation mark ('), backslash (\), or newline character escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \' \" \? \\ \a \b \f \n \r \t \v  octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit  Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)  The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:  char schar = 'x';               // Normal character constant wchar_t wchar = L'\x81\x19';    // Wide-character constant  Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.  Table 1.2   C++ Reserved or Nongraphic Characters  Character ASCII  Representation ASCII  Value Escape Sequence  Newline NL (LF) 10 or 0x0a \n  Horizontal tab HT 9 \t  Vertical tab VT 11 or 0x0b \v  Backspace BS 8 \b  Carriage return CR 13 or 0x0d \r  Formfeed FF 12 or 0x0c \f  Alert BEL 7 \a  Backslash \ 92 or 0x5c \\  Question mark ? 63 or 0x3f \?  Single quotation mark ' 39 or 0x27 \'  Double quotation mark " 34 or 0x22 \"  Octal number ooo — \ooo  Hexadecimal number hhh — \xhhh  Null character NUL 0 \0    If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.  Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.  Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:  wchar_t och = L'\076a';  // Sequence terminates at a char    ch = '\233';     // Sequence terminates after 3 characters  Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.  Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)

引用 13 楼 ccssddnn218 的回复:谢谢zhao4zhong1老师和其他网友的耐心查阅和回答。 八进制的写法,\000: "\005five" 十六进制写法,\xhh: "\x05five" 怎么看，我都觉得这两种写法表示的是同一个意思。我找不出任何不支持第2种写法的理由。 MSDN? 谁写的MSDN？！ 画个圈圈诅咒你：  八进制的写法没跑，\005 f i v e 十六进制的写法就比较坑，\x05f i v e，为什么呢？f是个有效的十六进制数啊，\x后面可以跟若干个十六进制数啊，标准规定的啊，12L就是标准的描述啊。

"H\x01ello World!\n" 这个字符串我是希望在"Hello World!"中插入一个'\x01'字节，看看程序的表现。如果采用多个引号的方法就只表表示成下面这样了： "H""\x01""ello World!\n" 我倒是想用第一种形式，无论是\x001还是\x0001都无所谓，只要格式能统一，但测试表明"...\x001e..."不是我想要的结果。 沮丧

更正一下！"\x0051" 引用 5 楼 ccssddnn218 的回复:你们都试验过"\0x0051"能行？在我的测试里表现并不是你们说的那样呢，还是“翻译”成了'Q'。 [quote=引用 4 楼 ForestDB 的回复:] LZ给的链接中https://msdn.microsoft.com/zh-cn/library/edsza5ck.aspx不是写得很清楚么：\xhhh，是3个数字，不是2个数字，既然0、5、1都是合法的h，那么自然是凑到一起来当作Q被识别。链接中也给出了"\x05""1"这样的技巧。 感觉"\x0051"这样比较符合LZ的审美。 引用 3 楼 paschen 的回复:1楼正解，"\x05""1"; 要分隔开，否则会连在一起判断，再或者写成："\x0051"[/quote]

你们都试验过"\0x0051"能行？在我的测试里表现并不是你们说的那样呢，还是“翻译”成了'Q'。 引用 4 楼 ForestDB 的回复:LZ给的链接中https://msdn.microsoft.com/zh-cn/library/edsza5ck.aspx不是写得很清楚么：\xhhh，是3个数字，不是2个数字，既然0、5、1都是合法的h，那么自然是凑到一起来当作Q被识别。链接中也给出了"\x05""1"这样的技巧。 感觉"\x0051"这样比较符合LZ的审美。 引用 3 楼 paschen 的回复:1楼正解，"\x05""1"; 要分隔开，否则会连在一起判断，再或者写成："\x0051"

仅供参考：#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> extern "C" HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     wchar_t wc[2];      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48,0,0,0,0,0,0,0,GB2312_CHARSET ,0,0,0,0,"宋体-方正超大字符集");     SelectObject(hdc,hfont);     wc[0]=0xD854u;     wc[1]=0xDC00u;     TextOutW(hdc,10,10,wc,2);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; } #if 0 代理项或代理项对是一对共同表示单个字符的 16 位 Unicode 编码值。需要记住的关键一点是： 代理项对实际上是 32 位单个字符，不能再假定一个 16 位 Unicode 编码值正好映射到一个字符。  使用代理项对 代理项对的第一个值是高代理项，包含介于 U+D800 到 U+DBFF 范围内的 16 位代码值。 该对的第二个值是低代理项，包含介于 U+DC00 到 U+DFFF 范围内的值。通过使用代理项对， 16 位 Unicode 编码系统可以对已由 Unicode 标准定义的一百多万个其他字符 (220) 进行寻址。  在传递给 XmlTextWriter 方法的任何字符串中都可以使用代理项字符。不过，代理项字符在编写的 XML 中应该有效。例如，万维网联合会 (W3C) 建议不允许在元素或属性的名称中使用代理项字符。 如果字符串包含无效的代理项对，则引发异常。  另外，可以使用 WriteSurrogateCharEntity 写出与代理项对相对应的字符实体。字符实体以十六 进制格式写出，并用以下公式生成：  (highChar -0xD800) * 0x400 + (lowChar -0xDC00) + 0x10000  如果字符串包含无效的代理项对，则引发异常。下面的示例显示将代理项对作为输入的 WriteSurrogateCharEntity 方法。  C#复制  // The following line writes 𐀀. WriteSurrogateCharEntity ('\uDC00', '\uD800'); 下面的示例生成一个代理项对文件，将其加载到 XmlReader 中，并用新的文件名保存文件。 然后，原始文件和新文件被加载回应用程序的 XML 文档对象模型 (DOM) 结构中以进行比较。  C#复制  char lowChar, highChar; char [] charArray = new char[10]; FileStream targetFile = new FileStream("SurrogatePair.xml",       FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);  lowChar = Convert.ToChar(0xDC00); highChar = Convert.ToChar(0xD800); XmlTextWriter tw = new XmlTextWriter(targetFile, null); tw.Formatting = Formatting.Indented; tw.WriteStartElement("root"); tw.WriteStartAttribute("test", null); tw.WriteSurrogateCharEntity(lowChar, highChar); lowChar = Convert.ToChar(0xDC01); highChar = Convert.ToChar(0xD801); tw.WriteSurrogateCharEntity(lowChar, highChar); lowChar = Convert.ToChar(0xDFFF); highChar = Convert.ToChar(0xDBFF); tw.WriteSurrogateCharEntity(lowChar, highChar);  // Add 10 random surrogate pairs. // As Unicode, the high bytes are in lower // memory; for example, word 6A21 as 21 6A. // The high or low is in the logical sense. Random random = new Random(); for (int i = 0; i < 10; ++i) {       lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));       highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));       charArray[i] = highChar;       charArray[++i] = lowChar; } tw.WriteChars(charArray, 0, charArray.Length);  for (int i = 0; i < 10; ++i) {       lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));       highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));       tw.WriteSurrogateCharEntity(lowChar, highChar); }  tw.WriteEndAttribute(); tw.WriteEndElement(); tw.Flush(); tw.Close();  XmlTextReader r = new XmlTextReader("SurrogatePair.xml");  r.Read(); r.MoveToFirstAttribute(); targetFile = new FileStream("SurrogatePairFromReader.xml",        FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);  tw = new XmlTextWriter(targetFile, null); tw.Formatting = Formatting.Indented; tw.WriteStartElement("root"); tw.WriteStartAttribute("test", null); tw.WriteString(r.Value); tw.WriteEndAttribute(); tw.WriteEndElement(); tw.Flush(); tw.Close();  // Load both result files into the DOM and compare. XmlDocument doc1 = new XmlDocument(); XmlDocument doc2 = new XmlDocument(); doc1.Load("SurrogatePair.xml"); doc2.Load("SurrogatePairFromReader.xml"); if (doc1.InnerXml != doc2.InnerXml) {       Console.WriteLine("Surrogate Pair test case failed"); } 在使用 WriteChars 方法（一次写出一个缓冲区的数据）写出时，输入中的代理项对可能 会在一个缓冲区内被意外拆分。由于代理项值是定义完善的，如果 WriteChars 遇到来自 较低范围或者较高范围的 Unicode 值，它将该值标识为代理项对的一半。当遇到  WriteChars 将导致从拆分代理项对的缓冲区写入的情况时，将引发异常。使用   IsHighSurrogate 方法检查缓冲区是否以高代理项字符结束。如果缓冲区中的最后一个   字符不是高代理项，可以将该缓冲区传递给 WriteChars 方法。  请参见 概念 使用 XmlTextWriter 创建格式正确的 XML XmlTextWriter 的 XML 输出格式设置 XmlTextWriter 的命名空间功能  #endif

引用 13 楼 ccssddnn218 的回复:谢谢zhao4zhong1老师和其他网友的耐心查阅和回答。 八进制的写法,\000: "\005five" 十六进制写法,\xhh: "\x05five" 怎么看，我都觉得这两种写法表示的是同一个意思。我找不出任何不支持第2种写法的理由。 MSDN? 谁写的MSDN？！ 画个圈圈诅咒你： 当初如果让你写MSDN，我估计你会写得更遭后人诅咒！

9楼正解！

难道这就是传说中的“陷阱”吗？

难道转义字符不能和普通字符混用？好吧，我想在正常字符串中加入特殊数据，“搞搞”程序，怎么办？我能想到的办法是把正常字符也用转义字符表示，比如'1'用'\x31'表示。不过，心里并不是很乐于接受这种方式。


Question: 刚入门遇到了一点小问题= =

1 产生原因 正如你所说，在scanf_s()中多了一个转义字符\n。在scanf_s中 “\n” 不是表示接受一个回车符，而是表示忽略所有的空白字符（包括回车,空格,tab ）。所以想要结束输入,输入任意一个非空白字符即可,但是该字符仍然会留在缓冲区中。 2 转义字符\n在scanf_s()中使用的时机 一般在输入字符时作为屏蔽回车键。例如 	scanf_s("%d", &a); 	scanf_s("%c", &b); printf("a=%d,b=%d\n", a, b); 输入1回车时，还没有输入字符，就输出了，如图所示  此时，a的值是1，b的值是10，即回车键 可以在scanf_s()中加入转义字符\n来屏蔽回车符 	scanf_s("%d\n", &a); 	scanf_s("%c", &b); printf("a=%d,b=%d\n", a, b); 此时，输入1回车a，如图所示  a的值是1，b的值是97，即'a' 3 拓展 不仅是转义字符\n能起到屏蔽回车的作用，空格键也可以实现该功能。 将上述代码改为 	scanf_s("%d ", &a); 	scanf_s("%c", &b); printf("a=%d,b=%d\n", a, b); 也能起到屏蔽回车的作用

啊  我找到问题了= =%d后面的\n让程序多了一个换行  就要多输入一次

我之前也是那么做的 用逗号分隔 输入的时候就加了逗号 但是还是需要输入一次确认后再随便输入一个数确认才能显示结果

之后还是这个样子。大佬能指导一下么= =

scanf_s("%d%d\n", &a, &b,4);//这一块的代码决定的 %d%d//主要是这块，如果改成%d，%d那么就需要用逗号分隔，如果是空格，那就需要用空格分隔，因为你要连续输入两个数，如果少输入一个就不会向下继续执行

scanf  后面那个4你没看到吗？ 还有main 返回值不是void  吗，return 0不报错吗？  你可以试试输入 1空格2空格3enter


Question: 7道C语言面试题，7分钟完成。你能做对几道？

第二个求i的值可能会有不同的值（不同编译器上编译）

第4题应指定大小端及short的大小，题目中就有两个错误。不做也罢

[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/25.gif][/img 卧槽！对比答案，我0分。。

不经意的话可能就掉坑里了


Question: 链表中如何给所有的结点的data值初始化

引用 5 楼 zihui0459 的回复:引用 4 楼 paschen 的回复:C语言的话就自己进行赋值，C++的话可以在构造函数中将data赋值为-1是每一个结点用的时候都得自己赋值吗  是的，你可以为创建节点写一个函数，函数中先创建，然后赋值，之后就只用调用这个函数就行

C语言的话就自己进行赋值，C++的话可以在构造函数中将data赋值为-1

这个。。。应该重写构造函数比较好吧。。 typedef struct LNode { LNode（） ：data(-1)  , next(nullptr) {}  int data; LNode*next; }LNode;

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

创建链表节点时，初始化为-1. for example:  LNode *p = (LNode *)malloc(sizeof(*p)); if (!p) {     fprintf(stderr, "malloc error!\n");     exit(-1); } p->data = -1; p->next = NULL;


Question: 用SOCK_RAW(原始套接字)模拟SYN Flood攻击，目标主机不响应ACK+SYN数据报

IP头校验码不对

引用 6 楼 赵4老师的回复:其实我也是略知皮毛。  现代中国人的能力差别很大程度上体现在会不会合理高效地使用百度上。 百度搜相关关键字。 我就是那个不会用百度的，有些问题在百度上搜不出来，这就很尴尬。

《TCPIP详解卷一：协议》

引用 4 楼 zhao4zhong1 的回复:《TCPIP详解卷一：协议》 请教一下赵老师，利用SOCK_RAW构造自己的TCP报文时，“IP数据报的首部校验和”以及“TCP报文的首部校验和”需要自己手动填写，还是内核自动填写？如果是手动填写，是不是要自己用C语言实现一个计算校验和的函数？

智能路由器上可能有过滤功能。 学会使用抓包软件分析具体原因。

引用 1 楼 zhao4zhong1 的回复:防火墙…… 我在Kali Linux上运行这段程序，目标主机是Windows 2003虚拟机，打开80端口，关闭win主机的防火墙，可还是得不到ACK+SYN响应。 你说是防火墙的原因，那为什么正常HTTP访问的SYN请求能建立连接？而我构造的SYN数据包不能。 我对比了一下这两个数据报，它们有差异：正常的SYN请求报文66字节，而我构造的SYN数据报60字节。 我也检查了它们的TCP首部和IP首部字段，都没问题啊，百思不得其解。。。

防火墙……


Question: C语言的函数名字的有效长度是多少

C89标准　　C99标准 内部标识符中的有效字符个数　　31　　　　　63 外部标识符中的有效字符个数　　6　　　　　 31

一般见名知义就好了，

255   ........

https://docs.microsoft.com/en-us/cpp/c-language/c-identifiers Microsoft Specific Although ANSI allows 6 significant characters in external identifier names and 31 for names of internal (within a function) identifiers, the Microsoft C compiler allows 247 characters in an internal or external identifier name. If you aren't concerned with ANSI compatibility, you can modify this default to a smaller or larger number using the /H (restrict length of external names) option. END Microsoft Specific  总的来说，标准（这里引用的应该是C89标准）指明了最小要支持的长度，任何支持标准的编译器实现，至少得遵循这个最小长度；然后特定的编译器实现，比如这里的微软C编译器，可以支持更长。  http://en.cppreference.com/w/c/language/identifier 这里有对C99前后的标准差异有描述。

每个编译器对函数名字的长度要求都不一样，但是每个项目都有各自的编码规则，一般是不超过30个字母

现在的C编译器一般都支持C++， 支持的函数名啥的有效长度非常非常大，  简单的测试了下 ， VS 大约 4K 个字符，   gcc 几百K 都没问题， 不过你写个 上百字符的函数名可能被人打死 ....

函数名和变量名一样，都会有字符数限制。所以，建议函数名能做到见名知意即可，有时为了减少名字长度还会考虑使用单词缩写，当然这些单词缩写也是大家都这么用，都了解，看到单词缩写就明白其意思。

函数名和变量名的长度都会有限制的，不要使用太长的变量名，例如50个字符，这很难阅读，而且可能超出一些编译器的限制； 有些公司或者机构对于编码都会有要求，比如每行不超过80个字符（包括前面换行的空格或者tab），这个是GNU内核有这样的要求。

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


Question: 新手求助！

还有就是i==5时的break..我是复制了前次没修改过的代码，修改了的就没有这个错误了

啊哈谢谢各位大神，知道怎么解决了！对，就是sum应该赋予另外一个值，因为它会变！

百度搜“倒推法”

引用 2 楼 cfjtaishan 的回复:#include<stdio.h> int main() {     int sum, i, peachs;     for (peachs = 0; peachs < 10000; peachs++)     {         sum = peachs;         for (i = 0; i < 5; i++)         {             if (sum % 5 == 1)                 sum = sum - (sum / 5) - 1;             else                 break;         }         if (i == 5) {   /*加上大括号*/             printf("最小的数目是：%d\n", sum);             break;         }     }      return 0; } 参考一下吧。 当算出最小数目的桃子时就要break出去，所以当i == 5时才要break;所以这个也是为什么一直没有输出，因为当sum == 0时，就break出外循环了。正解！~

我好像看错了呀~~  好尴尬~

算法是对的   里面的变量sum出了问题， sum作为循环条件，你每一次都在循环里面改变了sum的值 你可以跟踪一下sum变量， 看看它值的变化， sum肯定不是从1一直往上加的  解决办法： sum 作为循环变量 不要改变它 只用sum++操作，另外定义一个变量进行判断  如果解决了问题，还请给点分

应该逆向思考吧  	int sum = 1; 	for (int i = 0; i < 5; i++) 	{ 		sum = (sum * 5 + 1); 	}


Question: 求助

引用 4 楼 zhao4zhong1 的回复:#include <stdio.h> #include <string.h> #define maxn (10000000+10) int main() {     static char s[maxn];     fgets(s,maxn,stdin);     int tot = 0;     char *p=(char *)s;     while (1) {         if (*p == '1')  tot++;         if (*p==0) break;         p++;     }     printf("%d\n",tot); 	return	0; } 加括号与不加有啥区别

引用 8 楼 paschen 的回复:引用 5 楼 qq_38080117 的回复:[quote=引用 1 楼 paschen 的回复:]数组char s[maxn];太大了，应该在堆上申请空间其次，s[i] == 1 是否想表达的是：s[i] == '1'目的是统计1的个数，所以我也不知道是1还是‘1’。应该是哪个？  应该是后者，表示的是字符的1[/quote]谢谢

这个程序中没区别。加十是我照抄的。

引用 13 楼 zhao4zhong1 的回复:static int s[maxn*sizeof(int)];//将来如果有这么一句，加不加括号区别就大了！在这个程序里有啥区别吗？为啥要加10呢？

引用 9 楼 cfjtaishan 的回复:[quote=引用 6 楼 qq_38080117 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] #include <stdio.h> #include <string.h>  #define maxn   10000000+10  char s[maxn];  int main() {     int tot = 0;     int i;      scanf("%s", s);     for (i = 0; i < strlen(s);i++)         if (s[i] == '1')             tot++;      printf("%d\n",tot);     return  0; } 效率低是由于申请的栈上的空间太大，栈上的空间是有限的，你申请的栈上空间接近10M，代码是在栈上运行的，如果栈上空间不足就会从磁盘上开辟，并做数据交换，自然运行效率就低了。 建议你在数据段或者堆上申请这部分空间。如果不需要那么多空间，可以定义适量，也可以通过malloc和realloc逐步增加空间。 另外,字符'1'和数值1是不一样的它们的数值相差48那0和‘0’也不一样吗？它们也是相差48吗？效率的问题理解了，但是那么大的栈区空间会使程序崩溃吗？[/quote] 对呀，'0'的ascii值是48，数值0就是0,48 - 0 = 48；[/quote]谢谢，懂了

引用 6 楼 qq_38080117 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] #include <stdio.h> #include <string.h>  #define maxn   10000000+10  char s[maxn];  int main() {     int tot = 0;     int i;      scanf("%s", s);     for (i = 0; i < strlen(s);i++)         if (s[i] == '1')             tot++;      printf("%d\n",tot);     return  0; } 效率低是由于申请的栈上的空间太大，栈上的空间是有限的，你申请的栈上空间接近10M，代码是在栈上运行的，如果栈上空间不足就会从磁盘上开辟，并做数据交换，自然运行效率就低了。 建议你在数据段或者堆上申请这部分空间。如果不需要那么多空间，可以定义适量，也可以通过malloc和realloc逐步增加空间。 另外,字符'1'和数值1是不一样的它们的数值相差48那0和‘0’也不一样吗？它们也是相差48吗？效率的问题理解了，但是那么大的栈区空间会使程序崩溃吗？[/quote] 对呀，'0'的ascii值是48，数值0就是0,48 - 0 = 48；

引用 5 楼 qq_38080117 的回复:引用 1 楼 paschen 的回复:数组char s[maxn];太大了，应该在堆上申请空间其次，s[i] == 1 是否想表达的是：s[i] == '1'目的是统计1的个数，所以我也不知道是1还是‘1’。应该是哪个？  应该是后者，表示的是字符的1

引用 3 楼 user-4 的回复:问题1：在栈内存上申请一个的数组，会导致溢出，如楼上所言在堆上申请内存好一些 2.用scanf输入字符串时，其空格仍被当做字符输了进去 3.如一楼所示 其他，宏定义最后的常数一般加括号处理，for循环中的int i=0在一些编译器不能被支持弱弱的问句，加括号是啥意思，有何区别？不加会出错吗？

引用 2 楼 cfjtaishan 的回复:#include <stdio.h> #include <string.h>  #define maxn   10000000+10  char s[maxn];  int main() {     int tot = 0;     int i;      scanf("%s", s);     for (i = 0; i < strlen(s);i++)         if (s[i] == '1')             tot++;      printf("%d\n",tot);     return  0; } 效率低是由于申请的栈上的空间太大，栈上的空间是有限的，你申请的栈上空间接近10M，代码是在栈上运行的，如果栈上空间不足就会从磁盘上开辟，并做数据交换，自然运行效率就低了。 建议你在数据段或者堆上申请这部分空间。如果不需要那么多空间，可以定义适量，也可以通过malloc和realloc逐步增加空间。 另外,字符'1'和数值1是不一样的它们的数值相差48那0和‘0’也不一样吗？它们也是相差48吗？效率的问题理解了，但是那么大的栈区空间会使程序崩溃吗？

引用 1 楼 paschen 的回复:数组char s[maxn];太大了，应该在堆上申请空间  其次，s[i] == 1 是否想表达的是：s[i] == '1'目的是统计1的个数，所以我也不知道是1还是‘1’。应该是哪个？


Question: 请问 全局变量赋初值是在什么阶段

操作系统加载exe时。

程序退出后，程序里所申请的空间，不论是栈上的，堆上的，还是数据段上的都会被释放。这个我们看不到，是系统负责处理的。 所以，再次运行时，就会重新申请，重新赋值等等。 所以每次执行都是一样的

你多次运行你main函数，main对全局变量的改变会保存下来吗？每次运行main之前才分配赋值吧

全局变量在main之前就申请好的。

程序加载的时候，进入Main之前。 如果你会C++，可以在C++里自定义一个类，然后在类的构造函数中打印一个信息。 用这个类，定义一个全局变量。 看什么时候打印出构造函数信息，就是什么时候执行的。 下面的代码供参考：  #include <iostream> using namespace std;  class abc { public: 	abc(); 	~abc();  private:  };  abc::abc() { 	cout << "abc Init" << endl; }  abc::~abc() { 	cout << "abc destroy" << endl; }  abc a; int main() { 	cout << "main" << endl; 	return 0; }


Question: 指针新手求问大神个问题

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

void ptr_subtraction_001 (){      int buf1[10];      int buf2[5];      intptr_t offset;      offset = buf1 - buf2;      sink = offset; } 从这几条语句看不出问题来，offset就是得到buf1和buf2的便宜量，可能的值是10 * 4 = 40个字节；是不是代码没有贴全？

void ptr_subtraction_002 () {     int x= 10;     int *ptr = &x;     int *buf = (ptr);     *buf = 20; /*重写x变量的值*/ } 这样写没问题，就是将变量x的值由10改成20，就是用20覆盖原来的10.


Question: C语言结构体数组定义

这个就是C语言的位段定义啊！ 在C语言教程里，在数据结构那段里呢

这个定义是位域的定义。

位域  ： 为了节省内存    不如int 占4个字节 32位   ，int（1）， 00000000 00000000 00000000 00000001 ，只占最后一位，，其他高位全是0 ，我们可以把高位的空间分配给其它量

后面是位数 占几位....

位域，就是把一个字节分（8位）成几个块，每块占几位。

仅供参考：#include <stdio.h> #pragma pack(push,1) union U {     unsigned char byte;     struct BF {         unsigned int b0:1;//a         unsigned int b1:1;//b         unsigned int b2:1;//c     } bf; } u; #pragma pack(pop) unsigned char bt; int a,b,c; int main() {     for (bt=0;bt<8;bt++) {         u.byte=(unsigned char)bt;         a=u.bf.b0;         b=u.bf.b1;         c=u.bf.b2;         printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);     }     for (c=0;c<2;c++)     for (b=0;b<2;b++)     for (a=0;a<2;a++) {         u.bf.b0=a;         u.bf.b1=b;         u.bf.b2=c;         bt=u.byte;         printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);     }     return 0; } //byte 0x00 -- c:0 b:0 a:0 //byte 0x01 -- c:0 b:0 a:1 //byte 0x02 -- c:0 b:1 a:0 //byte 0x03 -- c:0 b:1 a:1 //byte 0x04 -- c:1 b:0 a:0 //byte 0x05 -- c:1 b:0 a:1 //byte 0x06 -- c:1 b:1 a:0 //byte 0x07 -- c:1 b:1 a:1 //c:0 b:0 a:0 -- byte 0x00 //c:0 b:0 a:1 -- byte 0x01 //c:0 b:1 a:0 -- byte 0x02 //c:0 b:1 a:1 -- byte 0x03 //c:1 b:0 a:0 -- byte 0x04 //c:1 b:0 a:1 -- byte 0x05 //c:1 b:1 a:0 -- byte 0x06 //c:1 b:1 a:1 -- byte 0x07   C Bit Fields In addition to declarators for members of a structure or union, a structure declarator can also be a specified number of bits, called a “bit field.” Its length is set off from the declarator for the field name by a colon. A bit field is interpreted as an integral type.   Syntax  struct-declarator :  declarator type-specifier declarator opt : constant-expression  The constant-expression specifies the width of the field in bits. The type-specifier for the declarator must be unsigned int, signed int, or int, and the constant-expression must be a nonnegative integer value. If the value is zero, the declaration has no declarator. Arrays of bit fields, pointers to bit fields, and functions returning bit fields are not allowed. The optional declarator names the bit field. Bit fields can only be declared as part of a structure. The address-of operator (&) cannot be applied to bit-field components.   Unnamed bit fields cannot be referenced, and their contents at run time are unpredictable. They can be used as “dummy” fields, for alignment purposes. An unnamed bit field whose width is specified as 0 guarantees that storage for the member following it in the struct-declaration-list begins on an int boundary.   Bit fields must also be long enough to contain the bit pattern. For example, these two statements are not legal:  short a:17;        /* Illegal! */ int long y:33;     /* Illegal! */  This example defines a two-dimensional array of structures named screen.   struct  {     unsigned short icon : 8;     unsigned short color : 4;     unsigned short underline : 1;     unsigned short blink : 1; } screen[25][80];  The array contains 2,000 elements. Each element is an individual structure containing four bit-field members: icon, color, underline, and blink. The size of each structure is two bytes.  Bit fields have the same semantics as the integer type. This means a bit field is used in expressions in exactly the same way as a variable of the same base type would be used, regardless of how many bits are in the bit field.   Microsoft Specific —>  Bit fields defined as int are treated as signed. A Microsoft extension to the ANSI C standard allows char and long types (both signed and unsigned) for bit fields. Unnamed bit fields with base type long, short, or char (signed or unsigned) force alignment to a boundary appropriate to the base type.  Bit fields are allocated within an integer from least-significant to most-significant bit. In the following code   struct mybitfields {     unsigned short a : 4;     unsigned short b : 5;     unsigned short c : 7; } test;  void main( void ); {     test.a = 2;     test.b = 31;     test.c = 0; }  the bits would be arranged as follows:  00000001 11110010 cccccccb bbbbaaaa  Since the 8086 family of processors stores the low byte of integer values before the high byte, the integer 0x01F2 above would be stored in physical memory as 0xF2 followed by 0x01.  END Microsoft Specific

一个字节是8位，column占5位，row占3位。两个字段总共占8位，即一个字节。

位域               。


Question: stack和dqueue的底层是什么

感谢各位大神

数据结构啊。

如果你指的是标准库的stack和queue的话，底层默认是deque，当然你也可以自己指定，比如  std::stack<int> s; // 底层是默认的deque std::stack<int, std::vector<int>> s; // 底层是vector  只要满足相应要求即可。  具体要求见 stack queue

一般而言是链表，其他的我不清楚你想问什么。

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


Question: 求助：将结构体地址作为函数形参，但在函数中无法读取内存参数

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

代码贴的不全。

已找到解决方法


Question: 求dos系统下的矢量汉字库的库文件

这里有： https://blog.twofei.com/embedded/hzk.html  TC（Turbo C）老代码（比如小游戏）最好看懂了以后，理解了算法和过程，用VC改写成Windows平台的。  楼主如果想用C玩玩图形、小游戏编程，可以了解一下EasyX，EasyX是Windows平台最简单的绘图函数库（名副其实），兼容BC和TC的绘图函数，在VC下用EasyX来编程跟在TC下编程绘图差不多是完全一样的。EasyX既可以绘图，也支持图像显示和处理。  下载一个EasyX包，里面有完整的函数手册EasyX_Help.chm，有示例。EasyX官网有很多网友上传的实例，包括游戏。  仅供参考： 用绘图语句画机器猫（初学C语言的同学必看） http://blog.163.com/tab_98/blog/static/1192409720150316223680/

C源代码:显示指定字符在指定字体中对应的由直线段和Bezier曲线段组成的笔划形状的命令行工具FontPath http://download.csdn.net/download/zhao4zhong1/6588091


Question: 萌新小白求大神解决char 与 ASCⅡ的问题

为什么不阅读printf的源代码crt\src\output.c呢？

直接用printf的%c输出即可。或者用putchar(a);也是可以的。 变量b也是可以用着两种方式打印出来。

直接输出到控制台就可以了 printf....  控制台会显示   输出试一试 实践才是验证真理的唯一标准

动手实验就好了啊 换行的那个：  printf("%c",a);  蜂鸣的那个确实是： printf("%c", beep); 就可以。

直接把你想输入的打印出来试试，用printf

很困惑，希望对你有帮助


Question: scanf

各位都是大神666

引用 2 楼 cfjtaishan 的回复:如果想获取一行里的所有字符放到缓存里，建议使用fgets函数。 scanf遇到空格就认为是下一个格式的字符了，除了%c  char buf[80]; fgets(buf, 80, stdin);   char buf[80]; fgets(buf, 80, stdin); if ('\n'==buf[strlen(buf)-1]) buf[strlen(buf)-1]=0; //去掉buf末尾的\n，如果有

scanf(“%[^\n]”,str);输入回车就代表输入完成。这样就可以输出hello word了


Question: '=' : cannot convert from 'char *' to 'char'

#include<stdio.h>  char *sm(int i,char o[20]);  int main() {     char *m;    /*定义位char *类型*/     int len=1;     char l[20]={"adasdas"};     m=sm(len,l);     printf("%s",m);     return 0; } /*该函数没有意义呢，数组名可以看成指针常量*/ char *sm(int i,char o[20]) {     char *p;     p=o;     return p; }

2楼是正确答案 不过这函数确实没啥意义 不如直接 char *m; char l[20] = {"  123"}; m = l;

不过主要错在char m;

char m; ===>char* m

数组不能传值，会自动转成相对应的指针


Question: 请教一个算法的逻辑！

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

首先肯定是构造二叉树，5个数字作叶节点，非叶节点是节表达式的值。5个数字可以1与4个的结合以及2与3个的结构两种情况。  暴力枚举： 现在是5个数字和任意4个符号组成的表达式。可选符号为6种；括号根据树结构可以明显知道的，所以不考虑括号。 5个数字的排序是A(5,5) = 120种，4个符号可重复有6^4 = 1296种。乘积大概15万*2约30万次，可怕。  递归遍历拆解： 先看1个与4个结合的情况， 循环选1个数字，循环选1个符号，求出能得到要求值的参数，再将该参数作为要求值，递归。  再考虑2个与3个结合的情况..............


Question: CodeBlocks怎么设置编辑器

参考Quake3源代码。

你说的是编译器吧，预先装好GCC或者VS，codeblocks能检测到的。 游戏开发中C++就是一个开发工具啊


Question: C语言 文件读取……

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

引用 1 楼 zjq9931 的回复:这两句不用取地址，因为数组名，本身就已经是首地址了。  		scanf("%s", stu[i].num);	//不用取地址 		scanf("%s", stu[i].name);	//不用取地址  赞同。 对于这类问题，建议楼主在写文件前，先将其输出到终端，这样可以判定写入的是什么数据。

stu[i].num已经表示num数组的首地址了，你又取地址就没必要了，直接stu[i].num就好了


Question: 新手，想问问这两者执行为什么有差异

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

楼主的代码中，修改这一处：if(s[i]>='0' && s[i]<='9') 之后，两种写法应该就是一致的了。

#include<stdio.h> #include<conio.h>  void fun(char *s) {     int i,j;      for(i=0,j = 0;s[i]!='\0';i++)         if(s[i] >= '0' && s[i]<='9')    /*此处判断有误，应该用i遍历字符串，用j存放数字。*/             s[j++]=s[i];     s[j]='\0'; }  int main(void) {     char item[80];      gets(item);     fun(item);     puts(item);     return 0; } 用gets不够安全，建议使用fgets函数代替gets

你代码有问题，改成 if(s[i]>='0' && s[i]<='9') 代码原理是把数字放到原数组，因为数字个数肯定不会大于所有字符个数，所以用j当统计数字字符的下标，会小于等于i最后添加个尾零，输出。

不好意思，刚才楼上的解答严重有问题。 s[j++]=s[i]; 可以拆分成两步，第一步是s[j] = s[i]，第二步是j++，就相当于if(s[j]>='0' && s[i]<='9')这个条件下有两步要执行。  楼主写成下面这样，就表示if(s[j]>='0' && s[i]<='9')这个条件下有只有s[j] = s[i]这一句了。  for(i=0,j=0;s[i]!='\0';i++，j++)         if(s[j]>='0' && s[i]<='9')           s[j]=s[i];

做了一下调试： 下面的代码输出的是原封不动的数组。  #include<stdio.h> #include<conio.h> void fun(char *s) { 	int i,j; 	for(i=0,j=0;s[i]!='\0';i++) 	{ 		if(s[j]>='0' && s[i]<='9') 			s[j]=s[i]; 			j++; 	}	 	s[j]='\0'; } void main() { 	char item[80]; 	gets(item); 	fun(item); 	puts(item); }  但是下面的代码会只输出数字字符：  #include<stdio.h> #include<conio.h> void fun(char *s) { 	int i,j; 	for(i=0,j=0;s[i]!='\0';i++) 	{ 		if(s[j]>='0' && s[i]<='9') 			s[j++]=s[i]; 	}	 	s[j]='\0';  } void main() { 	char item[80]; 	gets(item); 	fun(item); 	puts(item); }  做对比就应该清楚：s[j++]=s[i]; 执行的是j++，再执行的是赋值。


Question: C++指针问题  超级简单的 求大佬解释一下

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

链表操作，end_ptr这个缺少定义，这个链表是尾插法，即每次新节点都是在链表的尾部插入链表。end_ptr是指向尾节点。

这个应该是链表操作吧？你可以去看看c语言关于链表的实现

这个得问出来，哪里不明白。


Question: 求助！链表向后循环2位如何算？


Question: C语言调用java JNI_CreateJavaVM只能调用一次

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

这是我的执行结果，除了第一条执行了jar包中的代码，之后的两条都没有执行


Question: C调用java JNI_CreateJavaVM只能调用成功一次

在执行c调用java的过程中只要执行一次JNI_CreateJavaVM，结束之后在执行DestroyJavaVM，不要把JNI_CreateJavaVM执行多次

你好，关于用jni调用java虚拟机，JNI_CreateJavaVM后，DestroyJavaVM，然后在JNI_CreateJavaVM出错了，返回-1，这个要怎么解决，还望指点一二，谢谢

因为代码开发的是dll文件 ，不能单独初始化，  我选择将java虚拟机做成静态，但是注销虚拟机这个操作就没法进行了。感谢大家的帮助，这个贴我结了！

jvm 在进程内就是只能初始化一次的， 你把jvm寄宿从功能调用中分离出来单独初始化

直接通过命令行调用更简单： java -jar xxx.jar param1 param2... >out.txt 其中param1等是传入的命令行参数，数据可以作为参数传入，或者作为文件名传入。 然后通过读取out.txt获取它的运行结果。

c语言通过读写临时文本文件，间接调用java写的读写相同临时文本文件并调用jar包的程序。

您好 ，   跨语言并非我所愿，只是因为需求是这样的，本来运行IBM的optim的脱敏函数接口是用C语言开发的。但是客户需要我们用他们的算法，而且不给算法我们，只给我一个jar包让我们调用，现在大部分难点都慢慢解决了 ，但是卡在c语言重复调用jar包的问题上了，希望赵老师能给我提供一点思路


Question: C双链表的逆序操作

单步跟踪程序执行，观察每一步变量变化情况，就容易理解了

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

#include<stdio.h> #include <malloc.h>  typedef struct Node {     int element;     struct Node *next; }Node;  Node * Create(int n) {     Node *head,*p,*tail,*q;     int i,x;      head = NULL;     tail = NULL;     q = NULL;     for(i=0;i<n;i++)     {         p=(Node *)malloc(sizeof(Node));         printf("输入一个数:  \n");         scanf("%d", &x);         p->element = x;         p->next = NULL;         if(NULL==head)             head = p;         else             tail->next = p;         tail = p;          if (i == n)             p->next = q;     }     return head;  } void print(Node * head) {     Node *p;     p = head;     if(!head) {         printf("链表为空！\n");     } else {         printf("如下所示：\n");         while(p) {             printf("%d ",p->element);             p = p->next;         }     }     putchar(10); }  Node * Inverse(Node * head) {     Node *p, *q, *s;      if(!head)         return NULL;      p = head;     s = head->next;     head->next = NULL;      while (s) {         q = s->next;         s->next = p;         p = s;         s = q;         /*        Node *r;         r = p;         while (r) {             printf("%d\t", r->element);             r = r->next;         }         putchar(10);         */     }      return p;  } int main() {     Node *head;     int x;     printf("链表内有几个数： \n");     scanf("%d",&x);     head = Create(x);     print(head);     head = Inverse(head);     printf("逆转后的链表为：");     print(head);     return 0; } 链表逆序，参考一下吧

弄明白了，谢谢提示！

r不是NULL，你拿个笔，纸，画画就知道了

r为什么是NULL


Question: 自定义取整数各位数函数计算错误

int divNum[4]; void intGet(int pInt) {     int i;     for (i = 0; i < 4; i++) {         divNum[i] = pInt %  10;         pInt /= 10;     } } 上面的有误，用这个吧

int divNum[4]; void intGet(int pInt) {     divNum[0] = pInt%10;     divNum[0] = pInt/10%10;     divNum[0] = pInt/100%10;     divNum[0] = pInt/1000%10; } 都把每个整数值赋值给divNum[0],这怎么可以呢。  int divNum[4]; void intGet(int pInt) {     int i;     for (i = 0; i < 4; i++)         divNum[i] = pInt % ((i + 1) * 10); } 参考一下这个。

首先, 数组序号全部都是0   再有 int divNum[4];   这个变量的位置很关键. 既然是一个函数, 并且固定是4位数.  那么你可以把这个传进去. void intGet(int *divNum,  int pInt) {     divNum[0] = pInt%10;     divNum[1] = pInt/10%10;     divNum[2] = pInt/100%10;     divNum[3] = pInt/1000%10; }