Question: c语言   返回上一级目录

case 4:return; // "void one()" return. case 5:break;  // "switch" break.

switch会有break的, case:没有break会往下执行的. 所以case 4: break;有没有break都一样.  return就是函数返回.

好吧，我想通了,case 5中的break只是终止了one1函数,返回到被调用处后又遇到continue，故继续执行我想到利用返回值来操作。不过还是谢谢您…………#include<stdio.h> int one() { 	for(;;) 	{ 		int q; 		scanf("%d",&q); 		switch(q) 		{ 		case 1:printf("1_1的内容\n");continue; 		case 2:printf("1_2的内容\n");continue; 		case 3:printf("1_3的内容\n");continue; 		case 4:return(0);//结束函数 		case 5:return(1);//返回上一级 		} 		//break; 		//printf("haha\n"); 	} 	//break; }      #include <stdio.h> void main() { 	while(1) 	{ 		int i,q; 		scanf("%d",&i); 		switch(i) 		{ 		case 1:q=one(); 			if(q==1) 				continue; 			else 				break; 	//	case 2:two();continue; 	//	case 3:three();continue; 		case 4:break; 		} 		break; 	} }

上楼的大哥，小弟听不懂啊？


Question: 问一下这个队列哪里出现了问题

void in_queue(struct queue *q,char a){     struct node *n=new node;     if(n==NULL){          return;     }     n->data=a;     n->next=NULL;     if(q->rear)     {         q->rear->next=n;     }else{        q->front=n;     }     q->rear=n; // 我刚才漏了这个。 }

void in_queue(struct queue *q,char a){     struct node *n=new node;     if(n==NULL){          return;     }     n->data=a;     n->next=NULL;     if(q->rear)     {         q->rear->next=n;     }else{        q->front=q->rear=n;     } }  void out_queue(struct queue *q){    struct node * tmp;     if(q->front==NULL)       return;    if(q->front==q->rear)    {       delete q->front;       q->front=q->rear=NULL;       return;    }     tmp=q->front;    q->front=temp->next;    delete tmp; }  void print(struct queue *q){     struct node *n=q->front;     while(n){        std::cout<< n->data << ' ';        n=n->next;     } }   粗看了下，你再试试？


Question: ACM题目   不知道判断方法是什么？求大大解释解释

谢谢@孩皮妞野  大神  我终于坐出来了  按照您的思路  还有那个排列组合  嘿嘿   但是不知道那个递归为什么会错  实在是想不明白   还有您提得那个问题  把if放到check()后面就行了  我明白了 谢谢  非常感谢

#include<stdio.h> #include<stdlib.h> #include<string.h> int n,m;//一共n元  一共m件物品 struct GOOD { 	int pi,mi,vi; }gd[17]; int MAX(int a,int b) { 	return a>b?a:b; } int makeMAX(int x,int y)//x件物品   剩余y元   递归 { 	int r1,r2;      	if(x==0)return 0; 	if(y>=gd[x].pi*gd[x].mi){ 		r1=0+makeMAX(x-1,y); 		r2=gd[x].mi+makeMAX(x-1,y-gd[x].pi*gd[x].mi); 	} 	else r1=makeMAX(x-1,y); 	return MAX(r1,r2); } int main() { 	int max; 	struct GOOD *p; 	while(scanf("%d%d",&n,&m)!=EOF) 	{ 		for(p=gd+1;p<=gd+m;p++) 		{ 			scanf("%d %d",&p->pi,&p->mi); 			p->vi=p->pi*p->mi; 		} 	    max=makeMAX(m,n); 		printf("%d\n",max); 		 	} 	return 0; }  这个我用递归作的(买或者不买)  我自己想的那些数据都能通过 但是还是WA  每信心了

引用 8 楼 FancyMouse 的回复:bool都不懂就别做acm题了。先搞懂怎样写程序再来搞acm 大一新生刚参加呀  下学期才开始培训  这个是寒假的作业.......

bool都不懂就别做acm题了。先搞懂怎样写程序再来搞acm

上面的方法特意跳过了全部不选的组合。你知道怎样加上吗？如果不加，能不能保证仍然可以得到正确的解？

哦，bool就是只能为逻辑值(真或假)的数据类型。现在C也有了，#include <stdbool.h>就好了。  一个函数直接或间接调用自身，就叫递归。递归是一种比较一般化的术语，这里用的回溯法就是一种递归遍历的方法。  语言是来表达思想的，它并不教你如何思想。算法是思想本身。程序=数据结构+算法。  简单的程序可以这样，先把商品信息读入一个数组中，可以不排序。然后用一个同等大小的数组 int picked[count]; 如果picked[i]为0，表示不选这种商品，如果picked[i]为1，表示选取了这个商品。你能够想出办法产生所有选取商品的方案吗？如果你排列组合有一点基础，你应该不难理解这是一个乘法原理问题，第一个商品有选和不选两种可能，第二种也是，....第count种也是，所以总组合数是2x2x....x2=2^count. 如果你对2进制有了一些认识，你会发现这又相当于是count位的二进制数的从0开始自增到重归于0(溢出)能表达的数。  那么你可以这样写程序  // 先把picked数组初始化为0，都为0就是都不选... for(int i=0; i<count; ++i)     picked[i]=0 // 然后开始自增 // 把最低位+1， 如果得到的是2，那就往更高位进位，如果更高位进位后得到2，就往 // 更更高位进位。如果需要进位到count位(这里是按c的惯例从0开始数), 我们就得到了所有的可能 while(1) {     int i=0;     while(i!=count && ++picked[i]==2)// +1或进位后，第i位溢出     {           picked[i]=0; //归0           ++i; //向更高为进位     }     if(i==count) //要往更高位进位了，这时我们已经处理了所有可能的组合，退出循环         break;     // 好了，我们得到了独一无二的一种组合，如果picked[i]位为0，表示小B选中了这个商品，反之     // 表示小B放弃该商品     check(); // 检查这个组合，两个方面，第一，合法性，有没有超支？ 第二，最优性，该组合的              // 的数量是否大于目前最好组合的数量? 如果是当然记住这个更优解的数量 }   check函数留给你自己写。花点功夫理解我上面的解释。好的习惯是努力想，想不明白再问。

汗   好多没学过的东西  bool什么的不懂  是数据结构的莫  我现在才刚刚学完c语言 我问了问我的老师  他说用递归遍历   汗  也不懂 每学过   大神  有简单的程序莫

呕，这个原则上是按单价从低到高。  排序是为了方便贪心选择剪枝。如果不考虑剪枝，无需排序。  0-1背包，和这题都是典型的状态空间是子集树的搜素问题，时间复杂度是O(2^n), 回溯法是系统搜索状态空间是子集树或排序树的极好算法，简单，不易写错--在你掌握了这个方法之后。那个基本是套公式，子集树和排序树各一个公式。你觉得无处下手，估计还不了解这个方法，建议搜索学习之。  多说一下为什么是2^n. 对每一中商品，我可做两种选择，选或者不选，这样n中商品就有2^n次方中可能，我只要把这2^n次方中可能都列出来，去掉不可行的，从剩下的找出有最大值的，这个问题就解决了。因为我枚举了整个状态空间，得到的必然是最优解。但是指数增长是很快的，实际上在搜索的中途，对肯定非法(钱不够了)或者肯定不能产生最优解的分支，都可以直接剪掉。比如我的一组16总商品的测试数据，只需8000多次back_track, 而非65536次...

剪枝效果并不明显。这个问题规模较小，不剪枝也应该可以   #include <stdio.h> #include <algorithm>  //#define _DEBUG  struct item{ 	int price; 	int qty; 	bool operator <(const item& i){ return price<i.price; } };  item items[16]; bool picked[16]; int count; int money; int maxqty;  #ifdef _DEBUG int track_count; #endif   void back_track(int n, int& curqty, int& curbalance); bool greedy_pick();  int main() { 	int curqty, curbalance; 	scanf("%d%d",&money, &count); 	for(int i=0; i<count; ++i) 		scanf("%d%d", &items[i].price, &items[i].qty); 	std::sort(items, items+count); 	maxqty=0; 	curqty=0; 	curbalance=money; 	if(!greedy_pick()) 		back_track(0, curqty, curbalance); #ifdef _DEBUG 	printf("back track called %d times\n", track_count); #endif 	printf("%d\n", maxqty); 	return 0; }   bool viable(int curqty, int curbalance) { 	return true; 	for(int i=0; i<count; ++i) 	{ 		if(!picked[i] && curbalance>items[i].price*items[i].qty) 		{ 			curqty+=items[i].qty; 			curbalance-=items[i].price*items[i].qty; 		}else{ 			curqty+=curbalance/items[i].price; 			break; 		} 	} 	return curqty>maxqty; }  void back_track(int i, int& curqty, int& curbalance) { #ifdef _DEBUG 	++track_count; #endif	 	if(i==count) 	{ 		if(curqty>maxqty) 			maxqty=curqty; 		return; 	} 	if(viable(curqty, curbalance)){ 		back_track(i+1, curqty, curbalance); 		if(curbalance>items[i].price*items[i].qty) 		{ 			picked[i]=true; 			curqty+=items[i].qty; 			curbalance-=items[i].price*items[i].qty; 			back_track(i+1, curqty, curbalance); 			curbalance+=items[i].price*items[i].qty; 			curqty-=items[i].qty; 			picked[i]=false; 		} 	} }  bool greedy_pick() { //	return false; 	int bal, qty; 	bool all_picked=true; 	bal=money; 	qty=0; 	for(int i=0; i<count; ++i) 	{ 		if(bal>items[i].qty*items[i].price) 		{ 			bal-=items[i].qty*items[i].price; 			qty+=items[i].qty; 		}else 			all_picked=false; 	} 	maxqty=qty; 	return all_picked; }    不剪枝版本，供比较理解算法之用  #include <stdio.h> #include <algorithm>  //#define _DEBUG  struct item{ 	int price; 	int qty; 	bool operator <(const item& i){ return price<i.price; } };  item items[16]; int count; int money; int maxqty;  void back_track(int n, int& curqty, int& curbalance); bool greedy_pick();  int main() { 	int curqty, curbalance; 	scanf("%d%d",&money, &count); 	for(int i=0; i<count; ++i) 		scanf("%d%d", &items[i].price, &items[i].qty); 	std::sort(items, items+count); 	maxqty=0; 	curqty=0; 	curbalance=money; 	if(!greedy_pick()) 		back_track(0, curqty, curbalance); 	printf("%d\n", maxqty); 	return 0; }   void back_track(int i, int& curqty, int& curbalance) { 	if(i==count) 	{ 		if(curqty>maxqty) 			maxqty=curqty; 		return; 	} 	// 不选该商品 	back_track(i+1, curqty, curbalance); 	 	// 如果与余额够，选取该商品 	if(curbalance>items[i].price*items[i].qty) 	{ 		curqty+=items[i].qty; 		curbalance-=items[i].price*items[i].qty; 		back_track(i+1, curqty, curbalance); 		curbalance+=items[i].price*items[i].qty; 		curqty-=items[i].qty; 	} }  bool greedy_pick() { 	int bal, qty; 	bool all_picked=true; 	bal=money; 	qty=0; 	for(int i=0; i<count; ++i) 	{ 		if(bal>items[i].qty*items[i].price) 		{ 			bal-=items[i].qty*items[i].price; 			qty+=items[i].qty; 		}else 			all_picked=false; 	} 	maxqty=qty; 	return all_picked; }

我的思路是先排序，再判断   但是我不太清楚该怎么排序，什么优先级不知道  就是该先买什么不知道

感觉是0-1背包的变种，回溯法+贪心算法剪枝，应该不难搞定。


Question: 下列不符合C语言规定赋值的是

引用 6 楼 KenZhang1031 的回复:这种题，舍本逐末，对学习C没作用，不用理会。 赞一个，%只能是整数操作，c选项有问题， 这种题不要看了  而A选项等号右边是逗号表达式，但=优先级比，高 引用 5 楼 ForestDB 的回复:BCD都是赋值语句，而A是逗号表达式语句。 因为=的优先级比,高

这种题，舍本逐末，对学习C没作用，不用理会。

是的 A本质上来说似乎并不叫赋值语句 因为=操作符优先级高，A算作是赋值语句+一个额外语句的组合语句

答案是 C。  #include <stdio.h> int main(void) { 	double a=22; 	int i; 	i=a%11;  }  编译提示左值类型非法。  选项 A  是正确的。

本来有答案，看了大家的回答，我也拿不准了

BCD都是赋值语句，而A是逗号表达式语句。 因为=的优先级比,高

c  double无法进行%操作吧

好象答案是A吧。

异样->一样

C语言不了解，但是应该和C++异样。 答案是C。double不能应用%，只有char long int之类整形才可以。 A可以，没有问题。


Question: C和INI文件如何连接

引用 11 楼 baichi4141 的回复:[quote=引用 10 楼 u011497426 的回复:] 英语好孬的  不懂 你觉得你在笑给谁看？谁会为了你听不懂英语而高兴或伤心？ 我无意找茬，让你不爽我也得不到任何好处。我只想劝你一句，只有在学校才有人逼着你学习什么，进入社会之后你能力不足就被淘汰，除了你的家人没人会在乎你。所以别再“没学过”“看不懂”了，真的，没人逼着你学，也没人在乎你学得会学不会。大家提一些意见解答一些疑点，帮自强努力的人一把没什么，要让别人QQ一步一步像带小孩一样指导你？你觉得大家很闲么？[/quote]我曾经这么给自己说过，如果一个和你不相关的人都会来说教，那你肯定做得太过分了，所以我很感谢你对我说这些，我一定会努力改变的，非常感谢

windows有读写INI文件函数

引用 10 楼 u011497426 的回复:英语好孬的  不懂 你觉得你在笑给谁看？谁会为了你听不懂英语而高兴或伤心？ 我无意找茬，让你不爽我也得不到任何好处。我只想劝你一句，只有在学校才有人逼着你学习什么，进入社会之后你能力不足就被淘汰，除了你的家人没人会在乎你。所以别再“没学过”“看不懂”了，真的，没人逼着你学，也没人在乎你学得会学不会。大家提一些意见解答一些疑点，帮自强努力的人一把没什么，要让别人QQ一步一步像带小孩一样指导你？你觉得大家很闲么？

听说一个没学过的东西，百度该用什么教材，下载电子书学习 如果非要别人手把手教会你——转行吧，技术行业不适合你

没有  我是个新手   你说的这个API是什么我都不知道

英语好孬的  不懂

find some source code

好吧   我知错了   我也在想办法充实自己  提升自己的

LZ确定学会了文件操作的API？

没学过

为什么不试下xml呢？

说实话，你说得高深了，你说的有的知识点我还没学，可不可以把你QQ给我，在论坛上聊太慢了，你加我也行，我QQ是：295812562

如果只是学习文件操作，可以。INI不过就一文本文件。就用fopen, fgets一类的函数就剋搞定。就一文本格式文件的读取和写入的问题。也别INI了，你可以定义一非常简单的文件格式。比如每行一个记录，每个记录由 ID 名字 地址 电话 email QQ 等字段组成，字段间用'\t'分隔。你先试着往这个方向写一下，有具体问题再问。  如果要真正做个有点意思的东西，建议用数据库，比如sqlite, 这样你需要的技能编程: 1. 掌握如何把外部库(dll及 lib)加入你的工程； 2. 基本的SQL知识。  这个可以先放一放，你就用你最初的想法， 练习一下文本文件的读写吧。


Question: 关于rand()%X实现等概率随机的问题

其实这个是伪随机的。

#include <stdio.h> #include <stdlib.h> #include <time.h> unsigned long ulrand(void) {     return (      (((unsigned long)rand()<<24)&0xFF000000ul)     |(((unsigned long)rand()<<12)&0x00FFF000ul)     |(((unsigned long)rand()    )&0x00000FFFul)); } unsigned __int64 ullrand(void) {     return (      (((unsigned __int64)ulrand())<<32)     | ((unsigned __int64)ulrand())); } int i; unsigned long ul; unsigned __int64 ull; void main() {     srand(time(NULL));     for (i=0;i<10;i++) {         ul=ulrand();         printf("%010lu 0x%08x\n",ul,ul);     }     for (i=0;i<10;i++) {         ull=ullrand();         printf("%020I64u 0x%016I64x\n",ull,ull);     } } //3971076432 0xecb1d150 //2433428051 0x910b2a53 //1415415336 0x545d8628 //1312330759 0x4e389407 //1845758378 0x6e0409aa //0008069933 0x007b232d //4202720757 0xfa806df5 //2669855255 0x9f22c217 //0312068736 0x1299ca80 //2084555989 0x7c3fccd5 //03502077880857307931 0x3099e1472040ab1b //16884702393146816355 0xea52835e19b43763 //01877364819396611730 0x1a0dbd5b45f34e92 //07839440151924835771 0x6ccb4948756a05bb //09471412086917299176 0x8371371c820bfbe8 //04411255971577469925 0x3d37edef2f321be5 //13735846279546091130 0xbe9f876a65b7367a //04512980766520059820 0x3ea15418aa9927ac //15821377118299441610 0xdb90d2a9f1bb49ca //15512417228822200185 0xd7472d480398bf79

在使用rand()%x进行模拟随机是，如果x的值不是rand()最大范围的倍数应该就没有办法实现等概率随机了吧?  如果你需要rand超过最大范围的数, 可以使用多次rand来组合.

建议使用如下真正获取随机数的函数：   #include <stdio.h> #include <stdlib.h>  //获得CPU自上电以来的时钟周期数 __declspec (naked) unsigned __int64 GetCpuCycle() { 	_asm 	{ 		rdtsc 		ret 	} }  #define RAND() (srand((unsigned int)GetCpuCycle()), rand())  void main() { 	for (int i = 0; i < 10; i++) 	{ 		int x = RAND() % 9 + 1;	//获取1-9之间的一个随机数 		int y = RAND() % 9 + 1;	//获取1-9之间的一个随机数 		printf("%d %d\n", x, y); 	} }

不应该那么写，应该这么写： int rnd0to100() {     int x = 101;     while (x > 100)     {         x = rand0to150();     }     return x; }

rand() * MAX / RAND_MAX 再注意一下溢出、舍入什么的

严格来说，你是对的，但这样的影响维乎其微，可以忽略。  真的要较真，也是可以调整的。  比如你想要的是0-99 (即%100)这100个整数完全等概，因为机器的限制，RAND_MAX不是正好是100的整数倍，这昂就会导致有那么一些数字(0 到 RAND_MAX%100)比其余的数字有多一次的出现机会，当范围较大的时候，这个影响有时甚至不能忽略，怎么办才能然他们严格等概呢？  最简单的办法是抛弃掉机会不均等的区间的那些值，我们看看是哪些值破坏了严格均等。是大于等于(RAND_MAX-RAND_MAX%范围)的数。 关于边界，我们可以用一组小的数字来考察，比如RAND_MAX是10， 范围是9，那么0-8是等概的，9，10应该被抛弃，所以你可以定义一个自己version的rand()   int myrand(int max) {      int v;      do{        v=rand();      }while(v>=RAND_MAX-RAND_MAX%max);      return v%max;      }   这样就可以保证严格等概了。


Question: c语言中如何在debug下查看stdin所指向的内容呢

#include <stdio.h> FILE *f; int main() {     f=(FILE *)stdin;     printf("stdin->_ptr     ==0x%p\n",f->_ptr     );     printf("stdin->_cnt     ==%d  \n",f->_cnt     );     printf("stdin->_base    ==0x%p\n",f->_base    );     printf("stdin->_flag    ==%d  \n",f->_flag    );     printf("stdin->_file    ==%d  \n",f->_file    );     printf("stdin->_charbuf ==%d  \n",f->_charbuf );     printf("stdin->_bufsiz  ==%d  \n",f->_bufsiz  );     printf("stdin->_tmpfname==0x%p\n",f->_tmpfname);     return 1; } //stdin->_ptr     ==0x10259860 //stdin->_cnt     ==0 //stdin->_base    ==0x10259860 //stdin->_flag    ==257 //stdin->_file    ==0 //stdin->_charbuf ==0 //stdin->_bufsiz  ==4096 //stdin->_tmpfname==0x00000000 //

stdin是一个系统预先定义好的FILE *类型的变量，不用程序员定义，程序员可以直接使用。  如下片段是从stdio.h文件中抽出来的：  _CRTIMP extern FILE _iob[]; #define stdin  (&_iob[0])  在debug模式下，不能直接从变量观察窗口查看其值，用如下代码可以打印出其地址： 	printf("%x08\n", stdin); 在VC6.0下，其值为 0x424A3008 这个地址，该地址是受系统保护的，查看不了其中的值。


Question: [C]动态数组

具体说哪里看不明白，这是一个二维数组的初始化过程

你想 引用 9 楼 ALNG 的回复:int array[5][4]; 怎样把它传递给调用函数以便调用函数还能用[][] 完全可以是 void foo(int parr[][4]) { parr[4][3] = 99; } foo(array);  不一定得用一维数组模拟

引用 10 楼 lin5161678 的回复:你想 [quote=引用 9 楼 ALNG 的回复:] int array[5][4]; 怎样把它传递给调用函数以便调用函数还能用[][] 完全可以是 void foo(int parr[][4]) { parr[4][3] = 99; } foo(array);  不一定得用一维数组模拟[/quote]  试了，确实可以。谢谢！

引用 3 楼 ALNG 的回复:我觉得恰恰相反，这个才叫二维数组。C那个使用一维数组模拟的二维或多维数组，是通过编译器特殊处理糊弄过去的，效率高，但有语法上的漏洞。  int array[5][4];  array是个什么东东？ 假定我在local作用域，比如main函数体中声明/定义它，怎样把它传递给调用函数以便调用函数还能用[][]来存取其中的元素？ 不考虑C中不存在的模板方式，也不许取巧把它放在一个结构体中。没有办法。这时它就得现出一维数组的原形，要把它cast成int *p, 再用类似p[i*4+j]的语法来访问具体的元素。你没用过 数组指针?

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

引用 8 楼 lin5161678 的回复:[quote=引用 3 楼 ALNG 的回复:] 我觉得恰恰相反，这个才叫二维数组。C那个使用一维数组模拟的二维或多维数组，是通过编译器特殊处理糊弄过去的，效率高，但有语法上的漏洞。  int array[5][4];  array是个什么东东？ 假定我在local作用域，比如main函数体中声明/定义它，怎样把它传递给调用函数以便调用函数还能用[][]来存取其中的元素？ 不考虑C中不存在的模板方式，也不许取巧把它放在一个结构体中。没有办法。这时它就得现出一维数组的原形，要把它cast成int *p, 再用类似p[i*4+j]的语法来访问具体的元素。你没用过 数组指针?[/quote]  什么意思，要免费教我吗？洗耳恭听。

第一个*是unary, 只有一个操作数的，这里表示指针，比如我们声明一个指针 int *a; 那么sizeof(int*)和sizeof(a)都会返回同样的结果，在32位编译器上出来是4， 64位编译器出来是8，就是一个整型指针占用的字节数。  第二个*是乘法，这里是整数的乘法  如果sizeof(int*)是4，那么sizeof(int*)*length就是4*length.  因为要分配足够容纳length个int*的空间，所以需要的字节数是length*sizeof(int*)或sizeof(int*)*length.

前面一个是指针，后面一个表示乘法。

引用 3 楼 ALNG 的回复:我觉得恰恰相反，这个才叫二维数组。C那个使用一维数组模拟的二维或多维数组，是通过编译器特殊处理糊弄过去的，效率高，但有语法上的漏洞。  int array[5][4];  array是个什么东东？ 假定我在local作用域，比如main函数体中声明/定义它，怎样把它传递给调用函数以便调用函数还能用[][]来存取其中的元素？ 不考虑C中不存在的模板方式，也不许取巧把它放在一个结构体中。没有办法。这时它就得现出一维数组的原形，要把它cast成int *p, 再用类似p[i*4+j]的语法来访问具体的元素。再问一下，定义size的部分还是没看懂：(sizeof(int*)*length)，没分清两个*的用法，谢谢了

严格来说，这个不叫二维数组，而是数组的数组。 二维数组的特点是每行每列元素相等。并且连续在内存中存放。本质上说，二维数组是一维数组下标分成两部分作乘法的语法糖。  所谓“动态”，在这里主要体现在malloc上，它的作用就是为指针分配内存。分配的大小由sizeof得到的单个元素的大小和元素个数的乘积决定。 malloc得到的内存记得要用free释放，否则会造成泄露。

它是建立一个lengthxlength的二维整型数组，在实用中这并不是一个好方式（成本高), 但用来理解指针和数组还是有一定的意义的。  好了，把length放一个比较小的值，实际比划一下就更容易明白了。大过年的，让我们来二一把吧，就放2.  先看看我们怎么用它。如果对Arr做一次indirection, 比如 *Arr, Arr[0], Arr[1], 我们得到什么呢。答对了，从类型去掉一个*号，成了 int *。什么意思Arr应该是长度为2（length)的整型指针数组。理所当然，如果要从堆中动态分配，应该 Arr=(int **)malloc(sizeof(int*)*length/*2*/); 现在，Arr[0]和Arr[1]放的是什么。整型指针，不过是垃圾指针，指向随机地址，不能拿来用的。怎么办，一个一个来。 Arr[0]应该指向一个长度为2的整型数组，所以 Arr[0]=（int*)malloc(sizeof(int)*length/*2*/); 同样的 Arr[1]=（int*)malloc(sizeof(int)*length/*2*/);  那如果length很大的时候，上面的写法不是要累死人吗？简单，用循环，看以看到，就是Arr的下标变了，其他不变 for(int i=0; i<length; ++i)     Arr[i]=(int*)malloc(sizeof(int)*length);  这就是你看到的。


Question: 用了动态链表输出文件内容，但是运行到最后总是出现debug assertion failed failed fscanf.c line 54

错误或者可改进的地方还真不少   #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define len sizeof(struct student)  struct student {     int number;     char name[20];     struct student *next; };  // 原型声明调出去，这样main更简练 struct student *creat(void); void print(struct student *p4);   int main() {     print(creat()); }  struct student * new_node() { 	struct student* p=(struct student*)malloc(sizeof(struct student)); 	if(!p) 	{     	printf("不能成功分配存储空间。");      	exit(1); 	} 	// 建议把next指针初始化为NULL, 不要节省这点cpu 	// next=NULL; 	return p;	 }  // return NULL if fail to read... struct student* read_a_student(FILE* fp, struct student * s) { 	 //    if(2!=fscanf(fp,"%d%s\n",&s->number,&s->name)) //    { //        printf("读取学生信息失败。文件格式错误或未预期的文件结束！"); //        exit(1); //    }     return 2!=fscanf(fp,"%d%s\n",&s->number,&s->name) ? NULL : s; }  struct student* read_student_ex(FILE*fp) { 	return read_a_student(fp, new_node()); }  struct student *creat(void) {     struct student *p1,*p, *p2;     // 用p指向表头，p1指向表尾，或者用head, tail更容易理解     // 你最后返回的p什么地方初始化的，好像没有？也许我看错了。     //     FILE *fp;        // 下面的错误最恐怖最致命，遗憾的是c编译器发现不了，     // 我还真没注意，把文件名改成cpp, 编译器一下帮我发现了。     // 所以...     if((fp=fopen("name2.txt","r"))==NULL)     {         printf("cannot open");         exit(0);     }          //p1=(struct student *)malloc(len); //    if((p=(struct student *)malloc(len)) == NULL) //    { //    } //    else       printf("hello");          p=p1=read_student_ex(fp);          while(p1->number!=2012210420 && NULL!=(p2=read_student_ex(fp)))     { //      没必要，一个指表头，一个指表尾，总是加在表尾         //        if(i>1) //        { //            p2->next=p1; //            p2=p1; //        } //        else //        	p=p1; //        i++;  		// 链入新增节点，然后更新表尾指针以备下一次append 		p1->next=p2; 		p1=p2; 		 //        p1=(struct student *)malloc(len); //        if((p1=(struct student *)malloc(len)) == NULL) //        { //         printf("不能成功分配存储空间。"); //         exit(1); //        } //        fscanf(fp,"%d%s\n",&p1->number,&p1->name);     }     p1->next=NULL;      //free(fp);     fclose(fp);     return(p); } void print(struct student *p4) {        struct student *p;     p=p4;     do     {         printf("%d %s\n",p->number,p->name);         p=p->next;     }while(p!=NULL); }

p1=(struct student *)malloc(len);         if((p1=(struct student *)malloc(len)) == NULL) 为什么分配两次  fp并不是动态分配的，为什么要free?  fscanf真没看出问题，可能是其他地方的问题. 上面两个肯定是问题，但未必是导致你观测到的错误的问题。程序写得是有点乱的，完成主功能的create函数做太多事了，要分派一些出去，让它精简一些，更容易阅读和维护


Question: 本人刚自学，有些疑问，可以用C语言编写游戏吗

完全可以！还是c++、c# 做界面方便

书 名: Windows程序设计（第五版 珍藏版） 作　者：佩措尔德(CharlesPetzold) 可以让你用纯C写界面程序。 如果你懂点C++，懂点MFC，尝试自己用C++的思想把书中的东西封装成自己的类库。 然后在去学下C#,你会发现。。。。。。。

C语言是绝对可以的，写出的游戏效率还要高呢

引用 25 楼 AGong1990 的回复:以上有几楼说的不太准确，我也来说说我的看法 C语言当然可以写出有界面的程序，当然这得依赖操作系统提供的API或GUI包装库之类的，在windows上最典型的就是GDI相关的API函数，这些函数都是C语言写的，但是界面程序的入口是变成WinMain了，里面还涉及到消息循环，窗口，窗口消息之类的东西，至于楼上有同学说用C#来做界面，至于桌面开发的天堂我就不同意了 桌面软件开发的主流还是C/C++，用C#的话运行效率肯定没有C/C++好，兼容性问题是硬伤，依赖于.net framework，像QQ,360等等软件基本都是C/C++开发的，当然都是用界面库了，或自己做的，或买的了。如开发的界面库duilib，也有很多软件产品使用了，QT的话YY语音在用，WPS好像也是  游戏的话C/C++也是主流，小游戏用GDI即可，大型的一般都会用游戏引擎了，不会直接用DirectX

可以依托库和游戏引擎  C+WinAPI，你可以写出任何windows程序

可以写游戏。  界面与C无关，需要界面相应的API。  学C推荐看TCPL。

C+WinAPI，你可以写出任何windows程序

请教qt是什么

很多优秀的游戏都是用C语言写的、

可以学mfc和qt，mfc就是用vc++6.0编写可视化界面的，如果单纯靠c只能写出类似dos环境下的黑白界面!

c语言很强大的，其实不同语言还是相通的，你熟练其中之一，在熟悉其他的也不会吃力的

谢谢你的经验分享！其实我觉得c入门可能简单点，但想要精通得费不少功夫

有些头目了0 0  新手还是要有毅力啊 。。。。。

受教了，我也是新手

c++作为起点、、转向C#、、、那才是桌面开发的天堂

我也是学习C的新手，之前自学了其他语言，略懂一些，这里和你分享一下我的看法： 要快速的写windows上的软件，那就去学习C#，开发速度很快，界面也还可以，看你自己的美工！ java我不知道了，但看过相关的文章，现在手机上的游戏基本都是这个平台开发 C这个是很强大的，可以开发任何东西，看个人能力，你可以用它来写底层，如开发系统，驱动编写等等，当然，你也可以用它写软件，不是很复杂的完全可以用C写，要是复杂一点就要用C++来写了，C不是面向对象的语言，写大东西会有气无力的~ 汇编就不说了，精通汇编的人基本是开挂投胎的，我们不讨论  最后，要是我早点知道C不难学，我就不会走那么多弯路了。但想想，走过弯路才知道更多的经验

1.c和指针 2.c缺陷与陷阱 3.c专家编程 4.编程珠玑 自己可以在csdn上搜索，我说不全

引用 10 楼 u010913001 的回复:[quote=引用 9 楼 caozhy 的回复:] 谭浩强之流学得如同皮毛的皮毛。  好比你说学好数学可以预测天气预报么？很遗憾，学会小学一年级的算术估计不能。  用程序设计语言编写程序究竟能写出什么不在于语言，而在于人。所有的通用编程语言都是图灵完备的，或者说是等价的，这意味着没有任何一种语言有超越计算机本身或者另一种语言的特异功能。 最后一句读的好不通顺啊[/quote] Google 图灵完备 图灵等价。

引用 9 楼 caozhy 的回复:谭浩强之流学得如同皮毛的皮毛。  好比你说学好数学可以预测天气预报么？很遗憾，学会小学一年级的算术估计不能。  用程序设计语言编写程序究竟能写出什么不在于语言，而在于人。所有的通用编程语言都是图灵完备的，或者说是等价的，这意味着没有任何一种语言有超越计算机本身或者另一种语言的特异功能。 最后一句读的好不通顺啊


Question: 求助求助,二叉排序树删除结点的问题

大哥,您太好了 这是辛苦了

看别人的代码辛苦，不如我们来说说这个事应该或者说可以怎么做。  首先，假定我们把我们要做的函数的原型声明成这样  node * remove_node_with_value(node * tree， int value);   它干什么呢，给定一颗输入的binary search tree, 和特定的值，从树中删除值为给定值的节点，但要保证其他剩余的节点还是构成一株binary search tree，返回这颗新树的根节点。这个函数怎么写呢？树的特点就是递归，如果value比根节点的value小，从其左子树中删之，如果value比根节点的value大，从其右子树删之。难点是当要删除的节点就是根节点的时候。先易后难，这个难点我们先保留，好了代码出来了  node * remove_node_with_value(node * tree， int value) {      if(tree)      {           if(value<tree->value)                tree=remove_node_with_value(tree->left, value);           else if(value>tree->value)                tree=remove_node_with_value(tree->right, value);           else                tree=remove_root_node(tree);      }      return tree; }   好了，在我们把重心转向我们新的难点remove_root_node之前，我们来想想上面的方法可能的漏洞。binary search tree一般是允许节点的值重复的，它的构造方式一般是如果比根节点的值小，加在左树，反之加在右树。也就是说当要删除的值在根节点时，不能排除右子树还有同值的节点，这个节点该不该删除了？这是需求定义的，如果需要，上面的代码就该改成这样  node * remove_node_with_value(node * tree， int value) {      if(tree)      {           if(value<tree->value)                tree=remove_node_with_value(tree->left, value);           else{                if(tree->value==value)                    tree=remove_root_node(tree);                               tree=remove_node_with_value(tree->right, value);          }      }      return tree; }   好了注意力转回remove_root_node, 我们需要这个函数做的事是，对给定的排序二叉树，删除其根节点，但要保证其余的节点构成一株排序二叉树。同样的，返回值是新的树的根节点(指向其的指针)。  分三种情形，该节点的左子树为空，直接返回右子树就好；该节点的左子树为空，直接返回左子树就好；第三种左右子树都非空，这个是难点，先易后难，好了代码出来了  /* param: tree should not be empty */ node * remove_root_node(node * tree) {       node * n;       if(!tree->left)           n=tree->left;       else if(!tree->right)           n=tree->right;       else{ // both left and right are non-empty         // to be continued ...       }       free(tree);       return n; }   如果一个树的根节点的左右子树都非空，怎样搬走它呢？我们知道，所有左子树的节点的值都小于根节点的值，从而也都小于右子树的节点的值，如果我们能把左子树节点中值最大的节点提拔上来做新树的根节点，可以直接把原右子树做为这个节点的右子树，新树构成一株去掉了原根节点后的新的排序二叉树，而这这是我们要的。现在问题有转化成给定一株树，如何廉价地从它构造出一颗新的排序二叉树，该树包含了原树的所有节点，但根节点的右子树为空。在具体实现这个函数时，我们先给他起个名字，定个原型  node * reform_tree_to_null_right_tree(node * tree);   有了它，上面的函数就可以完满了。如下  /* param: tree should not be empty */ node * remove_root_node(node * tree) {       node * n;       if(!tree->left)           n=tree->left;       else if(!tree->right)           n=tree->right;       else{ // both left and right are non-empty           n=reform_tree_to_null_right_tree(tree->left);           n->right=tree->right;       }       free(tree);       return n; }   转战reform_tree_to_null_right_tree。树的最大节点是最右边的那个节点。这个节点必须被提拔到最高层。代码如下:   node * reform_tree_to_null_right_tree(node * tree) { 	node * n, *m; 	if(tree->right==NULL) 		return tree; 	n=tree; 	while(n->right) 	{ 		m=n; 		n=n->right; 	} 	m->right=n->left; 	n->left=tree; 	return n; }   什么意思呢？如果根节点的右子树本来就为空，共产主义已经实现，还折腾啥？直接返回吧！否则向右再向右，直到行到水穷处，好了这个家伙就是最大个的了。我们需要记住它的父节点，把这个节点的左子树交给父节点做右子树就好了(为什么？）  到这里就完成了。程序不重要，甚至找出你的错误不重要。这里展示的一种分而治之，自顶向下设计的思维方式，是面向过程的C程序员必须具备并能熟练运用的。这个技能到C++或者其他语言的时候，也还是继续有效的。  下面是一个简单测试过的完整实现:  #include <stdio.h> #include <stdlib.h>  typedef struct node{ 	int value; 	struct node *left, *right; }node;  node* binary_tree_add(node * tree, int value) { 	if(!tree) 	{ 		node * n; 		n=(node*)malloc(sizeof(node)); 		n->value=value; 		n->left=n->right=NULL; 		return n; 	} 	if(value<tree->value) 		tree->left=binary_tree_add(tree->left, value); 	else 		tree->right=binary_tree_add(tree->right, value); 	 	return tree; }   void left_root_right(node * n) { 	if(!n) 		return; 	left_root_right(n->left); 	printf("%d ", n->value); 	left_root_right(n->right); }  void print_tree(node *n) { 	left_root_right(n); 	putchar('\n'); }   /* remove the root node of a tree  * and return the pointer to the root of the new binary search   * tree with the original rood node removed  *   * param: tree should not be empty  */ node * remove_root(node * tree);  node * delete_node_with_value(node * tree, int value) { 	if(tree) 	{ 		if(value<tree->value) 			tree->left=delete_node_with_value(tree->left, value); 		else{ 			if(tree->value==value) 				tree=remove_root(tree); 			if(tree && tree->right) 				tree->right=delete_node_with_value(tree->right, value); 		} 	} 	return tree; }  /* for input binary search tree t, build a new binary search tree such that  * the right child of the new tree is NULL.   *  * param: tree should not be NULL  */  node * reform_tree_to_null_right(node * tree);  node * remove_root(node * tree) { 	node * n; 	if(tree->left==NULL) 		n=tree->right; 	else if(tree->right==NULL) 		n=tree->left; 	else{ 		n=reform_tree_to_null_right(tree->left); 		n->right=tree->right; 	} 	free(tree); 	return n;		 }  node * reform_tree_to_null_right(node * tree) { 	node * n, *m; 	if(tree->right==NULL) 		return tree; 	n=tree;  	while(n->right) 	{ 		m=n; 		n=n->right; 	} 	m->right=n->left; 	n->left=tree; 	return n; }   int main(int argc, const char *argv[]) { 	 	 	node * tree=NULL; 	 	srand(time(NULL)); 	 	for(int i=0; i<20; ++i) 		tree=binary_tree_add(tree,rand()%100); 	tree=binary_tree_add(tree,50); 	 	print_tree(tree);  	tree=delete_node_with_value(tree,50);  	print_tree(tree);  	return 0; }


Question: 函数指针的声明

没问题。

typedef int (*cmpfunction)(point_t*, point_t *); cmpfunction pf; pf=myfun1; int result=pf(&p1,&p2);

没问题，亲！

没问题


Question: getchar读取缓冲区字符问题

getchar()只接受一个，你的循环结束不了，吃回车的

肯定的啊，回车也算是一个字符了。输入e回车，这是两个字符，进入循环两次。  ead回车，除了a不满足条件，其余都满足，会循环三次。

getchar每收到一个值的时候就返回,键入回车也同样返回。

引用 11 楼 robert_chen1988 的回复:[quote=引用 10 楼 a345485527 的回复:] [quote=引用 9 楼 robert_chen1988 的回复:] [quote=引用 4 楼 a345485527 的回复:] lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出  我想问一下，e进入循环两次后，为啥getchar没有字符读了呢，它为什么不一直读换行符呢？ [/quote] 为什么要一直读换行符呢？ 和读完e之后要读取下一个字符一个道理呀 因为按照输入，缓冲区中目前只有两个字符，<e，回车> 读完e之后，可以理解为把e踢出去了，下一个再读回车，然后再读，发现缓冲区没数据了，所以就等待用户输入了 照您这种想法来说，为什么不一直读e呢？ 这里有个博客，刚刚查的，它用开闸放水做了类比，可以参考下[/quote]  非常感谢，我目前c语言只看了谭浩强的两本书，还没有缓存区的概念，谢谢了，看来需要学的还有不少[/quote] 看完谭浩强的就看国外的书，虽然我没看过老谭的，不过口碑很不好，误人子弟

引用 10 楼 a345485527 的回复:[quote=引用 9 楼 robert_chen1988 的回复:] [quote=引用 4 楼 a345485527 的回复:] lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出  我想问一下，e进入循环两次后，为啥getchar没有字符读了呢，它为什么不一直读换行符呢？ [/quote] 为什么要一直读换行符呢？ 和读完e之后要读取下一个字符一个道理呀 因为按照输入，缓冲区中目前只有两个字符，<e，回车> 读完e之后，可以理解为把e踢出去了，下一个再读回车，然后再读，发现缓冲区没数据了，所以就等待用户输入了 照您这种想法来说，为什么不一直读e呢？ 这里有个博客，刚刚查的，它用开闸放水做了类比，可以参考下[/quote]  非常感谢，我目前c语言只看了谭浩强的两本书，还没有缓存区的概念，谢谢了，看来需要学的还有不少

引用 9 楼 robert_chen1988 的回复:[quote=引用 4 楼 a345485527 的回复:] lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出  我想问一下，e进入循环两次后，为啥getchar没有字符读了呢，它为什么不一直读换行符呢？ [/quote] 为什么要一直读换行符呢？ 和读完e之后要读取下一个字符一个道理呀 因为按照输入，缓冲区中目前只有两个字符，<e，回车> 读完e之后，可以理解为把e踢出去了，下一个再读回车，然后再读，发现缓冲区没数据了，所以就等待用户输入了 照您这种想法来说，为什么不一直读e呢？ 这里有个博客，刚刚查的，它用开闸放水做了类比，可以参考下

引用 4 楼 a345485527 的回复:lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出  我想问一下，e进入循环两次后，为啥getchar没有字符读了呢，它为什么不一直读换行符呢？

引用 7 楼 a345485527 的回复:[quote=引用 6 楼 u012757050 的回复:] [quote=引用 4 楼 a345485527 的回复:] lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出回车也符合循环条件？不懂。[/quote] ASCII码 十进制 回车13，a是97，满足条件[/quote]了解

引用 6 楼 u012757050 的回复:[quote=引用 4 楼 a345485527 的回复:] lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出回车也符合循环条件？不懂。[/quote] ASCII码 十进制 回车13，a是97，满足条件

引用 4 楼 a345485527 的回复:lz我记得你.... getchar吃回车 输入  e 回车，进入循环两次 由于没有字符读了，所以阻塞在while循环中的getchar函数处 输入ead,a不满足循环条件，所以循环退出回车也符合循环条件？不懂。


Question: C语言怎样写代理服务器，能实现GET请求和CONNECT请求

说白了，就是映射一下当前连接，数据转发而已

搜一下socket编程, 一般都有示范代码, 没有特殊要求的话, 代码很简单.


Question: 【求助帖】循环产生随机数的问题

应用程序初始化的时候调用即可，比如main函数进入后，即可执行随机种子初始化。

引用 1 楼 user-3 的回复:随机数的种子没有变化， 在主函数里面 加 srand (time (NULL)); 要注意这个函数，放的位置，   函数应该放在哪个位置呢？

LS正解，srand(time(NULL));


Question: 看看这句话是什么意思

引用 10 楼 richyhuang 的回复:把ulong型的数据赋给float型的变量,我认为结果没有任何意义。那应该怎么做

把ulong型的数据赋给float型的变量,我认为结果没有任何意义。

这样赋值是不对的吧，没有什么实质作用吧

感觉意义不大啊，语句的作用好像是把long型的值的二进制形式解释成了float值

引用 6 楼 user-3 的回复:你从哪里挖的代码？这段代码是不是用于学习和理解浮点数用的？嘿嘿，在做一个测试，搞不懂，这是别人的程序。

你从哪里挖的代码？这段代码是不是用于学习和理解浮点数用的？

我不十分确定你的目的，很难描述。  可以试试：  unlong1 = strtoul(buf2,NULL,16); f5 = (float)unlong1;

引用 3 楼 user-3 的回复:直接赋值可能得到一个为止的结果。  这句说错了，太绕了。  其实是想说，如果没有经过整型到浮点变化的赋值，会得到一个未知结果。  就说你运行你写那段代码，可能得到未知结果。这句代码应该怎么改，程序原来的语句是这样的：        unlong1 = strtoul(buf2,NULL,16);         *((unsigned long *)&f5)=unlong1; buf2是char类型，长度为 256。如果直接赋值，unlong1和f5就是一样的。这块应该是将unlong1转换成float 类型.谢谢！！

引用 1 楼 user-3 的回复:有区别，直接赋值，是将一个整型进行浮点变化后，赋值给一个浮点数。  用指针赋值是将浮点数的内存区域直接用整型替换掉，不涉及整形到浮点的变换。  直接赋值可能得到一个为止的结果。  另外这段代码在64位的linux上会有问题。还好，我的是32位系统，我打印输出之后，发现f5是-NAN


Question: 为什么我写的快排比堆排序要慢得多？

for那里。。。是从left到right遍历一次，相当于每次递归，你都要遍历一次，当然你这个有点像动态规划，交换次数可能比插入要少一点  要是序列稍微特殊一点，你这个算法就直接是O(N^2)了

应该是数据分布不佳所致，一般数组小到一个程度转成插入排序，递归过深转为堆排，不要全程都是快排...

先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\qsort.c

都是用release版本测试的吗？

没看出来这个是快排,感觉你这个复杂度为O(n^2) 因为你一个for,再加了一个递归  感觉像是变形的冒泡~~~~  堆排序复杂度是lgn*n     你这个方法说的不好听的  比2个for还烂  如果设计到数据查找的话,  最好还是用红黑树  每次插入最多做3次旋转即可,当然你这种已经存在大批量的数据的画,最快的还是快排 但是如果是频繁性的插入和查找的话还是应该用rbtree

交换太多  字数补丁


Question: 求c语言大学课程视频

C语言视频教程:  http://www.tudou.com/plcover/z5u9lwXuPKU/

鱼C论坛上有个C入门视频  既然是大二看起来肯定很轻松

“C Primer Plus” 大神书籍，还需要看视频？

百度网盘上有赫斌老师的c语言视频

建议看郝斌的C语言视频，讲的不错，适合入门

建议看国外的~


Question: ACM A == B ? 问题

如下修改可AC: #include<stdio.h> #include<string.h>  int main() {      int num,i,j;   static char a[100000],b[100000];//改  char a[100],b[100];   while(scanf("%s%s",a,b)!=EOF)   {     //加 判断正负号     if((a[0]=='-' && b[0]!='-' ) || (a[0]!='-' && b[0]=='-'))     {       printf("NO\n");       continue;     }     if(a[0]=='+' || a[0]=='-')         a[0]='0';       if(b[0]=='+' || b[0]=='-')         b[0]='0';        num=strlen(a);      for(i=0;i<num-1;i++)//改  for(i=0;i<num;i++) 处理前置的0，如果a[0]=0,就把a[1]的值及后面的值向前挪一位      {       if(a[i]=='0')        {//加         for(j=0;j<num;j++)         {           a[j]=a[j+1];           //删 i--;         }         i--;//加        }//加       else break;     }      num=strlen(a);     for(i=0;i<num;i++)//处理后置的0 ，检测到小数点就从最后一位开始检测是否为0，如果是就把0用\0代替        if(a[i]=='.')       {         for(i=num-1;i>0;i--)         {           //printf("ai=%c\n",a[i]);           if(a[i]=='0')             a[i]='\0';           else break;         }       }      if (a[strlen(a)-1]=='.') a[strlen(a)-1]='\0'; //加      //printf("%s\n",a);	      num=strlen(b);     for(i=0;i<num-1;i++)//改 for(i=0;i<num;i++)     {       if(b[i]=='0') //改 if(b[0]=='0')        {//加         for(j=0;j<num;j++)         {           b[j]=b[j+1];           //删 i--;         }         i--;//加        }//加       else break;     }     num=strlen(b);     for(i=0;i<num;i++)       if(b[i]=='.')       {         for(i=num-1;i>0;i--)         {           if(b[i]=='0')             b[i]='\0';           else break;         }       }        //printf("%s\n",b);	     if (b[strlen(b)-1]=='.') b[strlen(b)-1]='\0'; //加      if(strcmp(a,b)==0)       printf("YES\n");     else printf("NO\n");   }   return 0; }

引用 2 楼 ALNG 的回复:如果输入限制在整数，你不用这么辛苦。  如果输入有可能是浮点数，你的程序貌似处理不了1.5e10一类的输入。  建议，先用int试，不行再用double试。用double的话，记得比较相等不要直接用==，看他们的差的绝对值是否小于 epsilon.这个题的坑爹之处就是题目要求太少，可能性太大，我在网上找了AC的代码，思路应该是这样的没错，可是就是不知道哪里有问题   #include <stdio.h> #include <string.h>  void A(char *s) {     int len = strlen(s);     char *p = s + len - 1;     if (strchr(s, '.'))     while (*p == '0') *p-- = 0;     if (*p == '.') *p = 0; }  int main(void) {     char *pa, *pb;     char a[100024], b[100024];      while (scanf("%s%s", &a, &b) != EOF)     {         pa = a; pb = b;         while (*pa == '0') pa++;         while (*pb == '0') pb++;         A(pa); A(pb);         puts(strcmp(pa, pb) ? "NO" : "YES");     }      return 0; }


Question: 求更好的方法，谭浩强习题讨论

引用 3 楼 lpcads 的回复:void divproc(int a) //递归函数 { 	if(a!=0) 	{ 		divproc(a/10); 		cout<<a%10<<endl; //显示余数 	} 	return; } int main( )  { 	//若n为0，则需打印出‘0’ 	//if(n==0)  		//cout<<'0'<<endl; 	divproc(n); 	system("pause"); 	return 0; } 这是以前学汇编时的legacy了，功能是顺序输出每一位数字，现在看看写得真烂。 特别改了下： #include <iostream> using namespace std;  void each_digit_recursion(int a) //递归函数 { 	if (a == 0) 		return ;  	each_digit_recursion(a / 10); 	cout << a % 10 << ' '; //显示余数 	 }  void output_each_digit(int a) { 	cout << "each digit: "; 	if (a == 0) 		cout << '0'; 	else 		each_digit_recursion(a);  }   void reverse(int a) { 	cout << "reverse: "; 	while (true) 	{ 		cout << a % 10; 		a /= 10; 		if (a == 0) 			break; 	} 	 }  int main() { 	int n = 1234567; 	cout << "num: " << n << endl; 	output_each_digit(n); 	cout << endl; 	reverse(n);  	cout << endl; 	cout << endl;  	n = 0; 	cout << "num: " << n << endl; 	output_each_digit(n); 	cout << endl; 	reverse(n);  	cout << endl;  	system("pause"); 	return 0; }

首先要明确给出的数字的数据类型  计算机不是人

使用递归啊。

写的太复杂了，这个会不会简单点？ #include <stdio.h>  int main(void) { 	int a, b = 0, dig, count = 0;  	printf("Please input a integer: "); 	scanf("%d", &a); 	 	while(a) 	{ 		dig = a % 10; 		printf("%d\n", dig);  // 输出每个数字 		b = b * 10 + dig; 		a /= 10; 		count++; 	} 	printf("Digit number is %d\n", count); // 输出位数 	printf("Reverse order is %d\n", b);    // 输出反序 	getchar(); 	getchar(); 	return 0; }


Question: C控制结构与链表的插入操作问题

谢谢啦……。

这些地方有错误: 1. print_matrix里面的if(p || p->j==b)应该是if(p && p->==b) 2. create_matrix里面的 	    r=k/M->m; 	    c=k%M->m; 应该改成 	    r=k/M->n; 	    c=k%M->n; 3. Matrix插入节点的函数整个混乱，改无可改，两个链表应该分别插入。    #include "stdio.h" #include "stdlib.h" #include "stdbool.h"  typedef struct node { 	int i,j,val; 	struct node *row,*col; }Node;  typedef struct matrix { 	int m,n; 	struct node *rhead[10],*chead[10]; }Matrix;  Matrix* insert_matrix(Matrix* M,Node* N) { 	/* 分别插入行列链表不就容易了？ 	 */ 	Node *p; 	//插入行链表 	if(!(p=M->rhead[N->i])) 		M->rhead[N->i]=N; 	else{ 		while(p->row && p->j<N->j) 			p=p->row; 		if(p->j<N->j) // append as the last node 			p->row=N; 		else if(p->j==N->j) // update data 		{ 			p->val=N->val; 			free(N); 			// no need to worry about chead list as it's correct already! 			return M; 		}else{ // link in as p's next node 			N->row=p->row; 			p->row=N; 		} 	} 	//插入列链表 	if(!(p=M->chead[N->j])) 		M->chead[N->j]=N; 	else{ 		while(p->col && p->i<N->i) 			p=p->col; 		if(p->i<N->i) // append as the last node 			p->col=N; 		else { // link in as p's next node 			N->col=p->col; 			p->col=N; 		} 	} 	return M; }  Matrix* creat_matrix() { 	Matrix *M; 	Node *N; 	int k,v,r,c; 	M=(Matrix*)malloc(sizeof(Matrix)); 	for(k=0;k<10;k++) 		M->rhead[k]=NULL; 	for(k=0;k<10;k++) 		M->chead[k]=NULL; 	printf("请输入矩阵的行,列数:"); 	scanf("%d%d",&M->m,&M->n); 	printf("请输入矩阵元素:"); 	for(k=0;k<M->m*M->n;k++) 	{ 	 	scanf("%d",&v); 	    r=k/M->n; 	    c=k%M->n; 		if(v!=0) 		{ 		   N=(Node*)malloc(sizeof(Node)); 		   N->i=r;N->j=c; 		   N->val=v; 		   N->row=N->col=NULL; 		   M=insert_matrix(M,N); 	   } 	 }	 	 return M; }  void printf_matrix(Matrix *M) { 	int a,b; 	Node *p; 	for(a=0;a<M->m;a++) 	{ 		p=M->rhead[a]; 		for(b=0;b<M->n;b++) 		{ 			if(p && p->j==b) 			{ 				printf("%d ",p->val); 				p=p->row; 			} 			else 				printf("0 "); 		} 		printf("\n"); 	} }  main ( ) {  Matrix *M;  M=creat_matrix();  printf_matrix(M);  return 0;	 }


Question: getchar函数与purchar函数到底是怎样啊？

getchar一次读一个字符 putchar一次输出一个字符  BUT  问题的关键在于，你是在一个循环中使用putchar和getchar。

引用 4 楼 a345485527 的回复:[quote=引用 2 楼 u012757050 的回复:] [quote=引用 1 楼 a345485527 的回复:] 输出什么lz跑一次就知道了 getchar一次是只读一个字符，但是是从缓冲区中读取， 输入she walks in beauty会存至缓冲区中，每次取出一个字符，然后Putchar ctrl+z结束  另外，求助she walks in beauty怎么翻译我是新手，未在电脑操作过，请问我输入句子后回车，打印出s吗？ 然后其他字符怎么取出来。[/quote] 会打印整句话 输入句子后，she walks in beauty会存储在缓冲区中 getchar从该缓冲区中一个一个读取字符， 首先读取's'，然后putchar 由于处于while循环中，所以继续调用getchar，这次调用从缓冲区中取出第二个字符'h'，然后putchar 以此类推，一直循环取出每个字符，然后putchar这个字符，所以你会看到输出了完整的一句话 当遇到EOF时结束[/quote]明白 谢谢

引用 2 楼 u012757050 的回复:[quote=引用 1 楼 a345485527 的回复:] 输出什么lz跑一次就知道了 getchar一次是只读一个字符，但是是从缓冲区中读取， 输入she walks in beauty会存至缓冲区中，每次取出一个字符，然后Putchar ctrl+z结束  另外，求助she walks in beauty怎么翻译我是新手，未在电脑操作过，请问我输入句子后回车，打印出s吗？ 然后其他字符怎么取出来。[/quote] 会打印整句话 输入句子后，she walks in beauty会存储在缓冲区中 getchar从该缓冲区中一个一个读取字符， 首先读取's'，然后putchar 由于处于while循环中，所以继续调用getchar，这次调用从缓冲区中取出第二个字符'h'，然后putchar 以此类推，一直循环取出每个字符，然后putchar这个字符，所以你会看到输出了完整的一句话 当遇到EOF时结束

getchar只要你输入马上就退出了。

引用 1 楼 a345485527 的回复:输出什么lz跑一次就知道了 getchar一次是只读一个字符，但是是从缓冲区中读取， 输入she walks in beauty会存至缓冲区中，每次取出一个字符，然后Putchar ctrl+z结束  另外，求助she walks in beauty怎么翻译我是新手，未在电脑操作过，请问我输入句子后回车，打印出s吗？ 然后其他字符怎么取出来。


Question: 怎样让程序往txt文件里的字符，在txt里实时显示，最好是往txt里写一个字符，txt文件就显示一个字符

fflush(你打开的文件的指针)

FILE *fp; //... fprintf(fp,...); fflush(fp); 不过看需求好像是要实时显示？

fflush意味着缓冲区内容写入文件指针（如果参数是一个文件指针的话） 然后 清空缓冲区，是我没有表述明白？

你的意思是写一个字符就flush一次啊 能不能flush函数的语句的给我写一下 我是用fprintf往txt文件写数据的哦

写好数据调用下这个 fflush


Question: 菜鸟求助，ping程序无法记录时间

引用 8 楼 zhao4zhong1 的回复:我看错了，可以不带"-t "前缀的。上帖第224行去掉注释。 听说Win7下不让SOCK_RAW了，或者需要提权啥的，搜“Win7 SOCK_RAW”。 我是Windows Server 2003 为什么我用你上面改过的代码，确跑不出你  Limitations on Raw Sockets  On Windows 7, Windows Vista, Windows XP with Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3), the ability to send traffic over raw sockets has been restricted in several ways: TCP data cannot be sent over raw sockets. UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address). A call to the bind function with a raw socket for the IPPROTO_TCP protocol is not allowed.  哎，正如你所说，win7限制SOCK_RAW的使用了，看来得找其他方案实现ping了。非常感谢你热心的帮助，谢谢！

GetTickCount计时精度不如timeGetTime #include <stdio.h> #include <stdlib.h> #include <winsock.h> #include <mmsystem.h> #pragma comment(lib, "ws2_32") #pragma comment(lib, "winmm") #define ICMP_ECHOREPLY 0 //ICMP回应答复 #define ICMP_ECHOREQ 8 //ICMP回应请求 #define REQ_DATASIZE 32 //请求数据报大小 #include <iostream> using namespace std;  //定义IP首部格式 typedef struct _IPHeader {     u_char VIHL; //版本和首部长度     u_char ToS; //服务类型     u_short TotalLen; //总长度     u_short ID; //标识号     u_short Frag_Flags; //片偏移量     u_char TTL; //生存时间     u_char Protocol; //协议     u_short Checksum; //首部校验和     struct in_addr SrcIP; //源IP地址     struct in_addr DestIP; //目的地址 } IPHDR, *PIPHDR;  //定义ICMP首部格式 typedef struct _ICMPHeader {     u_char Type; //类型     u_char Code; //代码     u_short Checksum; //首部校验和     u_short ID; //标识     u_short Seq; //序列号     char Data; //数据 } ICMPHDR, *PICMPHDR;  //定义ICMP回应请求 typedef struct _ECHOREQUEST {     ICMPHDR icmpHdr;     DWORD dwTime;     char cData[REQ_DATASIZE]; } ECHOREQUEST, *PECHOREQUEST;  //定义ICMP回应答复 typedef struct _ECHOREPLY {     IPHDR ipHdr;     ECHOREQUEST echoRequest;     char cFiller[256]; } ECHOREPLY, *PECHOREPLY;  //计算校验和 u_short checksum(u_short *buffer, int len) {     register int nleft = len;     register u_short *w = buffer;     register u_short answer;     register int sum = 0;     //使用32位累加器,进行16位的反馈计算     while ( nleft > 1 ) {         sum += *w++;         nleft -= 2;     }     //补全奇数位     if ( nleft == 1 ) {         u_short u = 0;         *(u_char *)(&u) = *(u_char*)w;         sum += u;     }     //将反馈的16位从高位移到低位     sum = (sum >> 16) + (sum & 0xffff);     sum += (sum >> 16);     answer = ~sum;     return (answer); }  //发送回应请求函数 int SendEchoRequest(SOCKET s, struct sockaddr_in *lpstToAddr) {     static ECHOREQUEST echoReq;     static int nId = 1;     static int nSeq = 1;     int nRet;     //填充回应请求消息     echoReq.icmpHdr.Type = ICMP_ECHOREQ;     echoReq.icmpHdr.Code = 0;     echoReq.icmpHdr.Checksum = 0;     echoReq.icmpHdr.ID = nId++;     echoReq.icmpHdr.Seq = nSeq++;     //填充要发送的数据     for (nRet = 0; nRet < REQ_DATASIZE; nRet++) {         echoReq.cData[nRet] = '1' + nRet;     }     //存储发送的时间     echoReq.dwTime = timeGetTime();     //计算回应请求的校验和     echoReq.icmpHdr.Checksum = checksum((u_short*)&echoReq, sizeof(ECHOREQUEST));     //发送回应请求     nRet = sendto(s,(LPSTR)&echoReq,sizeof(ECHOREQUEST),                   0,(struct sockaddr*)lpstToAddr,sizeof(SOCKADDR_IN));     if (nRet == SOCKET_ERROR) {         printf("send to() error:%d\n", WSAGetLastError());     }     return (nRet); }  //接收应答回复并进行解析 DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) {     ECHOREPLY echoReply;     int nRet;     int nAddrLen = sizeof(struct sockaddr_in);     //接收应答回复     nRet = recvfrom(s,(LPSTR)&echoReply,sizeof(ECHOREPLY),                     0,(LPSOCKADDR)lpsaFrom,&nAddrLen);     //检验接收结果      if (nRet == SOCKET_ERROR) {         printf("recvfrom() error:%d\n",WSAGetLastError());     }     //记录返回的TTL     *pTTL = echoReply.ipHdr.TTL;     //返回应答时间     return(echoReply.echoRequest.dwTime); }  //等待回应答复,使用select模型 int WaitForEchoReply(SOCKET s) {     struct timeval timeout;     fd_set readfds;     readfds.fd_count = 1;     readfds.fd_array[0] = s;     timeout.tv_sec = 1;     timeout.tv_usec = 0;     return(select(1, &readfds, NULL, NULL, &timeout)); }  //PING功能实现 void Ping(char *pstrHost,bool logic) {     SOCKET rawSocket;     LPHOSTENT lpHost;     struct sockaddr_in destIP;     struct sockaddr_in srcIP;     DWORD dwTimeSent;     DWORD dwElapsed;     u_char cTTL;     int nLoop,k=4;     int nRet,minimum=100000,maximum=0,average=0;     int sent=4,reveived=0,lost=0;     //创建原始套接字,ICMP类型     rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);     if (rawSocket == SOCKET_ERROR) {         printf("socket() error:%d\n", WSAGetLastError());         return;     }     //检测目标主机     lpHost = gethostbyname(pstrHost);     if (lpHost==NULL) {         printf("Host not found:%s\n", pstrHost);         return;     }     //设置目标机地址     destIP.sin_addr.s_addr = *((u_long FAR*)(lpHost->h_addr)); //设置目标IP     destIP.sin_family = AF_INET;  //地址规格     destIP.sin_port = 0;     //提示开始进行PING     printf("\nPinging %s [%s] with %d bytes of data:\n",pstrHost,inet_ntoa(destIP.sin_addr),REQ_DATASIZE);     //发起多次PING测试     for (nLoop=0; nLoop<k; nLoop++) {         if (logic)k=k+1;         //发送ICMP回应请求         SendEchoRequest(rawSocket, &destIP);         //等待回复的数据         nRet = WaitForEchoReply(rawSocket);         if (nRet == SOCKET_ERROR) {             printf("select() error:%d\n", WSAGetLastError());             break;         }         if (!nRet) {             lost++;             printf("\nRequest time out.");             continue;         }         //接收回复         dwTimeSent = RecvEchoReply(rawSocket, &srcIP, &cTTL);         reveived++;         //计算花费的时间         dwElapsed = timeGetTime() - dwTimeSent;         if(dwElapsed>maximum)maximum=dwElapsed;         if(dwElapsed<minimum)minimum=dwElapsed;         average+=dwElapsed;         printf("\nReply from %s: bytes = %d time = %ldms TTL = %d",                inet_ntoa(srcIP.sin_addr),REQ_DATASIZE,dwElapsed,cTTL);     }     printf("\n\n");     printf("Ping statistics for %s:\n",inet_ntoa(srcIP.sin_addr));     printf("    Packets: Sent = %d, Received = %d, Lost = %d (%.f%% loss),\n",            sent,reveived,lost,(float)(lost*1.0/sent)*100);     if(lost==0) {         printf("Approximate round trip times in milli-seconds:\n");         printf("    Minimum = %dms, Maximum = %dms, Average = %dms\n",minimum,maximum,average/sent);     }     printf("\n\n");     nRet = closesocket(rawSocket);     if (nRet == SOCKET_ERROR) {         printf("closesocket() error:%d\n", WSAGetLastError());     } }  void main() {     printf("Welcome to the Ping Test\n");     while(1) {         WSADATA wsd;//检测输入的参数         //初始化Winsock         if (WSAStartup(MAKEWORD(1, 1), &wsd) != 0) {             printf("加载 Winsock 失败!\n");         }         char opt1[100];         char *ptr=opt1;         bool log=false;         printf("Ping ");         cin.getline(opt1,100,'\n');         if((opt1[0]=='-')&&(opt1[1]=='t')&&(opt1[2]==' ')) { //          log=true;             ptr=opt1+3;         }         //开始PING         Ping(ptr,log);         //程序释放 Winsock 资源         WSACleanup();     } } //Welcome to the Ping Test //Ping -t www.baidu.com // //Pinging www.baidu.com [119.75.217.56] with 32 bytes of data: // //Reply from 119.75.217.56: bytes = 32 time = 4ms TTL = 51 //Reply from 119.75.217.56: bytes = 32 time = 2ms TTL = 51 //Reply from 119.75.217.56: bytes = 32 time = 2ms TTL = 51 //Reply from 119.75.217.56: bytes = 32 time = 2ms TTL = 51 // //Ping statistics for 119.75.217.56: //  Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), //Approximate round trip times in milli-seconds: //  Minimum = 2ms, Maximum = 4ms, Average = 2ms // // //Ping ^C

引用 4 楼 zhao4zhong1 的回复:第241行：        if((opt1[0]=='-')&&(opt1[1]=='t')&&(opt1[2]==' ')) 说明 你需要在显示Ping时输入“-t www.baidu.com” 不应将%ld替换为%I64d cmd里。ping百度的time在18ms左右，TTL在54ms左右。

引用 4 楼 zhao4zhong1 的回复:第241行：        if((opt1[0]=='-')&&(opt1[1]=='t')&&(opt1[2]==' ')) 说明 你需要在显示Ping时输入“-t www.baidu.com” 不应将%ld替换为%I64d 那样会不停的ping，而且获得的时间time比真实的大，ttl倒是蛮靠近真实值  你可以从结果看来，代码运行是错误的，我ping了百度，但返回的结果中间居然还参杂着我自己的ip。。哎，头疼。如果你能在你的机子上跑一下上面的代码，你就能知道它有多蛋疼了。。

坐等大神。。

引用 1 楼 zhao4zhong1 的回复:将%ld改为%I64d 你好，我将第208行按照你说的改了，结果运行结果变成下面那张图那样了，你能帮我看一下图片吗？我怀疑它根本就没有工作，因为结果是一下子都出来的，而不像我们在cmd上那样是一行一行出来。


Question: 额，C语言scanf函数缓冲区的问题

while(scanf("%d-%d-%d",&yy,&mm,&dd)!=3);  顺便鄙视zhao4zhong1 无用功

Read formatted data from the standard input stream. These are versions of scanf, _scanf_l, wscanf, _wscanf_l with security enhancements as described in Security Enhancements in the CRT.    int scanf_s(    const char *format [,       argument]...  ); int _scanf_s_l(    const char *format,    locale_t locale [,       argument]...  ); int wscanf_s(    const wchar_t *format [,       argument]...  ); int _wscanf_s_l(    const wchar_t *format,    locale_t locale [,       argument]...  );    Parameters format Format control string.  argument Optional arguments.  locale The locale to use.  Return Value Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end-of-file character or the end-of-string character is encountered in the first attempt to read a character. If format is a NULL pointer, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, scanf_s and wscanf_s return EOF and set errno to EINVAL.  For information on these and other error codes, see _doserrno, errno, _sys_errlist, and _sys_nerr.  Remarks The scanf_s function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. If copying takes place between strings that overlap, the behavior is undefined.  wscanf_s is a wide-character version of scanf_s; the format argument to wscanf_s is a wide-character string. wscanf_s and scanf_s behave identically identically if the stream is opened in ANSI mode. scanf_s doesn't currently support input from a UNICODE stream.  The versions of these functions with the _l suffix are identical except that they use the locale parameter passed in instead of the current thread locale.  Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or [. The buffer size is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if reading a string, the buffer size for that string is passed as follows:  char s[10];  scanf("%9s", s, 10);  The buffer size includes the terminating null. A width specification field may be used to ensure that the token read in will fit into the buffer. If no width specification field is used, and the token read is too big to fit in the buffer, nothing will be written to that buffer.  Note:  The size parameter is of type unsigned, not size_t.    In the case of characters, one may read a single character as follows:  char c;  scanf("%c", &c, 1);  When reading multiple characters for non-null terminated strings, integers are used as the width specification and the buffer size.  char c[4];  scanf("%4c", &c, 4); // not null terminated  For more information, see scanf Width Specification.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _UNICODE defined   _tscanf_s  scanf_s  scanf_s  wscanf_s   _tscanf_s_l  _scanf_s_l  _scanf_s_l  _wscanf_s_l    For more information, see Format Specification Fields — scanf functions and wscanf Functions.   Requirements Routine  Required header   scanf_s, _scanf_s_l  <stdio.h>   wscanf_s, _wscanf_s_l  <stdio.h> or <wchar.h>    For additional compatibility information, see Compatibility in the Introduction.  Example   Copy Code  // crt_scanf_s.c // This program uses the scanf_s and wscanf_s functions // to read formatted input.    #include <stdio.h>  int main( void ) {    int      i,             result;    float    fp;    char     c,             s[81];    wchar_t  wc,             ws[81];     result = scanf_s( "%d %f %c %C %s %S", &i, &fp, &c, 1,                      &wc, 1, s, 80, ws, 80 );    printf( "The number of fields input is %d\n", result );    printf( "The contents are: %d %f %c %C %s %S\n", i, fp, c,            wc, s, ws);    result = wscanf_s( L"%d %f %hc %lc %S %ls", &i, &fp, &c, 2,                       &wc, 1, s, 80, ws, 80 );    wprintf( L"The number of fields input is %d\n", result );    wprintf( L"The contents are: %d %f %C %c %hs %s\n", i, fp,             c, wc, s, ws); }     Copy Code  71 98.6 h z Byte characters 36 92.3 y n Wide characters     Copy Code  The number of fields input is 6 The contents are: 71 98.599998 h z Byte characters The number of fields input is 6 The contents are: 36 92.300003 y n Wide characters    .NET Framework Equivalent System::Console::Read  System::Console::ReadLine  See also Parse methods, such as System::Double::Parse.  See Also Concepts Floating-Point Support Stream I/O Locale fscanf, _fscanf_l, fwscanf, _fwscanf_l printf, _printf_l, wprintf, _wprintf_l sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l sscanf, _sscanf_l, swscanf, _swscanf_l

引用 6 楼 goldfishrui 的回复:#include<stdio.h>  int main()  {  char c;  printf("Input for c:\n");  scanf_s("%c",&c);  printf("c=%c\n",c);  } 编译之后，结果就是"c=  ";无法给字符C赋值。  请大侠帮忙解答一下。  我这里可以正常运行  可以看一下你的输入是否符合要求，记得是字符型的不是字符串型的

引用 2 楼 wh653 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 #include <stdio.h> #include <string.h> char s[80]; int i; char c; int main() {     while (1) {         printf("Input a integer:");fflush(stdout);         rewind(stdin);         fgets(s,80,stdin);         if (strlen(s)>10) {             printf("Input too long(>9)!\n");             continue;         }         if (2==sscanf(s,"%d%c",&i,&c)) {             if ('\n'==c) {                 printf("%d is a integer.\n",i);                 break;             }         }         if ('\n'==s[strlen(s)-1]) s[strlen(s)-1]=0;         printf("\"%s\" is NOT a integer!\n",s);     }     return 0; }      并没用。。。我想要，输入了不符合%d-%d-%d格式的，就再次等待输入，直到输入了%d-%d-%d格式的为止。 然后进行yy,mm,dd的处理，但是，，输个错的格式，第二次就算输入对的格式，还是等待输入的。。不知道怎么办[/quote] 检查scanf("%d-%d-%d")的返回值，不是3的话用一个gets吃掉然后返回去重新scanf

#include <stdio.h>  int main() {     int yy,mm,dd;     int flag=0;     int day=0;     int r;     while (1) {         printf("请输入一个日期，比如2012-1-1:");fflush(stdout);         rewind(stdin);         r=scanf("%d-%d-%d",&yy,&mm,&dd);         if (r==3) {             //判断闰年             if(yy%400==0 || (yy%4==0 && yy%100!=0))             {                 flag++;             }              switch(mm-1)             {                 case 11:{day+=30;}                 case 10:{day+=31;}                 case 9:{day+=30;}                 case 8:{day+=31;}                 case 7:{day+=31;}                 case 6:{day+=30;}                 case 5:{day+=31;}                 case 4:{day+=30;}                 case 3:{day+=31;}                 case 2:{day==day+28+flag;}                 case 1:{day+=31;}                 case 0:{day+=0;}             }              day+=dd;             printf("这天是这年的%d天\n",day);             break;         }     }     return 0; }

引用 1 楼 zhao4zhong1 的回复:在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 #include <stdio.h> #include <string.h> char s[80]; int i; char c; int main() {     while (1) {         printf("Input a integer:");fflush(stdout);         rewind(stdin);         fgets(s,80,stdin);         if (strlen(s)>10) {             printf("Input too long(>9)!\n");             continue;         }         if (2==sscanf(s,"%d%c",&i,&c)) {             if ('\n'==c) {                 printf("%d is a integer.\n",i);                 break;             }         }         if ('\n'==s[strlen(s)-1]) s[strlen(s)-1]=0;         printf("\"%s\" is NOT a integer!\n",s);     }     return 0; }      并没用。。。我想要，输入了不符合%d-%d-%d格式的，就再次等待输入，直到输入了%d-%d-%d格式的为止。 然后进行yy,mm,dd的处理，但是，，输个错的格式，第二次就算输入对的格式，还是等待输入的。。不知道怎么办


Question: while (getchar () !=‘\n’） continue求解

如果代码是这样的话： char ch; while ((ch = getchar ()) != ‘#’） { .....若干语句 while (getchar () !=‘\n’） continue; }  那么意味着： 1、某行以#开头的话，结束处理。 2、ch在你所谓的“.....若干语句”中应该有进一步的操作；或者说，以非#字符开头的行的处理被你用“.....若干语句”省略掉了。 3、由于你的while(getchar()!='\n')continue;并没有将取得字符显示保存下来，所以表示在“……若干语句”中的处理之后，跳过了到行末尾的所有输入字符的处理。 4、如果你输入了dev后又敲了回车，并且在此程序内没有其他地方出现getchar()之类的函数的话，那么，显然，程序会对d进行“……若干语句）的处理，然后，跳过ev和回车键的输入，最后，接着等待您进行新的字符的输入，直到输入了#字符。

输入dev后回车，然后呢？

主要的目的是，用户输入dev三个字符的时候，操作系统并不会吧输入立刻传送给程序，一定要遇到回车才会发送字符串，也就是说没有回车，你的程序，两个while都接受不到字符，但是呢\n回车并不是输入想要的，是辅助的，所以就特别处理 \n

改用getch函数会比较符号你的要求。  引用 楼主 u012757050 的回复:char ch while ((ch = getchar ()) != ‘#’） { .....若干语句 while (getchar () !=‘\n’） continue;  假如我输入dev，是不是只有d读入到ch? 第二个while语句是什么意思？是指getchar读取我之前输入的dev，然后全部舍弃吗？  问题补充：如果没有第二个while语句，当第一次输入dev,第二次输入a时，ch会赋予a吗？

第一个是 以# 为结束符，跳出循环  第二个是以\n 回车为结束符,跳出循环  看这写的就取了第一个字符，后面的不要了，若换行（\n）就再取一个，若第一个是#就退出吧


Question: 請教一支程式的執行流程

感謝回覆 我是想知道每個程序的步驟 可否幫忙說明一下  感謝您

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。

他就是这么一步一步的跑下来的啊~~~


Question: 请教几个服务器端 SOCKET 的问题

1 上libuv，用过的都说好 2 除了加机器没有什么好办法了 可以参考C10K 3 这个不懂不敢乱说

带宽总要够用吧。

2、大并发，增加服务器，有共享软件可以处理负载平衡 3、如有大数据请求，另开socket通道，参考telnet  1、如果要跨平台，考虑e-poll或其它的共享软件


Question: C 检测安全密码

#include <stdio.h> #include <string.h> int main() {     int a,i,j,L;     char s[51],c;     int f[4]={0,0,0,0};      scanf("%d",&a);     getchar();     for (i=0;i<a;i++) {         fgets(s,51,stdin);         L=strlen(s);         if ('\n'==s[L-1]) {s[L-1]=0;L--;}         if (8<=L && L<=16) {             for (j=0;j<L;j++) {                 c=s[j];                      if ('a'<=c && c<='z'   ) f[0]=1;                 else if ('A'<=c && c<='Z'   ) f[1]=1;                 else if ('0'<=c && c<='9'   ) f[2]=1;                 else if (strchr("~!@#$%^",c)) f[3]=1;             }             if (f[0]+f[1]+f[2]+f[3]>=3)                 printf("YES\n");             else                 printf("NO\n");         } else  printf("NO\n");     }     return 0; }

switch(1) 这种用法是比较少见。

引用 2 楼 FancyMouse 的回复:switch(1) case 1: 给跪怎么了

引用 1 楼 user-6 的回复:LZ程序中switch的用法比较特别。 如下修改可ac: #include<stdio.h> #include<string.h> int main() {   int a,i,j;   char s[51];   scanf("%d",&a);   getchar();//加   for(i=0;i<a;i++)   {     //删 getchar();     gets(s);     if(strlen(s)>=8&&strlen(s)<=16)     {     	int flag[4]={0,0,0,0};       for(j=0;j<strlen(s);j++)       {         switch(1)         {         case 1:if(s[j]>='a'&&s[j]<='z')  flag[0]=1;         case 2:if(s[j]>='A'&&s[j]<='Z')  flag[1]=1;         case 3:if(s[j]>='0'&&s[j]<='9')  flag[2]=1;         case 4:if(s[j]=='~'||s[j]=='!'||s[j]=='@'||s[j]=='#'||s[j]=='$'||s[j]=='%'||s[j]=='^') flag[3]=1;	         }       }       if(flag[0]+flag[1]+flag[3]+flag[2]>=3)         printf("YES\n");       else         printf("NO\n");     }     else printf("NO\n");   }   return 0;//加 }可能就是gets那里的问题，因为我换成scanf就AC了，最后的return 0；我经常不加，有关系吗

引用 3 楼 buyong 的回复:why switch(1)?懒的写if else，用switch比较方便

why switch(1)?

switch(1) case 1: 给跪

引用 4 楼 ZXvivian 的回复:你的switch case语句块有误，switch(1)就只会执行case :1的语句。既然你的switch中有if分支，那又何必多此一举加switch，直接2层for循环，内部四个分支就够了因为switch结构后不加break就会按case顺序执行下去,所以我就用这种1方法了


Question: 请用C实现过电信短信网关SMGP3.0协议的大侠进来看下

现在有logresp是有了 问题每次都返回21  卡在这了 你Q多少 讨论讨论

同样的 问题 不知道 楼主找到答案了吗？

这是我抓到tcp包  前8字节是账号 接着16字节是md5密码 1字节 登录模式  1字节版本  4字节 时间戳   做过的大侠帮忙看看是不是这样的

遇到这种问题，可以抓下tcp包。按照SMGP3.0协议，看下报文是否正确。

MSG_Login log;     log.nLoginMode = 0x0;     log.nVersion = 0x30;     time_t a = time(NULL);     struct tm *time  = gmtime(&a);     log.nTimeStamp = (time->tm_mon+1)*100000000+time->tm_mday*1000000+time->tm_hour*10000+time->tm_min*100+time->tm_sec;     strcpy(log.sUser, "xxxxxxxx");     MD5_CTX md5;     MD5Init(&md5);     UCHAR md5res[16];     MD5Update(&md5, (unsigned char*)"xxxxxxxx", strlen("xxxxxxxx"));     MD5Final(&md5,md5res);     int i;     for(i=4;i<12;i++)     {         sprintf(log.sAuthenMD5+(i-4)*2, "%02x",md5res[i]);     }    以上是本人LOGIN包的内容  麻烦各位大侠看看有没什么问题     发过去之后连接直接被网关给断开了


Question: 请教一个多线程realloc的问题

仅供参考//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #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 WIN32 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,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 WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,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 WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     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 WIN32     _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 WIN32     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; }

好像把rq = strncat(rq, buff, nbytes);这条注释掉就不会报上面的错。不知道是什么原因

引用 1 楼 A3872215 的回复:invalid next size:    地址无效  memory corruption     内存崩溃  应该是动态分配的内存 把堆耗尽了吧！ 没申请多少内存啊，奇怪的是单线程就不会报这个


Question: 如何将一个字符串指针中的数据显示出来?

如果buf中不时字符串,而只是一个缓冲区而已的话,你要自行实现,至少标准库中没有现成的. 参考一下吧:http://blog.csdn.net/mujiok2003/article/details/8650584

引用 22 楼 huabinsir 的回复:[quote=引用 20 楼 bijiaoben 的回复:] 你在用%s打印的时候，是遇到'\0'认为是字符串结束。strcpy的时候也是遇到'\0'的时候认为是字符串结束吧？这样子两种操作有区别吗？ 另外问一下，楼主有没有同时使用2种方式打印一个相同地址的字符串？会是不同结果吗？  有区别, pBuf(new 产生的) 可能是放在堆上, 经过 strcpy(buf, pBuf), 数据放在 栈上(buf 是局部变量).[/quote] 你没有明白我的意思，我的意思是打印的内容真的有区别吗？ 一个在堆上一个在栈上，你不如说两个地址不一样好了。。。你确定你们的系统在打印堆上和栈上的内容会有不同处理吗？ 还是先确定最基本的字符串的内容吧，不然你的strcpy的结果都可能不对，弄不好还会造成你栈上的数组的溢出。

乱码是你给pBuf指向的字符串赋值时就已经不对了，不然直接printf pBuf应该是可以的

乱码是因为你的板子上字符集的问题。 而不是打印的问题。 对于系统，这个指针传过去的就是一堆二进制的东西，而且是正确的，但是没有正确显示出来而已。  我认为应该是这样。

引用 24 楼 bug1190 的回复:系统返回的BUF肯定还同时还同时返回了有效字节长吧，要想PRINTF没乱码，必须把该BUF拿出来，重新在后面强制0，就没有了  《-----个人觉得, 这个有道理.

引用 12 楼 huabinsir 的回复:这里所说的 pBuf (字符串指针) 是系统返回的， 我想显示时，是不是要给它再补0 ?   pBuf 不处理的话，直接显示，经常出现乱码, 请问应如何正确地显示pBuf (字符串指针) 中的数据.   <---这是我的一个疑问 我的疑问，直接printf("%s\n",pBuf)显示不正确，那么 char buf[100]={0}; strcpy(buf, pBuf); printf(buf); 这个显示就是正确的吗？printf(buf);是什么用法？

仅供参考： FILE_NOTIFY_INFORMATION The FIND_NOTIFY_INFORMATION structure describes the changes found by the ReadDirectoryChangesW function.  typedef struct _FILE_NOTIFY_INFORMATION {    DWORD NextEntryOffset;    DWORD Action;    DWORD FileNameLength;    WCHAR FileName[1]; } FILE_NOTIFY_INFORMATION;  Members NextEntryOffset  Specifies the number of bytes that must be skipped to get to the next record. A value of zero indicates that this is the last record.  Action  Specifies the type of change that occurred. Value Meaning  FILE_ACTION_ADDED The file was added to the directory.  FILE_ACTION_REMOVED The file was removed from the directory.  FILE_ACTION_MODIFIED The file was modified. This can be a change in the time stamp or attributes.  FILE_ACTION_RENAMED_OLD_NAME The file was renamed and this is the old name.  FILE_ACTION_RENAMED_NEW_NAME The file was renamed and this is the new name.    FileNameLength  Specifies the length, in bytes, of the filename portion of the record. Note that this length does not include the terminating null character.  FileName  This is a variable-length field that contains the filename relative to the directory handle. The filename is in the Unicode character format and is not null-terminated.  QuickInfo   Windows NT: Requires version 4.0 or later.   Windows: Unsupported.   Windows CE: Unsupported.   Header: Declared in winnt.h.  See Also File I/O Overview, File Structures, ReadDirectoryChangesW     void WINAPI CheckAddedFile( LPDIRECTORY_INFO lpdi, PFILE_NOTIFY_INFORMATION lpfni) {     TCHAR      szFullPathName[MAX_PATH];     TCHAR      szFileName[MAX_PATH];      memcpy( szFileName, lpfni->FileName ,lpfni->FileNameLength);     szFileName[lpfni->FileNameLength/sizeof(TCHAR)]=0;     lstrcpy( szFullPathName, lpdi->lpszDirName );     lstrcat( szFullPathName, L"\\" );     lstrcat( szFullPathName, szFileName );     wprintf( L"%s\n", szFullPathName );     bufput(szFileName);     wprintf( L"%s added\n",szFileName);//Zz renamed\n",szFileName); }

引用 8 楼 gz_qmc 的回复:[quote=引用 4 楼 huabinsir 的回复:] [quote=引用 2 楼 gz_qmc 的回复:] 直接printf pBuf不行吗？2  直接printf pBuf ， 有时后面会有乱字符出现 .[/quote]  你应该补一下基础了，字符串是以零作为结束的 所以一般定义字串都是  char *pBuf="akjdhfkjadflajd\0";  对于书组型的字串，如果是8字符，就应该申请9个，最后一个为零 比如： char ppp[9]="ABCDEFGH";  否则，没有结尾，不乱码才怪[/quote] 你画蛇添足了。

应该要的。

引用 8 楼 gz_qmc 的回复:[quote=引用 4 楼 huabinsir 的回复:] [quote=引用 2 楼 gz_qmc 的回复:] 直接printf pBuf不行吗？2  直接printf pBuf ， 有时后面会有乱字符出现 .[/quote]  你应该补一下基础了，字符串是以零作为结束的 所以一般定义字串都是  char *pBuf="akjdhfkjadflajd\0";  对于书组型的字串，如果是8字符，就应该申请9个，最后一个为零 比如： char ppp[9]="ABCDEFGH";  否则，没有结尾，不乱码才怪[/quote]  这里所说的 pBuf (字符串指针) 是系统返回的， 我想显示时，是不是要给它再补0 ?   <---这是我的一个疑问

引用 22 楼 huabinsir 的回复:[quote=引用 20 楼 bijiaoben 的回复:] 你在用%s打印的时候，是遇到'\0'认为是字符串结束。strcpy的时候也是遇到'\0'的时候认为是字符串结束吧？这样子两种操作有区别吗？ 另外问一下，楼主有没有同时使用2种方式打印一个相同地址的字符串？会是不同结果吗？  有区别, pBuf(new 产生的) 可能是放在堆上, 经过 strcpy(buf, pBuf), 数据放在 栈上(buf 是局部变量).[/quote]  我也怀疑你的strcpy究竟能不能正常工作。 按照我现在的理论，应该也并不是pBuf里的内容才对。

引用 20 楼 bijiaoben 的回复:你在用%s打印的时候，是遇到'\0'认为是字符串结束。strcpy的时候也是遇到'\0'的时候认为是字符串结束吧？这样子两种操作有区别吗？ 另外问一下，楼主有没有同时使用2种方式打印一个相同地址的字符串？会是不同结果吗？  有区别, pBuf(new 产生的) 可能是放在堆上, 经过 strcpy(buf, pBuf), 数据放在 栈上(buf 是局部变量).

c

我个人认为: 可能是这个小型嵌入式系统 eLIBs_printf 处理得不是很好, pBuf 本可直接输出，但用eLIBs_printf输出时，时常是乱码（有可能和别的地址上的数据连在一起了）。  char buf[100]={0}; strcpy(buf, pBuf); <==这样， 会在字符串结尾处自动加上一个 \0, 但定义 char buf[100]={0}时，消耗了资源(虽然会释放), 语句也多了几条.

引用 15 楼 huabinsir 的回复:[quote=引用 14 楼 bijiaoben 的回复:] [quote=引用 12 楼 huabinsir 的回复:] 这里所说的 pBuf (字符串指针) 是系统返回的， 我想显示时，是不是要给它再补0 ?   pBuf 不处理的话，直接显示，经常出现乱码, 请问应如何正确地显示pBuf (字符串指针) 中的数据.   <---这是我的一个疑问 我的疑问，直接printf("%s\n",pBuf)显示不正确，那么 char buf[100]={0}; strcpy(buf, pBuf); printf(buf); 这个显示就是正确的吗？printf(buf);是什么用法？[/quote]  printf(buf) ==> eLIBs_printf("..%s..\n\n", buf); (一个小型嵌入式系统上的输出函数)	 [/quote] 楼主认为这两种方法有差别吗？

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

eLIBs_printf("..%s..\n\n", pBuf); (这样，经常出现乱字符)


Question: 关于大端模式读数的问题

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

0000:0000 68 10 a7 00 8b 01 70 00-16 00 a9 03 8b 01 70 00 ..... 表示从内存地址0000:0000处开始有16个字节68 10 a7 00 8b 01 70 00 16 00 a9 03 8b 01 70 00  因为是以小端模式保存，所以 0000:0000处开始的两个字节68 10可以看作是一个4位十六进制数0x1068，其中0x10为高字节，0x68为低字节， 0000:0000处开始的四个字节68 10 a7 00可以看作是一个8位十六进制数0x00a71068，其中0x00a7为高字，0x1068为低字。  如果是以大端模式保存，那么 0000:0000处开始的两个字节68 10可以看作是一个4位十六进制数0x6810，其中0x68为高字节，0x10为低字节， 0000:0000处开始的四个字节68 10 a7 00可以看作是一个8位十六进制数0x6810a700，其中0x6810为高字，0xa700为低字。  2位十六进制，即 8位二进制为一个字节。 4位十六进制，即16位二进制为一个字。 8位十六进制，即32位二进制为一个双字。

是6810h，小端模式才是1068h。  引用 楼主 mounty_fsc 的回复:对于这么一串数0000:0000 68 10 a7 00 8b 01 70 00-16 00 a9 03 8b 01 70 00 有数0x1068    MS-DOS大端模式，10h为高位 68h为低位，所以  0000:0000 68 10 a7 00 8b 01 70 00-16 00 a9 03 8b 01 70 00.....  左边是地址高位，右边是地址低位? 要如何理解？ 为什么 68 10 读出来是1068h?


Question: 指针做参数的疑惑

如果想通过指针之间赋值的方式改变pt2的内容，可以这样：  #include <stdio.h> #include <string.h> void test(char *point); int main(void ) {   char *pt1 = "haoren";   char *pt2;   pt2 = (char *)malloc(sizeof(pt2));   pt2 = pt1;   printf("pt2 is %s\n",pt2);   return 0; }

如果还是原来的 test(char *point) { char *q = {"haoren"}; //strcpy(point,q); 	 point = q; } 这样，实质test函数没有改变什么，因为虽然改变了point的值，但字符串常量是无法被改变的，但是malloc申请的内存是可以被改变的。还有，改变的point的值仅仅是在test函数作用域中。 比如 #include <stdio.h> #include <string.h> void test(char *point); int main(void ) {   char *pt2;   pt2 = (char *)malloc(sizeof(pt2));   test(pt2);   printf("pt2 is %s\n",pt2);   return 0; }  void test(char *point) {   char *q = {"haoren"};   strcpy(point, q); //  point =  q; } 这可以更改所指向的值，但是下面的代码应该是乱数据。  #include <stdio.h> #include <string.h> void test(char *point); int main(void ) {   char *pt2;   pt2 = (char *)malloc(sizeof(pt2));   test(pt2);   printf("pt2 is %s\n",pt2);   return 0; }  void test(char *point) {   char *q = {"haoren"}; //  strcpy(point, q);   point =  q; }

LS说的对。

#include <stdio.h> #include <string.h> #include <stdlib.h> void main() { 		char *pt1 = {"woshi"}; 		char *pt2; 		pt2 = (char *)malloc(sizeof(pt2)); 		printf("%d\n",strlen(pt2)); 	//	test(pt1);这句加上编译无错 但是运行会出现段错误的，你的pt1是一个指向字符串常量的指针，他指向的这个字符串常量是不能被修改的， 		test(pt2);//这个pt2在堆上动态申请了有效的存储空间，所以pt2所指向的那块地址会被重新修改位"haoren". 		printf("pt1 is =%s\n",pt1); 		printf("pt2 is =%s\n",pt2); }  test(char *point) { 		char *q = {"haoren"}; 		strcpy(point,q); //		point = q; } 你可以把 *pt1 改为 pt1【10】 再试试，看有什么不同！

引用 9 楼 majia2011 的回复:strcpy(point,q)  strlen（point，q）；这句编译过不了的  对，是strcpy(point,q)，有点蒙了

引用 3 楼 allenltiverson 的回复:按照你写的代码来说理论上说是不可能改变的  抱歉， test(char *point) {   char *q = {"haoren"};  /* 测试时用的是*/strlen（point，q）；   /*不是*/point = q; }

引用 2 楼 Qian_F 的回复:pt1和pt2的指针指向的地址都不会改变的。只是pt1和pt2的值作为实参传给了test函数的形参point，test函数体里改变了point的值，但是这跟main()函数里的pt1和pt2没有关系，pt1和pt2的值都没有改变。   抱歉， test(char *point) {   char *q = {"haoren"};   strlen（point，q）；   /*不是*/point = q; }

引用 1 楼 q245879 的回复:你在哪个平台运行的?  我这边运行出来pt2是没有被改变的。  visual stdio 2010

看汇编~~~~~~~

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

按照你写的代码来说理论上说是不可能改变的

你在哪个平台运行的?  我这边运行出来pt2是没有被改变的。


Question: 有序二叉树的递归

引用 3 楼 ALNG 的回复:OK 根节点问左右子树，你们各有多少节点。  左右子树又分别问他们的左右子树....  一直到页节点。叶节点忘了算自己，说是0. 收到这个消息的上级节点，很遗憾，它的左右子树基于同样的原因都报自己高度为0，而它也不知道算上自己，还是向上级报0. 就这样一层骗一层，一直骗到档中央---根节点发现左右子树都是0个子树，忘了算自己它就把0报告给外部世界了。   高度计算的理由同此。  你用颗简单的树模拟一下就知道了。一直走到叶节点，啥都明白了。可以看出递归的总数是从一个一个1累加来的，如果把这个1换0了，多少个0相加也走不出0的黑洞。赞～！例子生动活泼引人入胜绕梁三日不知肉味

递归函数的运行有两种了解方法，一种是抽象层次上，就像数学公式一样理解。    二叉树的节点数=1. 树是空树时，为0， 否则             2. 1+左（子)数的节点数+右（子树)的节点数  你看这个公式本身就是递归的，读懂这个公式，就读懂了抽象意义上的递归。  另外一种是从特定的实现细节上理解。有点简单的汇编常识更容易明白上面的抽象的公式形成的递归函数在具体的硬件上是怎样执行的。这个你可以用一个相对简单的二叉树，单步执行跟踪一下，最好把堆栈的情形看清楚。

引用 1 楼 ALNG 的回复:1是节点自身啊。比如根节点左子树有10个节点，右子树犹20个节点，那总结点数是不是10+20+1（自己)? 所以  int tjjd(node * n) {     int count;           if(!n)         return 0;     count=1;     if(n->left)         count+=tjjd(n->left);     if(n->right)         count+=tjjd(n->right); }  或者 int tjjd(node * n) {     return n==NULL?0:1+tjjd(n->left)+tjjd(n->right);  }   高度也一样，一颗树的高度为max(左子树高度，右子树高度)+1（这个1也是根节点自身)   typedef struct node node; #define max(a,b)  ((a)<(b)?(b):(a))  int height(node *n) {      return n==NULL?0:1+max(height(n->left),height(n->right)); } 这个我知道阿，为就想问为什么不加一就会输出0，不是应该就少1个节点吗


Question: 今年暑假不AC

the algothrim is key factor

引用 3 楼 user-1 的回复:my method: 0 put all element in result set 1 create a "conflict" table 2 stat which element has the most occurance in "conflict" table 3 remove the element in result set and in "conflict" table 4 repeat step 2-3 until "conflict" table becomes empty. 5 stat the number in result set好牛逼啊，可惜英语太渣看不太明白

求大神解答！！


Question: C求多边形面积

哦，你直接把a[]定义成float了，那不用再cast, 也可考虑用double, 如果考虑了凹多边形不能解决问题的话。

第二个:   s=(fabs((a[2*i-2]-a[0])*(a[2*(i+1)-1]-a[1]))+fabs((a[2*(i+1)-2]-a[0])*(a[2*i-1]-a[1])))/2;  乘法可能溢出(加减也可能溢出)，可以先cast成float再运算。  inline float _a(int i){ return float(a[i]); }  ... s=(fabs((_a(2*i-2)-a[0])*(_a(2*(i+1)-1)-a[1]))+       fabs((_a(2*(i+1)-2)-a[0])*(_a(2*i-1)-a[1])))/2;

要注意凹多变形的问题。   比如  ---------- |       / |      / |      \ |       \ |---------    你如果从坐上出发，用你的方法得到结果的必定会大得多。不知道题目有没有明确说明是凸多边形。

typdef long long int64; 所有中间过程全部用int64.  设这些点是(data[0].x, data[0].y) ... (data[n-1].x, data[n-1].y) 在最后一个点：(data[n].x, data[n].y) = (data[0].x, data[0].y)  然后计算 data[i].x data[i].y data[i+1].x data[i+1].y 的行列式求和得到S，其中i从0到n-1。  S取绝对值。  S为偶数时，答案是[S/2].0 S为奇数时，答案为[S/2].5


Question: Hanoi递归问题。

这个肯定会超时的， 你什么编译器

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

引用 1 楼 truelance 的回复:你不会单步跟一下么我单步调试的时候，系统就是来回递归。可是我不明白为什么既然来回递归，运行的时候还是会出现Press any key to continue     我用while（1）{;}这个死循环测试的时候    就不会出现上述那句话。

每个递归函数都需要有一个判断结束的分支，比如你的if(number == 1)，就是说你输入一个数字，进入函数后会每次m-1,直到m==1的时候执行move(one,three)之后结束。如果你输入的数字小于1例如（0，-1，-2.。。。）则会出现段错误。

你不会单步跟一下么


Question: 活到老学到老，我要开始学习C语言了

以博客的形式写出来，效果会更好，对自己也是一个补充！

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 8 楼 jiandingzhe 的回复:C不适合作为入门语言，也不适合处理日常事务，因为你需要考虑太多与业务逻辑不相关的机器逻辑。 建议你学Python。Python一点都不了解哇，先把我计划中的学完了再考虑Python吧，哈哈，谢了

引用 7 楼 caozhy 的回复:除非你想了解计算机本身，而不是编程，否则用C意义不大，有非常非常多的好的语言可以选择。 学习它们你不会错过任何编程思想的训练，也不必纠结于大量和编程本身无关的东西，更重要的是，它们确实可以让新手编写出有用的程序。这样的语言包括Python C# Ruby Go等等。 谢谢了，不过我就是想从C入门的，其他的慢慢来嘛，哈哈~

引用 6 楼 zhao4zhong1 的回复:先下载Win-TC，然后参考C:\Win-TC\tcstudy.chm  bc++3.1 帮助里面对每个函数都有一小段能拷贝出来运行看效果的例子程序。非常适合初学C语言。相比较而言VC带的帮助MSDN就没有。http://download.csdn.net/source/2805028多谢了，不过我还是按照我自己的思路来学习吧，因为我是要在linux下用的，哈哈~

引用 3 楼 buyong 的回复:还是学个工作中用得上的比较靠谱。你们白盒测试有什么语言？或者开发个测试工具我是想转行了啊，开发测试工具也要学C啊，C是一切的基础。准备先把C学完了再考虑别的，哈哈

还是学个工作中用得上的比较靠谱。你们白盒测试有什么语言？或者开发个测试工具

引用 1 楼 user-6 的回复:楼主现在做什么工作啊  测试，当初毕业时被坑了啊，一不小心就进入了测试的行业、、

楼主现在做什么工作啊


Question: 一个c的问题，请大家解答

引用 10 楼 u013541454 的回复:如果我把static去掉了，能运行就是少了一个答案 我用的编译器是dev-c++ k[n]=i; //这条语句，要求n的值不能大于9，当n大于9，会越界，导致流程异常

取有意义的变量名吧.  多半是因为越界访问.

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。

看来你没有理解static关键字的意义和作用。static用来声明静态变量，程序中k[10]数组是一个静态局部变量，他的生命周期包括整个程序运行期间，k[10]数组的初始化之在程序开始时执行一次。就是说你的k数组可以在多个函数中使用，并且只需要初始化一次。

静态变量可以保持不变性，你可以认为相当于局部的全局变量。 就你这个程序，不用static也可以

我用CFree测试，不用静态也可以

你的课本太老啦

不用非要static, 你看错了提示吧， 可能是别的地方有问题

就这个程序, 删除static也没有问题

在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。

可以为非static 不会越界？

局部数组声明的前面加static将其从堆栈数据段挪到全局数据段，从而可以在退出函数上下文后该局部数组的内容保持可用。


Question: C程序，模拟酒店住房管理系统，TXT文件输出住房信息时遇到问题，华电大一狗求助

请检查scanf和fscanf的返回值。  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fread,fwrite,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试（F11，Shift+F11，F10）和设断点调试（F9、F5）是程序员必须掌握的技能之一。

引用 8 楼 zhao4zhong1 的回复:[quote=引用 7 楼 u012494298 的回复:] [quote=引用 6 楼 zhao4zhong1 的回复:] fflush(fu);  将fprintf改成fflush后，CFree报错。  [Error] E:\C\酒店管理系统\模拟酒店住房管理系统.c:559: error: too many arguments to function `fflush'[/quote] 我的意思不是将fprintf改为fflush；而是在每个fprintf语句后加一句fflush(fu); [/quote]  赵老师，我已经再加了fflush(fu);user.txt还是空白，没用 void rewrite() { 	FILE *fa, *fb, *fc, *fu; 	int i, j; 	fa=fopen("single.txt", "w"); 	if(fa==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<aroom; i++) 		fprintf(fa, "%5d", a[i]);                 fflush(fa); 	fclose(fa); 	fb=fopen("double.txt", "w"); 	if(fb==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<broom; i++){ 		for(j=0; j<bbed; j++) 			fprintf(fb, "%5d", b[i][j]);                         fflush(fb); 		fprintf(fb,"%c", '\n');	                 fflush(fb); 	} 		 	fclose(fb); 	fc=fopen("triple.txt", "w"); 	if(fb==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<croom; i++){ 		for(j=0; j<cbed; j++) 			fprintf(fc, "%5d", c[i][j]);                         fflush(fc); 		fprintf(fc,"%c", '\n');	                 fflush(fc); 	} 		 	fclose(fc); 	fu=fopen("users.txt", "w"); 		if(fu=NULL){ 			printf("文件打开错误!"); 			exit(1); 		}     for(i=0; i<people; i++){ 		fprintf(fu, "%s\t%d\t%d\t%s\t%d", user[i].name, user[i].age, user[i].sex, user[i].date, user[i].rank);                 fflush(fu); 		fprintf(fu,"%c", '\n');                 fflush(fu); 	}  fclose(fu);	 }

fflush Flushes a stream.  int fflush( FILE *stream );  Function Required Header Compatibility  fflush <stdio.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  fflush returns 0 if the buffer was successfully flushed. The value 0 is also returned in cases in which the specified stream has no buffer or is open for reading only. A return value of EOF indicates an error.  Note   If fflush returns EOF, data may have been lost due to a write failure. When setting up a critical error handler, it is safest to turn buffering off with the setvbuf function or to use low-level I/O routines such as _open, _close, and _write instead of the stream I/O functions.  Parameter  stream  Pointer to FILE structure  Remarks  The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. fflush negates the effect of any prior call to ungetc against stream. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.  Buffers are normally maintained by the operating system, which determines the optimal time to write the data automatically to disk: when a buffer is full, when a stream is closed, or when a program terminates normally without closing the stream. The commit-to-disk feature of the run-time library lets you ensure that critical data is written directly to disk rather than to the operating-system buffers. Without rewriting an existing program, you can enable this feature by linking the program’s object files with COMMODE.OBJ. In the resulting executable file, calls to _flushall write the contents of all buffers to disk. Only _flushall and fflush are affected by COMMODE.OBJ.  For information about controlling the commit-to-disk feature, see Stream I/O, fopen, and _fdopen.  Example  /* FFLUSH.C */  #include <stdio.h> #include <conio.h>  void main( void ) {    int integer;    char string[81];     /* Read each word as a string. */    printf( "Enter a sentence of four words with scanf: " );    for( integer = 0; integer < 4; integer++ )    {       scanf( "%s", string );       printf( "%s\n", string );    }     /* You must flush the input buffer before using gets. */    fflush( stdin );    printf( "Enter the same sentence with gets: " );    gets( string );    printf( "%s\n", string ); }   Output  Enter a sentence of four words with scanf: This is a test This is a test Enter the same sentence with gets: This is a test This is a test   Stream I/O Routines  See Also   fclose, _flushall, setvbuf

引用 7 楼 u012494298 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] fflush(fu);  将fprintf改成fflush后，CFree报错。  [Error] E:\C\酒店管理系统\模拟酒店住房管理系统.c:559: error: too many arguments to function `fflush'[/quote] 我的意思不是将fprintf改为fflush；而是在每个fprintf语句后加一句fflush(fu);

引用 6 楼 zhao4zhong1 的回复:fflush(fu);  将fprintf改成fflush后，CFree报错。  [Error] E:\C\酒店管理系统\模拟酒店住房管理系统.c:559: error: too many arguments to function `fflush'

fflush(fu);

引用 4 楼 focuslight 的回复:for(i=0; i<people; i++){         fprintf(fu, "%s\t%d\t%d\t%s\t%d", user[i].name, user[i].age, user[i].sex, user[i].date, user[i].rank);         fprintf(fu,"%c", '\n');     }    这里断点看看  断了，user.txt还是一样空白，所以这段代码相当于没作用？

void rewrite() { 	FILE *fa, *fb, *fc, *fu; 	int i, j; 	fa=fopen("single.txt", "w"); 	if(fa==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<aroom; i++) 		fprintf(fa, "%5d", a[i]); 	fclose(fa); 	fb=fopen("double.txt", "w"); 	if(fb==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<broom; i++){ 		for(j=0; j<bbed; j++) 			fprintf(fb, "%5d", b[i][j]); 		fprintf(fb,"%c", '\n');	 	} 		 	fclose(fb); 	fc=fopen("triple.txt", "w"); 	if(fb==NULL){ 		printf("文件打开错误！\n"); 		exit(1); 	} 	for(i=0; i<croom; i++){ 		for(j=0; j<cbed; j++) 			fprintf(fc, "%5d", c[i][j]); 		fprintf(fc,"%c", '\n');	 	} 		 	fclose(fc); 	fu=fopen("users.txt", "w"); 		if(fu=NULL){ 			printf("文件打开错误!"); 			exit(1); 		}     for(i=0; i<people; i++){ 		fprintf(fu, "%s\t%d\t%d\t%s\t%d", user[i].name, user[i].age, user[i].sex, user[i].date, user[i].rank); 		fprintf(fu,"%c", '\n'); 	}  fclose(fu);	 }

源代码也贴上来吧 #include <stdio.h> #include <stdlib.h> #include<string.h> #include<process.h> #include <dos.h> #define aroom 6 #define broom 3 #define bbed 2 #define croom 2 #define cbed 3  #define people 18  /*people=aroom+(broom*bbed)+(croom*cbed); */ int a[aroom]={0};  int b[broom][bbed]={0}; int c[croom][cbed]={0};   struct  { 	char name[20]; 	int age; 	int sex; 	char date[15]; 	int rank; }user[people]; int main() { 	int a; 	void prepare(); 	void Register(); 	void Checkout(); 	void rewrite(); 	printf("\n      =================================================================\n"); 	printf("                           欢迎来到海天大酒店!\n"); 	printf("\t(本酒店单人间6个，双人间3个，三人间2个，总共可住18人)\n"); 	prepare(); 	while(1){ 		printf(" \n请选择你所需要的服务(例如：1)：\n"); 		printf(" 1、旅客登记\n 2、退房\n 3、退出\n"); 		scanf("%d", &a); 		getchar(); 		switch(a){ 			case 1:  				Register(); break; 			case 2: 				Checkout(); break; 			case 3: 				rewrite(); 				printf("             	        欢迎下次光临!"); 				printf("\n     ==================================================================\n"); 				system("pause"); 				exit(1);  			default:  				printf("选择服务错误，请重新选择！\n"); 	 		}	 	} 	return 0; }  void prepare() { 	FILE *fa,*fb,*fc,*fu; 	int i, j; 	fa=fopen("single.txt","r"); 	if(fa==NULL) 	{ 		printf("\n清场!"); 		fa=fopen("single.txt","w"); 		for(i=0;i<aroom;i++) 		{ 			fprintf(fa,"%5d",0); 		} 		fclose(fa);	 	} 	int aa; 	i=0; 	while(fscanf(fa,"%d",&aa)!=EOF) 	{ 		a[i]=aa; 		i++; 	} 	fclose(fa); 	fb=fopen("double.txt","r"); 	if(fb==NULL) 	{ 		printf("\n清场!"); 		fb=fopen("double.txt","w"); 		for(i=0;i<broom;i++) 		{ 			for(j=0;j<bbed;j++) 			{ 				fprintf(fb,"%5d",0);	 			} 				fprintf(fb,"%c", '\n');	 		} 		fclose(fb);	 	} 	int bb; 	j=0, i=0; 	while(fscanf(fb,"%d",&bb)!=EOF){ 		if(j==bbed) 		{ 			i++; 			j=0;		 		} 		b[i][j]=bb; 		j++; 	} 	fclose(fb); 	fc=fopen("triple.txt","r"); 	if(fc==NULL) 	{ 		printf("\n清场!"); 		fc=fopen("triple.txt","w"); 		for(i=0;i<croom;i++) 		{ 			for(j=0;j<cbed;j++) 			{ 				fprintf(fc,"%5d",0);	 			} 				fprintf(fc,"%c", '\n');		 		} 		fclose(fc);	 	}     int cc;     i=0, j=0; 	while(fscanf(fc,"%d",&cc)!=EOF){ 		if(j==cbed) 		{ 			i++; 			j=0;		 		} 		c[i][j]=cc; 		j++; 	} 	fclose(fc); 	fu=fopen("users.txt","r"); 	if(fu==NULL) 	{ 		printf("\n清场!"); 		fu=fopen("users.txt","w"); 		for(i=0;i<people;i++) 		{ 				fprintf(fu,"%s\t%d\t%d\t%s\t%d","0",0,0,"0",0); 				fprintf(fu,"%c", '\n');	 		} 		fclose(fu);	 	} 	int age,sex,rank; 	char name[20],data[15]; 	i=0; 	while(fscanf(fu,"%s %d %d %s %d",name,&age,&sex,data,&rank)!=EOF){ 		strcpy(user[i].name,name); 		user[i].age=age; 		user[i].sex=sex; 		strcpy(user[i].date,data); 		user[i].rank=rank; 		i++; 	} 	fclose(fu); 	 }  void Register() { 	char name[20],  date[15]; 	int age, rank, i, j, sex; 	printf("register\n"); 	printf("请输入您的姓名:\n"); 	scanf("%s",name); 	getchar(); 	while(1){ 		printf("请输入您的年龄:\n"); 		scanf("%d", &age); 		if(age>0 && age<200) 			break; 		else 			printf("输入年龄格式有错，请重新输入！\n");	 			getchar(); 	} 	while(1) 	{ 		printf("请输入您的性别(1代表男士， 2代表女士):\n"); 		scanf("%d", &sex); 		if(sex<1|| sex>2) 		{ 			printf("输入性别格式错误，请重新输入!\n"); 			getchar(); 			continue; 		} 		else 			break; 			 	} 	 	printf("请输入您的到达日期:\n"); 	scanf("%s", date); 	while(1) 	{ 		int flag1=0, flag2=0; 		while(1) 		{ 			printf("请输入您所需要的房间等级\n输入1（为单人标间，代号A）\n输入2（为双人标间，代号B）\n输入3（为三人标间，代号C）\n"); 			scanf("%d", &rank);  			if(rank<1 || rank>3) 			{ 				printf("输入房间等级错误，请重新输入！\n"); 				getchar(); 				continue; 			}  			else 				break; 			 		} 		 		switch(rank){ 			case 1:  				for(i=0; i<aroom; i++)  				{ 					if(a[i]==0) 					{	 						a[i]=sex;  						strcpy(user[i].name,name); 						user[i].age=age; 						user[i].sex=sex; 						strcpy(user[i].date, date); 						user[i].rank=rank; 						printf("恭喜您订房成功！\n"); 						printf("您的订单信息如下:\n"); 						printf("姓名\t年龄\t性别(1男2女)\t入住日期\t房间号码\n"); 						printf("%-s\t%-d\t%-d\t\t%-s\t\tA%d", user[i].name, user[i].age, user[i].sex=sex, user[i].date, i+1); 						flag2=1; 						break; 					} 				} 				if(i==aroom) 				{ 					printf("单人标间已满！\n"); 					flag1=1;	 				} 				break; 			case 2:  				 				for(i=0; i<broom; i++)  				{ 					for(j=0; j<bbed; j++) 					{ 					 						if(b[i][j]==0) 							if(j==0) 							{	 								int order=aroom+i*bbed+j; 								b[i][j]=sex;  								strcpy(user[order].name,name); 								user[order].age=age; 								user[order].sex=sex; 								strcpy(user[order].date, date); 								user[order].rank=rank; 								printf("恭喜您订房成功！\n"); 								printf("您的订单信息如下:\n"); 								printf("姓名\t年龄\t性别(1男2女)\t入住日期\t房间号码\n"); 								printf("%-s\t%-d\t%-d\t\t%-s\t\tB%d床位%d", user[order].name, user[order].age, user[order].sex=sex, user[order].date, i+1, j+1); 								flag2=1; 								break; 								 							} 							else 								if(sex==b[i][j-1]) 								{ 									int order=aroom+i*bbed+j; 									b[i][j]=sex; 									strcpy(user[order].name,name); 									user[order].age=age; 									user[order].sex=sex; 									strcpy(user[order].date, date); 									user[order].rank=rank; 									printf("恭喜您订房成功！\n"); 									printf("您的订单信息如下:\n"); 									printf("姓名\t年龄\t性别(1男2女)\t入住日期\t房间号码\n"); 									printf("%-s\t%-d\t%-d\t\t%-s\t\tB%d床位%d", user[order].name, user[order].age, user[order].sex=sex, user[order].date, i+1, j+1); 									flag2=1; 									break; 								} 								else 									break; 					} 					if(flag2==1) 						break; 				} 				if(i==broom) 				{ 					printf("双人标间已满！\n"); 					flag1=1;	 				} 				break; 	 			case 3:  				 				for(i=0; i<croom; i++)  				{ 					for(j=0; j<cbed; j++) 					{ 						if(c[i][j]==0) 							if(j==0) 							{ 								int order=aroom+broom*bbed+i*cbed+j;	 								c[i][j]=sex;  								strcpy(user[order].name,name); 								user[order].age=age; 								user[order].sex=sex; 								strcpy(user[order].date, date); 								user[order].rank=rank; 								printf("恭喜您订房成功！\n"); 								printf("您的订单信息如下:\n"); 								printf("姓名\t年龄\t性别(1男2女)\t入住日期\t房间号码\n"); 								printf("%-s\t%-d\t%-d\t\t%-s\t\tC%d床位%d", user[order].name, user[order].age, user[order].sex=sex, user[order].date, i+1, j+1); 								flag2=1; 								break; 							} 							else 								if(sex==c[i][j-1]) 								{ 									int order=aroom+broom*bbed+i*cbed+j; 									c[i][j]=sex; 									strcpy(user[order].name,name); 									user[order].age=age; 									user[order].sex=sex; 									strcpy(user[order].date, date); 									user[order].rank=rank; 									printf("恭喜您订房成功！\n"); 									printf("您的订单信息如下:\n"); 									printf("姓名\t年龄\t性别(1男2女)\t入住日期\t房间号码\n"); 									printf("%-s\t%-d\t%-d\t\t%-s\t\tC%d床位%d", user[order].name, user[order].age, user[order].sex=sex, user[order].date, i+1, j+1); 									flag2=1; 									break; 								} 								else 									break; 					} 					if(flag2==1) 						break; 				} 				if(i==croom) 				{ 					printf("三人标间已满！\n"); 					flag1=1;	 				} 				break; 	 			default:  				printf("没有此类等级，请重新选择！\n");  		} 		int choice, flag3=0;  		if(flag1==1) 		{ 			while(1) 			{ 				printf("您选择的此类等级房间已满！退出请输入0，重新选择请按1\n");  				scanf("%d", &choice); 				switch(choice) 				{ 					case 0:  						rewrite(); 						printf("             	             欢迎下次光临!"); 						printf("\n     ==================================================================\n"); 						exit(1); 					case 1: 						flag3=1; 						break; 					default: 						printf("您输入的格式有错，请重新选择！\n");	  				} 				if(flag3==1) 					break;  			} 		} 		if(flag2==1) 		{ 			break;	 		} 		for(i=0;i<people;i++) 		{ 			if(user[i].age==0) 				break; 			else  				continue;	 		} 		if(i==people) 		{ 			printf("                  全店客满，欢迎下次再来！\n"); 			printf("     ==================================================================\n"); 			system("pause"); 			rewrite(); 			exit(1);  		}		  	}  } void Checkout() {  	int rank,  bed, room, flag=0; 		while(1)  	{ 		printf("checkout\n"); 		while(1) 		{ 			printf("请输入房间等级:\n"); 			scanf("%d",&rank);   			if(rank<1 || rank>3) 			{ 				printf("输入房间等级错误，请重新输入！\n"); 				getchar(); 				continue; 			}  			else 				break; 		} 		printf("请输入房间号（输入数字即可，例如A1，只需输入1，B2只需输入2）:\n"); 		scanf("%d",&room);  		getchar();  		printf("请输入床位号(单人标间请输入1):\n"); 		scanf("%d",&bed);  		switch(rank) 		{ 			case 1:  				if(room<0 || room>aroom) 				{  					printf("输入房间号错误，请重新输入！\n"); 					break;  				}  					if(bed==1)  					{ 						if(a[room-1]==0)				 						{  							printf("输入房间未住人，请重新输入相关信息！\n"); 							break; 						} 						else 						{ 							a[room-1]=0;  							strcpy(user[room-1].name,"0"); 							user[room-1].age=0; 							user[room-1].sex=0; 							strcpy(user[room-1].date,"0"); 							user[room-1].rank=0; 							flag=1; 							printf("退房成功!\n"); 						}	 					} 					else 						printf("输入床位号码有错，请重新输入！\n"); 					break; 			case 2: 				if(bed<0 || bed>broom) 				{  					printf("输入房间号错误，请重新输入！\n"); 					break;  				}  					if(room>=0 && room<=bbed) 					{ 						if(b[room-1][bed-1]==0) 							printf("输入房间未住人，请重新输入相关信息！\n"); 						else 						{ 							int order=aroom+(room-1)*bbed+bed-1; 							b[room-1][bed-1]=0;  							strcpy(user[order].name,"0"); 							user[order].age=0; 							user[order].sex=0; 							strcpy(user[room].date,"0"); 							user[order].rank=0; 							flag=1; 							printf("退房成功!\n"); 						} 			 					} 					else 						printf("输入床位号码有错，请重新输入！\n"); 					break; 				 			case 3: 				if(room<0 || room>croom) 				{  					printf("输入房间号错误，请重新输入！\n"); 					break;  				}  					if(bed>=0 && bed<=cbed) 					{ 						if(c[room-1][bed-1]==0) 							printf("输入房间未住人，请重新输入相关信息！\n"); 						else 						{ 							int order=aroom+broom*bbed+(room-1)*cbed+bed-1; 							c[room-1][bed-1]=0;  							strcpy(user[order].name,"0"); 							user[order].age=0; 							user[order].sex=0; 							strcpy(user[room].date,"0"); 							user[order].rank=0; 							flag=1; 							printf("退房成功!\n"); 						} 			 					} 					else 						printf("输入床位号码有错，请重新输入！\n"); 					break; 				 				default:  					printf("房间类型错误，请重新输入信息！\n");	 			 		} 		if(flag==1) 			break; 	} 	 }


引用 3 楼 codewaggon 的回复:建工程的时候选择Win32 GUI Project 就可以了。 已解决，3Q

引用 1 楼 jerry_dqh 的回复:那是使用mfc吧。 codeblocks使用wxWidget吧。 win32编程是MFC？？不是吧

建工程的时候选择Win32 GUI Project 就可以了。

试试QT

那是使用mfc吧。 codeblocks使用wxWidget吧。


Question: 用宏判断数是不是2的n次幂

引用 1 楼 IAccepted 的回复:给你找了下，我以前曾经用过一个宏，也是实现这个功能  #define s(x) (!((x-1) & x))  我用的这个宏只能找正数（不包括0），所以你的循环要从0开始谢谢 多了种思路

引用 3 楼 CharlesSimonyi 的回复:按照你这个宏的算法，随便取一个数试试吧 比如6的二进制是00000110 按位取反后是   11111001 加1后          11111010 按位与上6得    00000010 判断结果为真 6这个数是2的n次幂 当然不对恩 谢谢明白了 我看了下算法 发现错了 最后只有一位是1 应该和原数比较才对

上个回答补充，s（x）返回1为2^n 返回0即不是

引用 1 楼 IAccepted 的回复:给你找了下，我以前曾经用过一个宏，也是实现这个功能  #define s(x) (!((x-1) & x))  我用的这个宏只能找正数（不包括0），所以你的循环要从0开始 正解