Question: 队列中入队入不进去

#include＜stdio.h＞ #include＜stdlib.h＞ typedef struct Qnode { 	int time; 	 int seq;  	char *payload; 	struct Qnode *next; }Qnode,*QueuePtr; typedef struct { 	QueuePtr front;     QueuePtr rear; }LinkQueue; void initQueue(LinkQueue &Q); void Enqueue(LinkQueue &Q,int t,int s); void Queuetraverse(LinkQueue &Q); void Dequeue(LinkQueue &Q); void initQueue(LinkQueue &Q) { 	Q.front=Q.rear=(QueuePtr)malloc(sizeof(Qnode)); 		if(!Q.front) 		exit(0); } void Enqueue(LinkQueue &Q,int t,int s) { 	QueuePtr q; 	q=(QueuePtr)malloc(sizeof(Qnode)); 	  if (!q)  		  exit(0);  	q-＞time=t;  	q-＞seq=s;   			q-＞payload=(char *)malloc(sizeof (char ));      *q-＞payload=0; 	 q-＞next=0; 	 Q.rear-＞next=q;  	 Q.rear=q; 	 //free(d.payload); } void Queuetraverse(LinkQueue &Q) { 	QueuePtr a; //	a=(QueuePtr)malloc(sizeof (Qnode)); 	a=Q.front-＞next; 	while (a) 	{ 		printf("Current RIP Packet with Timestamp:"); 		 printf("%d ",a-＞time);  		 printf("%d ",a-＞seq); 		 printf("%c\n",a-＞payload);  		 a=a-＞next; 	 }	 } void Dequeue(LinkQueue &Q) { 	QueuePtr b,t; 	 b=Q.front-＞next; 	 while (b) 	 {   	    printf("%d ",b-＞time); 	    printf("%d\n",b-＞seq); 	    t=b; 	 	b=b-＞next;   	 	free(t); 	 } } int main() { 	int num; 	int seq; 	int time,i,c; 	LinkQueue a; 	printf("请输入包数："); 	scanf("%d",&num); 	printf("请输入序号："); 	scanf("%d",&seq); 	printf("请输入时间："); 	scanf("%d",&time); 	//完成输入 	initQueue(a); 	printf("******入队*****\n"); 	for (i=0;i＜num;i++) 	{ 		int t; 	    int s;      	    t=time+i*3600; 	    s=seq+i;  	    Enqueue(a,t,s); 	    printf("Current RIP Packet with Timestamp:%d\t",t); 	    printf("CSeq:%d\t",s); 	    printf("Payload:%c\n",'0');      } 	 //完成入队 	 c=a.front-＞next-＞seq;  	 printf("神经病"); 	 printf("%d",c); 	 Queuetraverse(a);  //完成出队 	 Dequeue(a);    //释放队列 	 return 1; }

我怎么还没看懂。。。。。。。。。。。。。

初始化，入队，清队写得都有问题，我根据你的意思给改了下，你看看，数据成员上你自己再完善下： // csdn.cpp : Defines the entry point for the console application. //  #include "stdafx.h" #include<stdio.h> #include<stdlib.h> #include<crtdbg.h>  typedef struct Qnode{     int time;     int seq;     char payload;     struct Qnode *next; }Qnode,*QueuePtr;  typedef struct{     QueuePtr front;     QueuePtr rear; }LinkQueue;  void initQueue(LinkQueue &Q); void Enqueue(LinkQueue &Q,int t,int s); void Queuetraverse(LinkQueue &Q); void Dequeue(LinkQueue &Q);  void initQueue(LinkQueue &Q) {     Q.front=Q.rear=NULL; }  void Enqueue(LinkQueue &Q,int t,int s) {     QueuePtr q;      q=(QueuePtr)malloc(sizeof(Qnode));     if(!q) exit(0);      q->time=t;      q->seq=s;     q->payload= 'R';     q->next=0;      if(NULL == Q.front)     {         Q.front = q;     }     else     {         Q.rear->next=q;     }     Q.rear = q;  }  void Queuetraverse(LinkQueue &Q) {     QueuePtr a = Q.front;     while(a)     {         printf("Current RIP Packet with Timestamp:");         printf("%d,",a->time);         printf("seq=%d,",a->seq);         printf("payload=%c\n",a->payload);         a=a->next;     }  }  void Dequeue(LinkQueue &Q) {     QueuePtr b;     b=Q.front;     while(!b)     {         free(b);         b=b->next;     }   }  int _tmain(int argc, _TCHAR* argv[]) {     int num;     int seq;     int time;      printf("请输入包数：");scanf("%d",&num);     printf("请输入序号：");scanf("%d",&seq);     printf("请输入时间：");scanf("%d",&time);     //完成输入    LinkQueue a;     initQueue(a);     printf("******入队*****\n");     for(int i=0;i<num;i++)     {            int t;         int s;         t=time+i*3600;s=seq+i;         Enqueue(a,t,s);         printf("Current RIP Packet with Timestamp:%d\t",t);         printf("CSeq:%d\t",s);         printf("Payload:%c\n",'0');     }     //完成入队   int c;     c=a.front->next->seq;      printf("%d",c);      Queuetraverse(a);      //完成出队   Dequeue(a);//释放队列   _CrtDumpMemoryLeaks();     getchar();     return 0; }

引用 4 楼 IT_Blossom 的回复:paschen，您好，您说得其他两个地方我分别为它们分配了内存空间即你所说的初始化，我还有一点没明白 “while(!a) { printf("Current RIP Packet with Timestamp:");printf("%d",a->time); printf("%d",a->seq);printf("%c\n",a->payload); a=a->next; }  此时a为NULL才进入循环，而循环中a->time将对NULL指针进行访问” 这个我改为a=Q.front->next;然而程序依旧显示没有入队，这是怎么回事呢  while(!a) 表示只有a为NULL才进入循环，楼主意思是否应该是要写成while(a)

完全不明白为什么要这样用。 while(!a){...........} a是空指针，直接->解引用会发生异常 还有下面的while(!b){ b=b->next; .............}

Dequeue函数中的b 没有初始就使用了

Enqueue中的q没有初始化就使用了


Question: setbuf的问题


Question: 请教一下linux使用定时器的问题

使用pthread_mutex_lock ？


Question: 是编译的问题，还是书上的写错了

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];  关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

输出浮点数使用 %f    %d是整数类型

一楼正解，估计你的那个平均数小于1，所以就打印出0了，程序应该结构没错

打印时应当用 %f 却使用了 %d


Question: 为什么会打印出'D'来

引用 7 楼 fefe82 的回复:[quote=引用 6 楼 hijack00 的回复:] 严格来说，你的代码是错误的，应该改成下面这样 printf("%c\n", *n); 但是由于编译器进行了隐式类型转换，所以你的代码也能编译通过。  这种隐式类型转换其实也是C语言中很多怪异错误的源泉，需要程序员对C语言语言特性有深入了解。 在类型转换这一点上，C++做了一些改进（static_cast, ...），能够减少此类错误发生。  匹配 ... 的时候指针没有隐式类型转换。  这就是一个 UB 。[/quote]  我的理解是：printf里面调用了vsnprintf，遇到%c的时候会将它遇到的参数，也就是n隐式转换为一个char类型。同理，如果遇到%f，就会将n隐式转换为一个float类型。也就是说，隐式转换是根据格式字符串来的。

引用 6 楼 hijack00 的回复:严格来说，你的代码是错误的，应该改成下面这样 printf("%c\n", *n); 但是由于编译器进行了隐式类型转换，所以你的代码也能编译通过。  这种隐式类型转换其实也是C语言中很多怪异错误的源泉，需要程序员对C语言语言特性有深入了解。 在类型转换这一点上，C++做了一些改进（static_cast, ...），能够减少此类错误发生。  匹配 ... 的时候指针没有隐式类型转换。  这就是一个 UB 。

printf("%c\n",              n);       //^^ 需要一个 char    ^^提供了一个 char*

通过％x将n的地址给打出来看看，将这个值第一个字节或者最后一个字节的数取出来的数正好是‘D’的ascii码的值。

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0];

编译器不会去做这种类型检查（可变参数），所以能通过编译。为什么不做检查？因为技术上压根就做不到。format字符串在编译时可以压根不存在。比如这个format是通过读取文本内容来得到。  D是指针指向的地址，该段地址的第一个字节正好是D的acsii编码值

可以编译，因为printf是可变参数函数，参数类型编译时不会检查  输出D由于是按字符去解释这个指针的值


Question: sprintf(tmp,"%02x",sign_result[i])，tmp出来8个16位数字的问题

sprintf(tmp,"%02x",(unsigned char)sign_result[i]);

3#/4#的方法都可以。

sprintf(tmp, "%02x", sign_result[i] & 0xff);

是 tmp 还是 sign_result[i] ？  %x 是用来输出 int 的，sign_result[i] 是 int 嘛？


Question: 关于C语言的Static关键字

那就看这个：http://en.cppreference.com/w/cpp/language/static

static是存储限定符 它作用于函数时是：限定函数具有file scope，即文件作用域，在另外一个文件调用是肯定不行的，如果我没有记错的话 static作用域变量时： 看标准的示例，已经很明确了 int i1 = 1;         //definition, external linkage static int i2 = 2;  //definition, internal linkage extern int i3 = 3;  //definition, external linkage int i4;             //tentative definition, external linkage static int i5;      //tentative definition, internal linkage

全局变量，在本文件中调用

static就是将这个东西"私有化", 如果用在一个头文件里面static修饰一个全局变量. 那么每一个#include该头文件的源文件都将持有独立的全局变量, 也就是在一个源文件修改将不会影响到 其他源文件, 这个特性当然是为了免得函数/变量重名了导致链接失败.

不知所云


Question: 单链表插入！！！

引用 12 楼 YXTS122 的回复:因为p要后移，所以引入ptr来保存p当前指向的结点的地址，保存这个地址后面会用到 嗯  好的  我懂了

引用 7 楼 a7716021 的回复:[quote=引用 6 楼 a7716021 的回复:] [quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 刚才看错了 不是if 语句 是while里面    其实都是一样的 while(表达式){  }  当while 小括号里面的表达式 为真时 就会一直循环 直到表达式的值为假时 才会跳出循环  [/quote] 那ptr是一个指针吗？为什么要多一个ptr呢？

引用 9 楼 a7716021 的回复:[quote=引用 8 楼 xinye1230 的回复:] [quote=引用 7 楼 a7716021的回复:][quote=引用 6 楼 a7716021 的回复:] [quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 刚才看错了 不是if 语句 是while里面    其实都是一样的 while(表达式){  }  当while 小括号里面的表达式 为真时 就会一直循环 直到表达式的值为假时 才会跳出循环  [/quote] 那后面怎么又出来一个p->data>=data呢？是它为假跳出循环时的条件嘛？[/quote]  根据你这个代码 我感觉是对一个已有的有序链表进行有序插入，  所以需要对插入数据 进行大小判断。 前面的循环是用来定位当前数据该插入的数据， 比如你对1 3 5 7 9 这个链表要进行插入， 插入数据为6  他就先需要逐一判断 1357然后把数据插入到5和7之间，  最后的那个if 是用来判断链表末尾的，也就是说 如果你插入的数据，比链表里所有的数据都大，则把它放在最后一项。[/quote]  最后的那个if(p->data >=data) 是在循环外面的 所以不是跳出循环。（循环的有效范围是循环本身的{}  ）

引用 8 楼 xinye1230 的回复:[quote=引用 7 楼 a7716021的回复:][quote=引用 6 楼 a7716021 的回复:] [quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 刚才看错了 不是if 语句 是while里面    其实都是一样的 while(表达式){  }  当while 小括号里面的表达式 为真时 就会一直循环 直到表达式的值为假时 才会跳出循环  [/quote] 那后面怎么又出来一个p->data>=data呢？是它为假跳出循环时的条件嘛？[/quote]  根据你这个代码 我感觉是对一个已有的有序链表进行有序插入，  所以需要对插入数据 进行大小判断。 前面的循环是用来定位当前数据该插入的数据， 比如你对1 3 5 7 9 这个链表要进行插入， 插入数据为6  他就先需要逐一判断 1357然后把数据插入到5和7之间，  最后的那个if 是用来判断链表末尾的，也就是说 如果你插入的数据，比链表里所有的数据都大，则把它放在最后一项。

引用 7 楼 a7716021的回复:[quote=引用 6 楼 a7716021 的回复:] [quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 刚才看错了 不是if 语句 是while里面    其实都是一样的 while(表达式){  }  当while 小括号里面的表达式 为真时 就会一直循环 直到表达式的值为假时 才会跳出循环  [/quote] 那后面怎么又出来一个p->data>=data呢？是它为假跳出循环时的条件嘛？

引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 引用 6 楼 a7716021 的回复:[quote=引用 4 楼 xinye1230 的回复:] [quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）[/quote] 刚才看错了 不是if 语句 是while里面    其实都是一样的 while(表达式){  }  当while 小括号里面的表达式 为真时 就会一直循环 直到表达式的值为假时 才会跳出循环

引用 4 楼 xinye1230 的回复:[quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  p->data  <  data 就是把你传进来的形参数据 data  和指针p 所指向的 链表中的 数据 进行对比， 如果 p 指向的数据  小于 形参传进来的数据    则进到if语句里面（当然 p->data < data 只是其中一个条件）

引用 4 楼 xinye1230 的回复:[quote=引用 2 楼 a7716021 的回复:] 楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂[/quote]  你不懂的是p->data  <  data ? 这句么？

引用 2 楼 a7716021 的回复:楼上正解， data 根本没有被定义， e 也没有被使用， 估计是形参写错了   代码本身有问题。 把e改成data 应该就能看懂了吧  void InsertList(LinkList L,int e) en   是的  形参我打错了  但是改成data 还是不太懂

引用 1 楼 qq423399099 的回复:你确定你的第二个参数是int e而不是int data? PS:而且21行少了个= 嗯  是的  void InsertList(LinkList L,int data)


Question: c语言  静态  内部链接


我也想要一个

禁止win10更新已经快成为windows开发者的常识了！

引用 3 楼 luciferisnotsatan的回复:都win10了，还用vc6。 想要继续用vc6，win10上装个虚机，虚机里装win98，然后win98上装vc6 装了虚拟机感觉电脑要爆掉

用vs2013及以上。或者codeblocks,codelite,qt.全部免费好用

想办法用英文版的msdev.exe替换中文版的msdev.exe

用命令行方式使用VC6试试？ msdev myproj.dsw /MAKE "myproj - Win32 Debug" /REBUILD

换成VS http://blog.csdn.net/cometnet/article/details/19551125

不要用VC6，珍爱生命，远离VC6


Question: C语言新手，为什么i还是1

因为sizeof不是函数，其在编译期就确定了，而不是地运行期计算，所以你根本没有执行到++i


Question: gets放置位置问题

引用 10 楼 luciferisnotsatan 的回复:[quote=引用 9 楼 Nick_gcmh 的回复:] [quote=引用 7 楼 luciferisnotsatan 的回复:] 编译器太老，或者你设置编译器使用C89标准。 C89标准里规定要放最前面。C99标准里，变量声明可以不用放在最前面。 我是网上直接下的VC6....是不是版本过低,有什么好的版本推荐下吗？谢谢~[/quote] vs201x版本的都没问题。[/quote] 多谢啦，我待会去下载试下。

编译器问题，变量声明语句必须在其他语句前面

引用 9 楼 Nick_gcmh 的回复:[quote=引用 7 楼 luciferisnotsatan 的回复:] 编译器太老，或者你设置编译器使用C89标准。 C89标准里规定要放最前面。C99标准里，变量声明可以不用放在最前面。 我是网上直接下的VC6....是不是版本过低,有什么好的版本推荐下吗？谢谢~[/quote] vs201x版本的都没问题。

引用 7 楼 luciferisnotsatan 的回复:编译器太老，或者你设置编译器使用C89标准。 C89标准里规定要放最前面。C99标准里，变量声明可以不用放在最前面。 我是网上直接下的VC6....是不是版本过低,有什么好的版本推荐下吗？谢谢~

引用 3 楼 lzhui1987 的回复:编译器问题，变量声明语句必须在其他语句前面 多谢回答！

引用 2 楼 weixin_29983527 的回复:你的编译器太古老了，更新吧 多谢啦！

引用 2 楼 weixin_29983527 的回复:你的编译器太古老了，更新吧 请问用什么编译器较好？我用的好像是Vc6...

引用 1 楼 user-4 的回复:C语言要求变量声明在函数开关，C++下则没问题 谢谢答复

你的编译器太古老了，更新吧

C语言要求变量声明在函数开关，C++下则没问题


Question: 关于scanf的问题

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 3 楼 loveqise的回复:引用 1楼paschen 的回复:显然越界了，不要用不出错来证明是对的重要的是num 20我没有初始化，按照正常来说应该指向一个未知区域，数值未知。可是每次程序运行都正常，正好点击我输入的第二十一个字母 因为你的输入把不属于你的内存给覆盖了

引用 2楼小灸舞 的回复:越界并不等于程序崩溃。 如果你越界写入的地方并没有重要信息或者被别的变量占用，一般程序是不会崩溃的。重要的是num 20我没有初始化，按照正常来说应该指向一个未知区域，数值未知。可是每次程序运行都正常，正好是我输入的第二十一个字母

显然越界了，不要用不出错来证明是对的


Question: 求高手看看，C语言，判断式子里的圆括号是否配对，利用链栈方法，遇到‘（’进栈，遇到‘）’出栈，最后判断‘（’栈中是否是空，空则对称，但一直运行不出，快疯了！！

#include＜stdio.h＞   #include＜stdlib.h＞   typedef struct node { 	char ch;   	 struct node *next; }linkstack;   int judgeemply(linkstack *s ) {     	if (s-＞next==NULL)            	return 1; 	else 	    return 0; }   linkstack *setstack() {     	 linkstack *s;     	 s=(linkstack*)malloc (sizeof (linkstack));      	 s-＞next=NULL;      	return s; }   	linkstack *pushu(linkstack *s,char  a) {    	 linkstack *p;     	p=(linkstack*)malloc(sizeof (linkstack));     	       p-＞ch=a;           p-＞next=s;       s=p;           return s; }          linkstack *popstack(linkstack *s) {           linkstack *p;           p=s;       s=s-＞next;       free(p);          return s; }     void Judgepair(linkstack *s) { 	char c;           linkstack *p;           p=(linkstack*)malloc(sizeof (linkstack));       printf("Please input ico fanishi '#'\n");           c=getchar();           while (c!='#')          {               switch(c)     {           case'(':                   p=pushu(p,c);                break;        case')':                {                        if (judgeemply(p))                     {             	printf("YES\n");         	}                 	  else       	      p=popstack(p);                 }          }              c=getchar();          } 	if (judgeemply(p))            	  printf("YES\n");          else             printf("NO\n"); }    int main() { 	linkstack *p;         p=setstack();        Judgepair(p);    return 0; }

引用 5 楼 iamyuqy的回复:这个问题的原题应该不是必须采用堆栈方法吧，很多公司的中初级程序员都会考这道题，直接使用一个变量是不是就能很快的搞定了，遇到 ‘(’ 加一，遇到 ‘)’ 减一，while循环中如果发现数字被减翻的时候退出当前循环，最后检查如果该变量不是0返回错误就行了。 谢谢提醒 但题目要求是用栈

仅供参考：#include<stdio.h> #include<malloc.h> #include<string.h> #define STACK_INIT_SIZE 10 #define STACK_GROW_SIZE 5 #define ELEMTYPE char #define OK 1 #define ERROR 0 typedef struct { /*建立一个栈的首结点*/     ELEMTYPE * base;     ELEMTYPE * top;     int stacksize; } SpStack; int InitStack(SpStack *s) { /*建立空的栈并返回首地址*/     s->base=((ELEMTYPE*)malloc(STACK_INIT_SIZE*sizeof(ELEMTYPE)));     if (!s->base) return ERROR;     s->top=s->base;     s->stacksize=STACK_INIT_SIZE;     return OK; } int StackEmpty(SpStack *s) { /*判断栈是否为空*/     if (s->top==s->base) return OK;     else                 return ERROR; } int Push(SpStack *s,ELEMTYPE e) { /*往栈顶插入元素即进栈*/     if (s->top-s->base>=s->stacksize) { /*判断是否栈满*/         s->base=((ELEMTYPE*)realloc(s->base,(s->stacksize+STACK_GROW_SIZE)*sizeof(ELEMTYPE)));         if (!s->base) return ERROR;         s->stacksize+=STACK_GROW_SIZE;         s->top=s->base+s->stacksize;     }     *s->top++=e;     return OK; } int Pop(SpStack *s,ELEMTYPE *e) { /*让栈顶元素依次输出即出栈*/     if (StackEmpty(s)) return ERROR;     *e=*(--s->top);     return OK; } int Comp(ELEMTYPE a,ELEMTYPE b) {     if ((a=='('&&b!=')')       ||(a=='['&&b!=']')       ||(a=='{'&&b!='}')) {         return ERROR;     } else return OK; } int Count(SpStack *s) {     ELEMTYPE e[STACK_INIT_SIZE*2];     ELEMTYPE e1;     int i;      InitStack(s);     fgets(e,STACK_INIT_SIZE*2,stdin);     if ('\n'==e[strlen(e)-1]) e[strlen(e)-1]=0;     printf("%s\n",e);     for (i=0;e[i]!='\0';i++) {         switch (e[i]) {         case '(':         case '[':         case '{':             Push(s,e[i]);             break;         case ')':         case ']':         case '}':             if (StackEmpty(s)) {                 printf("%*s↖右括号多余\n",i+1,"");                 return(ERROR);             } else Pop(s,&e1);             if (!Comp(e1,e[i])) {                 printf("%*s↖左右匹配出错\n",i+1,"");                 return(ERROR);             }         }     }     if (!StackEmpty(s)) {         printf("%*s↖左括号多余\n",i,"");         return(ERROR);     } else {         printf("匹配正确\n");         return(OK);     } } void main() {     SpStack s;     Count(&s);     free(s.base); }

非常感谢大家的慷慨帮助，我是计算机专业的，但感觉编程有点吃力，可又不想白白浪费大学时光，所以我把程序发上来，希望能得到大神们的指点。 我现在 又改了思路，我的思路是这样的，扫描输入的字符，当发现“（”时把其输入栈p中，“（”都入栈后，再扫描“）”，发现一个“）”就把栈p里的“（”出栈，再扫描“）”之前要判断栈p是否为空，若为空，breeak结束扫描，因为一个左括号配对一个右括号，所以我给扫描这两个括号各一个计算器i和j，最后判断p是否为空且i与j是否相等，若满足，就是对称的，若不满足就是不对称的。代码如下，但都是只输出YES, #include<stdio.h> #include<stdlib.h> typedef struct node{     char ch;     struct node *next; }linkstack; int judgeemply(linkstack *s) {     if (s->next == NULL)         return 1;     else         return -1; } linkstack *setstack() {     linkstack *s;     s = (linkstack*)malloc(sizeof(linkstack));     s->next = NULL;     return s; } linkstack *pushu(linkstack *s, char a) {     linkstack *p;     p = (linkstack*)malloc(sizeof(linkstack));     p->ch = a;     p->next = s->next;     s->next = p;     return s; } linkstack *popstack(linkstack *s) {      linkstack *p;     p = s->next;     s->next = p->next;     free(p);     return s;  } void Judgepair(linkstack *p) {     char c;int i=0,j=0;    // linkstack *p = (linkstack*)malloc(sizeof(linkstack));     printf("Please input ico fanishi '#'\n");     c = getchar();     while (c != '#')     {         switch (c){         case'(':            {                p = pushu(p, c);                i++;             break;            }         case')':         {                    j++;                    if (judgeemply(p))                           break;                    else                        p = popstack(p);         }         }         c = getchar();     }     if (judgeemply(p))         printf("YES\n");     else         printf("NO\n"); } void main() {     linkstack *p;     p = setstack();     Judgepair(p); } 可能我的代码很白痴，希望能得到大神们的指点指点，谢谢谢谢

错误是由于你的Judgepair函数里linkstack *p;没有初始化引起的，应该改成linkstack *p = (linkstack*)malloc(sizeof(linkstack)); 而且你的逻辑我也不是很看的懂，最好学会自己单步调试 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  #include<stdio.h> #include<stdlib.h> typedef struct node{ 	char ch; 	struct node *next; }linkstack; int judgeemply(linkstack *s) { 	if (s->next == NULL) 		return 1; 	else 		return -1; } linkstack *setstack() { 	linkstack *s; 	s = (linkstack*)malloc(sizeof(linkstack)); 	s->next = NULL; 	return s; } linkstack *pushu(linkstack *s, char a) { 	linkstack *p; 	p = (linkstack*)malloc(sizeof(linkstack)); 	p->ch = a; 	p->next = s->next; 	s->next = p; 	return s; } linkstack *popstack(linkstack *s) { 	linkstack *p; 	p = s->next; 	s->next = p->next; 	free(p); 	return s; } void Judgepair(linkstack *s) { 	char c; 	linkstack *p = (linkstack*)malloc(sizeof(linkstack)); 	printf("Please input ico fanishi '#'\n"); 	c = getchar(); 	while (c != '#') 	{ 		switch (c){ 		case'(': 			p = pushu(p, c); 			break; 		case')': 		{ 				   if (judgeemply(p)) 				   { 					   printf("NO\n"); 				   } 				   else 					   p = popstack(p); 		} 		} 		c = getchar(); 	}if (judgeemply(p)) 		printf("YES\n"); 	else 		printf("NO\n"); } void main() { 	linkstack *p; 	p = setstack(); 	Judgepair(p); }

if(judgeemply(p)) 这句里的p可能会出现没初始就使用的情况


Question: c语言的编程清晰与资源利用的思路，是不是可行？这方面以前就想到过，现在觉得比较有必要，但好像关心的不多。

主贴中下面的描述  malloc 失败 retvar=-1 用 goto 跳转到 1号代码段结束  不准确，应改为  malloc 失败 retvar=-1 用 goto 跳转到 函数代码段结束

引用 2 楼 anhuizhuanjiao 的回复:年轻人，多看书，少空想，这种思路是已经被C++淘汰N久的东西了，auto_ptr 引用 2 楼 anhuizhuanjiao 的回复:年轻人，多看书，少空想，这种思路是已经被C++淘汰N久的东西了，auto_ptr    我用c++编过一些程序，我的意思是在尽可能用简单的技术情况下实现尽可能自动化的快速的资源释放，同时几乎是“硬性地”保持代码结构清晰，而且自动化很重要，这样的思路基本天然具有资源尽量快速自动释放的要求，我看了一段新的智能指针 unique_ptr 的好象是比较有权威性的代码，    memobj1 new  memobj2 new  。。。。。。。。。   memobj2 move from memobj1    //此处比较隐蔽地释放开始时 memobj2 的资源 但是把 memobj2 的衣服套在了 menobj1 所代表的资源上，而 memobj1 的衣服不再被需要了  这时开始时 memobj1 所分配的资源还在        所以  memobj1  存续期是完全包含 memobj2 的存续期，这与我说的犬牙交错，即内部对象突破包含它的外部对象的作用范围的情况不符。由于是比较权威的发布，所以我觉得智能指针设计的本意重心可能并不是为了平衡代码清晰与资源尽量及时释放的冲突，可能重点是为了防止内存泄漏以及多线程资源并发访问类似的问题的。  我用  unique_ptr 大概写了一段伪代码，来演示怎么应对内部对象突破包含它的外部对象的作用范围的情况，还要使代码尽量清晰，资源尽量及时释放。     memobj1 new  memobj2 new  。。。。。。。。。   memobj1 move from memobj2    //此处比较隐蔽地释放开始时 memobj1 的资源 但是把 memobj1 的衣服套在了 menobj2 所代表的资源上，而 memobj2 的衣服不再被需要了 memobj2 delete  做一个伪代码,提示 memobj2 的衣服不再被使用，从而使代码尽量清晰。  memobj1 delete    //此处比较隐蔽地释放开始时 memobj2 的资源 但是 memobj2 的资源披上了 menobj1 的衣服，从而使代码尽量清晰    可以看出，这样的代码与用类似 c语言 代码比较基本并没有什么比较大的简洁性，面向对象的特性使对象在到达作用范围之外被析构并释放资源，但如果在作用范围内，还是需要手动释放资源的，也没什么自动性，我的意思是能用简单的工具就尽量用简单的工具，    我再比较详细地用类似c语言的代码演示怎么应对内部对象突破包含它的外部对象的作用范围的情况：     memvar1 malloc  在memvar1中找一个字符串 str1  如果找到 str1 那么  		 memvar2 malloc 		 memvar2     被注入 一个文件名 ，文件名所标示的文件被 注入 memvar1 的内容， 		 memvar3=memvar2 memvar2=memvar1 memvar1=memvar3 		 这时 memvar1 占用的资源不再被需要了，但为了代码的简洁明晰，交换 memvar1 与 memvar2 的值，并进行下面的操作 		 memvar2 free      由于前面的交换， memvar2 的本质是 memvar1 ,即 memvar1 穿着 memvar2 的衣服向系统提出释放自己占用的资源 这样一来及时地释放了 memvar1 所占用的资源，又使代码结构清晰  memvar1 free  由于前面的交换， memvar1 的本质是 memvar2 ,即 memvar2 穿着 memvar1 的衣服向系统提出释放自己占用的资源 这样一来及时地释放了 memvar2 所占用的资源，又使代码结构清晰    代码层面 内部对象 不涉及到外部，有面相对象的意味，尽量平衡节省资源与代码清晰易懂之间的冲突。

引用 1 楼 zhao4zhong1 的回复:请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。   我觉得编程的目的基本是实现一个目标，在尽量减少错误与尽量快速应用并推向市场等等等等类似的事情这样两个目标之间我的想法是尽量减少错误，我提出的思路可能开发速度比较慢，所以可能需要很多人稳妥地按照这样的思路开发，如果人够多，并能稳妥运用这样的方法（当然方法也许还有改进），应该能以非常稳定的速度源源不断地持续生产出比较好的产品。这种思路好像八股文，但是这是在尽量平衡追求收益与减少损失之间的冲突。 性能问题我觉得这样的思路开发主要是开发的速度慢，程序运行的速度可能会受一些影响，但是如果还要提高速度，那应用的技术可能会是比较极端的技巧了，这样极端的技术那基本就适合在画面效果非常非常好的游戏这样的程序中运用了，在工厂医院这样的场所应用的软件我觉得不适合应用太极端极致的技巧，往深里说多备份系统可能能缓解极端的技巧所带来的可能的副作用，这样就引入了新的思路，可以另外讨论。


Question: lseek 参数

引用 10 楼 wdkcbang 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] 搜“使用gdb调试”  可这是个系统调用，那我岂不是还得编译ubuntu内核，开内核hacker，然后阅读内核代码，找对应的驱动，才能设置正确的断点。然后应该是kgdb吧，还要有两条电脑，一台作为目标机，单步跟到猴年马月了。。[/quote] 只为成功找方法，不为失败找理由。

搜“使用gdb调试”

引用 6 楼 zhao4zhong1 的回复:对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  哈哈，初始发帖，竟然看到赵老师的经典回复。不过我实话实说，普通的磁盘文件操作，汇编不会，ubuntu内核断点调试更不会，要单步调试看结果感觉基本不可能。

引用 2 楼 paschen 的回复:你从文件头偏移一个负的距离没有意义吧，传参过程中不会转换成其他类型，如果函数实现中可能会根据不同情况采取不同操作  是的，我猜错了，打印返回值，根据返回值，的确没有被转换，是被特殊处理了，但是不明白为何特殊处理了int和long型的参数，使用-10000l就会正常返回-1. 就是普通的文件操作，对应的是磁盘驱动。

引用 9 楼 zhao4zhong1 的回复:搜“使用gdb调试”  可这是个系统调用，那我岂不是还得编译ubuntu内核，开内核hacker，然后阅读内核代码，找对应的驱动，才能设置正确的断点。然后应该是kgdb吧，还要有两条电脑，一台作为目标机，单步跟到猴年马月了。。

错了，是产生一个 4.3G 的文件。如果使用 -10000l 就没有问题，会返回-1，打印errno是参数错误。如果是-10000就会被转换成无符号int。

引用 2 楼 paschen 的回复:你从文件头偏移一个负的距离没有意义吧，传参过程中不会转换成其他类型，如果函数实现中可能会根据不同情况采取不同操作  你可以试试，ubuntu12.04 64位下，会产生一个3.4G的文件，按理说应该是参数错误，返回-1才对。

引用 1 楼 user-3 的回复:为什么会认为隐式转换为long long? 那也应该用llseek, 而不是lseek  因为参数原形是long long，传一个int，难道不是应该转换为long long吗？我写一个简单的函数，就可以打印值，而且打印的是一样的，  void long_long(long long a) {     printf("a %lld \n", a); }  int mainL() {     long_long(-10000);     long_long(-10000l); }  但是我用 lseek(fd, -10000, SEEK_SET); 就会产生一个3.4G的文件，显然-10000被传到驱动后变成了无符号int，用-10000l就没有问题。系统是ubuntu12.04 64 位，不知道什么原因。  至于你说的llseek也是一样的结果啊，SEEK_SET应该不接受负值才对。


Question: 如果不涉及数组/指针越界的话,栈有没有可能损坏?

x86上调用约定不一样也会, 不过这个调试模式下, 也是函数返回时直接报错, 错误信息也是非常清楚..

其实都是越界操作, 越界操作还不算啥, 这可能修改到已存在的数据, 很难检查出来. #include <iostream> #include <functional>  auto f() {     int a = 0;     return std::function<void()>([&]() { a = 1; }); }  auto test(std::function<void()> func) {     int tmp[10] = { 0 };     func(); }  int main() {     test(f());     return 0; }

无限递归会导致栈溢出

struct big_struct {     int a[1000000]; // 足够大 };  void func (struct big_struct param) {     return; }  在某些调用协议、CPU、编译器下，如果 sizeof(struct big_struct) 足够大，返回的时候堆栈会直接坏掉。


Question: 用scanf把值赋给指针指向的值，提示出错

引用 1 楼 Rewen 的回复:和编译器有关吧。  你可以写在一个函里面试试看，比如  abc(){     int  x  = 0;   int *p  = &x;   scanf("%d", p); }  我看很多编译器是不会报错的。 我用的Code::Blocks 16.01， 把你的代码运行了一下没有问题，加上printf打印也没有问题……  引用 1 楼 Rewen 的回复:和编译器有关吧。  你可以写在一个函里面试试看，比如  abc(){     int  x  = 0;   int *p  = &x;   scanf("%d", p); }  我看很多编译器是不会报错的。 谢谢……我用的codeblocks，后来仔细一看是一个逗号标错位置了……改了一下好了……不好意思


Question: C语言抽象语义树(AST)的构建

我记得 VS 里，在函数名字上右键，有一个 View Call  Hierarchy 的选项

参考Tiny C Compiler源代码相关片断？


Question: WriteProcessMemory参数只能一个字节 ？

我看的是win32汇编程序设计 用的它的例子  地址正确 目标可写 汇编定义 db   字节数改了 也不行

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

BOOL WINAPI WriteProcessMemory(   _In_  HANDLE  hProcess,   _In_  LPVOID  lpBaseAddress,   _In_  LPCVOID lpBuffer,   _In_  SIZE_T  nSize,   _Out_ SIZE_T  *lpNumberOfBytesWritten );   Parameters  hProcess [in]      A handle to the process memory to be modified. The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process. lpBaseAddress [in]      A pointer to the base address in the specified process to which data is written. Before data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for write access, and if it is not accessible, the function fails. lpBuffer [in]      A pointer to the buffer that contains data to be written in the address space of the specified process. nSize [in]      The number of bytes to be written to the specified process. lpNumberOfBytesWritten [out]      A pointer to a variable that receives the number of bytes transferred into the specified process. This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is ignored.   nSize参数为写入的字节数，你代码里不是1吗，当然只会写入一个

1.确定0x0040101F地址有效 2.确定目标内存可写 3.用倒数第二个参数指定要写入的字节数

先调用VirtualProtect()修改页面属性为可写

倒数第二个参数，你设置成1了。 当然只能写一个字节。  BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesWritten );  nSize 应该 = sizeof(lpBuffer）的。


Question: 【高手】中文标点符号或者全角字符和十六进制的相互转换（c语言）

有utf8编码的字符串与十六进制之间转换的示例吗？

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

引用 3 楼 u013283985 的回复:有utf8编码的字符串与十六进制之间转换的示例吗？ 上面代码中44～63行用于utf8编码的字符串毫无违和感。


Question: 很简单，创建一个单向链表------------------------------------------

（1）  insert(name,mark);   (2) t->next != NULL; t= t->next  (3)  p = (link *) malloc( sizeof(link));  (4) p->next = NULL;  (5)  p->next = head;


Question: 多进程使用共享内存出现errno.22 is: Invalid argument,求解答!

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


Question: 写单链表时，为什么传入结构指针不可以初始化，而对于插入删除时传入结构指针却可以改变其值？

因为你的InitList函数是要在函数内改变指针的指向，所以必须传二级指针或者一级指针的引用才行。 而一般的InsertList或者DeleteList都仅仅只需要改变指针所指向的值，传一级指针就够了

引用 5 楼 DBZ002 的回复:[quote=引用 3 楼 paschen 的回复:] 你需要这样写；   void InitList (Linklist* L) {     	*L =(Linklist)malloc(sizeof(Node)); 	//............... }   否则你是按值传递，函数中的参数只是一个复制品，你申请到的内存也是给一个复制品的，并不会对函数外的变量有影响   自己好好体会一下那为什么做插入删除会影响呢？[/quote]  那你提供你插入删除的代码

引用 2 楼 dustpg 的回复:请把一个文件夹的一个快捷方式复制到桌面上, 然后属性中重定向到另一个文件夹. 请问原来那个文件夹有任何修改么  请把一个文件夹的一个快捷方式复制到桌面上, 然后双击进去该文件夹, 新建一个文件 请问原来那个文件夹有任何修改么貌似没有解决我的问题，大神所说的我明白。

引用 3 楼 paschen 的回复:你需要这样写；   void InitList (Linklist* L) {     	*L =(Linklist)malloc(sizeof(Node)); 	//............... }   否则你是按值传递，函数中的参数只是一个复制品，你申请到的内存也是给一个复制品的，并不会对函数外的变量有影响   自己好好体会一下那为什么做插入删除会影响呢？

引用 1 楼 user-4 的回复:引用而对于插入删除时传入结构指针却可以改变其值  改变不了“其值”。 改变的是它指向的东西。谢谢纠正


Question: a bullet with your name, a ticking time grenade

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


Question: leetcode5. Longest Palindromic Substring的C实现

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

引用 5 楼 user-2 的回复:[quote=引用 3 楼 yang1018679 的回复:] [quote=引用 1 楼 user-2 的回复:] 如果字符串为空，那么将会malloc 0 大小内存，而这是一个未定义行为  也不行，刚才加了个if判断语句，还是卡在同样的testcase上[/quote]  检查使用分配到的内存是否会越界  char *sp = (char *)malloc(sizeof(char) * (len / 2));   这句有没有考虑 len 为奇数的情况是否会越界  另外，动态分配的内存记得free是一个好的习惯[/quote] 问题已解决。在expand()中给str分配空间是应该是2*len + 3，多出来的一个用来存储字符串结束符'\0'。 len/2 不会越界，因为str原先长度为2*len + 2，此处除以2之后为len+1，必然大于最长回文子串长度。 结束时的确应该释放掉str，谢谢提醒。

引用 3 楼 yang1018679 的回复:[quote=引用 1 楼 user-2 的回复:] 如果字符串为空，那么将会malloc 0 大小内存，而这是一个未定义行为  也不行，刚才加了个if判断语句，还是卡在同样的testcase上[/quote]  检查使用分配到的内存是否会越界  char *sp = (char *)malloc(sizeof(char) * (len / 2));   这句有没有考虑 len 为奇数的情况是否会越界  另外，动态分配的内存记得free是一个好的习惯

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

引用 1 楼 user-2 的回复:如果字符串为空，那么将会malloc 0 大小内存，而这是一个未定义行为  也不行，刚才加了个if判断语句，还是卡在同样的testcase上

也不行，刚才加了个if判断语句，提交还是失败

如果字符串为空，那么将会malloc 0 大小内存，而这是一个未定义行为


Question: 关于C/C++中函数形参和局部变量地址分配的问题

对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）

这种东西都是编译器看情况处理，没有规定一定要按照某种规则。 所以挨着还是不挨着没啥关系。

引用 2 楼 pengzhixi 的回复:在i和a之间还需要保存 函数的返回地址，旧的ebp值和一些必要的寄存器值。 函数的返回地址和寄存器的值是保存在形参和局部变量之间吗？我之前看过一些资料是说压栈顺序分别是： 寄存器值->函数返回地址->函数返回值->形参->局部变量，所以一直以为形参和局部变量地址是紧挨着的？

看了汇编代码，虽然不怎么懂，但是还是看了些端倪，linux中每次都是先压入形参，然后再预留20个字节存放函数的返回地址和返回值，最后在存入局部变量，windows系统可能预留的字节数不一样，但是原理大同小异。

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

看汇编压入栈的内容，还会有函数的返回地址等

在i和a之间还需要保存 函数的返回地址，旧的ebp值和一些必要的寄存器值。

看汇编  看看他们都在哪


Question: 输入数据之后程序没有反应是什么情况 求指点

设了断点但是调试不了  一运行输入之后程序就没反应了

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

内存循环是 j =0 ，而不是 i = 0

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


Question: 大神们 这是判断字符串对称的函数 现小弟想变成可以输入任意长度的字符串的函数，怎么改啊？（这个函数现在只能判断4个字符）

引用 1 楼 user-1的回复:如果必须用数据结构的话，建议用顺序栈，涟栈太复杂了，任意大小字符串只是代表栈的字符串数组的大小而已！ 谢谢提醒 现在已经搞出来了


Question: 请问如何用头插法创建一个链表？

3楼代码应该加一句： // ©zhao4zhong1版权所有

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

#include<iostream>  #include<malloc.h> using namespace std;  typedef struct Node { 	int data; 	Node *next; }Lnode,*List;  int Allocate(List &p) //必须要有引用，否则指针p分不到内存空间  {   p=(List)malloc(sizeof(Lnode));   p->next=NULL;   return 0; }  int HeadCreatlist(List p1)  //头插法  {   List s;     Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   s->next=p1->next;   p1->next=s;   return 0; }  int TailCreatlist(List &p3) //尾插法  {   List s;    Allocate(s);   cout<<"Please input the data"<<endl;   cin>>s->data;   p3->next=s;   p3=s;   return 0; }  int Travellist(List P) //遍历函数  {   List p=P->next;   while(p!=NULL)   {   	cout<<p->data<<" ";   	p=p->next;   }   return 0; }  int main() {   List p1;   int i;   Allocate(p1);   for(int i=0;i<4;i++)   HeadCreatlist(p1);   Travellist(p1); //头插法用的代码       List p2;   Allocate(p2);   List p3=p2; //尾插法用的存储当前指针   for(int i=0;i<4;i++)  TailCreatlist(p3);  Travellist(p2);//尾插法用的代码     return 0; }


Question: 数据结构顺序表

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

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

引用 1 楼 user-3的回复:Location 变量没有声明  Locate(*L,e);  改成  Iocate(*L,e); 嗯，好的，谢谢。

引用 3 楼 小灸舞的回复:1.int Locate(SqList L,int e)写成了int Iocate(SqList L,int e) 2.location = Locate(*L, e);写成了Location = Locate(*L, e); 3.InitList没有返回值 4.case 5:里面，遍历输出的时候，应该是for (i = 0; i < L->length; i++)，你多了个等号  #include<stdio.h> #include<malloc.h> #define MAXSIZE 100 #define ERROR 0 #define TRUE 1  typedef struct { 	int data[MAXSIZE]; 	int length; }SqList; void InitList(SqList *L, int e) { 	L->length = e; }//组建  int Insert(SqList *L, int i, int e) { 	int k; 	if (i<1 || i>L->length + 1) 	{ 		return ERROR; 	} 	if (L->length >= MAXSIZE) 	{ 		return ERROR; 	} 	for (k = L->length - 1; k >= i - 1; k--) 	{ 		L->data[k + 1] = L->data[k]; 	} 	L->data[i - 1] = e; 	L->length++; 	return 1; }//插入  int DestroyList(SqList *L, int i, int *e) { 	int k; 	if (i<1 || i>L->length) 	{ 		return ERROR; 	} 	*e = L->data[i - 1]; 	for (k = i; k < L->length; k++) 	{ 		L->data[k - 1] = L->data[k]; 	} 	L->length--; 	return 1; }//删除  int Locate(SqList L, int e) { 	int i = 0; 	while ((i <= L.length) && (L.data[i] != e)) 		i++; 	if (i <= L.length) 		return i + 1; 	else 		return ERROR;  }//查找 void menu() { 	printf("请第一步建立线性表\n"); 	printf("1、建立线性表***********\n"); 	printf("2、插入**********\n"); 	printf("3、删除**********\n"); 	printf("4、查找**********\n"); 	printf("5、遍历输出********\n"); 	printf(""); 	printf("*6、退出**********\n"); } int main() { 	int num, length, number, location; 	int i, e; 	int *data; 	data = (int*)malloc(sizeof(int)); 	SqList *L = NULL; 	menu(); 	while (1) 	{ 		printf("请输入你的选择:\n"); 		scanf("%d", &num); 		switch (num) 		{ 		case 1: 			L = (SqList *)malloc(sizeof(SqList)); 			printf("请输入线性表的长度"); 			scanf("%d", &length); 			InitList(L, length); 			printf("依次输入线性表的%d个值", length); 			for (i = 0; i < length; i++) 			{ 				scanf("%d", &number); 				L->data[i] = number; 			} 			printf("输入完成"); 			break; 		case 2: 			printf("请输入你要插入的数值和位置"); 			scanf("%d %d", &e, &location); 			if (Insert(L, location, e) == TRUE) 				printf("插入成功"); 			else 				printf("插入失败"); 			break; 		case 3: 			printf("请输入你要删除的节点数"); 			scanf("%d", &i); 			if (DestroyList(L, i, data)) 				printf("删除成功,删除的节点数值为%d", number); 			else 				printf("删除失败"); 			break; 		case 4: 			printf("请输入你要查找的数值"); 			scanf("%d", &e); 			location = Locate(*L, e); 			printf("你要查找的节点数值为%d", location); 			break; 		case 5: 			for (i = 0; i < L->length; i++) 				printf("%d", L->data[i]); 			break; 		case 6: 			return 0; 		} 	} 	printf("\n"); 	return 0;   }  每次你都会很耐心的帮我，找错误，认真分析，还把详细的代码发过来，特别感谢！谢谢虽然我现在学的特别少，很多东西都弄不懂，我会继续努力的，希望多多关照！

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


Question: 大一新生小白求助

引用 4 楼 qwertypkgg 的回复:[quote=引用 3 楼 user-1 的回复:] [quote=引用 2 楼 qwertypkgg 的回复:] [quote=引用 1 楼 user-1 的回复:] putchar函数需要的参数类型不是double    我应该怎么改呢[/quote]  printf("%f", a);[/quote] 谢谢拉  有没有学习的技巧什么的？？[/quote]  多看书，多思考，多实践！

引用 3 楼 user-1 的回复:[quote=引用 2 楼 qwertypkgg 的回复:] [quote=引用 1 楼 user-1 的回复:] putchar函数需要的参数类型不是double    我应该怎么改呢[/quote]  printf("%f", a);[/quote] 谢谢拉  有没有学习的技巧什么的？？

引用 2 楼 qwertypkgg 的回复:[quote=引用 1 楼 user-1 的回复:] putchar函数需要的参数类型不是double    我应该怎么改呢[/quote]  printf("%f", a);

引用 1 楼 user-1 的回复:putchar函数需要的参数类型不是double    我应该怎么改呢

putchar函数需要的参数类型不是double


Question: 我要下载visual studio 2010学习版 该下载哪个版本？（图片进入可见）

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

直接去 msdn 我告诉你，下载完整版、旗舰版的VS。

建议装vs2015社区版，可以用c11的东西

一楼说得对，安装完之后，百度一个密钥，就可以了！

直接下载Ultimate那个版本，功能最强


Question: char *p 赋值而不改变地址

如果你是要拷贝字符串，用strcpy

strcpy

char *s1="A",*s2="B"; char *p; p=s1; p=s2;

重新组织一下你的问题吧


Question: C语言学的不精，大神求100位数和100位整数的加法运算？？

谢谢大家了，哈哈哈，多多学习

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

#include<stdio.h> #include<string.h> char d1[1010],d2[1010],result[1010]; int count;  void converse(){     int i,len=strlen(result);     char c;     for(i=0;i<len/2;i++){         c=result[i];         result[i]=result[len-i-1];         result[len-i-1]=c;     } }  void add(){     int len1=strlen(d1)-1;     int len2=strlen(d2)-1;     count=0;     int flag=0,t;     while(len1>=0 && len2>=0){         t=d1[len1]-'0'+d2[len2]-'0'+flag;         if(t>=10)flag=1;         else flag=0;         result[count++]=t%10+'0';         len1--;         len2--;     }     while(len1>=0){         t=d1[len1]-'0'+flag;         if(t>=10)flag=1;         else flag=0;         result[count++]=t%10+'0';         len1--;     }     while(len2>=0){         t=d2[len2]-'0'+flag;         if(t>=10)flag=1;         else flag=0;         result[count++]=t%10+'0';         len2--;     }     if(flag>0)result[count++]=flag+'0';     result[count]='\0';     converse(); }  int main(){     int T,i;     scanf("%d",&T);     for(i=1;i<=T;i++){         scanf("%s%s",d1,d2);         add();         printf("Case %d:\n",i);         printf("%s + %s = %s\n",d1,d2,result);         if(i!=T)printf("\n");     }     return 0; } 代码仅供参考

C Primer Plus  C语言程序设计：现代方法：第2版(被誉为"近10年来最好的一部C语言著作") C和指针 或者谭浩强 以上任选一本就差不多了，以下为参考书： 《深入理解C指针》 《C陷阱与缺陷》 《C专家编程》 《C语言点滴》 《C语言课程设计案例精编》 C语言程序开发范例宝典 C语言经典编程282例

百度一下，高精度算法！

用字符串来存，然后从低位依次相加，自己处理进位等


Question: 新手 求助 一道简单ACM的+++++++

引用 3 楼 qq423399099 的回复:1.不多于5位，意味着可能是5位数，你必须char a[6];因为最后必须要留一位放'\0' 2.你这个输入了1个四位数，不管正序还是逆序都会多输出一个0，这样符合要求么？好的 多谢了

字符串还要加上最后的\0，所以char a[5] 数组大小不够

引用 1 楼 AnonymousRookie 的回复: # include <stdio.h>  void main() {     int n;     int i;     int temp;     int count=0;     int a[10];     printf("输入一个不多于5位的整数：\n");     scanf("%d",&n);     temp=n;     while(temp!=0)     {         a[count++]=temp%10;         temp/=10;     }     printf("%d是%d位数.\n各位数分别是：",n,count);      for(i=count-1;i>=0;--i)     {         printf("%d",a[i]);     }     printf("\n");       printf("逆序输出各位数字:");     for(i=0;i<count;++i)     {         printf("%d",a[i]);     }     printf("\n"); } 我主要想知道我这个哪有有问题 越详细越好


Question: 怎么运行时会弹出这个框，程序什么问题？

a[0] 和 a[1] 是两个指针，你要给他指向的 int 赋值，你都没分配内存也没指向某个变量，当然会崩溃。

引用 15 楼 pkuzhx 的回复:[quote=引用 14 楼 pkuzhx 的回复:] [quote=引用 7 楼 imkelt 的回复:] a[2] = {0}; a[0]被初始化为0，a[1]你没有为他赋值，则被值初始化为0  人家问的是数组指针，你非要跟他说数组……[/quote] 不对，应该是指针数组，数组的元素是int指针[/quote] 看漏了

你这个本身就是数组，数组的元素是int*类型，即指针。但是你给两个指针分配的地址都是0,0地址你不能写数据的。 #include <stdio.h> int main() { 	int *a[2] = {0}; 	int b = 0, c = 0; 	a[0] = &b; 	a[1] = &c; 	*a[0] = 1; 	*a[1] = 11; 	printf("%d %d\n", b, c); 	return 0; }

引用 14 楼 pkuzhx 的回复:[quote=引用 7 楼 imkelt 的回复:] a[2] = {0}; a[0]被初始化为0，a[1]你没有为他赋值，则被值初始化为0  人家问的是数组指针，你非要跟他说数组……[/quote] 不对，应该是指针数组，数组的元素是int指针

引用 7 楼 imkelt 的回复:a[2] = {0}; a[0]被初始化为0，a[1]你没有为他赋值，则被值初始化为0  人家问的是数组指针，你非要跟他说数组……

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

正解在#1和#2楼

引用 10 楼 u014325402 的回复:[quote=引用 9 楼 imkelt的回复:]比如你*a[0]取到的是值0，而0=1这个表达式你觉得能成立吗，你赋值不就是想改数组元素的值吗，那为什么还要取值呢 那要如何改？。。。。。[/quote] 上面说啦 a[0] = 1; a[1] = 11;

引用 9 楼 imkelt的回复:比如你*a[0]取到的是值0，而0=1这个表达式你觉得能成立吗，你赋值不就是想改数组元素的值吗，那为什么还要取值呢 那要如何改？。。。。。

引用 6 楼 u014325402 的回复:[quote=引用 5 楼 imkelt的回复:]a[0]、a[1]已经是引用了，不用在用取地址符，可以直接赋值 这是指针数组，* 是取值。[/quote] 取值取到的是右值，是不能被赋值的

引用 5 楼 imkelt的回复:a[0]、a[1]已经是引用了，不用在用取地址符，可以直接赋值 这是指针数组，* 是取值。

a[0]、a[1]已经是引用了，不用在用取地址符，可以直接赋值

引用 2 楼 user-6的回复:要赋值你得先为指针分配一块内存 如何用简单的方式分配，而不用malloc函数

用malloc来分配吗？  还有其他简单的方法吗？

要赋值你得先为指针分配一块内存

a[0]的值是0 （NULL）  这块内存是不可读的，不能被解引


Question: 如何把一个数组或者一段内存一次性的写入文件中

引用 4 楼 paschen 的回复:使用文件内存映射方式打开文件，然后直接使用memcpy拷贝整段内存内容到文件虽然我没明白你说的映射方式。

引用 6 楼 user-4 的回复:楼主似乎是要写人类可读的那种格式，这个没有标准库函数，需要自己写循环或者递归整个程序我已经写完了。就是速度慢。我现在在想办法提高运行速度。对于这个问题，如何写入。我的办法是在写入之前，或者说运算到结尾，我直接把数字加上48，使其对应上asc码，然后用fwrite一次性写入。  感谢各位的帮助。谢谢大家。

这个中文版的 MSDN 哪里可以下载 引用 5 楼 zhao4zhong1 的回复:无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

使用文件内存映射方式打开文件，然后直接使用memcpy拷贝整段内存内容到文件

楼主似乎是要写人类可读的那种格式，这个没有标准库函数，需要自己写循环或者递归

引用 2 楼 zhao4zhong1 的回复:电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了赵老师，我没明白你的意思。按我的理解，确实，计算机中所有数据的存储都是按照二进制的形式存储的。但是，我需要把我数组a[200]的信息写入到1.txt中，并且是按照fprintf(fp,"%d",a[i]);这种形式写进去啊。当然了，问题在于 fprintf 这个函数一次只能写数组的一个元素，我是想一次把数组的一行甚至整个二维数组写进去。否则用for循环，一次写一个太慢了。每写一个字符就要进行一次判断，i 也要进行一次加一。太耗费时间了。

对了，我的存储方式是ASC|| 型，不是二进制。即文件中要显示的是123456789


Question: C语言 函数调用栈问题

引用 4 楼 baise47 的回复:报错那行是汇编语言，把ebp寄存器的内容复制到新建的临时变量里，从而获取上一个函数的栈底地址。 这道题的目的，就是不传递参数，通过函数调用栈的栈底地址，根据变量保存的顺序，获取变量的值。 主要考察，对函数调用栈的理解。  引用 2 楼 qq_34143240 的回复:参数没有传递，报错那行什么意思？  使用ebp寻址涉及到很多，建议看汇编看生成的汇编来判断变量位置

楼主首先要学会在内存窗口中查看堆栈。我觉得。 http://bbs.csdn.net/topics/391944619

不好意思，笔误。 main函数和print函数应该分开。  引用 1 楼 paschen 的回复:你把main函数放在print函数里什么意思：   #include <stdio.h> void print() { 	unsigned int _ebp; 	__asm{ 		mov _ebp,ebp 	} 	int *p = (int*)(*(int *)_ebp- 4-4-4-7*4); 	for (int i=0; i<7; i++) 	{ 		printf("\r\n %d \t", p[i]); 	} }  int main() { 	int a =1; 	int b = 2; 	char c = 'a'; 	int arr[]={11,12,13,14,15,16,17}; 	print(); 	return 0; }  引用 1 楼 paschen 的回复:你把main函数放在print函数里什么意思：   #include <stdio.h> void print() { 	unsigned int _ebp; 	__asm{ 		mov _ebp,ebp 	} 	int *p = (int*)(*(int *)_ebp- 4-4-4-7*4); 	for (int i=0; i<7; i++) 	{ 		printf("\r\n %d \t", p[i]); 	} }  int main() { 	int a =1; 	int b = 2; 	char c = 'a'; 	int arr[]={11,12,13,14,15,16,17}; 	print(); 	return 0; }

对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）

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

参数没有传递，报错那行什么意思？


Question: 新人求助  大神快来看看！！！！！！！

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

ss指针没有分配空间啊，你的SqStack *ss;定义的是指针。你可以定义实体或者给这个指针分配空间。

给SqStack *ss分配个空间才行  #include<stdio.h> #include<math.h> #include<string.h> #include<malloc.h> #include<stdlib.h> #include<conio.h> #define SIZE 100 typedef int DataType;  typedef struct SqStack { 	DataType *base; 	DataType *top; 	int size; }SqStack;  void initial(SqStack *s) { 	s->base = (DataType*)malloc(SIZE*sizeof(DataType)); 	if (!s->base)  exit(-1); 	s->top = s->base; 	s->size = SIZE; }  int empty(SqStack  *ss) { 	return ss->base == ss->top; } int full(SqStack *ss) { 	return ss->top - ss->base == SIZE - 1; } void push(SqStack  *ss, int x) { 	if (full(ss)) 	{ 		printf("满了"); 		exit(1); 	} 	*ss->top++ = x; } DataType pop(SqStack *ss) { 	if (empty(ss)) 	{ 		printf("空了"); 		exit(1); 	} 	return *--ss->top; } DataType top(SqStack *ss) { 	if (empty(ss)) 	{ 		printf("空了"); 		exit(1); 	} 	return *(ss->top - 1);  } void zh(int a, int b) { 	int i; 	SqStack *ss = (SqStack*)malloc(sizeof(SqStack)); 	initial(ss); 	while (a) 	{ 		push(ss, a%b); 		a = a / b; 	} 	while (!empty(ss)) 	{ 		i = pop(ss); 		printf("%d", i); 	} }  int main() { 	int n, m; 	printf("输入一个数"); 	scanf("%d", &n); 	printf("转换进制"); 	scanf("%d", &m); 	zh(n, m);  	return 0;  }

你的initial函数是按值传递的，也就是函数中得到的参数只是外面参数的一个复制品，你把申请的内存给了一个复制品，并不会改变函数外的参数  你应该传递指针的指针到函数中!

#include<stdio.h> #include<math.h> #include<string.h> #include<malloc.h> #include<stdlib.h> #include<conio.h> #define SIZE 100 typedef int DataType;  typedef struct SqStack { 	DataType *base; 	DataType *top; 	int size ; }SqStack;  void initial(SqStack *s) { 	s->base=(DataType*)malloc(SIZE*sizeof(DataType));     if(!s->base)  exit(-1); 	s->top=s->base; 	s->size=SIZE; }  int empty(SqStack  *ss) { 	return ss->base==ss->top; } int full(SqStack *ss) { 	return ss->top-ss->base==SIZE-1; } void push(SqStack  *ss,int x) { 	if(full(ss)) 	{printf("满了"); 	exit(1);} 	*ss->top++=x; } DataType pop(SqStack *ss) { 	if(empty(ss)) 	{ 		printf("空了"); 		exit(1); 	} 	return *--ss->top; } DataType top(SqStack *ss) { 	if(empty(ss)) 	{ 		printf("空了"); 		exit(1); 	} 	return *(ss->top-1);  } void zh(int a,int b) { 	int i; 	SqStack *ss; 	initial(ss); 	while(a) 	{ 		push(ss,a%b); 		a=a/b; 	} 	while(!empty(ss)) 	{	i=pop(ss); 	printf("%d",i);} }  int main() { 	int n,m; 	printf("输入一个数"); 	scanf("%d",&n); 	printf("转换进制"); 	scanf("%d",&m); 	zh(n,m);  return 0;  }

有图吗.....


Question: 为什么在C语言中用文件操作将一个视频文件分割后再合成 结果不能播放了

//合成文件使用比如 WinExec("cmd /c copy /b 文件1+文件2+文件3 文件123",SW_HIDE);

仅供参考：#include <sys\stat.h> #include <io.h> #include <fcntl.h> #include <share.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <string.h> #define MAX_CLU_BYTES 65536 FILE *fo; int fh; __int64 offs,offs1; __int64 rvi64; int rv,wrv; unsigned char buf[MAX_CLU_BYTES]; char ofn[_MAX_PATH]; char offstr[80]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; char fullpath[_MAX_PATH]; void strcpybutcomma(char *t,char *s) {     char c;      while (1) {         c = *s++;         if (','!=c) *t++ = c;         if (0==c) break;     } } int main(int argc,char **argv) {     if (argc<3) {         printf("Copy File Tail.\n");         printf("Usage:\n");         printf("    cft filename.ext {Offset_Begin|-Offset_End|Offset_Begin-Offset_End}\n");         printf("Copy filename.ext {OB|-OE|OB-OE} to {OB|~OE|OB-OE}-filename.ext\n");         printf("Note: Byte at OE is NOT included.\n");         printf("Example:\n");         printf("    cft abc.rar 12345\n");         printf("Copy abc.rar offset 12345-end to 12345-abc.rar\n");         printf("    cft abc.rar -12345\n");         printf("Copy abc.rar offset -12345-end to ~12345-abc.rar\n");         printf("    cft abc.rar 123-12345\n");         printf("Copy abc.rar offset 123-12345 to 123-12345-abc.rar\n");         printf("    cft abc.rar 0xAB-0xCD\n");         printf("Copy abc.rar offset 0xAB-0xCD to 0xAB-0xCD-abc.rar\n");         return 1;     }     strcpybutcomma(offstr,argv[2]);     rv=sscanf(offstr,"%I64i-%I64i",&offs,&offs1);     if (rv==0) {         printf("offset %s is not number\n",argv[2]);         return 2;     }     if (NULL==_fullpath(fullpath,argv[1],_MAX_PATH)) {         printf("Can not get fullpath of %s\n",argv[1]);         return 10;     }     fh=_sopen(fullpath,_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYNO);     if (fh==-1) {         printf("_sopen %s errno=%d %s\n",fullpath,errno,strerror(errno));         return 3;     }     if (rv==1) {         offs1=_filelengthi64(fh);         if (offs1==-1i64) {             printf("%I64d=_filelengthi64 errno=%d %s\n",offs1,errno,strerror(errno));             _close(fh);             return 4;         }         if (offs<0i64) {             offs=offs1+offs;             if (offs<0i64) offs=0i64;         }     } else {//rv==2         if (offs>offs1) {             printf("%s offset_begin %I64d > %I64d offset_end error\n",argv[2],offs,offs1);             _close(fh);             return 5;         }     }     rvi64=_lseeki64(fh,offs,SEEK_SET);     if (rvi64!=offs) {         printf("%I64d=_lseeki64 %I64d errno=%d %s\n",rvi64,offs,errno,strerror(errno));         _close(fh);         return 6;     }     _splitpath(fullpath,drive,dir,fname,ext);     if (offstr[0]=='-') offstr[0]='~';     sprintf(ofn,"%s%s%s-%s%s",drive,dir,offstr,fname,ext);     fo=fopen(ofn,"wb");     if (fo==NULL) {         printf("fopen %s errno=%d %s\n",ofn,errno,strerror(errno));         _close(fh);         return 7;     }     cprintf("\n%I64d\r",offs);     while (1) {         rv=_read(fh,buf,(unsigned int)__min(offs1-offs,MAX_CLU_BYTES));         if (rv==0) break;//         if (rv<0) {             printf("_read %s offset %I64d errno=%d %s\n",fullpath,offs,errno,strerror(errno));             fclose(fo);             _close(fh);             return 8;         }         wrv=fwrite(buf,1,rv,fo);         if (wrv!=rv) {             printf("fwrite %s errno=%d %s\n",ofn,errno,strerror(errno));             fclose(fo);             _close(fh);             return 9;         } else {             offs+=rv;             cprintf("%I64d\r",offs);             if (offs>=offs1) break;//         }     }     fclose(fo);     _close(fh);     printf("Copy %s offset %s to %s OK.\n",fullpath,argv[2],ofn);     return 0; }

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

肯定是读文件和写文件生成的文件内容不一致引起的啊。 先比较一下2个文件，然后再单步一下。

while(!feof(fp)) { ch=fgetc(fp); fputc(ch,fp1); } 貌似有问题，试试： ch=fgetc(fp); while(!feof(fp)) { fputc(ch,fp1); ch=fgetc(fp); }

在文件合成的接口处多了一个FF

我用过CRC校验的一个小工具看过，生成的校验码不一样，我要怎么才能实现最终的播放呢，有没有什么方法

视频文件不是简单的流，还带格式信息。

原文件与分割、合成后的文件比较过完全一样吗？可以计算MD5，也可以cmd命令行fc命令来比较。


Question: 一道简单的题不至于删我的提问吧?????csdn!!!!!!!!!!!

#include<stdio.h> #include<malloc.h> struct stu { int num; struct stu *next; }; struct stu* creat(void)//建立一个链表 { int n; struct stu *p1,*p2,*head; scanf("%d",&n); p1=head=(struct stu *)malloc(sizeof(struct stu)); p1->next=NULL; for(int i=0;i<n;i++) { p2=(struct stu *)malloc(sizeof(struct stu)); p2->next=NULL; scanf("%d",&p2->num); p1->next=p2; p1=p2; } p1->next=NULL; return head; } int main() { 		struct stu *pc,*pt_a,*pt_b,*pa,*pb,*pp; 		struct stu* head=(struct stu *)malloc(sizeof(struct stu));//新链表的表头 		pc=head; 		pc->next=NULL; 		pt_a=creat(); 		pa=pt_a->next; 		pt_b=creat(); 		pb=pt_b->next; 		while(pa&&pb)//判断一个链表是否遍历到结尾 		{				//printf("%d",pa->num); 					if(pa->num<=pb->num)//判断大小 					{ 						pc->next=pa;//连接到新链表上 						pc=pa;//新表指针指向最后一个 						pa=pa->next;//原先的链表后移 					} 					 					else//(pt_a->next->num<pt_b->next->num) 					{ 						pc->next=pb;//连接到新链表上 						pc=pb;//新表指针指向最后一个 						pb=pb->next;//原先的链表后移 					} 		} 		pc->next=NULL; 		while(head->next!=NULL) 		{ 			printf("*%d      ",head->next->num); 			head=head->next; 		} 	return 0; }

好的 谢谢各位啦!这几天比较忙没有来看帖子,谢谢啦

1.你的creat函数是对的。 2.if (pt_a->next->num>pt_b->next->num);后面多了分号 3.你的连接链表不对，你想，假设第一次进入了else分支，第二次进入了if分支，那么第三次比较的时候，其实你已经丢失了pt_a链表的剩余部分了，自己在纸上画一下就明白了，或者单步调试一步步看下去。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

你这是要干嘛？合成新链表？麻烦大虾以后发帖，注意标题

p1->next==NULL; 是否想写：p1->next=NULL;  这里的if后面多了一个分号： if(pt_a->next->num>pt_b->next->num);

这个是把两个链表合成一个链表上


Question: c  问题求解

重开软件--重启电脑

不是代码问题，应该是重新生成EXE文件时，原来的EXE文件被占用着，重新启动下再试

估计你开了两个程序，关掉期中一个就好了！


Question: C语言学的半吊子，为什么输出结果不一样呢？

输入两个随便什么字符间隔的整数。 仅供参考：#include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }

scanf()是一个比较严格的函数，何谓严格，首先函数中是否包含空白/非空白字符对输入格式的影响很大：       比如：scanf("%d,%d",&a,&b);   scanf中有一个逗号，所以输入的格式应该是2,3==>a=2,b=3              scanf("%d%d",&a,&b);    可以用空格或回车来分隔两个输入 如 45==>a=4,b=5          scanf("%d  %d",&i,&j);   与上面相同

或者输入的时候，输入 C 2,3

scanf("%d,%d",&rows,&cols);  改成  scanf("%d%d",&rows,&cols);

但你那逗号不能省略啊

引用 1 楼 user-5 的回复:要和 "%d,%d" 格式对应,   应该判断 scanf 读取 返回的个数 C 2, 3[enter] 在输入过程中，scanf（）不是可以跳过空格、制表符和换行符的吗？输入c 2 3，是不是可以理解为ch='c',rows=2,cols=3？


Question: 关于sizeof的用法

感觉这就是C语言的特性，不需要过多纠结吧。 只要记住 1. sizeof(数组名)是获取数组的长度； 2. sizeof(指针)是4字节（32位机器上）； 3. 数组名做函数实参时会退化为指针（4字节）。 就行了。

在sizeof(a2)中，a2表示的含义是a2[]，因此返回整个数组的大小（这个大小在之前的数组定义中已经确定了）；而a1只是个指针，sizeof(a1)只能返回指针本身占用的字节数而不能确定为它指向的内容分配的空间的大小。

你需要理解数组和指针的区别。  1. 指针就是一个变量，你可以给它赋值，是可变的；而数组首元素，你可以看成是数组的指针，但是这个指针地址是不可变的  2. 在你的代码中，sizeof(p)是指针的大小，sizeof(a)是数组的大小  3. 当数组作为参数传递给函数时，这个时候，就是作为指针来使用的

数组类型和指针类型是两种不同的类型  唯一的联系是某些情况下，数组可以退化为指针

因为数组不是指针

sizeof 不进行退化。

数组在作为函数参数传递过程中，才会退化成指针

指针在32位上 都是4字节！ 数组你在主函数里 不会退化，所以你sizeof(a)的时候是整个数组的大小！如果你把数组作为参数传递就会退化为指针（也就是4个字节）！ 你得区分 指针和数组


Question: 小米2017校园招聘笔试第一题

引用 11 楼 u010963658 的回复:（"ZERO", "ONE", "TWO", "THREE", "FOUR",  "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"） 如果有Z, 一定是ZERO(0) 如果有W, 一定是TWO(2) 如果有U, 一定是FOUR(4) 如果有X, 一定是SIX(6) 如果有G, 一定是EIGHT(8) 根据这些关键字, 先去掉可以肯定有的数字, 剩下的就是 ONE, THERE, FIVE, SEVEN, NINE, 因为前面的ZERO已经将自己的O给移除了, 所以如果剩下的字符里面还有O, 那一定是ONE, 同理, 移除掉ONE后, 如果还有H, 就是THERE 移除掉THERE后, 如果还有F, 就是FIVE 移除掉FIVE后, 如果还有S, 就是SEVEN 移除掉SEVEN, 就剩下NINE了 然后将数据+2取个位, 就是原来的数, 从小到大排序即可这个思路是对的

公司外网虚拟机写不了代码，说下基本的思路不，大家可以指正下。因为字符串的顺序是打乱的，所以其实这个问题的本质就是一个解10元方程的问题，将原始的字符串按照从字母‘A’到‘Z’统计出来个数，在假设从0到9的个数搞一个方程的解就OK了。步骤如下：  1. 题目中说最多只有1000个字符的数组，因此需要创建一个1001个元素的数组来接纳这些值； 2. 创建一个10个元素的数组auiNumberCnt[10]，其中每一个元素auiNumberCnt[x]代表其中x数字的个数； 3. 创建一个24个元素的数组auiAlphabetCnt[24]，其中auiAlphabetCnt[0]代表字母A的个数，以此类推； 4. 先遍历原有的加密字符数组，分别得到字母‘A’到‘Z’的个数； 5. 剩余的事情就是得到一个方程式的解的过程中，比如数字0的个数就等于字母‘Z’的个数，这是一个10元10次方程组，因此是必然有解的； 6. 根据每一个数字的个数，得出相应的结果即可；

引用 3 楼 user-8 的回复:单纯得想问一下题目链接…… 看楼下雷锋啦~

引用 2 楼 fefe82 的回复:写几个片段吧 ...  //0 ~ 9 计数 int numes[10] = {0}; // ....            // 看你的程序，好像到偏移了 2? 0->2, 1->3, 2->4 ...            // 0 ，其它同           nums[2] += a[25];          a[4] -= a[25];          a[17]-=a[25];          a[14]-=a[25];          a[25] = 0;  // 输出 for (int i = 0; i < 10; i ++)     for (int j = 0; j < nums[i]; j++)          putchar('0' + i); putchar('\n');    ==============================              memset(nums, 0, len);             memset(a, 0, 26);             // 这里又输出了一遍是题目要求吗？这次已经清零了，就全是零了啊。             for(j = 0; j < len; ++j)                   printf("%d", nums[j]);                   // 你的 arr 够大吗？                   //memset(arr, '\0', strlen(arr));                   memset(arr, 0, sizeof(arr));  多谢回答，那个题目的要求就是+8取个位加密的，所以有类似偏移的地方。另外下面那个输出是我调试用的，我看看是否都清零了~

引用 1 楼 u012849694 的回复:你好，我今年也参加了小米公司的笔试，我也做了这个题目，我是第三题，当时调试了半天也没成功。请问您的笔试结果出来了吗？我今天查了半天没有查到笔试成绩的地址。 小米这个还能查笔试成绩吗？反正我做校招在线答题从来没听过有能查笔试成绩的呀，如果过了就会给你发短信让你去面试啦，我同学有今天上午去的，不造你咋样啦~

以下代码不保证没有bug，也不保证效率，但最起码测试原题数据是通过的：  #include <stdio.h> #include <string.h> #include <memory.h> int main() { 	char cipher[10001]; 	int T, i, j, len; 	int letters[26], numbers[10], numbers_minus_8[10]; 	scanf("%d", &T); 	while(T--) 	{ 		scanf("%s", cipher); 		memset(letters, 0, 26 * sizeof(int)); 		len = strlen(cipher); 		for (i = 0; i < len; i++) 		{ 			letters[cipher[i] - 'A']++; 		} 		// 0 ZERO: Z 		numbers[0] = letters['Z' - 'A']; 		letters['E' - 'A'] -= letters['Z' - 'A']; 		letters['R' - 'A'] -= letters['Z' - 'A']; 		letters['O' - 'A'] -= letters['Z' - 'A']; 		letters['Z' - 'A'] = 0; 		// 2 TWO: W 		numbers[2] = letters['W' - 'A']; 		letters['T' - 'A'] -= letters['W' - 'A']; 		letters['O' - 'A'] -= letters['W' - 'A']; 		letters['W' - 'A'] = 0; 		// 4 FOUR: U 		numbers[4] = letters['U' - 'A']; 		letters['F' - 'A'] -= letters['U' - 'A']; 		letters['O' - 'A'] -= letters['U' - 'A']; 		letters['R' - 'A'] -= letters['U' - 'A']; 		letters['U' - 'A'] = 0; 		// 6 SIX: X 		numbers[6] = letters['X' - 'A']; 		letters['S' - 'A'] -= letters['X' - 'A']; 		letters['I' - 'A'] -= letters['X' - 'A']; 		letters['X' - 'A'] = 0; 		// 4 FOUR: U 		numbers[8] = letters['G' - 'A']; 		letters['E' - 'A'] -= letters['G' - 'A']; 		letters['I' - 'A'] -= letters['G' - 'A']; 		letters['H' - 'A'] -= letters['G' - 'A']; 		letters['T' - 'A'] -= letters['G' - 'A']; 		letters['G' - 'A'] = 0; 		// second round 		// 1 ONE: O 		numbers[1] = letters['O' - 'A']; 		letters['N' - 'A'] -= letters['O' - 'A']; 		letters['E' - 'A'] -= letters['O' - 'A']; 		letters['O' - 'A'] = 0; 		// 3 THREE: H 		numbers[3] = letters['H' - 'A']; 		letters['T' - 'A'] -= letters['H' - 'A']; 		letters['R' - 'A'] -= letters['H' - 'A']; 		letters['E' - 'A'] -= letters['H' - 'A']; 		letters['E' - 'A'] -= letters['H' - 'A']; 		letters['H' - 'A'] = 0; 		// 5 FIVE: F 		numbers[5] = letters['F' - 'A']; 		letters['I' - 'A'] -= letters['F' - 'A']; 		letters['V' - 'A'] -= letters['F' - 'A']; 		letters['E' - 'A'] -= letters['F' - 'A']; 		letters['F' - 'A'] = 0; 		// 7 SEVEN: S 		numbers[7] = letters['S' - 'A']; 		letters['E' - 'A'] -= letters['S' - 'A']; 		letters['V' - 'A'] -= letters['S' - 'A']; 		letters['E' - 'A'] -= letters['S' - 'A']; 		letters['N' - 'A'] -= letters['S' - 'A']; 		letters['S' - 'A'] = 0; 		// only NINE left 		// 9 NINE: F 		numbers[9] = letters['I' - 'A']; 		// minus 8 		for (i = 0; i <=9; i++) 		{ 			numbers_minus_8[(i + 2) % 10] = numbers[i]; 		} 		// print answer 		for (i = 0; i <=9; i++) 		{ 			if(numbers_minus_8[i]) 			{ 				for (j = 0; j < numbers_minus_8[i]; j++) 				{ 					printf("%d", i); 				} 			} 		} 		printf("\n"); 	} 	return 0; }

nums[i++] = 2; 这是什么意思？ 而且题目说范围是10000，你数组取做10001，这不是常识吗？虽然10000也不影响你做题，但是总觉得你代码习惯非常不严谨，大思路是对的，小思路混乱，看不懂

这代码没救了……连题目给出的四个数据都过不了

活雷锋来了~我来甩原题链接~ http://wenku.baidu.com/link?url=4NYfyGHC3RpzJhuI4ipsfNzDwvK_OZFjDCXQXoxCzAvpU_6PirwVRUKMxG2Q7Et5IKayi5pgMQxDm4vthg7j09KVGkDMeWzNN1lvSAVRDvW 我也是弄好半天调试不出来 最后才看到三四行 字母其实被打乱了==== 死的不明不白 还想接着把它弄出来 不知道楼主要不要一起讨论看看==

单纯得想问一下题目链接……


Question: 求运用一维数组统计学生成绩及每个人三门的平均成绩，学生数由键盘输入

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

外层循环每次要将sum清零：  #include <stdio.h> int main() {    	int n,i,j,chinese,math,english,sum=0; 	float av; 	printf("how many students are in your class?"); 	scanf("%d",&n); 	printf("please input students three scores:\n"); 	int b[3]; 	for (i=1;i<=n;i++) 	{ 		printf("the no.%d:",i); 		sum = 0; 		for(j=0;j<3;j++) 		{ 			scanf("%d",&b[j]); 			sum+=b[j]; 			av=sum/3.0;//平均值为输入的所有数据除以3，并非个人的三门成绩平均值。  		} 	} 	printf("num  chinese math english    av\n"); 	for(i=1;i<=n;i++) 	{ 		printf("%2d",i); 		for(j=0;j<3;j++) 		{ 			printf("%7d",b[j]);//数组b只可以一次赋值，输入多组数据只能存储到最后一组  		} 		printf("%9.2f",av); 		printf("\n"); 	} 	return 0;  }


Question: C语言scanf

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

fscanf（fp，“s%”，name）puts（name）是几个意思？ 应该编译通不过吧？ fscanf(fp，“%s”，name); puts(name);  "我的想法是fscanf读完一个单词进入第二次循环后，会在单词末尾加空字符，不知道对不对！" 不是在字符串末尾加空字符，而是加字符串结束符，即'\0'

引用 2楼paschen 的回复:http://en.cppreference.com/w/c/io/fscanfIf width specifier is used, matches up to width or until the first whitespace character, whichever appears first. Always stores a null character in addition to the characters matched (so the argument array must have room for at least width+1 characters)

引用 1楼user-5 的回复:第一次循环也会加空字符啊。  %s 会自动加 '\0' 的。就是读完%s后scanf会在结尾加空字符吗？

第一次循环也会加空字符啊。  %s 会自动加 '\0' 的。


Question: 一个批量重命名文件出错

出错时应输出尽量多的相关变量当前的值。

引用 1 楼 user-3 的回复:目录输入一个 \ 就够了。 嗯，那么还有什么错误吗？

目录输入一个 \ 就够了。


Question: 这里的scanf函数是怎么会是？

不那样会更麻烦。不信你可以随便试。

引用 6 楼 赵4老师的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 int c; scanf("%c",&c); //时，都改为 char s[2]; int c; scanf("%1s",s); c=s[0]; 老师，你好，程序为什么要改为那样写，那样写是不是麻烦了？

用scanf("%c",...)或者getchar()的时候，要特别注意输入缓冲区内的数据（因为它能读入空格，制表符，回车符） 可以用fflush(stdin);来清空输入缓冲区

直接输入abcd，中间是不需要加空格的,空格也是一种一种字符

%c 会将你回车产生的换行符\n也读进去

空格也会读的

char m,p; m前面是光标吗？

格式是%c%c%c%c而不是%c %c %c %c


Question: 执行printf之后出现某指针被修改问题

问题原因找到了,是其它地方没有注意函数参数的值传递问题.不过还是多谢2位回答

判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

引用 1 楼 user-2 的回复:检查数组是已经越界了 看log没有越界                         fmin = Astar_map[x_index][y_index].f;                         printf("next node x = %d,y = %d,f = %d\n",(x_index),(y_index),fmin);的log如下        next node x = 5,y = 0,f = 250 Astar_map数组是[20][20]的

检查数组是已经越界了


Question: 位域定义的问题？

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

编译器怎么做都可以  http://en.cppreference.com/w/c/language/bit_field

编译器愿意怎么放都可以。


Question: 贪吃蛇问题

引用 2 楼 u010165006 的回复:#include "stdafx.h" #include "colorConsole.h"  /* HANDLE initiate() { 	HANDLE hOutput;  	hOutput = GetStdHandle(STD_OUTPUT_HANDLE); 	return hOutput; } */  BOOL textout(HANDLE hOutput,int x,int y,WORD wColors[],int nColors,LPTSTR lpszString) {     DWORD cWritten;      BOOL fSuccess;      COORD coord;      	coord.X = x;              // 输出第一个字符所在的列即X坐标      coord.Y = y;              //   所在的行即Y坐标           fSuccess = WriteConsoleOutputCharacter(		//输出字符串         hOutput,              // 屏幕缓冲区的句柄         lpszString,           // 指向字符串的指针          lstrlen(lpszString),  // 字符串长度         coord,                // 输出第一个字符的坐标         &cWritten);           // 实际输出字符的个数     if (! fSuccess)          cout<<"error:WriteConsoleOutputCharacter"<<endl;      	     	for (;fSuccess && coord.X < lstrlenA((LPCSTR)lpszString)+x; coord.X += nColors)      {         fSuccess = WriteConsoleOutputAttribute(		//为已输出的字符串上色             hOutput,          // 屏幕缓冲区的句柄             wColors,          // 颜色数组             nColors,          // 颜色数目             coord,            // 输出第一个字符的坐标             &cWritten);       // 实际输出字符的个数     }     if (! fSuccess)      	cout<<"error:WriteConsoleOutputAttribute"<<endl;  	return 0; }  谢谢，但是不知道怎么用。

引用 1 楼 paschen 的回复:可以考虑不全部清除重画，可以将光标移到要擦除的地方，输出空格覆盖，移到需要更新的地方，输出更新的东西 好的，谢谢。但是我打印的方法好像对你的解决方法不行

console屏幕处理例子程序。终端窗口屏幕处理相关API使用例子。来自MSVC20\SAMPLES\win32\console\ http://download.csdn.net/detail/zhao4zhong1/3461309


Question: 单入单出无锁实现

确保先写后读，还有一种方法。 就是每次写数据都给它设置一个“首部” “首部”中设置一个读写字段 flag  如果是1，就是已写，如果是0就是未写。 每次读写操作都相应地设置好这个flag。 每次读之前都对检查这个flag。如果是1就执行读操作，如果是0就等待。

"假如写100个的话，写到64之后就会说满了" 每次写之前都判断是否有足够的内存。 由于两个线程同时执行，总会有数据被读取出去。那么就会有新的内存可以写了。 如果暂时满了，可以让写线程稍等一下。等读线程读出数据再接着写。

无锁。。。。 好吧，我觉得即使没有锁，也需要其他形式的锁。。。

你说“每次都是先读后写”。这就有问题了。 必须确保先写后读。也就是在读之前须要判断写过了没有。 通过head和tail的关系来判断。 1、head==tail，没有数据，不可以读。 2、head!=tail，有数据，可以读。 注意：写满之后，head==tail又成立了。所以，不允许写满。空出一个字节，不让head追上tail.

用head和tail作为数组的号，比如创建64个buf，head等于64写入完成之后让它归0，重复利用。就是两线程读和写同时调用的话，每次都是先读后写，读的都是空，假如写100个的话，写到64之后就会说满了。如何才能让读和写同时运行呢。在用是sleep让速度慢下来，是可以实现的。就是不用sleep会出现问题。。。。内存屏障能解决这个问题么？

volatitle和多线程没有关系。我觉得。

这么高大上的东西楼主都敢自己做。难道无锁的结构只需要volatile就可以实现了？好歹得用个自旋锁吧？问题是就算手动做出来，如何测试正确性？还是老老实实使用库里的组件吧


Question: 堆栈出问题了

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

word w=malloc(sizeof*w);这是啥？ 你得说下你输入的是啥，还有就是scanf("%c", &A);类似这样读一个字符的时候，要搞清楚输入缓冲区有没有遗留的回车符 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

出错时点中断，通过调用堆栈定位到相关代码观察分析原因  如果要别人帮你调试，起码说出你是要怎么输入


Question: printf格式打印的问题

参与匹配的是"%s Value:%d"  与"ID:%d" 中的%d 无关

是这么回事啊，基础的都忘记了，奇怪的是3没有格式输出居然没有报错，不知道内部编译器语法是怎么运行的。

printf()函数的调用格式为: printf("<格式化字符串>", <参量表>) 第一个参数是格式化字符串，后面的都是参量，你后面的包括格式化的字符串是作为参量传入printf的，所以里面的格式符不会对应输出

因为%s 是输出字符串，你，后面的"ID:%d"就是%s的内容，然后Value:%d中的%d会自动使用"ID:%d"后，之后的值，即2024,。 所以3没有意义。

引用 4楼我是你的主体 的回复:int i =8; printf("++i=%d\n ++i=%d\n --i=%d\n --i=%d\n",++i,++i,--i,--i);  这个为啥打印的是 ++i=8 ++i=8 --i=8 --i=8未定义行为，不要在一个表达式里对同一个变量进行++和--操作 http://bbs.csdn.net/topics/370153775