Question: 求快速排序算法

仅供参考：  /*********************************************************  * From C PROGRAMMING: A MODERN APPROACH, Second Edition *  * By K. N. King                                         *  * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. *  * All rights reserved.                                  *  * This program may be freely distributed for class use, *  * provided that this copyright notice is retained.      *  *********************************************************/  /* qsort.c (Chapter 9, page 207) */ /* Sorts an array of integers using Quicksort algorithm */  #include <stdio.h>  #define N 10  void quicksort(int a[], int low, int high); int split(int a[], int low, int high);  int main(void) {   int a[N], i;    printf("Enter %d numbers to be sorted: ", N);   for (i = 0; i < N; i++)     scanf("%d", &a[i]);    quicksort(a, 0, N - 1);    printf("In sorted order: ");   for (i = 0; i < N; i++)     printf("%d ", a[i]);   printf("\n");    return 0; }  void quicksort(int a[], int low, int high) {   int middle;    if (low >= high) return;   middle = split(a, low, high);   quicksort(a, low, middle - 1);   quicksort(a, middle + 1, high); }  int split(int a[], int low, int high) {   int part_element = a[low];    for (;;) {     while (low < high && part_element <= a[high])       high--;     if (low >= high) break;     a[low++] = a[high];      while (low < high && a[low] <= part_element)       low++;     if (low >= high) break;     a[high--] = a[low];   }    a[high] = part_element;   return high; }

引用 8 楼 zhao4zhong1 的回复:先 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笑了~~哈哈哈，赵老师连软件安装一起教了啊！

int Partition(int nArray[], int nLeft, int nRight) { 	int nMiddle = (nLeft + nRight) / 2; 	int nIndex = nLeft - 1; 	for(int i = nLeft; i <= nRight; i++) 	{ 		if(nMiddle == i) 			continue; 		if(nArray[i] <= nArray[nMiddle]) 		{ 			nIndex++; 			if(nIndex == nMiddle) 				nIndex++; 			Swap(nArray, i, nIndex); 		} 	} 	if(nIndex < nMiddle) 		nIndex++; 	Swap(nArray, nIndex, nMiddle);  	return nIndex; }  void Sort_Fast(int nArray[], int nLeft, int nRight) { 	if(nLeft >= nRight) 		return; 	int nMiddle = Partition(nArray, nLeft, nRight); 	Sort_Fast(nArray, nLeft,nMiddle - 1); 	Sort_Fast(nArray, nMiddle + 1, nRight); }  直接取的中值作为阈值。

#include <stdio.h> #include <stdlib.h> #define NUM_OF_ARRAY	100 void quick_sort(int *array, int left, int right) { 	int old_left = left; 	int old_right = right; 	int standard_data = array[left]; 	 	printf("."); 	while(left < right) 	{ 		while((array[right] >= standard_data) && (left < right))	right--; 		if(left != right) 		{ 			array[left] = array[right]; 			left++; 		} 		 		while((array[left] <= standard_data) && (left < right))		left++; 		if(left != right) 		{ 			array[right] = array[left]; 			right--; 		} 	} 	array[left] = standard_data; 	if(old_left < left) 		quick_sort(array, old_left, left-1); 	if(old_right > left) 		quick_sort(array, left+1, old_right); } int main(int argc, char *argv[]) { 	int arr[NUM_OF_ARRAY] = {0}; 	int i=0; 	 	srand(getpid()); 	for(i=0; i<NUM_OF_ARRAY; i++) 	{ 		arr[i] = rand(); 		printf("%d\n", arr[i]); 	}  	quick_sort(arr, 0, NUM_OF_ARRAY-1); 	printf("\n"); 	 	for(i=0; i<NUM_OF_ARRAY; i++) 	{ 		printf("%d\n", arr[i]); 	} 	 	return 0; }

#include "stdio.h"  void swap(int *a,int *b) {                            /*序列中元素位置的交换*/   int tmp;   tmp = *a;   *a = *b;   *b = tmp; }  void print(int k[]) { 	int i; 	static int cont = 0;  	cont++; 	printtf("\n第 %d 次:   ",cont); 	for(i=0;i<10;i++) 	{ 		printtf("%d ",k[i]); 	} 	printf("\n");  } void quicksort(int k[], int s,int t) {                            /*快速排序*/     int i,j;      if(s<t)//划分结束条件 	{         i = s;         j = t+1;         while(1) 		{             do 			{ 				i++;             }while( !(k[s]<=k[i] || i==t) );   //从第一个开始求出第一个大于基准值的元素位置i              			do  			{ 				j--; 			}while(!(k[s]>=k[j] || j==s));    	//从最后开始求出第一个小于基准值的元素位置j             			if(i<j) 			{                 swap(&k[i],&k[j]);            	/*交换k[i]和k[j]的位置*/ 				//print(k); 			}             else                 break;          }         swap(&k[s],&k[j]);                		//将基准元素与从后往前的第一个大于s的元素进行交换，即放在中间 		quicksort(k,s,j-1);                    	/*递归排序基准元素前面的子序列*/ 		quicksort(k,j+1,t);                    	/*递归排序基准元素后面的子序列*/     } }  int main() {     int k[10]={2,5,6,3,7,8,0,9,12,1} , i;     printf("The data array is\n") ;     for(i=0;i<10;i++)                        	/*显示原序列之中的元素*/         printf("%d ",k[i]); 	printf("\n");      quicksort(k,0,9);                        	/*快速排序*/     printf("\nThe result of quick sorting for the array is\n");     for(i=0;i<10;i++)                        	 /*显示排序后的结果*/         printf("%d ",k[i]); 	printf("\n");  	return 0; }

引用 楼主 u012800735 的回复:急求快速排序算法，最好有实现 看这里，http://www.ghostasm.com/forum.php?mod=viewthread&tid=949

这还用问，直接google，一大堆。

void QuikSort(int a[], long low, long high) { 	if(low >= high) 	{ 		return; 	} 	long nlow = low; 	long nhigh = high; 	int temp = 0;	 	bool flag = false;  	while(nlow<nhigh) 	{ 		if(a[nlow] > a[nhigh]) 		{ 			temp = a[nlow]; 			a[nlow] = a[nhigh]; 			a[nhigh] = temp; 			flag = !flag; 		} 		if(flag) 		{ 			nlow++; 		} 		else 		{ 			nhigh--; 		} 	}  	QuikSort(a, low, nhigh); 	QuikSort(a, nhigh+1, high); }


Question: 用rand() 函数去100 个随机的整数的问题

1.rand()函数返回什么 rand()函数式stdlib.h里声明的函数。 它生成一个[0, RAND_MAX]的均匀随机整数。 其中，RAND_MAX至少为32767（2^15-1） returns a pseudo-random number 0 through 32767. 2. (double) rand() / (double) RAND_MAX): 这是把生成的随机数范围缩小到[0,1]，double/double得出结果不是0，而是double型数据  3. 要是 去 100 个 随机 整数，这个程序对吗？ 不对。 乘以RANGE_MAX是让随机数的范围扩大到[0, RANGE_MAX],加上RANGE_MIN是让随机数的范围限制到[RANGE_MIN, RANGE_MAX]

参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\rand.c /*** *rand.c - random number generator * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       defines rand(), srand() - random number generator * *******************************************************************************/  #include <cruntime.h> #include <mtdll.h> #include <stddef.h> #include <stdlib.h>  /*** *void srand(seed) - seed the random number generator * *Purpose: *       Seeds the random number generator with the int given.  Adapted from the *       BASIC random number generator. * *Entry: *       unsigned seed - seed to seed rand # generator with * *Exit: *       None. * *Exceptions: * *******************************************************************************/  void __cdecl srand (         unsigned int seed         ) {         _getptd()->_holdrand = (unsigned long)seed; }   /*** *int rand() - returns a random number * *Purpose: *       returns a pseudo-random number 0 through 32767. * *Entry: *       None. * *Exit: *       Returns a pseudo-random number 0 through 32767. * *Exceptions: * *******************************************************************************/  int __cdecl rand (         void         ) {         _ptiddata ptd = _getptd();          return( ((ptd->_holdrand = ptd->_holdrand * 214013L             + 2531011L) >> 16) & 0x7fff ); }

取100个要循环执行100次，这只是一个

rand()返回值是int RANGE_MAX取值应该为100，这样就是一个0-100范围内的随机数


Question: C如何获取函数地址?

再一次证明： 对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！

要么用函数指针，或者汇编吧！

改用Release模式即可。我猜。

获取函数地址的最佳方式是用函数指针。  引用 楼主 xlrtx 的回复: #include <stdio.h> typedef unsigned long DWORD; int main() { 	DWORD lpMain = 0; 	lpMain = (DWORD)main; 	return 0; }  这是测试的c代码..  可是debug的时候,发现获取的地址不正确..  情况很奇葩,如图:   内存中的地址没有问题,可是赋值的时候值突然变了..  仔细看了一下,获取的内容好像是IAT表对应main函数的地址.   不知道有没有什么方法能够直接得到main函数在内存中的地址..

turingo: 谢谢你,不过可能我问题没有描述清楚..  我的意思是,程序在debug的时候获取的函数地址是IAT表中的地址,而不是真正的入口地址..因为需要计算函数大小,所以当用iat表地址相减的时候,得到的差总是5.  zhao4zhong1: 谢谢,这个方法很好用..  _DEBUG时候要加上5(一个jmp xxxx命令的长度),因为两个跳转指令并不是在一个地址上. 所以debug时函数的大小是(int *)((int)fun2+1)-*(int *)((int)fun1+1) + 5; release情况下本地函数没有IAT跳转直接减就可以.   刚才又吧debug和release两种情况的代码反汇编看了下..总结下.. 1.不管是debug还是release,函数都是16字节对齐的,空着的地方会被填充烫烫烫 2.debug的函数比release的函数体积大,仔细看了下,仿佛debug的函数会将堆栈填满0xcc,并且在调用一个函数后会检查堆栈. 3.release的函数体积会小很多,没有堆栈检查..  我这是想写一个可以将自己代码插入其他程序运行的程序..想着用api重定位就行了,可是写到现在发现C还有个C库,想要脱离它还要考虑其他问题..略麻烦..考虑用汇编了..

仅供参考//仅对VC6 #include <stdio.h> void fun1() {     int f1=1;     printf("fun1\n");     printf("fun1\n"); } void fun2() {     int f2=2;     printf("fun2\n"); } void fun3() { } void main() { #ifdef _DEBUG     printf("sizeof(fun1)==%d\n",*(int *)((int)fun2+1)-*(int *)((int)fun1+1));     printf("sizeof(fun2)==%d\n",*(int *)((int)fun3+1)-*(int *)((int)fun2+1)); //sizeof(fun1)==59 //sizeof(fun2)==43 #else     printf("sizeof(fun1)==%d\n",(int)fun2-(int)fun1);     printf("sizeof(fun2)==%d\n",(int)fun3-(int)fun2); //sizeof(fun1)==32 //sizeof(fun2)==16 #endif }

找到解决的方法了  链接器加上/INCREMENTAL:NO即可将IAT中本模块的函数跳转取消,只保留系统函数调用 (不知道这样叫好不好,IAT本意是pe头里的数据结构,这里表示程序中调用函数的跳转表)  还有一个问题就是不知道如何取消函数间的int3,记得是debug用的,但是可不可以在debug编译的同时消除这些int3啊..影响计算函数体积..

#include <stdio.h>  typedef int (*entry_t)(int argc, char *argv[]);   int main(int argc, char *argv[]) { 	entry_t addr = main; 	printf("%p\n", main); 	printf("%p\n", addr);  	return 0; }  /** 输出信息 */ // 0x80483c4 // 0x80483c4  引用 5 楼 xlrtx 的回复:函数指针不能够获取函数真正的地址,只能够得到函数在IAT表中的地址啊..

引用 3 楼 zhao4zhong1 的回复:改用Release模式即可。我猜。  想要吧那些int3去掉..并且debug,求解..  因为需要计算函数的长度,但是debug模式下函数长度包括了许许多多的int3

函数指针不能够获取函数真正的地址,只能够得到函数在IAT表中的地址啊..


Question: 用c语言操作文本，求大神写一段代码？

读出来，匹配重新写！

引用 楼主 u011730237 的回复:一个文本文件src1.txt 内容如下： |ABC|我阿尼|分寸|AHO|好of |CXV|好哦好|的|的|AA 一个文本文件src2.txt  内容如下： 杭州	CXV	大学	FUCK 大连	ABC	ooo	ooo  需求： 通过对于的三个字母 ABC 识别到第二个文本，取得杭州 追加到src1文本下，想过如下 |ABC|我阿尼|分寸|AHO|好of|大连 |CXV|好哦好|的|的|AA|杭州  注意考虑要乱码，文本结尾。。求大神给写一下。 版主，你说的也太不靠谱了扼。。。。。

汉字当成两个字节，拆分字符串用strtok函数。  引用 楼主 u011730237 的回复:一个文本文件src1.txt 内容如下： |ABC|我阿尼|分寸|AHO|好of |CXV|好哦好|的|的|AA 一个文本文件src2.txt  内容如下： 杭州	CXV	大学	FUCK 大连	ABC	ooo	ooo  需求： 通过对于的三个字母 ABC 识别到第二个文本，取得杭州 追加到src1文本下，想过如下 |ABC|我阿尼|分寸|AHO|好of|大连 |CXV|好哦好|的|的|AA|杭州  注意考虑要乱码，文本结尾。。求大神给写一下。

引用 7 楼 u011730237 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。  可是我还是没有看懂你写的代码。。。哎，杯具啊。。。。。好底层啊。。。。。保存到那去了，我没有看懂。。[/quote] 比如将4楼编译生成了test.exe，连同src1.txt和src2.txt都在d:\mydir目录下 开始、运行、cmd 在弹出的黑色窗口中输入以下命令： cd /d d:\mydir test >src3.txt notepad src3.txt

引用 6 楼 zhao4zhong1 的回复:这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。  可是我还是没有看懂你写的代码。。。哎，杯具啊。。。。。好底层啊。。。。。保存到那去了，我没有看懂。。

这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。

kan  引用 4 楼 zhao4zhong1 的回复://一个文本文件src1.txt //内容如下： //|ABC|我阿尼|分寸|AHO|好of //|CXV|好哦好|的|的|AA //一个文本文件src2.txt //内容如下： //杭州 CXV 大学 FUCK //大连 ABC ooo ooo // //需求： //通过对于的三个字母 ABC 识别到第二个文本，取得杭州 追加到src1文本下，想过如下 //|ABC|我阿尼|分寸|AHO|好of|大连 //|CXV|好哦好|的|的|AA|杭州 #include <stdio.h> #include <string.h> #include <locale.h> #include <wchar.h> #define MAXC 30 #define MAXL 300 #define MAXN 100 FILE *f; wchar_t Citys[MAXN][MAXC]; wchar_t Codes[MAXN][MAXC]; wchar_t Code[MAXC]; wchar_t ln[MAXL]; int i,n,j; int main() {     setlocale(LC_ALL,"chs");     f=fopen("src2.txt","r");     if (NULL==f) {         fprintf(stderr,"Can not open file src2.txt!\n");         return 1;     }     i=0;     while (1) {         if (NULL==fgetws(ln,MAXL,f)) break;         if (2!=swscanf(ln,L"%29s%29s",Citys[i],Codes[i])) {             fprintf(stderr,"src2.txt Line %d format error:%S",i+1,ln);         }         i++;         if (i>=MAXN) break;     }     fclose(f);     n=i;     f=fopen("src1.txt","r");     if (NULL==f) {         fprintf(stderr,"Can not open file src1.txt!\n");         return 1;     }     i=0;     while (1) {         if (NULL==fgetws(ln,MAXL,f)) break;         if (1!=swscanf(ln,L"|%29[^|]",Code)) {             fprintf(stderr,"src1.txt Line %d format error:%S",i+1,ln);         } else {             for (j=0;j<n;j++) {                 if (0==wcscmp(Code,Codes[j])) break;             }             if (j<n) {                 if (L'\n'==ln[wcslen(ln)-1]) ln[wcslen(ln)-1]=0;                 printf("%S|%S\n",ln,Citys[j]);             } else {                 fprintf(stderr,"src1.txt Line %d can not find city of %S:%S",i+1,Code,ln);             }         }         i++;     }     fclose(f);     return 0; } //|ABC|我阿尼|分寸|AHO|好of|大连 //|CXV|好哦好|的|的|AA|杭州 //  经常看到你回帖。。谢谢大哥。


Question: 程序如何定时关闭？

就一个win32控制台程序

这是windows下的编程知识，可以看看win32编程。

试试shutdown /?

timer 控件

时间错了……   #include <thread> #include <chrono> #include <atomic>  int main() {     std::atomic<bool> exiting = false;     std::thread timer([&exiting](){           std::this_thread::sleep_for(std::chrono::minutes(40)); exiting = true; });          while (!exiting)     {         // do something     }      timer.join();     return 0; }

#include <thread> #include <chrono> #include <atomic>  int main() {     std::atomic<bool> exiting = false;     std::thread timer([&exiting](){  std::this_thread::sleep_for(std::chrono::seconds(10)); exiting = true; });          while (!exiting)     {         // do something     }      timer.join();     return 0; }

gettime() 多简单

win32console可以设置消息队列，使用 SetTimer(HWND,UNIT,UINT,TIMERPROC) 这个api来实现定时功能

定时器没玩过试试，或者线程每分钟轮询一次呗

long run_time = 40*60*1000;         clock_t begin,end; 	begin = clock(); 	end = clock(); 	while(end-begin<run_time) 	{ 	    ...             end = clock(); 	}

仅供参考#pragma comment(lib,"user32") #include <stdio.h> #include <time.h> #include <sys/timeb.h> #include <windows.h> char datestr[16]; char timestr[16]; char mss[4]; void log(char *s) {     struct tm *now;     struct timeb tb;      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,s); } VOID CALLBACK myTimerProc1(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc1\n"); } VOID CALLBACK myTimerProc2(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc2\n"); } int main() {     int i;     MSG msg;      SetTimer(NULL,0,1000,myTimerProc1);     SetTimer(NULL,0,2000,myTimerProc2);     for (i=0;i<20;i++) {         Sleep(500);         log("In main\n");         if (GetMessage(&msg,NULL,0,0)) {             TranslateMessage(&msg);             DispatchMessage(&msg);         }      }     return 0; } //2012-07-26 17:29:06.375 In main //2012-07-26 17:29:06.875 In myTimerProc1 //2012-07-26 17:29:07.375 In main //2012-07-26 17:29:07.875 In myTimerProc2 //2012-07-26 17:29:08.375 In main //2012-07-26 17:29:08.375 In myTimerProc1 //2012-07-26 17:29:08.875 In main //2012-07-26 17:29:08.875 In myTimerProc1 //2012-07-26 17:29:09.375 In main //2012-07-26 17:29:09.890 In myTimerProc2 //2012-07-26 17:29:10.390 In main //2012-07-26 17:29:10.390 In myTimerProc1 //2012-07-26 17:29:10.890 In main //2012-07-26 17:29:10.890 In myTimerProc1 //2012-07-26 17:29:11.390 In main //2012-07-26 17:29:11.890 In myTimerProc2 //2012-07-26 17:29:12.390 In main //2012-07-26 17:29:12.390 In myTimerProc1 //2012-07-26 17:29:12.890 In main //2012-07-26 17:29:12.890 In myTimerProc1 //2012-07-26 17:29:13.390 In main //2012-07-26 17:29:13.890 In myTimerProc2 //2012-07-26 17:29:14.390 In main //2012-07-26 17:29:14.390 In myTimerProc1 //2012-07-26 17:29:14.890 In main //2012-07-26 17:29:14.890 In myTimerProc1 //2012-07-26 17:29:15.390 In main //2012-07-26 17:29:15.890 In myTimerProc2 //2012-07-26 17:29:16.390 In main //2012-07-26 17:29:16.390 In myTimerProc1 //2012-07-26 17:29:16.890 In main //2012-07-26 17:29:16.890 In myTimerProc1 //2012-07-26 17:29:17.390 In main //2012-07-26 17:29:17.890 In myTimerProc2 //2012-07-26 17:29:18.390 In main //2012-07-26 17:29:18.390 In myTimerProc1 //2012-07-26 17:29:18.890 In main //2012-07-26 17:29:18.890 In myTimerProc1 //2012-07-26 17:29:19.390 In main //2012-07-26 17:29:19.890 In myTimerProc2

定时器，或者开启线程专门计时（通过开始运行时记录一个点，然后在循环中不停的检测当前点和之前那个点的值，如果超过40*60*1000就退出程序）

1 用alarm设置时间+捕获信号中断 2 开一个监控线程计时 3 主循环计时也是可以的，不过可能不精确


Question: 请教问题：大文件处理(C语言)

嗯，谢谢，我想象具体肿么整。

怕内存碎片就用一个内存池  看你的需求 我觉得是否对文件固定读取大小，逻辑处理，然后在读...如果返回大小=<0,就说明读完了. 不知道文件中的数据是否可以这切割处理.   你说用string那些东西，stl内部也是用了线程池的

可用double buffer，开两个比如4KB的buffer，一个用于读取数据，一个用于解析，完了把两个buffer交换一下，如此循环。  引用 楼主 xnini632d 的回复:问题： C语言 需要处理N个大文件，size有可能很大，但是大小上限不能具体知道。 需要并行处理文件。 文件的内容有可能涉及到解码什么的。  我一开始用了2个方法： <1>先声明一个超大数组，一次性读完文件。问题是太浪费内存，因为文件有可能是很小的。 <2>用malloc动态分配一个文件大小的space。问题是频繁的动态分配，会造成过多的内存碎片，不适合长时间的运行。 C++好像有内部内存管理的类string，但是C++不太拿出手。。。。 哪位大神帮忙想想办法。

CreateFileMapping The CreateFileMapping function creates a named or unnamed file-mapping object for the specified file.   HANDLE CreateFileMapping(   HANDLE hFile,              // handle to file to map   LPSECURITY_ATTRIBUTES lpFileMappingAttributes,                              // optional security attributes   DWORD flProtect,           // protection for mapping object   DWORD dwMaximumSizeHigh,   // high-order 32 bits of object size   DWORD dwMaximumSizeLow,    // low-order 32 bits of object size   LPCTSTR lpName             // name of file-mapping object );   Parameters hFile  Handle to the file from which to create a mapping object. The file must be opened with an access mode compatible with the protection flags specified by the flProtect parameter. It is recommended, though not required, that files you intend to map be opened for exclusive access.  If hFile is (HANDLE)0xFFFFFFFF, the calling process must also specify a mapping object size in the dwMaximumSizeHigh and dwMaximumSizeLow parameters. The function creates a file-mapping object of the specified size backed by the operating-system paging file rather than by a named file in the file system. The file-mapping object can be shared through duplication, through inheritance, or by name.   lpFileMappingAttributes  Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpFileMappingAttributes is NULL, the handle cannot be inherited.  Windows NT: The lpSecurityDescriptor member of the structure specifies a security descriptor for the new file-mapping object. If lpFileMappingAttributes is NULL, the file-mapping object gets a default security descriptor.   flProtect  Specifies the protection desired for the file view, when the file is mapped. This parameter can be one of the following values: Value Description  PAGE_READONLY Gives read-only access to the committed region of pages. An attempt to write to or execute the committed region results in an access violation. The file specified by the hFile parameter must have been created with GENERIC_READ access.  PAGE_READWRITE Gives read-write access to the committed region of pages. The file specified by hFile must have been created with GENERIC_READ and GENERIC_WRITE access.  PAGE_WRITECOPY Gives copy on write access to the committed region of pages. The files specified by the hFile parameter must have been created with GENERIC_READ and GENERIC_WRITE access.    In addition, an application can specify certain section attributes by combining (using the bitwise OR operator) one or more of the following section attribute values with one of the preceding page protection values: Value Description  SEC_COMMIT Allocates physical storage in memory or in the paging file on disk for all pages of a section. This is the default setting.  SEC_IMAGE The file specified for a section's file mapping is an executable image file. Because the mapping information and file protection are taken from the image file, no other attributes are valid with SEC_IMAGE.  SEC_NOCACHE All pages of a section are to be set as non-cacheable. This attribute is intended for architectures requiring various locking structures to be in memory that is never fetched into the processor's. On 80x86 and MIPS machines, using the cache for these structures only slows down the performance as the hardware keeps the caches coherent. Some device drivers require noncached data so that programs can write through to the physical memory. SEC_NOCACHE requires either the SEC_RESERVE or SEC_COMMIT to also be set.  SEC_RESERVE Reserves all pages of a section without allocating physical storage. The reserved range of pages cannot be used by any other allocation operations until it is released. Reserved pages can be committed in subsequent calls to the VirtualAlloc function. This attribute is valid only if the hFile parameter is (HANDLE)0xFFFFFFFF; that is, a file mapping object backed by the operating sytem paging file.     dwMaximumSizeHigh  Specifies the high-order 32 bits of the maximum size of the file-mapping object.  dwMaximumSizeLow  Specifies the low-order 32 bits of the maximum size of the file-mapping object. If this parameter and dwMaximumSizeHig are zero, the maximum size of the file-mapping object is equal to the current size of the file identified by hFile.  lpName  Pointer to a null-terminated string specifying the name of the mapping object. The name can contain any character except the backslash character (\).  If this parameter matches the name of an existing named mapping object, the function requests access to the mapping object with the protection specified by flProtect.   If this parameter is NULL, the mapping object is created without a name.   If lpName matches the name of an existing event, semaphore, mutex, waitable timer, or job, the function fails and the GetLastError function returns ERROR_INVALID_HANDLE. This occurs because these objects share the same name space.   Return Values If the function succeeds, the return value is a handle to the file-mapping object. If the object existed before the function call, the function returns a handle to the existing object (with its current size, not the specified size) and GetLastError returns ERROR_ALREADY_EXISTS.   If the function fails, the return value is NULL. To get extended error information, call GetLastError.   Remarks After a file-mapping object has been created, the size of the file must not exceed the size of the file-mapping object; if it does, not all of the file's contents will be available for sharing.   If an application specifies a size for the file-mapping object that is larger than the size of the actual named file on disk, the file on disk is grown to match the specified size of the file-mapping object. If the file cannot be grown, this results in a failure to create the file-mapping object. GetLastError will return ERROR_DISK_FULL.  The handle that CreateFileMapping returns has full access to the new file-mapping object. It can be used with any function that requires a handle to a file-mapping object. File-mapping objects can be shared either through process creation, through handle duplication, or by name. For information on duplicating handles, see DuplicateHandle. For information on opening a file-mapping object by name, see OpenFileMapping.   Windows 95: File handles that have been used to create file-mapping objects must not be used in subsequent calls to file I/O functions, such as ReadFile and WriteFile. In general, if a file handle has been used in a successful call to the CreateFileMapping function, do not use that handle unless you first close the corresponding file-mapping object.  Creating a file-mapping object creates the potential for mapping a view of the file but does not map the view. The MapViewOfFile and MapViewOfFileEx functions map a view of a file into a process's address space.   With one important exception, file views derived from a single file-mapping object are coherent, or identical, at a given time. If multiple processes have handles of the same file-mapping object, they see a coherent view of the data when they map a view of the file.   The exception has to do with remote files. Although CreateFileMapping works with remote files, it does not keep them coherent. For example, if two computers both map a file as writeable, and both change the same page, each computer will only see its own writes to the page. When the data gets updated on the disk, it is not merged.   A mapped file and a file accessed by means of the input and output (I/O) functions (ReadFile and WriteFile) are not necessarily coherent.   To fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile, and close the file mapping object handle by calling CloseHandle. The order in which these functions are called does not matter. The call to UnmapViewOfFile is necessary because mapped views of a file mapping object maintain internal open handles to the object, and a file mapping object will not close until all open handles to it are closed.   Note  To guard against an access violation, use structured exception handling to protect any code that writes to or reads from a memory mapped view. For more information, see Reading and Writing.  Windows CE: Windows CE does not use the lpFileMappingAttributes parameter. It must be NULL.  This function will not work on a device that does not support Page-In.  Example To implement a mapping-object creation function that fails if the object already exists, an application can use the following code.   hMap = CreateFileMapping(...);   if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS)  {      CloseHandle(hMap);      hMap = NULL;  }  return hMap;    QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also File Mapping Overview, File Mapping Functions, CloseHandle, DuplicateHandle, MapViewOfFile, MapViewOfFileEx, MapViewOfFileVlm, OpenFileMapping, ReadFile, SECURITY_ATTRIBUTES, UnmapViewOfFile, UnmapViewOfFileVlm, VirtualAlloc, WriteFile


Question: 关于结构体自引用的问题

引用 1 楼 turingo 的回复:只要最终能找到类型定义即可，不过提前声明是比较好的习惯，这里还有另外的写法：  typedef struct tag_2 {   	int value;   	struct tag_2 *link;       }NODE;     [quote=引用 楼主 missheaven2011 的回复:] 看到几个帖子，关于使用typedef实现结构体自引用，模板如下 struct tag_2;  //这里进行结构体不完整的声明 typedef struct tag_2 NODE;   struct tag_2{       int value;       NODE *link;       };    但是我看到有一个实际例子 typedef struct tag_2 NODE;   struct tag_2{       int value;       NODE *link;       };   缺少了struct tag_2;  //这里进行结构体不完整的声明，但是依然能编译成功，这是为什么？难道不是必须的么[/quote]+1这种做法是常用的

只要最终能找到类型定义即可，不过提前声明是比较好的习惯，这里还有另外的写法：  typedef struct tag_2 {   	int value;   	struct tag_2 *link;       }NODE;   引用 楼主 missheaven2011 的回复:看到几个帖子，关于使用typedef实现结构体自引用，模板如下 struct tag_2;  //这里进行结构体不完整的声明 typedef struct tag_2 NODE;   struct tag_2{       int value;       NODE *link;       };    但是我看到有一个实际例子 typedef struct tag_2 NODE;   struct tag_2{       int value;       NODE *link;       };   缺少了struct tag_2;  //这里进行结构体不完整的声明，但是依然能编译成功，这是为什么？难道不是必须的么


Question: 求大神帮助！

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fread,fwrite,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

可惜我都不知道去哪copy。呜呜。。。 求大神帮忙啊！

引用 2 楼 u011609505 的回复:我能看懂可是遇见这个问题就是写不出来啊！ 求大神帮忙！  那就copy, 改改

我能看懂可是遇见这个问题就是写不出来啊！ 求大神帮忙！

参考http://c.chinaitlab.com/basic/892627.html  引用 楼主 u011609505 的回复:有一个文件shop.dat，在该文件中以二进制方式存放了50个用于表示超市商品销 售记录的结构体类型数据。结构体的声明如下： struct Sales {     int ID;//商品编码     char name[30];//商品名称     int  num;//商品数量     float price;//商品单价 } 编写一个函数，将shop.dat 文件中的数据读出，并且构建1 个商品销售记录数组A； 编写一个函数，删除上述所生成数组A 中单价小于4000 元的商品销售记录； 编写一个函数，将经过上述处理的数组A 按照商品编码进行递增排序，并 将排序后的全部结果显示在屏幕上，每种商品的数据占一行，显示格式为： 111 IPad2 2 4688.00 122 Iphone4S 3 5899.00  求大神帮忙实习简单的代码！


Question: C、C++竞赛题（简单）

这作业，百度一下吧

这是C，C++作业题吧？，。。。

自己做哦，出现什么问题再提哦

楼主自己应该可以做出来吧，不难...

1. 156


Question: 关于rpm包请教下大家

赚积分的。。


Question: 有没有好心人帮忙写一个计算器的程序

表达式求值，对数据结构堆栈、二叉树等等要很了解了。

MSDN里面似乎有个step by step教程，实现WPF计算器。

引用 6 楼 u012705655 的回复:#include <graphics.h>      // 就是需要引用这个图形库，利用了easyX库函数 #include <conio.h> #include <stdio.h> #include <string.h>   void hz_anniu(void);      //绘制按钮  void main(void)  { 	HWND hWnd;     MOUSEMSG m;     initgraph(400,400);   // 这里和 TC 略有区别     setbkcolor(WHITE);    //设置程序背景颜色     cleardevice();     setcolor(BLUE);       hWnd = GetHWnd();    // 获取窗口句柄     SetWindowText(hWnd, "简单计算器1.1.0     作者：张鹏");     //修改窗口名称 	setlinestyle(PS_SOLID,3);        //设置线宽 	hz_anniu();      while(1)      { 		setcolor(BLACK);         //设置文字染色 		outtextxy(100,350,"点击鼠标右键退出程序");       //在特定的位置输出文字 		m = GetMouseMsg();        //将获取到的鼠标信息赋值给m  		switch(m.uMsg) 		{  			case WM_LBUTTONDOWN:             //鼠标左键按下消息         					if((m.x>30 && m.y>110) && (m.x<70 && m.y<140)) 						;                     if((m.x>300 && m.y>100) && (m.x<400 && m.y<200))                          ;                     if((m.x>500 && m.y>100) && (m.x<600 && m.y<200))                          ;    					if((m.x>700 && m.y>100) && (m.x<800 && m.y<200)) 					;	  					break; 			 			case WM_RBUTTONUP:                  printf("\007");                 return;     // 按鼠标右键退出程序            }        }     getch();     closegraph();          // 关闭图形界面  }  void hz_anniu(void)            //绘制按钮  { 	COLORREF col;     col=getcolor();    	setcolor(BLACK); 	setlinestyle(PS_SOLID,2); 	rectangle(30,20,370,90);  	rectangle(30,110,70,140); 	outtextxy(45,117,"7");  	rectangle(90,110,130,140); 	outtextxy(105,117,"8");  	rectangle(150,110,190,140); 	outtextxy(165,117,"9");  	rectangle(210,110,250,140); 	outtextxy(225,117,"+");  	rectangle(30,160,70,190); 	outtextxy(45,167,"4");  	rectangle(90,160,130,190); 	outtextxy(105,167,"5");  	rectangle(150,160,190,190); 	outtextxy(165,167,"6");  	rectangle(210,160,250,190); 	outtextxy(225,167,"-");  	rectangle(30,210,70,240); 	outtextxy(45,217,"1");  	rectangle(90,210,130,240); 	outtextxy(105,217,"2");  	rectangle(150,210,190,240); 	outtextxy(165,217,"3");  	rectangle(210,210,250,240); 	outtextxy(225,217,"*");  	rectangle(30,260,130,290); 	outtextxy(75,267,"0");  	rectangle(150,260,190,290); 	outtextxy(167,265,".");  	rectangle(210,260,250,290); 	outtextxy(225,267,"/");  	rectangle(270,110,370,190); 	outtextxy(315,140,"C");  	rectangle(270,210,370,290); 	outtextxy(315,240,"=");      setcolor(col); }    怎么才能通过鼠标按键，在框中输入数字 你的做法很独特，为什么自己画这些东西呢？ 当然，你这样也可以：在鼠标点击的callback里，判断鼠标点击的位置在那个元件里。不过实现一个功能完备的图形控件是很麻烦的。

会写代码不？如果你制作界面设计的话，你应该找一个写代码的搭档了。

弄3个变量 值1 v1，值2 v2，运算 op  按键点击值存入v1，v2 点击运算符存入 op 点击= 使用一个switch  switch(op) case '+': return v1+v2; case '-' return v1-v2; .....

引用 6 楼 u012705655 的回复:怎么才能通过鼠标按键，在框中输入数字  为什么要自己画框，而不用按钮和文本框控件呢？ 设置一个 string ,每次按按钮后, 把字符 push_back 进去, 再刷新文本框。

还真有人贴出代码,,csdn的分看来真挺厉害了

百度随便找。C#计算器，跟win7 下计算器一模一样的都有。

引用 2 楼 user-10 的回复:http://download.csdn.net/detail/lizugenggeng/4779623#comment 网络很多的，下载的源码参考下吧！   额，这种我可以做得。。但是我做的不是这种，是仿windows界面的计算器

引用 3 楼 u012705655 的回复:[quote=引用 1 楼 davidsu33 的回复:] 用脚本语言，python或则是lua都很容易实现你的功能。 但是最近查了很多资料，还是毫无头绪[/quote] 告诉你一个最简单的，Qt的Demo就有计算器，你可以看看

引用 1 楼 davidsu33 的回复:用脚本语言，python或则是lua都很容易实现你的功能。 但是最近查了很多资料，还是毫无头绪

用脚本语言，python或则是lua都很容易实现你的功能。


Question: 请问有没有谭浩强C程序设计题解与上机指导第三版，可以复制的版本

谭浩强还有需求( ⊙ o ⊙ )啊！

谭浩强的书害了不少人,还是看别的好书吧


Question: 请教一下各位关于学习C语言该看什么书

OK，谢谢各位了，确实平时实践比较少。

写代码出错，就说明你平时写的代码太少了。不是看书多就行的，就算你看的懂代码，自己写也是另外一回事，建议你多敲代码，多写写例子。

如果复杂算法都能看懂的话,那就自己多练习吧,写多了就很多都懂了

The c programming language

我记得刚学那会儿是看教程的 然后边看遍敲代码比较快

从基础开始看吧，C++ Primier 从简入深，本人经历。

C和指针

http://download.csdn.net/detail/user-7/6333711 这本基础指针入门书，看看

函数传参数都是值拷贝的形式完成的！ 你这里传递的是值而已！本身没有改变， 传指针也是传地址值过去，修改内存地址上的内容达到修改的目的的！


Question: 新手求教C语言内存监控的软件(主要是为了检测内存是否成功被free)

valgrind

用valgrind，简单易用~

/*****************************************************************  *  EXAMPLE  1                                                   *  *  This simple program illustrates the basic debugging features *  *  of the C runtime libraries, and the kind of debug output     *  *  that these features generate.                                *  *****************************************************************/  #include <stdio.h> #include <string.h> #include <malloc.h> #include <crtdbg.h>  // This routine place comments at the head of a section of debug output void OutputHeading( const char * explanation ) {    _RPT1( _CRT_WARN, "\n\n%s:\n**************************************\ ************************************\n", explanation ); }  // The following macros set and clear, respectively, given bits // of the C runtime library debug flag, as specified by a bitmask. #ifdef   _DEBUG #define  SET_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #define  CLEAR_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #else #define  SET_CRT_DEBUG_FIELD(a)   ((void) 0) #define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) #endif   void main( ) {    char *p1, *p2;    _CrtMemState s1, s2, s3;     // Send all reports to STDOUT    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );     // Allocate 2 memory blocks and store a string in each    p1 = malloc( 34 );    strcpy( p1, "This is the p1 string (34 bytes)." );     p2 = malloc( 34 );    strcpy( p2, "This is the p2 string (34 bytes)." );      OutputHeading(        "Use _ASSERTE to check that the two strings are identical" );    _ASSERTE( strcmp( p1, p2 ) == 0 );     OutputHeading(        "Use a _RPT macro to report the string contents as a warning" );    _RPT2( _CRT_WARN, "p1 points to '%s' and \np2 points to '%s'\n", p1, p2 );     OutputHeading(        "Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations" );    _CrtMemDumpAllObjectsSince( NULL );     free( p2 );     OutputHeading(        "Having freed p2, dump allocation information about p1 only" );    _CrtMemDumpAllObjectsSince( NULL );     // Store a memory checkpoint in the s1 memory-state structure    _CrtMemCheckpoint( &s1 );     // Allocate another block, pointed to by p2    p2 = malloc( 38 );    strcpy( p2, "This new p2 string occupies 38 bytes.");     // Store a 2nd memory checkpoint in s2    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Dump the changes that occurred between two memory checkpoints" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     // Free p2 again and store a new memory checkpoint in s2    free( p2 );    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Now the memory state at the two checkpoints is the same" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     strcpy( p1, "This new p1 string is over 34 bytes" );    OutputHeading( "Free p1 after overwriting the end of the allocation" );    free( p1 );     // Set the debug-heap flag so that freed blocks are kept on the    // linked list, to catch any inadvertent use of freed memory    SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );     p1 = malloc( 10 );    free( p1 );    strcpy( p1, "Oops" );     OutputHeading( "Perform a memory check after corrupting freed memory" );    _CrtCheckMemory( );     // Use explicit calls to _malloc_dbg to save file name and line number    // information, and also to allocate Client type blocks for tracking    p1 = _malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ );    p2 = _malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ );    strcpy( p1, "p1 points to a Normal allocation block" );    strcpy( p2, "p2 points to a Client allocation block" );     // You must use _free_dbg to free a Client block    OutputHeading(        "Using free( ) to free a Client block causes an assertion failure" );    free( p1 );    free( p2 );     p1 = malloc( 10 );    OutputHeading( "Examine outstanding allocations (dump memory leaks)" );    _CrtDumpMemoryLeaks( );     // Set the debug-heap flag so that memory leaks are reported when    // the process terminates. Then, exit.    OutputHeading( "Program exits without freeing a memory block" );    SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); }  Output  Use _ASSERTE to check that the two strings are identical: ************************************************************************** C:\DEV\EXAMPLE1.C(56) : Assertion failed: strcmp( p1, p2 ) == 0   Use a _RPT macro to report the string contents as a warning: ************************************************************************** p1 points to 'This is the p1 string (34 bytes).' and  p2 points to 'This is the p2 string (34 bytes).'   Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations: ************************************************************************** Dumping objects -> {13} normal block at 0x00660B5C, 34 bytes long  Data: <This is the p2 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 32 20 73  {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Having freed p2, dump allocation information about p1 only: ************************************************************************** Dumping objects -> {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Dump the changes that occurred between two memory checkpoints: ************************************************************************** 0 bytes in 0 Free Blocks. 38 bytes in 1 Normal Blocks. 0 bytes in 0 CRT Blocks. 0 bytes in 0 IgnoreClient Blocks. 0 bytes in 0 (null) Blocks. Largest number used: 4 bytes. Total allocations: 38 bytes.   Now the memory state at the two checkpoints is the same: **************************************************************************   Free p1 after overwriting the end of the allocation: ************************************************************************** memory check error at 0x00660B32 = 0x73, should be 0xFD. memory check error at 0x00660B33 = 0x00, should be 0xFD. DAMAGE: after Normal block (#12) at 0x00660B10.   Perform a memory check after corrupting freed memory: ************************************************************************** memory check error at 0x00660B10 = 0x4F, should be 0xDD. memory check error at 0x00660B11 = 0x6F, should be 0xDD. memory check error at 0x00660B12 = 0x70, should be 0xDD. memory check error at 0x00660B13 = 0x73, should be 0xDD. memory check error at 0x00660B14 = 0x00, should be 0xDD. DAMAGE: on top of Free block at 0x00660B10. DAMAGED located at 0x00660B10 is 10 bytes long.   Using free( ) to free a Client block causes an assertion failure: ************************************************************************** dbgheap.c(1039) : Assertion failed: pHead->nBlockUse == nBlockUse   Examine outstanding allocations (dump memory leaks): ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.   Program exits without freeing a memory block: ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.

可以用Malloc Hook、重载new/delete之类的技术监视内存泄露；或者使用测试软件

这个还是靠程序员自己编程养成良好的习惯纳！

google


Question: 有谁在写程序？单片机 SOP-8的

推荐你一个软件 KEIL C51

何不自己动动手，又不难

SOP-8的单片机很多，用汇编指令写就好。  引用 楼主 lvjianjun 的回复:我想得到一个程序，就是SOP-8的单片机，用在LED分段上面，开关一次，3脚输出高电平，再开关一次，6脚输出高电平 有酬代写


Question: 很简单的一个C语言问题，救命啊！！！

先弄懂：编译器，运行期。

我的理解是你在定义数组的时候 必须给数组定下分配多少空间 不能是一个变化的值。 要么就动态分配内存 malloc（）

引用int r_color[N]={0}； 写成int r_color[N]即可。  定义完毕就进行初始化操作是个很好的习惯，多敲几个也累不死啊

int r_color[N]={0}； 写成int r_color[N]即可。

int a; int(*p)[2]; a=p[0][N];

说错了 ，是数组指针来分配二维数组

可以定义指针数组来分配二维数组： int a; int （*）p[2]; a=p[2][N];

其实你想用变长数组吗

int N， *color; if (1 == scanf("%d", &N) && N > 0) {    color = (int*)calloc(N,sizeof(int)); }

引用 12 楼 haibo521333 的回复:int r_color[N]={0}； 写成int r_color[N]即可。 当你将N作为参数的时候，是无法进行初始化的，尤其是用在函数里。

先弄懂：编译期，运行期。

先弄懂：编译器，运行期。

看完网上的教程 我编写了下面的动态分配代码 不知道对不对 int i,j,N,*r_color,**metro;      scanf("%d",&N);     r_color=(int*)malloc(sizeof(int)*N); 	metro=(int**)malloc(sizeof(int)*N); 	  for(i=0;i<N;i++) 	  {   metro[i]=(int*)malloc(sizeof(int)*N);}

那如何分配二维数组 #include<stdio.h> #include<stdlib.h> #include<malloc.h> void main() {    int i,j,N,*r_color=0,*metro=0;      scanf("%d",&N);     r_color=(int*)malloc(sizeof(int)*N); 	metro=(int*)malloc(sizeof(int)*N*N); 	for(i=0;i<N;i++) 		r_color[i]=0;     for(i=0;i<N;i++) 		for(j=0;j<N;j++)         scanf("%d",&metro[i][j]);         color(metro,r_color,20);    for(i=1;i<=20;i++)/*输出着色方案*/      printf("%3d",r_color[i]); }

C89不支持变长数组，在C99标准上才支持变长数组；

只想把那个常量N被代替用scanf输入的任意变量...........不知道有没有这样命令

原来是动态分配问题，有没有可以把变量转化为常量的啊，不想一改就改全部，因为动态分配不太会... #include<stdio.h> #define N 21 void main() {  int r_color[N]={0};    int i;    int metro[N][N]={{0},/*邻接矩阵*/                             {0,1,1,1,1,1,1},                             {0,1,1,1,1},                             {0,1,1,1,0,0,1},                             {0,1,1,0,1,1},                             {0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,1},                             {0,1,0,1,0,1,1,1,1,1},                             {0,0,0,0,0,0,1,1,1},                             {0,0,0,0,0,0,1,1,1,1,0,0,1},                             {0,0,0,0,0,1,1,0,1,1,0,0,1,1,1,0,1},                             {0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0,0,1},                             {0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1},                             {0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,1,1},                             {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1},                             {0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1},                             {0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,1},                             {0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1},                             {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},                             {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},                             {0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1},                             {0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1}};         color(metro,r_color,20);    for(i=1;i<=20;i++)/*输出着色方案*/      printf("%3d",r_color[i]); } int color(int metro[N][N],int r_color[N],int sum) {    int i,j,k;    for(i=1;i<=sum;i++)/*检查所有城市*/      for(j=1;j<=4;j++)/*对每个城市尝试4种颜色的着色方案*/      {         r_color[i]=j;/*尝试着色*/         for(k=1;k<i;k++)/*检查是否与相邻城市颜色相同*/             if(metro[i][k]==1&&r_color[k]==r_color[i])                break;/*相同则跳出，此时有k<i，则下面条件不成立，继续尝试下一种颜色*/         if(k>=i)/*若不相同，则使用当前颜色，并检查下一个城市*/             break;      } }

你定义的静态数组 在编译的时候 就要决定在栈上分配多少内存 而你的N在运行时才确定 以上

声明数组长度用常量


Question: VS2013新建文件出错

似乎安装的不对，或安装文件不对

用“以管理员身份运行setup.exe”的方法重装试试。

楼上的不好意思 我是小白.... 我是刚装好VS2013 然后新建文件出错 没有命名不合法吧？

这错误怎么看的懂 创建文件  	FILE *f = fopen("d:/1.txt","w"); 	if (f) 	{ 		char *pData = "aaaaa"; 		int len = fwrite(pData , sizeof(pData) , 1 , f ); 		if (len <= 0 ) 		{ 			cout<<"write is faild!"<<endl; 		} 		fclose(f); 	}

是不是命名不合法，用纯英文的试试看。  引用 楼主 u013043054 的回复:刚装的VS2013新建文件出错，如下弹出窗口，请问这是怎么回事？


Question: 求教关于interlocked的问题

《Windows核心编程》

引用 1 楼 user-2 的回复:这涉及多线程同步处理机制，每种机制都不同   临界区（Critical Section）、互斥量（Mutex）、信号量（Semaphore）、事件（Event）  《秒杀多线程第六篇 经典线程同步 事件Event》已经发布，欢迎参阅。  《秒杀多线程第七篇 经典线程同步 互斥量Mutex》已经发布，欢迎参阅。  《秒杀多线程第八篇 经典线程同步 信号量Semaphore》已经发布，欢迎参阅。   http://blog.csdn.net/morewindows/article/details/7442333  不是多线程的同步问题 就是关于interlocked函数本身的工作情况


Question: 如何根据本计算机名判断其是否在某个域里？

结贴了，这个是C#写的查找域中所有的计算机名称，可以把要查询的计算机名称在list里面查询，看是否存在，如果存在则是域中计算机，不是则不在域中，不过这有个问题，就是你要查询的计算机名称有可能在域中有重名的情况，就是说有另外一个机器也叫这个名字，那就没法确定你要查的机器到底是不是在域里了         public static bool GetComputerList(string domainpath, string admin, string adminpwd, ref List<string> pcList)         {             try             {                 //这里必须是这种类型的格式才能获取到                 //LDAP://ry.com/CN=Computers,DC=ry,DC=com                 //这里对传入的参数进行处理                 string strDomain = "LDAP://";                 strDomain += domainpath;                 strDomain += "/CN=Computers,DC=";                 //接下来拆分域名                 int pos = domainpath.IndexOf('.');                 if (pos == -1)                 {                     return false;                 }                 else                 {                     string temp = domainpath.Substring(0, pos);                     strDomain += temp;                     strDomain += ",DC=";                     temp = domainpath.Substring(pos + 1, domainpath.Length - pos - 1);                     strDomain += temp;                  }                   DirectoryEntry entry = new DirectoryEntry(strDomain, admin, adminpwd);                  if (entry.Children != null)                 {                      foreach (DirectoryEntry domain in entry.Children)                     {                         string temp = domain.Properties["userAccountControl"].Value.ToString();                         if (temp == "4098" || temp=="4128")//4098:是已经和计算机管理过，被禁止的账户 4128:新建的账户，未使用过。                         {                             //pcList.Add(domain.Name);                             string strName = domain.Name;                             int iPos = strName.IndexOf("CN=");                             if (iPos == -1)                             {                                 pcList.Add(strName);                             }                             else                             {                                 strName = strName.Substring(iPos + 3, strName.Length - iPos - 3);                                 pcList.Add(strName);                             }                         }                     }                 }                 else                 {                     return false;                 }             }             catch (System.Exception ex)             {                 return false;             }              return true;         }

字符串匹配呗

#include "stdafx.h" #include "ifdns.h" #include <Lmjoin.h> #include <lm.h> #include <LsaLookup.h> #include <windows.h> #include "ntsecapi.h"  #pragma comment(lib, "Netapi32.lib")  LPWSTR name; NETSETUP_JOIN_STATUS njs = NetSetupUnknownStatus; NETSETUP_JOIN_STATUS njgg = NetSetupUnknownStatus; NET_API_STATUS iRetGetType = NetGetJoinInformation(NULL,&name, &njs);  新建个控制台可以直接运行是不是在域里可以根据njs的值来判断，如果是3则是在域里，如果是1则不在域里 这种方法是判断本机是否在域里，但是怎么判断本机是否在指定的域里

运行出来结果是 Domain ------------------------------------------------------------------------------- MSHOME                RY                    WORKGROUP             命令成功完成。  //我的问题是怎么判断一个计算机是否在指定的域里呢？ 比如名字叫WWW的计算机是否在DNS是192.168.0.179的域里

system("net view /domain >d:\\domain.txt"); //然后读文件d:\\domain.txt的内容

急死了，NetGetJoinInformation这个函数怎么用啊，百试不爽

忘了说建一个控制台程序(支持mfc的)，要加上这两个头文件才行 #include <Lmjoin.h> #include <lm.h>


Question: C语言 两张表合成一张表？

用excel吧，把第一个文本的文件copy到新建的xls文件，第一行第一咧，粘贴；把第二个文件的内容copy，粘贴到第一行第二列，OK；

引用 4 楼 zhao4zhong1 的回复:比如将3楼代码编译生成了test.exe，连同TWspellToChinaSpeel.txt和ChinaToChinaSpeel.txt都在d:\mydir目录下  开始、运行、cmd  在弹出的黑色窗口中输入以下命令： cd /d d:\mydir test >Result.txt notepad Result.txt   大哥 你怎么不编译呢。。。好吧，我当作参考了。。你怎么写那么多代码啊。。。

没实际编译链接调试，不一定对，仅供参考： #include <stdio.h> #include <string.h> #define MAXPY 20000 #define MAXL 10 char dlpy[MAXPY][MAXL]; char twpy[MAXPY][MAXL]; char py[MAXL]; char ln[80]; int i,n; FILE *f; int main() {     f=fopen("TWspellToChinaSpeel.txt","r");     fgets(ln,80,f);//跳过第一行//大陆拼音对台湾拼音     i=0;     while (1) {         if (2!=fscanf(f,"%9s%9s",dlpy[i],twpy[i])) break;         i++;         if (i>=MAXPY) break;     }     fclose(f);     n=i;     f=fopen("ChinaToChinaSpeel.txt","r");     while (1) {         if (2!=fscanf(f,"%2s%9s",ln,py)) break;         printf("%s %s ",ln,py);         for (i=0;i<n;i++) {             if (0==strcmp(py,dlpy[i]) {                 printf("%s\n",twpy[i]);                 break;             }         }     }     fclose(f);     return 0; }

看的不是太明白，如果是想做简体繁体读音的翻译软件，把不同的与简体拼音的规则，一一匹配.   用2个std::map存储一下对应关系.  typedef std::map<std::string , std::string>  Map_Type  汉语拼音对应汉语汉字 汉语拼音对应台湾拼音

定义三个结构体数组 其中两个用来存放源文件 然后遍历，遍历结果存在第三个结构体数组中 然后保存  请别人写代码 不如请个思路 然后自己写


Question: C和指针

引用 楼主 u012804737 的回复:自学C语言的孩子真是伤不起啊。好难。看C和指针，看到malloc那边以后，有些例子真的是云里雾里。 在不断的错误中找寻真理！

先记，后编，再调。出问题了想办法解决。解决完了想想理论。慢慢就懂了

没办法，只有多练多看

引用 13 楼 zhao4zhong1 的回复:malloc和free 相当于 借和还 而不相当于 创建和销毁。有借有还，再借不难。

Example  /*****************************************************************  *  EXAMPLE  1                                                   *  *  This simple program illustrates the basic debugging features *  *  of the C runtime libraries, and the kind of debug output     *  *  that these features generate.                                *  *****************************************************************/  #include <stdio.h> #include <string.h> #include <malloc.h> #include <crtdbg.h>  // This routine place comments at the head of a section of debug output void OutputHeading( const char * explanation ) {    _RPT1( _CRT_WARN, "\n\n%s:\n**************************************\ ************************************\n", explanation ); }  // The following macros set and clear, respectively, given bits // of the C runtime library debug flag, as specified by a bitmask. #ifdef   _DEBUG #define  SET_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #define  CLEAR_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #else #define  SET_CRT_DEBUG_FIELD(a)   ((void) 0) #define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) #endif   void main( ) {    char *p1, *p2;    _CrtMemState s1, s2, s3;     // Send all reports to STDOUT    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );     // Allocate 2 memory blocks and store a string in each    p1 = malloc( 34 );    strcpy( p1, "This is the p1 string (34 bytes)." );     p2 = malloc( 34 );    strcpy( p2, "This is the p2 string (34 bytes)." );      OutputHeading(        "Use _ASSERTE to check that the two strings are identical" );    _ASSERTE( strcmp( p1, p2 ) == 0 );     OutputHeading(        "Use a _RPT macro to report the string contents as a warning" );    _RPT2( _CRT_WARN, "p1 points to '%s' and \np2 points to '%s'\n", p1, p2 );     OutputHeading(        "Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations" );    _CrtMemDumpAllObjectsSince( NULL );     free( p2 );     OutputHeading(        "Having freed p2, dump allocation information about p1 only" );    _CrtMemDumpAllObjectsSince( NULL );     // Store a memory checkpoint in the s1 memory-state structure    _CrtMemCheckpoint( &s1 );     // Allocate another block, pointed to by p2    p2 = malloc( 38 );    strcpy( p2, "This new p2 string occupies 38 bytes.");     // Store a 2nd memory checkpoint in s2    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Dump the changes that occurred between two memory checkpoints" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     // Free p2 again and store a new memory checkpoint in s2    free( p2 );    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Now the memory state at the two checkpoints is the same" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     strcpy( p1, "This new p1 string is over 34 bytes" );    OutputHeading( "Free p1 after overwriting the end of the allocation" );    free( p1 );     // Set the debug-heap flag so that freed blocks are kept on the    // linked list, to catch any inadvertent use of freed memory    SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );     p1 = malloc( 10 );    free( p1 );    strcpy( p1, "Oops" );     OutputHeading( "Perform a memory check after corrupting freed memory" );    _CrtCheckMemory( );     // Use explicit calls to _malloc_dbg to save file name and line number    // information, and also to allocate Client type blocks for tracking    p1 = _malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ );    p2 = _malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ );    strcpy( p1, "p1 points to a Normal allocation block" );    strcpy( p2, "p2 points to a Client allocation block" );     // You must use _free_dbg to free a Client block    OutputHeading(        "Using free( ) to free a Client block causes an assertion failure" );    free( p1 );    free( p2 );     p1 = malloc( 10 );    OutputHeading( "Examine outstanding allocations (dump memory leaks)" );    _CrtDumpMemoryLeaks( );     // Set the debug-heap flag so that memory leaks are reported when    // the process terminates. Then, exit.    OutputHeading( "Program exits without freeing a memory block" );    SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); }  Output  Use _ASSERTE to check that the two strings are identical: ************************************************************************** C:\DEV\EXAMPLE1.C(56) : Assertion failed: strcmp( p1, p2 ) == 0   Use a _RPT macro to report the string contents as a warning: ************************************************************************** p1 points to 'This is the p1 string (34 bytes).' and  p2 points to 'This is the p2 string (34 bytes).'   Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations: ************************************************************************** Dumping objects -> {13} normal block at 0x00660B5C, 34 bytes long  Data: <This is the p2 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 32 20 73  {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Having freed p2, dump allocation information about p1 only: ************************************************************************** Dumping objects -> {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Dump the changes that occurred between two memory checkpoints: ************************************************************************** 0 bytes in 0 Free Blocks. 38 bytes in 1 Normal Blocks. 0 bytes in 0 CRT Blocks. 0 bytes in 0 IgnoreClient Blocks. 0 bytes in 0 (null) Blocks. Largest number used: 4 bytes. Total allocations: 38 bytes.   Now the memory state at the two checkpoints is the same: **************************************************************************   Free p1 after overwriting the end of the allocation: ************************************************************************** memory check error at 0x00660B32 = 0x73, should be 0xFD. memory check error at 0x00660B33 = 0x00, should be 0xFD. DAMAGE: after Normal block (#12) at 0x00660B10.   Perform a memory check after corrupting freed memory: ************************************************************************** memory check error at 0x00660B10 = 0x4F, should be 0xDD. memory check error at 0x00660B11 = 0x6F, should be 0xDD. memory check error at 0x00660B12 = 0x70, should be 0xDD. memory check error at 0x00660B13 = 0x73, should be 0xDD. memory check error at 0x00660B14 = 0x00, should be 0xDD. DAMAGE: on top of Free block at 0x00660B10. DAMAGED located at 0x00660B10 is 10 bytes long.   Using free( ) to free a Client block causes an assertion failure: ************************************************************************** dbgheap.c(1039) : Assertion failed: pHead->nBlockUse == nBlockUse   Examine outstanding allocations (dump memory leaks): ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.   Program exits without freeing a memory block: ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.

引用 13 楼 zhao4zhong1 的回复:malloc和free 相当于 借和还 而不相当于 创建和销毁。嗯，相当的同意，有借有还，再借不难，有借不还就是耍流氓。            体现在程序，就是如果一个程序五羞耻的借用内存，而从来不还给操作系统。这不就是病毒程序么？

竟然没分了竟然没分了竟然没分了，我要问问题啊，   int dc_3DesEncryption(unsigned int Lenght, unsigned char Index, unsigned char *Soure, unsigned char *ENC_Data)； 这个函数，在里面运行的时候，结果是对的。            int  redx; 	  unsigned int Lenght = 0x09; 	  unsigned char Index = 0x02; 	  unsigned char Soure[] = {0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01}; 	  unsigned char ENC_Data[500];    	  redx = dc_3DesEncryption(Lenght, Index, Soure, ENC_Data);  但是当他运行完毕后，为什么ENC_Data里面没有值？

malloc和free 相当于 借和还 而不相当于 创建和销毁。

7楼说的真心好

看《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对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解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

从定义方面考虑，从本质上了解指针。 指针也是一个变量，和普通变量不同的地方是其占用的地址空间是定长的4字节（32系统），地址空间里存放的不是的数值，而是地址值。

不要关心过程,在你只想要结果的时候

take easy！ 慢慢来！接受新东西，总是有个过渡期的！

这玩意你要一下子就明白了，那就神了，多练多琢磨就行了

指针很纠结，唯一的就是多动手动脑，多纠结，然后就不纠结了.....

指针确实很难，动手在纸上画画关系图会事倍功半的。  引用 楼主 u012804737 的回复:自学C语言的孩子真是伤不起啊。好难。看C和指针，看到malloc那边以后，有些例子真的是云里雾里。


Question: c调用c++的动态库

恭喜楼主解决问题。  其实你在定义的时候加上一个宏判断就可以了 #ifdef __cplusplus extern "C"{ #endif  // 具体定义  #ifdef __cplusplus } #endif  你统一改为g++也可以。

以下内容仅供参考：dll 导出函数名的那些事 关键字：　VC++ 　DLL  导出函数　 经常使用VC6的Dependency查看DLL导出函数的名字，会发现有DLL导出函数的名字有时大不相同，导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系。 VC++支持两种语言：即C/C++，这也是造成DLL导出函数差异的根源 我们用VS2008新建个DLL工程，工程名为“TestDLL” 把默认的源文件后缀 .CPP改为.C（C文件） 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 1. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 2. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： _MyFunction@4 __stdcall会使导出函数名字前面加一个下划线，后面加一个@再加上参数的字节数，比如_MyFunction@4的参数（int iVariant）就是4个字节 __fastcall与 __stdcall类似，不过前面没有下划线，而是一个@，比如@MyFunction@4 __cdecl则是始函数名。 小结：如果要导出C文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 下面我们来看一下C++文件 我们用VS2008新建个DLL工程，工程名为“TestDLL” 默认的源文件后缀为 .CPP （即C++文件）。 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 3. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 4. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： ?MyFunction@@YGHH@Z 可以看到 第二种方法得到的 导出函数名 并不是我们想要的，如果在exe中用显示方法（LoadLibrary、GetProcAddress）调用 MyFunction 肯定会失败。 但是用引入库(*.LIB)的方式调用，则编译器自动处理转换函数名，所以总是没有问题。 解决这个问题的方法是： 用VC 提供的预处理指示符 “#pragma” 来指定链接选项。 如下： #pragma comment(linker, "/EXPORT:MyFunction=?MyFunction@@YGHH@Z") 这时，就会发现导出的函数名字表中已经有了我们想要的MyFunction。但我们发现原来的那个 ?MyFunction@@YGHH@Z 函数还在，这时就可以把 __declspec() 修饰去掉，只需要 pragma 指令即可。 而且还可以使如下形式： #pragma comment(linker, "/EXPORT:MyFunction=_MyFunction@4,PRIVATE") PRIVATE 的作用与其在 def 文件中的作用一样。更多的#pragram请查看MSDN。 小结：如果要导出C++文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 同时可以用#pragma指令（C 中也可以用）。 总结： C++编译器在生成DLL时，会对导出的函数进行名字改编，并且不同的编译器使用的改编规则不一样，因此改编后的名字也是不同的（一般涉及到C++ 中的重载等）。 如果利用不同编译器分别生成DLL和访问DLL的exe程序，后者在访问该DLL的导出函数时就会出现问题。如上例中函数MyFunction在C++编译器改编后的名字是?MyFunction@@YGHH@Z。我们希望编译后的名字不发生改变，这里有几种方法。 第一种方法是通过一个称为模块定义文件DEF来解决。 LIBRARY TestDll EXPORTS MyFunction LIBRARY 用来指定动态链接库内部名称。该名称与生成的动态链接库名一定要匹配，这句代码不是必须的。 EXPORTS说明了DLL将要导出的函数，以及为这些导出函数指定的符号名。 第二种是定义导出函数时加上限定符：extern "C" 如：#define DLLEXPORT_API extern "C" _declspec(dllexport) 但extern "C"只解决了C和C++语方之间调用的问题(extern “C” 是告诉编译器，让它按C的方式编译)，它只能用于导出全局函数这种情况 而不能导出一个类的成员函数。 同时如果导出函数的调用约定发生改变，即使使用extern "C"，编译后的函数名还是会发生改变。例如上面我们加入_stdcall关键字说明调用约定（标准调用约定，也就是WINAPI调用约定）。 #define DLLEXPORT_API extern "C" _declspec(dllexport) 01 DLLEXPORT_API int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 编译后函数名MyFunction改编成了_MyFunction@4 通过第一种方法模块定义文件的方式DLL编译后导出函数名不会发生改变。 DLL(动态库)导出函数名乱码含义   C++编译时函数名修饰约定规则：       __stdcall调用约定：       1、以"?"标识函数名的开始，后跟函数名；         2、函数名后面以"@@YG"标识参数表的开始，后跟参数表；         3、参数表以代号表示：       X--void   D--char   E--unsigned char   F--short   H--int   I--unsigned int   J--long   K--unsigned long   M--float   N--double   _N--bool   ....       PA--表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以"0"代替，一个"0"代表一次重复；       4、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型,指针标识在其所指数据类型前；           5、参数表后以"@Z"标识整个名字的结束，如果该函数无参数，则以"Z"标识结束。       其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ"，例如                           int Test1(char *var1, unsigned long)-----"?Test1@@YGHPADK@Z"                      void Test2()-----"?Test2@@YGXXZ"         __cdecl调用约定：       规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YA"。       __fastcall调用约定：       规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YI"。       如果要用DEF文件输出一个"C++"类，则把要输出的数据和成员的修饰名都写入.def模块定义文件       所以...   通过def文件来导出C++类是很麻烦的,并且这个修饰名是不可避免的

引用 11 楼 zhanghuayi_xiyou 的回复:单独typedef 一个类型，再定义变量填初始值。  没法改源码，只有.h文件和.so文件

单独typedef 一个类型，再定义变量填初始值。

引用 8 楼 buyong 的回复:在C里用的时候，把 extern "C" 从头文件中去掉。  但是导出的函数有c规范不支持的特性，如带默认值的参数，这种要怎么解？谢谢

引用 3 楼 zhao4zhong1 的回复:学会使用objdump  这种方案只能放在后面了，先解决目前问题。谢谢

在C里用的时候，把 extern "C" 从头文件中去掉。

引用 5 楼 max_min_ 的回复:尝试用g++编译现有的c工程，没能成功，出现void*无法转换到void**的错误  修改下这个问题吧！这个应该是代码本身有问题  正在尝试修改代码。转换错误的问题已经解决。  版主有个新的错误，能否帮忙看看。  .c的文件中结构体对象这样初始化： struct user oneuser =  {    name:"Luck",    id:12,    home:"/home/Luck" }; 报错：sorry,unimplemented:non-trivial designated initializers not supported  我上网查到的都是.cpp的文件才会报错这个  我的gcc 4.4.7  谢谢了。

引用 4 楼 jmppok 的回复:[quote=引用 楼主 qq496683952 的回复:] 环境:centos 6.4 编译器：gcc  问题：在c的文件中使用c++的动态库  c++的动态库已经使用extern "C" {} 封装  查了网上的资料尝试了以下方法：  1、在c文件中使用extern { #include "库的头文件"}方式     可惜在c文件中的extern位置报错：expected identifier or ‘(’ before ‘{’ token   2、尝试用g++编译现有的c工程，没能成功，出现void*无法转换到void**的错误  烦请各位给点意见。谢谢  1、在c文件中使用extern { #include "库的头文件"}方式  还真没这么用过。  C++导出类应该用不了吧？ 如果导出的是全局函数，直接include头文件，调用就行了。[/quote]  那种方式我也是在论坛看帖子的时候看到的。  而c++导出类我只有一个.so文件和一个头文件，可以说是全局函数 直接include头文件报错，原因是因为头文件中存在extern "C"

感谢各位的帮助，谢谢大家。  问题解决了  办法如下：  1、c++的so库的头文件不变，依旧采用extern "C" 进行封装导出接口；  2、更换c工程的编译器为g++；  3、修改代码中的错误（由gcc变更为g++后出现的）；  4、使用-l方式链接so文件。  以上方面仅适用未使用c++动态库之前c工程能正常编译和运行，使用之后无法正常编译和运行的情况。  再次感谢各位的帮助和指导，谢谢。

引用 楼主 qq496683952 的回复:环境:centos 6.4 编译器：gcc  问题：在c的文件中使用c++的动态库  c++的动态库已经使用extern "C" {} 封装  查了网上的资料尝试了以下方法：  1、在c文件中使用extern { #include "库的头文件"}方式     可惜在c文件中的extern位置报错：expected identifier or ‘(’ before ‘{’ token   2、尝试用g++编译现有的c工程，没能成功，出现void*无法转换到void**的错误  烦请各位给点意见。谢谢  1、在c文件中使用extern { #include "库的头文件"}方式  还真没这么用过。  C++导出类应该用不了吧？ 如果导出的是全局函数，直接include头文件，调用就行了。

学会使用objdump

引用 1 楼 turingo 的回复:看起来似乎是你程序本身的问题，与动态库调用没多大关系。  [quote=引用 楼主 qq496683952 的回复:] 环境:centos 6.4 编译器：gcc  问题：在c的文件中使用c++的动态库  c++的动态库已经使用extern "C" {} 封装  查了网上的资料尝试了以下方法：  1、在c文件中使用extern { #include "库的头文件"}方式     可惜在c文件中的extern位置报错：expected identifier or ‘(’ before ‘{’ token   2、尝试用g++编译现有的c工程，没能成功，出现void*无法转换到void**的错误  烦请各位给点意见。谢谢[/quote]  可是我用gcc编译程序没问题，而且正常运行。

看起来似乎是你程序本身的问题，与动态库调用没多大关系。  引用 楼主 qq496683952 的回复:环境:centos 6.4 编译器：gcc  问题：在c的文件中使用c++的动态库  c++的动态库已经使用extern "C" {} 封装  查了网上的资料尝试了以下方法：  1、在c文件中使用extern { #include "库的头文件"}方式     可惜在c文件中的extern位置报错：expected identifier or ‘(’ before ‘{’ token   2、尝试用g++编译现有的c工程，没能成功，出现void*无法转换到void**的错误  烦请各位给点意见。谢谢


Question: 21点小游戏源代码错误，求指点

拷贝代码的之前，也要一定的基础吧！至少基本能看懂是什么意思！  引用 楼主 u013041733 的回复:#include<cstdlib> #include<iostream> #include<ctime> using namespace std;  class CCard { private: 	int m_Pip[5];//一共五张牌 	int m_Number;//发了多少张牌 	int m_Dollar;//赌本 	int m_Gamble;//赌注 	int m_Win;//赢局数 	int m_Lose;//输局数 	int m_Draw;//平局数 public: 	CCard();//构造函数。 	void FirstPlayTwo();//最初的两张牌 	int GetNumber();//返回牌张 	int GetPip();//返回点数 	void DisplayPip();//依次全部显示牌面的点数 	void DisplayPip(int);//除了第一张牌，依次显示全部牌面点数（针对计算机牌的显示） 	void TurnPlay();//出一张牌。 	void Win();//赢了计算赌注 	void Lose();//输了 	void Draw();//平局 	int SetGamble(int);//设置赌本，赌本不够返回-1 	int GetMoney();//返回钱数 	void DisplayInfo();//打印必要的信息 	int GetCurrentCard();//返回当前的牌点 };  int CCard::GetNumber()  return ( m Number);   CCard::CCard()//构造函数，初始化 { 	m_Number = 0; 	m_Dollar = 100;//初始赌注为100美元 	for(int i=0;i<5;i++) 		m_Pip[i] = 0; 	m_Gamble = 0; 	m_Win = m_Lose = m_Draw = 0; }  int CCard::GetMoney() { 	return m_Dollar; }  void  CCard::DisplayInfo()//打印必要的信息 { 	cout<<"\n\n\n\t\t\t您一共玩了"<<m_Win+m_Lose+m_Draw<<"局  "<<"赢了"<<m_Win<<"局  "<<"输了"<<m_Lose<<"局  "<<"平局"<<m_Draw<<"次。"<<endl; 	cout<<"\n\t\t\t\t您的赌本共计有$"<<m_Draw<<"。\n"<<endl; }  int CCard::SetGamble(int gamble) { 	if(gamble<0) 	{ 		cout<<"\n输入金额有误"<<endl; 		return -1; 	} 	if(m_Dollar-gamble<0) 	{ 		cout<<"\n金额不足"<<endl; 		return -1; 	}     else 		m_Gamble = gamble; 	m_Dollar -= gamble; 	return 0; }  void CCard::FirstPlayTwo()//最初两张牌 { 	m_Pip[0] = rand()%13+1; 	m_Pip[1] = rand()%13+1; 	m_Number = 2; }  int CCard::GetPip() { 	int SumPip = 0; 	for(int i=0;i<m_Number;i++) 	{ 		SumPip += m_Pip[i]; 	} 	return SumPip; }  void CCard::DisplayPip() { 	int i; 	for(i=0;i<m_Number;i++) 	{ 		cout<<m_Pip[i]<<'\t'; 	} 	cout<<endl; }  void CCard::TurnPlay() { 	m_Number++; 	m_Pip[m_Number-1] = rand()%13+1; }  void CCard::Win() { 	cout<<"赢家牌面："; 	DisplayPip(); 	cout<<"\n牌面点数："<<GetPip()<<endl; 	m_Dollar = m_Dollar + 2 * m_Gamble; 	m_Win++; 	cout<<"\n赌本：$"<<m_Dollar<<"     赢了"<<m_Win<<"次     "<<"输了"<<m_Lose<<"次      "<<"平局"<<m_Draw<<"次"<<endl; 	cout<<endl; 	cout<<endl; }  void CCard::Lose() { 	m_Lose++; 	cout<<"\n输家的牌面："; 	DisplayPip(); 	if(GetPip()>21) 		cout<<"\t\t\t\t\t\t\t\t暴了！"<<endl; 	else 		cout<<"牌面点数："<<GetPip()<<endl; 	cout<<"\n赌本：$"<<m_Dollar<<"      赢了"<<m_Win<<"次     "<<"输了"<<m_Lose<<"次     "<<"平局"<<m_Draw<<"次"<<endl; 	cout<<endl<<endl; }  void CCard::Draw() { 	m_Draw++; 	m_Dollar += m_Gamble; 	cout<<"\n平局牌面："; 	DisplayPip(); 	if(GetPip()>21) 		cout<<"\n暴了！"<<endl; 	else 		cout<<"牌面点数："<<GetPip()<<endl; 	cout<<"赌本：$"<<m_Dollar<<"      赢了"<<m_Win<<"次     "<<"输了"<<m_Lose<<"次     "<<"平局"<<m_Draw<<"次"<<endl; 	cout<<endl<<endl; }  void DisplayRule(void) {     cout<<endl<<endl; 	cout<<"\t※※※※※※※※※※欢迎进入21点游戏世界!※※※※※※※※※※\n\n"; 	cout<<"\t\t  游戏规则：\n";  	cout<<endl; 	cout<<"\t\t  1.玩家最多可以要5张牌；\n"; 	cout<<endl; 	cout<<"\t\t  2.如果牌点数的总数超过21点则暴点，自动判数；\n"; 	cout<<endl; 	cout<<"\t\t  3.赢家可得双倍的赌注；\n"; 	cout<<endl; 	cout<<"\t\t  4.计算机方在大于等于16点时不再要牌。\n"; 	cout<<endl; 	cout<<"\t※※※※※※※※※※※※※  祝您好运！ ※※※※※※※※※※\n"; 	cout<<endl<<endl; }  void Judge(CCard &cpu,CCard &player) { 	cout<<endl; 	if((cpu.GetPip()>21&&player.GetPip()>21)||cpu.GetPip()==player.GetPip()) 	{ 		cout<<"\n\n\t\t\t\t\t\t\t\t平局！\n"; 		cout<<"计算机数据：\t"; 		cpu.DisplayPip(); 		cout<<"牌面点数："<<cpu.GetPip()<<endl; 		cout<<"\n您的数据：\t"; 		player.Draw(); 		cout<<endl; 	} 	else if((cpu.GetPip()>21)||(player.GetPip()>cpu.GetPip()&&player.GetPip()<=21)) 	{ 		cout<<"\n\n\n\t\t\t\t\t\t\t\t恭喜您赢了！\n\n"; 		cout<<"计算机数据：\t"; 		cpu.DisplayPip(); 		cout<<"牌面点数："<<cpu.GetPip()<<endl; 		cout<<"\n您的数据：\t"; 		player.Win(); 		cout<<endl;		 	} 	else 	{ 		cout<<"\n\n\t\t\t\t\t\t\t\t很遗憾您输了！\n"; 		cout<<"计算机数据：\t"; 		cpu.DisplayPip(); 		cout<<"牌面点数："<<cpu.GetPip()<<endl; 		cout<<"\n您的数据：\t"; 		player.Lose(); 		cout<<endl; 	} } void CCard::DisplayPip(int n) { 	int i; 	cout<<""<<'\t'; 	for(i=1;i<m_Number;i++) 		cout<<m_Pip[i]<<'\t'; 	cout<<endl; }  void PlayTurn(CCard &cpu,CCard & player)//玩一局 { 	char chChoice; 	int blCpu = 1;//判断是否要牌 	int blPlayer = 1; 	cpu.FirstPlayTwo();//计算机和玩家各要两张牌 	player.FirstPlayTwo(); 	do 	{ 		cout<<"\n您的牌点为：\t"; 		player.DisplayPip(); 		cout<<"\n"; 		cout<<"您的牌面点数是："<<player.GetPip()<<endl; 		cout<<"\n计算机的牌点为：\t"; 		cpu.DisplayPip(1); 		 		if(blPlayer) 		{ 			cout<<"\n\n\t您是否继续要牌（Y/N）?\t\t\t"; 			cin>>chChoice; 			if((chChoice == 'Y'||chChoice == 'y')) 			{ 				if(player.GetNumber()<5) 				{ 					player.TurnPlay(); 					cout<<"\n您要的这张牌是："<<player.GetPip()<<endl; 					if(player.GetPip()>21) 						blPlayer = 0; 				} 				else 				{ 					cout<<"对不起，您已经要了5张牌，不能再要牌了！"; 					blPlayer = 0; 				} 			} 			if(chChoice=='n'||chChoice=='N') 				blPlayer = 0; 		} 		if(cpu.GetPip()<16&&cpu.GetNumber()<5) 		{ 			cpu.TurnPlay(); 			cout<<"\n计算机要牌，牌点是："<<cpu.GetPip()<<endl; 		} 		else 			blCpu = 0; 		if(blCpu&&player.GetNumber()<5&&player.GetPip()<21) 			blPlayer = 1; 	}while(blCpu||blPlayer); 	Judge(cpu,player); 	return ; }  int main() { 	srand((unsigned)time(NULL));//初始化随机数种子 	CCard cpu,player; 	int blLogic; 	int nMoney;// 	DisplayRule();// 	char chChoice; 	cout<<"是否现在开始游戏（Y/N）?\t\t"; 	cin>>chChoice; 	while(chChoice=='Y'||chChoice=='y') 	{ 		do 		{ 		    cout<<endl; 			cout<<"\t\t\t您现在有的赌本：$"<<player.GetMoney(); 			cout<<"\n\n请下注（赌注不能超过赌本）；"; 			cin>>nMoney; 			blLogic = player.SetGamble(nMoney); 			if(blLogic) 				cout<<"您的赌本不够，请重新下注！\n"; 		}while(blLogic); 		PlayTurn(cpu,player);// 		cout<<"是否继续21点游戏（Y/N）?\t\t\t"; 		cin>>chChoice; 	} 	player.DisplayInfo(); 	cout<<"\t\t\t您的选择是明智的，赌博有碍家庭和睦！\n"; 	cout<<"\n\n\t\t\t\t欢迎再次使用此程序！"<<endl<<endl<<endl;  	return 0; } 错误如下

return ( m_Number);

int CCard::GetNumber()   return ( m Number);  写法规范一点嘛：  int CCard::GetNumber(){ return m_Number;}

引用 1 楼 wusuopuBUPT 的回复:return那里出问题了：return (m_Number);楼上正解

return那里出问题了：return (m_Number);


Question: 关于hash函数的设计的问题

哈希算法和哈希数据结构是彼此独立的，所以需要研究各种哈希算法以便适应不同类型key的应用场景。

写错了，rc4不是。

书嘛，举例子。  你要复杂的也可以，比如rc4 md5 sha1 sha256 Tiger

<The Art of Computer Programming 2nd> Vol. 3  Chapter 6.4  Hashing

有没有更专业点的？

用素数可以减小冲突！

哈希表的数组是定长的，如果太大，则浪费，如果太小，体现不出效率。合适的数组大小是哈希表的性能的关键。哈希表的尺寸最好是一个质数，最小的质数尺寸是17


引用 6 楼 baichi4141 的回复:理由很简单 b[0x09]和b[0x10]之间隔了6个变量 b[0x0A]、b[0x0B]、b[0x0C]、b[0x0D]、b[0x0E]、b[0x0F] 这应该也不对，如果是b[0x10]的话，也不应该是  引用 6 楼 baichi4141 的回复:理由很简单 b[0x09]和b[0x10]之间隔了6个变量 b[0x0A]、b[0x0B]、b[0x0C]、b[0x0D]、b[0x0E]、b[0x0F] 谢谢，原来是这么回事！！ 回去验证结果如下  原来以十六进制表示时，变量也的系数也是要十六进制的。 以下是在十进制下查看的

不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。

VC6.0太古老了，即便在WindowsXP下也有不兼容的情形。  引用 楼主 lihuaxiong 的回复:运行程序时，进入调试状态，查看a,b变量的存储情况，发现在b变量中，看到是变量b的存储数据不一样。  但是，在屏幕中输出时，a，b变量的输出是一样的。无论是b是以指针*（b+i）输出，还是以数组b[i]输出，在屏幕上的输出结果都是一样。 左边是a变量，右边是b变量 我个人的猜测，可能是VC6.0的调试模式，在显示变量情况时，存在问题。因为看到问题都是出现在b[10]开始出现乱码（乱码可能是变量地址） 请大神指点。。 #include <stdio.h> #include <string.h>   int main(int argc, char *argv[]) {	int i,j; 	unsigned  char a[64] = {0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,\ 							0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,\ 							0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,\ 							0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67,0x01,0x23,0x45}; 	unsigned int * b=a; 	for(i=0,j=0;i<64/4;i++) 	{printf("%x%x%x%x\t%x\n",a[j+3],a[j+2],a[j+1],a[j],b[i]);j+=4;} 	 	return 0; }

引用 3 楼 focuslight 的回复:b指针变量， [i]就是 乱码但是在屏幕输出是正常输出的

b指针变量， [i]就是 乱码

不知用别的开发平台会不会也出现这种情况，本人只用过VC++6.0

有可能


Question: 文件如何读取结构体，并进行相应操作

如何是在同一个机器上，看你的代码应该不会有问题，你再GDB一下吧

为什么我这样读出来的数据  全是乱码呢，应该怎样读取二进制中的多个结构体数据？小白求解

这道题和我的毕设有点像啊，大神，能不能把代码给我发过来！ 十分感谢！

根据写进去的协议，怎么写进去，然后读出来通过结构体解析出来就好！ 匹配读写！

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fread,fwrite,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

该文件中以二进制方式 这需要规格书，或者打开文件分析二进制吗

参考http://c.chinaitlab.com/basic/892627.html  引用 楼主 xiaolanghh 的回复:有一个文件shop.dat，在该文件中以二进制方式存放了X个用于表示超市商品销 售记录的结构体类型数据。结构体的声明如下： struct Sales {     int ID;//商品编码     char name[30];//商品名称     int  num;//商品数量     float price;//商品单价 } 编写一个函数，将shop.dat 文件中的数据读出，并且构建1 个商品销售记录数组A； 编写一个函数，删除上述所生成数组A 中单价小于4000 元的商品销售记录； 编写一个函数，将经过上述处理的数组A 按照商品编码进行递增排序，并 将排序后的全部结果显示在屏幕上，每种商品的数据占一行，显示格式为： 111 IPad2 2 4688.00 122 Iphone4S 3 5899.00  写出关键的语句即可！如何读入结构体，要设置偏移量吗？如何删除记录等等！


Question: 如何学习c语言?

真心建议你去搜索郝斌的C语言视频，在看视频前先用浩强的书先预习，事半功倍。 我刚考完C语言，这个方法让我轻松掌握一些较浅的C语言知识。当你在短时间内学习忘谭浩强的C,你可以去寻找一些外国教材，这时候，你再花时间看外国教材就会更加有价值，要不你直接学习外国教材会很吃力。。 具体办法一定要多提疑问，Google里面对初学者的问题一般都会有比较好的解释，关键是你能不能提出有建设性的问题来帮助自己学习。 提出疑问的最好办法就是打代码，这不是自然科学，只是国外史前一群超级大牛定下的代码协定，规矩都是他们定，所以在打代码的时候要不断地提出疑问，就算今日不解决，随着深入学习原理，你会早晚会懂得的。 假如楼主是刚接触代码的，希望你能一路顺利，尽早发现代码的乐趣，那时候就会有源源不断的动力去支撑你去学习新的知识来满足自己。 还有，不懂的问题多上CSDN，这里卧虎藏龙，一定可以解决你的问题~

先看书,后写代码,理解了就上手了

我觉得C语言不适合0基础学习，你需要同时考虑业务逻辑与底层资源管理，这对初学者太麻烦了。 建议你先学python一类的，对编程有了概念再接触底层。

先看看浩强哥《c语言设计》，入门，知道什么是c语言，然后再看《c_program》,等你发现浩强哥的书有问题了，你就真正开始c语言了。

http://download.csdn.net/detail/max_min_/6333711 http://download.csdn.net/detail/max_min_/6333663 两本书，好好钻研钻研，入门了先！后面就开朗了

C程序设计语言，多动手试验

怎么下载不了

bc++3.1 帮助里面对每个函数都有一小段能拷贝出来运行看效果的例子程序。非常适合初学C语言。相比较而言VC带的帮助MSDN就没有。http://download.csdn.net/source/2805028

压力就是动力，找个项目或机会

引用 楼主 u013041173 的回复:如何学习从零基础开始学习c语言，有什么好的方法，有什么好的教材和视频，请各位多多给我建议，谢谢 买本入门书籍，仔细琢磨琢磨~ C的陷阱与缺陷，C专家编程，C和指针，很值得买本纸质的书学习~入门，少花点钱

参考http://blog.csdn.net/turingo/article/details/8115042  引用 楼主 u013041173 的回复:如何学习从零基础开始学习c语言，有什么好的方法，有什么好的教材和视频，请各位多多给我建议，谢谢

有四本介绍C语言比较经典的书，可以看看：C的陷阱与缺陷，C专家编程，C和指针，C语言。这几本书值得好好卡看

能给我具体点的建议吗？

C程序设计语言！ + 项目

C程序设计语言！ C与指针。


Question: 请求帮助

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

这种作业认真看一下书，然后google一下不就行了

请问那里面代码是在VC6.0 环境下实现的吗？

参考http://wenku.it168.com/d_000805985.shtml 参考http://download.csdn.net/tag/%E7%94%A8C%E8%AF%AD%E8%A8%80%E8%AE%BE%E8%AE%A1%E8%AE%A1%E7%AE%97%E5%99%A8%E7%A8%8B%E5%BA%8F%E6%BA%90%E4%BB%A3%E7%A0%81  引用 楼主 u013040721 的回复:如何用C语言实现计算器？这是我们的课程设计。谢谢啦！！

先写简单的加减乘除，然后再试压栈括号的问题！

本网站下载里搜 C语言实现计算器


Question: 【C的一道题】关于成绩管理系统的输入名字一点小问题，求解答。。

引用 3 楼 buyong 的回复:sizeof(struct student) 比较可疑 那应该肿么办呢 我把sizeof换成20了 在运行的时候有时候会突然好使，有时候就不好使，这是为什么啊。。。

引用 4 楼 uuuououlcz 的回复:可能有问题的地方，纯属个人意见，仅供参考：  struct student { 	int number;                   //学号 	float score[3];               //分数 	char name[100];               //名字，这么长的名字，有点多了吧？ }; void input(struct student *parr,int len)        //函数功能：手动输入学生信息或者选择读取文件 { 	char ch; 	printf("请选择你要录入学生信息的方式：1、手动输入  2、读取磁盘文件\n"); 	getchar();      //这个getchar()是干嘛的，等待键盘输入的方式选项？如果是为什么没有赋给ch 	scanf("%c",&ch);//这个是吃掉输入流中的'\n'换行符？还是，这才是等待键盘输入？                         //不管这个scanf是做什么用的，他都需要等待键盘输入 + Enter                         //而这个Enter会作为换行符留在输入流中，如果刚好选择的是手动输入'1'                         //则这个换行符直接遇到了scanf("%s",parr[i].name);，这又使                         //scanf字符串返回，parr[0].name为空 	switch(ch) 	{ 	case '1': 		int i; 		FILE *fp; 		fp=fopen("D:\\student.dat","w");//fopen("", "w")本身就会在没有则个文件的时候                                                 //创建一个新文件，并返回对应的文件结构指针                                                 //下面再一次fopen("", "w")是干嘛？ 		if((fopen("D:\\student.dat","w"))==NULL) 		{ 			printf("创建文件失败,请重新创建!"); 			exit(0); 		} 		printf("已创建成功！\n"); 		for(i=0;i<len;i++){ 			printf("请输入第%d个学生信息：\n",i+1); 			printf("姓名："); 			scanf("%s",parr[i].name);   //这里建议写作scanf(" %s",parr[i].name); 			printf("学号："); 			scanf("%d",&parr[i].number); 			printf("高等数学成绩："); 			scanf("%f",&parr[i].score[0]); 			printf("课程设计成绩："); 			scanf("%f",&parr[i].score[1]); 			printf("大学英语成绩："); 			scanf("%f",&parr[i].score[2]); 			fwrite(&parr[i],sizeof(struct student),1,fp); 		} 		printf("文件已保存！"); 		fclose(fp); 	case'2':  谢谢~  可是问题还是没有解决，输入名字依旧不能输入一个以上的字母。。

sizeof(struct student) 比较可疑

引用 1 楼 user-3 的回复:不能用scanf直接给数组赋值吧 不好意思，我搞错了，我这边试一下好像是可以的

不能用scanf直接给数组赋值吧


Question: 让系统留个指定大小的文件？大神进

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

引用 3 楼 baichi4141 的回复:[quote=引用 2 楼 qyxqyxqyx 的回复:] [quote=引用 1 楼 baichi4141 的回复:] 这样的做法会破坏磁盘的其他文件吗？ ——不会 文件指针会不会偏移到另一个文件内部，使得另一个文件截断了？？  ——不会  fseek仅仅只是改变了指针的值，没有改变文件的大小 fwrite读取指针值，发现现有文件大小不够大，改变文件大小并写入数据 写入的EOF是一个char型数据，任何数据都不可能截断一个文件——除非你分不清“函数从文件中读出的数据”和“函数读不到数据时的返回值” fseek偏移到1m的位置（此时文件大小没有改变），然后fwrite会先改变文件大小到1m（这个策略类似于内存malloc指定大小），如果发现无法做到（因为发现后面的磁盘空间被其他文件占用了），会返回失败，否则，改变文件大小，并写入EOF。 是这么个过程吗？[/quote] 文件由操作系统管理，在磁盘上不连续存放 只有当磁盘已经被其他文件占满或磁盘因故无法访问的时候才会出现改变文件大小失败的情形[/quote] 一个1m的文件在磁盘上可能是这儿有50k，那儿有100k,等等一片片的？就跟链表似的，这个意思？ 这在哪儿有介绍？ NT的稀疏文件怎么做到在某个指定文件指针位置存放数据，而只有一小块大小，可以在磁盘某个位置往上下扩张？

引用 2 楼 qyxqyxqyx 的回复:[quote=引用 1 楼 baichi4141 的回复:] 这样的做法会破坏磁盘的其他文件吗？ ——不会 文件指针会不会偏移到另一个文件内部，使得另一个文件截断了？？  ——不会  fseek仅仅只是改变了指针的值，没有改变文件的大小 fwrite读取指针值，发现现有文件大小不够大，改变文件大小并写入数据 写入的EOF是一个char型数据，任何数据都不可能截断一个文件——除非你分不清“函数从文件中读出的数据”和“函数读不到数据时的返回值” fseek偏移到1m的位置（此时文件大小没有改变），然后fwrite会先改变文件大小到1m（这个策略类似于内存malloc指定大小），如果发现无法做到（因为发现后面的磁盘空间被其他文件占用了），会返回失败，否则，改变文件大小，并写入EOF。 是这么个过程吗？[/quote] 文件由操作系统管理，在磁盘上不连续存放 只有当磁盘已经被其他文件占满或磁盘因故无法访问的时候才会出现改变文件大小失败的情形

引用 1 楼 baichi4141 的回复:这样的做法会破坏磁盘的其他文件吗？ ——不会 文件指针会不会偏移到另一个文件内部，使得另一个文件截断了？？  ——不会  fseek仅仅只是改变了指针的值，没有改变文件的大小 fwrite读取指针值，发现现有文件大小不够大，改变文件大小并写入数据 写入的EOF是一个char型数据，任何数据都不可能截断一个文件——除非你分不清“函数从文件中读出的数据”和“函数读不到数据时的返回值” fseek偏移到1m的位置（此时文件大小没有改变），然后fwrite会先改变文件大小到1m（这个策略类似于内存malloc指定大小），如果发现无法做到（因为发现后面的磁盘空间被其他文件占用了），会返回失败，否则，改变文件大小，并写入EOF。 是这么个过程吗？

感兴趣可以看Linux文件系统实现。

如果你想知道就去看source code吧 我也不知道

了解一下FAT、FAT32、NTFS等文件系统的工作原理吧。

另外创建空文件，和其他文件操作，没有任何冲突。 一般文件系统，都不会对文件实行清零操作，所以非零大小的“空”文件，也不是没有内容的， 这就像分配内存但并不初始化一样，里面也是会有内容的。 只要有大小，其实都不算空文件，真正的空文件，是没有内容的,大小为零，可能不会占有空间。 大小为零的空文件，可能不会分配磁盘空间，只占有所在目录的一个目录项  Windows 由于兼容DOS的缘故，这个似乎处理的不好，一个文件可能会占有多个目录项---如果文件名比较长的话  如果占有空间的话，也只有文件结束标志是文件的真正内容。 这样的文件才算空文件，你的那个有2M左右的文件，只是没有写入有意义的内容，不能算做真正的空文件。 别的文件，也不会和他有什么冲突。  一个文件的文件名，文件位置是写在目录项的记录里面的，不是记录在文件内容里面的。

在使用系统函数时，创建文件时，  没有办法做到，也没有必要做到“创建一个文件，分配给他连续的磁盘空间”。  除非自己写文件系统（驱动），自己处理文件的磁盘空间分配方案。

引用 4 楼 qyxqyxqyx 的回复:一个1m的文件在磁盘上可能是这儿有50k，那儿有100k,等等一片片的？就跟链表似的，这个意思？ 这在哪儿有介绍？ NT的稀疏文件怎么做到在某个指定文件指针位置存放数据，而只有一小块大小，可以在磁盘某个位置往上下扩张？ http://baike.baidu.com/link?url=MsOAwy3-92GhQR1oMyfguH_SnbpE-hel2kEgaMpWR4TFlX6iE7cvHlwXWOeKLezc 在问NT怎么做到之前，你该先弄清楚NT能不能做到 文件本来就是操作系统层面的概念。要在磁盘的指定区域读写文件，就自己写磁盘驱动取代操作系统本身的磁盘驱动


Question: C的静态函数问题

函数声明的时候没加static吧？

不懂帮顶。。。。

有种可能是你这个静态函数被声明为外部文件可访问。 就会报这个错误。

可以检查一下前面包含的头文件里面有没有哪个声明了非静态的abs函数。。

引用 11 楼 bluebai123 的回复:[quote=引用 7 楼 derekrose 的回复:] 发函数声明来看  #include "windows.h" #include "wintern.h" #include "device.h" #include <stdio.h> #include <stdlib.h> #include <string.h>  #if !(DOS_TURBOC | DOS_QUICKC | _MINIX | VXWORKS)   static int abs(int n) { 	return n >= 0? n: -n; } #endif  /*  * Update mouse status and issue events on it if necessary.  * This function doesn't block, but is normally only called when  * there is known to be some data waiting to be read from the mouse.  */[/quote]  show me the declaration

引用 7 楼 derekrose 的回复:发函数声明来看  #include "windows.h" #include "wintern.h" #include "device.h" #include <stdio.h> #include <stdlib.h> #include <string.h>  #if !(DOS_TURBOC | DOS_QUICKC | _MINIX | VXWORKS)   static int abs(int n) { 	return n >= 0? n: -n; } #endif  /*  * Update mouse status and issue events on it if necessary.  * This function doesn't block, but is normally only called when  * there is known to be some data waiting to be read from the mouse.  */

引用 3 楼 bijiaoben 的回复:函数声明的时候没加static吧？ 有呢吧，你看 static int abs()，我想着估计是gcc问题吧，

引用 1 楼 focuslight 的回复:有种可能是你这个静态函数被声明为外部文件可访问。 就会报这个错误。 可能吧，我在做micro Windows，编译第一个问题 就是这个，不行的话就直接把static 干掉，外部能访问就叫它能访问吧~ 多谢啦·

包含了定义 求绝对值函数 abs 的文件（可能也连接了对应的库） 实际上你的abs函数已经定义了，该定义或者他的原型声明 是个non-static declaration  你现在又定义一个新的 abs函数，这个新的定义是个static declaration  所以 static declaration of 'abs' follows non-static declaration  PS： C语言所有定义，都是声明。 声明未必是定义。

发函数声明来看

前面已经定义了另一个abs函数？

单纯这段代码是没有问题的，估计是你在其它文件有去调用abs函数。  引用 楼主 bluebai123 的回复:编译器 i386-rtems4.9-gcc 代码： static int abs(int n) { 	return n >= 0? n: -n; } 问题： error: static declaration of 'abs' follows non-static declaration  请问这个问题怎么解决呢 多谢啦


Question: 求助：~编写程序统计c源中标识符的个数

一个简单的词法分析, 或者更直接用正则表达式都可以.

参考TinyC的词法解析部分。  引用 楼主 u013022580 的回复:如题。 谢谢大家了~~


Question: 【求解释】关于scanf和getchar的区别！

你自己不是查到回车符会残留在缓冲区中。  scanf()以Space、Enter、Tab结束一次输入，不会舍弃最后的回车符（即回车符会残留在缓冲区中）；    the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). 忽略回车空格tab， 所以你要两个getchar. 一个读回车， 第二个等结束输入

引用 2 楼 jmuguy 的回复:不是说scanf()读取字符串的时候缓冲区中的'\n'不会残留在缓冲区中吗？  读取字符时：  scanf()以Space、Enter、Tab结束一次输入，不会舍弃最后的回车符（即回车符会残留在缓冲区中）；  getchar()以Enter结束输入，也不会舍弃最后的回车符；  你自己看错了，仔细看看

不是说scanf()读取字符串的时候缓冲区中的'\n'不会残留在缓冲区中吗？

scanf()以Space、Enter、Tab结束一次输入，不会舍弃最后的回车符（即回车符会残留在缓冲区中）； 第一个getchar();读取了缓冲区中的'\n' 第二个getchar();等待你输入字符

这个和scanf还是getchar没关系，你所有的输入，都会在流／stream中，包括回车；回车之所以特殊，是因为流一般是“行缓冲”的，即只有你敲回车之后，才会把缓冲中的输入，放入流中。

我不明白的地方是为什么以下代码运行后的结果都是一样的，getchar为啥可以少输入一次？

那为什么这段代码只要两个getchar就可以了？按照道理应该要有三个getchar啊 // 5.1Tallback.cpp : 可以提供一些信息的对话程序 //  #include "stdafx.h" #include <string.h> #define DENSITY 62.4   int _tmain(int argc, _TCHAR* argv[]) { 	float weight,volume; 	int size,letters; 	char name[40];  	printf("Hi!What's your first name?\n"); 	scanf("%s",name); 	printf("%s,what's your weight in pounds?\n",name); 	scanf("%f",&weight); 	size=sizeof name; 	letters=strlen(name); 	volume=weight/DENSITY; 	printf("Well,%s,your volume is %2.2f cubic feet.\n", 		name,volume); 	printf("Also,your first name has %d letters,\n",letters); 	printf("and we have %d bytes to store it in.\n",size); 	getchar(); 	getchar(); 	return 0; }

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。