Question: 赵老师，一个C语言问题请教

C:\windows_2000_source_code\win2k\private\windows\base\client\lmem.c     133: HLOCAL     134: WINAPI     135: LocalReAlloc(     136:     HLOCAL hMem,     137:     SIZE_T uBytes,     138:     UINT uFlags     139:     )     140: {     141:     PBASE_HANDLE_TABLE_ENTRY HandleEntry;     142:     LPSTR p;     143:     ULONG Flags;     144:      145:     if ((uFlags & ~(LMEM_VALID_FLAGS | LMEM_MODIFY)) ||     146:         ((uFlags & LMEM_DISCARDABLE) && !(uFlags & LMEM_MODIFY))     147:        ) {     148: #if DBG     149:         DbgPrint( "*** LocalReAlloc( %lx ) - invalid flags\n", uFlags );     150:         BaseHeapBreakPoint();     151: #endif     152:         SetLastError( ERROR_INVALID_PARAMETER );     153:         return( NULL );     154:         }     155:      156:     Flags = 0;     157:     if (uFlags & LMEM_ZEROINIT) {     158:         Flags |= HEAP_ZERO_MEMORY;     159:         }     160:     if (!(uFlags & LMEM_MOVEABLE)) {     161:         Flags |= HEAP_REALLOC_IN_PLACE_ONLY;     162:         }     163:      164:     RtlLockHeap( BaseHeap );     165:     Flags |= HEAP_NO_SERIALIZE;     166:     try {     167:         if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {     168:             HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)     169:                 CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );     170:      171:             if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {     172: #if DBG     173:                 DbgPrint( "*** LocalReAlloc( %lx ) - invalid handle\n", hMem );     174:                 BaseHeapBreakPoint();     175: #endif     176:                 SetLastError( ERROR_INVALID_HANDLE );     177:                 hMem = NULL;     178:                 }     179:             else     180:             if (uFlags & LMEM_MODIFY) {     181:                 if (uFlags & LMEM_DISCARDABLE) {     182:                     HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;     183:                     }     184:                 else {     185:                     HandleEntry->Flags &= ~BASE_HANDLE_DISCARDABLE;     186:                     }     187:                 }     188:             else {     189:                 p = HandleEntry->Object;     190:                 if (uBytes == 0) {     191:                     hMem = NULL;     192:                     if (p != NULL) {     193:                         if ((uFlags & LMEM_MOVEABLE) && HandleEntry->LockCount == 0) {     194:                             if (RtlFreeHeap( BaseHeap, Flags | HEAP_NO_SERIALIZE, p )) {     195:                                 HandleEntry->Object = NULL;     196:                                 HandleEntry->Flags |= BASE_HANDLE_DISCARDED;     197:                                 hMem = (HANDLE)&HandleEntry->Object;     198:                                 }     199:                             }     200:                         else {     201: #if DBG     202:                             DbgPrint( "*** LocalReAlloc( %lx ) - failing with locked handle\n", &HandleEntry->Object );     203:                             BaseHeapBreakPoint();     204: #endif     205:                             }     206:                         }     207:                     else {     208:                         hMem = (HANDLE)&HandleEntry->Object;     209:                         }     210:                     }     211:                 else {     212:                     Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;     213:                     if (p == NULL) {     214:                         p = RtlAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, uBytes );     215:                         if (p != NULL) {     216:                             RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );     217:                             }     218:                         }     219:                     else {     220:                         if (!(uFlags & LMEM_MOVEABLE) &&     221:                             HandleEntry->LockCount != 0     222:                            ) {     223:                             Flags |= HEAP_REALLOC_IN_PLACE_ONLY;     224:                             }     225:                         else {     226:                             Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;     227:                             }     228:      229:                         p = RtlReAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, p, uBytes );     230:                         }     231:      232:                     if (p != NULL) {     233:                         HandleEntry->Object = p;     234:                         HandleEntry->Flags &= ~BASE_HANDLE_DISCARDED;     235:                         }     236:                     else {     237:                         hMem = NULL;     238:                         SetLastError( ERROR_NOT_ENOUGH_MEMORY );     239:                         }     240:                     }     241:                 }     242:             }     243:         else     244:         if (!(uFlags & LMEM_MODIFY)) {     245:             hMem = RtlReAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, (PVOID)hMem, uBytes );     246:             if (hMem == NULL) {     247:                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );     248:                 }     249:             }     250:         }     251:     except (EXCEPTION_EXECUTE_HANDLER) {     252:         hMem = NULL;     253:         BaseSetLastNTError( GetExceptionCode() );     254:         }     255:      256:     RtlUnlockHeap( BaseHeap );     257:      258:     return( (LPSTR)hMem );     259: }

理解和讨论之前请先学会如何观察！  观察的具体办法：Linux下参考相关源代码。Windows下有源代码参考相关源代码，没源代码参考单步时执行过的汇编代码以及中途调用过的API。

new是new（≈alloc＋construct） alloc是alloc

引用 32 楼 zhao4zhong1 的回复:不能使用new返回的指针！ 为毛

引用 30 楼 zhao4zhong1 的回复:不过如果遇上realloc较原来大的一块内存，且无法在原地分配（后面紧挨着的内存以被分配）时，还真得在新位置分配新的，再将旧内容拷贝到新位置，然后“自动free掉旧的”。 看来某种程度上我也是二把刀啊！ 老赵，，刚才用代码试过了，WINDOWS下，当发生内存块移动时，以前的那个旧指针用_CrtIsValidHeapPointer函数检查不过，会导致程序挂掉的，或者用_msize函数检查也是一样的结果，，一个有效的地址用这两个检查都是通的过的，，所以是被自动给释放掉的，

不能使用new返回的指针！

以被分配→已被分配

realloc()  changes  the  size  of the memory block pointed to by ptr to        size bytes.  The contents will be unchanged to the minimum of  the  old        and new sizes; newly allocated memory will be uninitialized.  If ptr is        NULL, the call is equivalent to malloc(size); if size is equal to zero,        the  call is equivalent to free(ptr).  Unless ptr is NULL, it must have        been returned by an earlier call to malloc(),  calloc()  or  realloc().        If the area pointed to was moved, a free(ptr) is done.

realloc的语义是改变原内存块的大小，并没有生成一块新内存，所以就没必要free了。 至于哪个二把刀说“会自动free掉旧的”，权当笑话那么一听吧。  想从根本上理解，可参考Linux源代码中realloc的具体实现代码。

引用 24 楼 zhao4zhong1 的回复:以下回复再次证明本ID只会复制粘贴MSDN内容： realloc Reallocate memory blocks.  void *realloc( void *memblock, size_t size );  Routine Required Header Compatibility  realloc <stdlib.h> and <malloc.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  realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.  Parameters  memblock  Pointer to previously allocated memory block  size  New size in bytes  Remarks  The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to calloc, malloc, or realloc.  The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument.  realloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode. The new handler mode indicates whether, on failure, malloc is to call the new handler routine as set by _set_new_handler. By default, malloc does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when realloc fails to allocate memory, malloc calls the new handler routine in the same way that the new operator does when it fails for the same reason. To override the default, call   _set_new_mode(1)  early in your program, or link with NEWMODE.OBJ.  When the application is linked with a debug version of the C run-time libraries, realloc resolves to _realloc_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.  Example  /* REALLOC.C: This program allocates a block of memory for  * buffer and then uses _msize to display the size of that  * block. Next, it uses realloc to expand the amount of  * memory used by buffer and then calls _msize again to  * display the new amount of memory allocated to buffer.  */  #include <stdio.h> #include <malloc.h> #include <stdlib.h>  void main( void ) {    long *buffer;    size_t size;     if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )       exit( 1 );     size = _msize( buffer );    printf( "Size of block after malloc of 1000 longs: %u\n", size );     /* Reallocate and show new size: */    if( (buffer = realloc( buffer, size + (1000 * sizeof( long )) ))          ==  NULL )       exit( 1 );    size = _msize( buffer );    printf( "Size of block after realloc of 1000 more longs: %u\n",              size );     free( buffer );    exit( 0 ); }   Output  Size of block after malloc of 1000 longs: 4000 Size of block after realloc of 1000 more longs: 8000   Memory Allocation Routines  See Also   calloc, free, malloc 砖家，，这段文字从头到尾都没有明确的提到说realloc会自动将发生内存块移动时，将旧的内存块给释放掉啊，，，网上说会自动释放，但我想看看标准说明，，还有realloc函数的入参除了是calloc malloc realloc函数返回的结果外，可不可以是new返回的结果？？？？？我要标准说明，，，

引用 23 楼 bug1190 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 bug1190 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 严重怀疑楼主不会用realloc函数。 我干，，我暴露了，， 是要配合realloc才能完美解决，，，老赵，我好心给你分享答案，，你来揭我短儿，，[/quote] 用realloc要小心，参考下面： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; } [/quote] 老赵，，为什么用realloc分配成功时，不把此前的旧的内存给delete掉一次，不删除不会有内存泄漏吗[/quote] 刚才查资料说是会自动free掉旧的，，，MSDN上没见到有标准说明啊，能否给我引用一段，不要COPY没用的啊

free Deallocates or frees a memory block.  void free( void *memblock );  Function Required Header Compatibility  free <stdlib.h> and <malloc.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  None  Parameter  memblock  Previously allocated memory block to be freed  Remarks  The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc. The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc). If memblock is NULL, the pointer is ignored and free immediately returns. Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.  After a memory block has been freed, _heapmin minimizes the amount of free memory on the heap by coalescing the unused regions and releasing them back to the operating system. Freed memory that is not released to the operating system is restored to the free pool and is available for allocation again.  When the application is linked with a debug version of the C run-time libraries, free resolves to _free_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.  Example  /* MALLOC.C: This program allocates memory with  * malloc, then frees the memory with free.  */  #include <stdlib.h>         /* For _MAX_PATH definition */ #include <stdio.h> #include <malloc.h>  void main( void ) {    char *string;     /* Allocate space for a path name */    string = malloc( _MAX_PATH );    if( string == NULL )       printf( "Insufficient memory available\n" );    else    {       printf( "Memory space allocated for path name\n" );       free( string );       printf( "Memory freed\n" );    } }   Output  Memory space allocated for path name Memory freed   Memory Allocation Routines  See Also   _alloca, calloc, malloc, realloc, _free_dbg, _heapmin

引用 10 楼 zhao4zhong1 的回复:[quote=引用 6 楼 bug1190 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 严重怀疑楼主不会用realloc函数。 我干，，我暴露了，， 是要配合realloc才能完美解决，，，老赵，我好心给你分享答案，，你来揭我短儿，，[/quote] 用realloc要小心，参考下面： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; } [/quote] 老赵，，为什么用realloc分配成功时，不把此前的旧的内存给delete掉一次，不删除不会有内存泄漏吗

赵老师在哪里教书啊？

c是一个老生常谈的问题，好难

不明觉厉啊！！我是Java系的菜鸟魔法师

我不说话，就看着你们装逼

引用 13 楼 bug1190 的回复:[quote=引用 11 楼 user-7 的回复:] c++中有, std::ostringstream, 再也不用操心这些事情了。 我日你亲哥，在MFC下面或者是在ATL下面，CString也能轻松完成这功能，而且格式都基本不用变，这说的是C好不，看清点[/quote] 难得理你，不要引用我。


Question: 关于HZK16数字和字母的字模提取

引用 7 楼 chenpeng3 的回复:有人会用C#写这段代码吗，求赐教请问你搞定了吗，同求啊

有人会用C#写这段代码吗，求赐教

最近刚好看这个相关的东东。  HZK16 应该是GB2312， 分别有94个区和94个位。  内码和区位码的转换： 内码高字节 = 区码+0xA0H 内码低字节 = 位码+0xA0H  转成区位码之后 计算 内存中的偏移： 偏移 = ((区码- 1) * 94 + 位码 - 1) * 32;  提取的方式嘛，简单可以指定一个中文字符串：  “1234567890” （当然这个要输入法 输入中文的数字字符，编译文件指定是ANSI编码） 一个循环，每次2个字符分别代表了内码的高低字节。 然后转区位码，然后计算偏移，然后就拿到了32字节的点阵数据啦。  当然要使用的话，一般转成8字节的数据。

引用 2 楼 zhao4zhong1 的回复:ASC16  搜索下载UCDOS，里面有HZK16和ASC16这两个文件  仅供参考： #include <mem.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <graphics.h> const unsigned char bit[8]={128,64,32,16,8,4,2,1}; //-------------------------------------------------------- void dis(xoff,code)     unsigned int xoff,code; {     unsigned char *buffer;     FILE *hzk;     unsigned long offset;     unsigned int q,w;     int x,y,width;      buffer=calloc(32,1);     if ((code&0xFF00)!=0) {         w=(code&0x00FF)-0xA1;         q=((code>>8)&0x00FF)-0xA1;         offset=q*0x5E+w;         offset*=32;         if ((hzk=fopen("HZK16","rb"))==NULL) {             closegraph();             printf("Can not open HZK16\r\n");             exit(1);         }         fseek(hzk,offset,SEEK_SET);         fread(buffer,1,32,hzk);         fclose(hzk);         width=2;     }     else {         if ((hzk=fopen("ASC16","rb"))==NULL) {             closegraph();             printf("Can not open ASC16\r\n");             exit(1);         }         offset=code*16;         fseek(hzk,offset,SEEK_SET);         fread(buffer,1,16,hzk);         fclose(hzk);         width=1;     }     for (y=0;y<16;y++) for (x=0;x<8*width;x++) {         if (buffer[y*width+x/8]&bit[x%8]) putpixel(xoff+x,y,15);     }     free(buffer); } //-------------------------------------------------------- void display(p)     unsigned char *p; {    int i;   unsigned int qw;    i=0;   while (1) {     if (p[i]==0x0D||p[i]==0x1A) break; 	if (p[i]>0xA0) { 		qw=((unsigned int)p[i]<<8)|((unsigned int)p[i+1]&0x00FF); 		dis(8*i,qw); 		i+=2; 	} 	else { 		qw=(unsigned int)p[i]&0x00FF; 		dis(8*i,qw); 		i++; 	}   }  } //-------------------------------------------------------- void main() { 	int gdriver = DETECT, gmode, errorcode; 	long fl; 	FILE *hz; 	unsigned char *p;  	initgraph(&gdriver, &gmode, "c:\\borlandc\\bgi"); 	errorcode = graphresult(); 	if (errorcode != grOk) { 	   printf("Graphics error: %s\n", grapherrormsg(errorcode)); 	   exit(1); 	} 	hz=fopen("hz","rb"); 	fseek(hz,0,SEEK_END); 	fl=ftell(hz); 	p=calloc((int)fl,sizeof(unsigned char)); 	rewind(hz); 	fread(p,1,(int)fl,hz); 	fclose(hz); 	display(p); 	free(p); 	getch(); 	closegraph(); }    谢谢赵四老师的回答，我会下载一个ASC16的字库试试，但是这里我还是有一个疑问，HZK16字库里面A1-A9 是符号区，我看字模数据表，里面也有字母和数字，不知道这些字符在HZK16里面要怎么读取出来呢

引用 4 楼 zhao4zhong1 的回复:全角符号（Ａａ１＃），半角符号（Aa1#） 开始、运行、charmap、确定，在字符映射表中查看对应字符的GBK码。  用ASC16确实可以得到标点和英文的数据，谢谢。


Question: 为什么按回车不能结束输入呢？ 小白求解答

上面说的越界不是真正意义上的越界。你可能申请的是有1000个元素的数组，但是你真正用到的只有前8个。但你在使用的时候用到了第9个元素，这个元素的值就会是的个大数字（如果你没初始化过数组）。

从你那个-842150451来看，是你在操作数组的过程中越界了，好好检查下操作数组的代码。你每次运行的这个值应该是不固定的。但一般都是很大的负数或正数。

scanf返回输入成功的参数个数，对于scanf("%d", &n)要么返回1（输入成功），要么返回0（包含空数字字符）或EOF(windows环境CTRL + Z, linux环境CTRL + D)

sizeof(n) = 4（32位机器），死循环了，下面代码输入非数字或空白字符即可退出循环  while (scanf("%d", &n) == 1) { ... }

ctrl + z试试阿

引用 6 楼 hhhhhhhhhhkkkkkkkkkk 的回复: 我用的VC6.0的。必须按Ctrl+Z才能结束，而且我在建立两个线性表后按升序合并后倒数第二个总会出现一个这个

按Ctrl+C或Ctrl+Break结束。

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

应该是你编译器的问题。刚才我试了一下是可以的。

你用的什么编译器？

引用 1 楼 hhhhhhhhhhkkkkkkkkkk 的回复:能的啊，不过你的循环是死的。 可是我这不能啊，这样也不行   while(scanf("%d",&n)!='\n')

能的啊，不过你的循环是死的。


Question: 那个大神，有C#学生补考管理系统

补考管理系统。。。应该很少有人做这种项目。 去C#技术区吧，这里是C++。去.NET技术板块的C#技术区

童鞋，这个不会有人直接给你答案的，建议自己搜一个，仔细认真看源码，争取看懂吧


Question: 如何用C语言写出windows窗口程序，而不再是控制台

Windows系统：“不要调用我，请先填写好未来收到某个消息时你的处理流程，在那个消息到来时我会调用你！”

windows窗口就是个界面，实现相对很复杂，即使你用源码写出来了，也很难对它进行灵活的控制。为什么一定要源码呢？有成型的框架可用。比如：VC++、C-Free等这些工具直接就可以建一个窗口，鼠标一拽就拽出来一个控件。源码很复杂，使用很简单。ps：vc++编写界面使用c++语言，c-free编写界面可以用c语言。

请详细研读《windows程序设计》。 这本书从头到尾讲述了怎么做。 赵老师的回答也非常不错。

赵老师回答必属精品！

引用 7 楼 u013131224 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 u013131224 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }  这个是windows编程么？[/quote] 如假包换！ 下面这个也是Windows编程： #pragma comment(lib,"user32") #include <windows.h> #include <conio.h> void main() {     int r;      cprintf("press any key...");     getch();     r=MessageBox(NULL,"Hello!","MsgBox",MB_OKCANCEL|MB_SETFOREGROUND);     cprintf("\r\nr=%d",r); } [/quote] 额，这个不是C语言程序吧[/quote] 这不是C，是什么？谁能回答我？

如果是想用C来做windows程序，个人建议可以试试labWindows（CVI）。是NI公司的C语言windows程序开发环境

引用 6 楼 zhao4zhong1 的回复:[quote=引用 4 楼 u013131224 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }  这个是windows编程么？[/quote] 如假包换！ 下面这个也是Windows编程： #pragma comment(lib,"user32") #include <windows.h> #include <conio.h> void main() {     int r;      cprintf("press any key...");     getch();     r=MessageBox(NULL,"Hello!","MsgBox",MB_OKCANCEL|MB_SETFOREGROUND);     cprintf("\r\nr=%d",r); } [/quote] 额，这个不是C语言程序吧

引用 4 楼 u013131224 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }  这个是windows编程么？[/quote] 如假包换！ 下面这个也是Windows编程： #pragma comment(lib,"user32") #include <windows.h> #include <conio.h> void main() {     int r;      cprintf("press any key...");     getch();     r=MessageBox(NULL,"Hello!","MsgBox",MB_OKCANCEL|MB_SETFOREGROUND);     cprintf("\r\nr=%d",r); }

引用 4 楼 u013131224 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }  这个是windows编程么？[/quote]应该是吧，调用的都是win下面的API来着，反正跟我用的linux下的api不一样

引用 1 楼 zhao4zhong1 的回复:#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     PAINTSTRUCT ps;     HDC hdc;     HFONT hfont,ohfont;     RECT r;     COLORREF oc;      switch(message) {     case WM_CLOSE://按Alt+F4退出         PostQuitMessage(0);         break;     case WM_PAINT:         BeginPaint(hWnd, &ps);         hdc = ps.hdc; // the device context to draw in         GetClientRect(hWnd, &r); // Obtain the window's client rectangle         hfont = CreateFont(240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");         ohfont=(HFONT)SelectObject(hdc,hfont);         oc=SetTextColor(hdc,0x00C080FF);         SetBkMode(hdc, TRANSPARENT);         TextOut(hdc,r.left+r.right/2-720, r.top+r.bottom/2-120,"最短画图程序",12);         SelectObject(hdc,ohfont);         SetTextColor(hdc,oc);         DeleteObject(hfont);         EndPaint(hWnd, &ps);         break;     default:         return DefWindowProc(hWnd, message, wParam, lParam);     }     return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {     MSG msg             = {0};     WNDCLASS wc         = {0};     HBRUSH hbrh;     hbrh=CreateSolidBrush(0x00000000);     wc.lpfnWndProc      = WndProc;     wc.hInstance        = hInstance;     wc.hbrBackground    = hbrh;     wc.lpszClassName    = "minwindowsapp";     wc.hCursor          = LoadCursor(NULL,IDC_ARROW);     if( FAILED(RegisterClass(&wc)) ) return 1;      if(FAILED(CreateWindow(wc.lpszClassName,                         "Minimal Windows Application",                         WS_POPUP|WS_VISIBLE,                         0,                         0,                         GetSystemMetrics(SM_CXSCREEN),                         GetSystemMetrics(SM_CYSCREEN),                         0,                         0,                         hInstance,                         NULL)))         return 2;      while( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {         DispatchMessage( &msg );     }     DeleteObject(hbrh);     return 0; }  这个是windows编程么？

使用 windows提供的API。

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


Question: c语言文件操作，读不到数据啊？

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

for( i = 0; i != COL ; i++){ for( j = 0; j < VOL; j++){ fscanf(fp,"%.3f", &val); printf("\t %f \n", val); if( val > 1000 && val < 10000){	 grid[i][j] = val; } 你的val没初始化，都是-107374176.000。你自己检查下


Question: 大家帮我看看，为什么我输出的值是101？

谢谢赵4老师的谨言，我会铭记的。

袄，非常感谢

for (i=2; i<=100; i++ );  // 这一行最后多了个分号


Question: 这一题很有意思   求各路大神指导  为什么我的栈溢出了

#include<stdio.h> #include<stdlib.h> #include<time.h> #define MAX 100000 // 元素个数 #define NUM_MAX 100000 // 随机数的最大值+1 int Partition(int a[],int n,int low,int high)//快速寻找分界点 { int pivotkey,t; pivotkey=a[low]; while(low<high) { while(low<high&&a[high]>=pivotkey) high--; t=a[low]; a[low]=a[high]; a[high]=t; while(low<high&&a[low]<=pivotkey) low++; t=a[low]; a[low]=a[high]; a[high]=t; } return low; }  void QSort(int a[],int n,int low,int high)//快速排序 { int pivotloc; if(low<high) { pivotloc=Partition(a,n,low,high); QSort(a,pivotloc,low,pivotloc-1); QSort(a,high-pivotloc,pivotloc+1,high); } } void swap(int a[], int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }  void BubbleSort(int a[],int n)//冒泡排序 { int t,i,j; for(j=1;j<=n-1;j++) for(i=1;i<=n-j;i++) if(a[i-1]>a[i]) { t=a[i-1]; a[i-1]=a[i]; a[i]=t; } }  int main() {  srand(time(00)); int i,a[MAX]; clock_t begin, end; double cost;  for(i=0;i<MAX;i++) a[i]=rand()%NUM_MAX; begin = clock(); BubbleSort(a,MAX); end = clock(); cost = (double)(end - begin) / CLOCKS_PER_SEC; printf("冒泡排序用时为：%lf 秒\n", cost);   begin = clock(); QSort(a,MAX,0,MAX-1); end = clock(); cost = (double)(end - begin) / CLOCKS_PER_SEC; printf("快速排序用时为：%lf 秒\n", cost); system("pause"); return 0; }

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

在函数内部定义临时变量，100000个整型肯定会导致栈溢出。应该使用new生成变量。  不过没有代码，说个jb啊。

用第归了没？ 嵌套层次是否太深

没代码那还说啥

static int a[MAX]; #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)); } int i; unsigned long ul; void main() {     srand(time(NULL));     for (i=0;i<10;i++) {         ul=ulrand();         printf("%010lu 0x%08x\n",ul,ul);     } } //2337588057 0x8b54c359 //1977377429 0x75dc6295 //3607316769 0xd7034921 //0009828482 0x0095f882 //3350859779 0xc7ba1003 //0945794621 0x385fae3d //3400869024 0xcab524a0 //3097846779 0xb8a563fb //4287421124 0xff8cdac4 //3934016258 0xea7c5302

不是   我用vs运行的

int Partition(int a[],int n,int low,int high)//快速寻找分界点 { int pivotkey,t; pivotkey=a[low];//这个还支持变量长度的数组？新版c++吗？最好还是改成new 吧。


Question: 初学链表有问，大神帮忙

scanf("%d",&n);

好吧，手误....

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


Question: 在C语言中说补码运算是可交换和可结合的，它具体指的是什么意思？

关键不在补码上，而是说整数可以进行交换和组合而不影响精度，因为整数运算不失精度。 但浮点运算是要丢失精度的，不能随便改变计算顺序。 比如计算 1.00001 + (- 1.0) + 0.000000001，按正常顺序可以得到0.00001+0.000000001, 两个数相差不大，结果可以保持较高精度。 但如果改为1.00001 + (-1.0 + 0.000000001)，后两者相差太大，可能0.000000001被丢失。

这句话出自《深入理解计算机系统》第五章中的5.9节------“提高并行性”。其中为了提高程序的性能在循环中定义多个临时积累变量。它说：补码运算是可交换和可结合的，所以这样优化不会影响运算结果的正确性，但浮点乘法和加法不是可结合的，所以这样的优化会产生不同的运算结果。  不太清楚它说的所谓的：可结合与可交换是指数学上的，还是C语言的特性，具体情况是什么？ 请高手解答一下，谢谢！！

C语言对整数编码不作要求，请给出更多信息（哪本书，具体怎么说）。 另外，数学上交换和结合分别指 a*b=b*a 和 (a*b)*c=a*(b*c)

“结合律”

搜“交换律”、“结合率”。

嗯，就你这么举例一说，的确整数运算时改变计算顺序，不会改变运算的结果，而浮点运算就不同了。 改变了原来的计算顺序可能会产生不同的运算结果，尤其是当发生四舍五入或溢出时。


Question: 谁有C语言版的CMPP协议，求大神赐教

how much


Question: 构造法

1）数组 b 没有有初始化，默认为 0？？？ 2）a[n] 这个数据没输入，默认为0？？？ 3）输入过程中 b[a[i]] 中最后一个更新的数据（编号）保存了下来，所以 数组 b非 0数据，比n要少。 4）while(n--) 中，用排过序的数据作为下标，处理b中的数据      4.1）b[a[i]]=x-b[a[i]];（b镜像？），和翻转处理(a)      4.2）对全体数据(n+1个)，再做一次    b镜像，a翻转  这个原问题没给出，猜测很吃力

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

scanf("%d",&a[i]);  b[a[i]]=i;  //a[i]是输入的一个数, b[a[i]]表示这个数是第几个被输入的


Question: C语言实现push pop操作

struct 结构体可根据需要自己补充变量

typedef struct tag_Queue{     int array[5]; 	int number; }Queue;   Queue *queue; void push(Queue *queue, int value){     //填充内容  	if (queue->number >= 5) 		return; 	queue->array[queue->number] = value; 	queue->number++; 	 }   int pop(Queue *queue){     //填充内容 	if (queue->number <= 0) 		return 0; 	queue->number--;  	return queue->array[queue->number]; }  pop出错和push出错都没有处理，一个返回了0 一个直接不添加。要想处理出错情况要修改下参数。


Question: 我这有个函数看不明，望指教

引用 7 楼 u010211892 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 赵老师，我好想举报你，永远在复制粘贴！！！[/quote] 我好想举报整个IT界，永远在使用冯诺依曼架构。

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

感觉你这个不是2进制转换器，而是256进制转换器。l = l*256 + (long)psBinString[i];中的256是等于多少进位的数，进几进制数，比如1*10+2，就是十进制转换。二进制转换器应该是l = l*2+ (long)psBinString[i]; 你的二进制字符串是："1100"这种么，其中的每个数字就是一个二进制位，还是？？？

引用 2 楼 shuitamen 的回复:[quote=引用 1 楼 MisteryMethod 的回复:] psBinString[n] 是一个UCHAR 0x00000000 占用8bit  所以每次偏移一个UCHAR 就需要乘256  0x00000001 0x00000002 转换为10进制 不就是 2+1*256 我试着放了一个“A5”进行运算，A5换算成十进制是165，但得到的l却大得离谱：16693，是我用错了，还是说需要在转换一下？[/quote]   A5 是按照字符串传进去的。。 也就是说 第一个UCHAR 存入的是 A 的 ASCII码对应的值65，第二个对应的是5对应的ASCII码的值 53 内存位置是这样0x01000001 0x00110101 65 * 256 + 53 = 16693  A5是 16进制表示的话，0xA5应该是 一个UCHAR对应的是 psBinString[0] = 165 或者 psBinString[0] = 0xA5;

1.psBinString在这里是缓冲区的概念 2.(long)psBinString[i],这里做了强制转换,步长是8Byte(看上去你这是64位系统,否则不会乘以256)

引用 1 楼 MisteryMethod 的回复:psBinString[n] 是一个UCHAR 0x00000000 占用8bit  所以每次偏移一个UCHAR 就需要乘256  0x00000001 0x00000002 转换为10进制 不就是 2+1*256 我试着放了一个“A5”进行运算，A5换算成十进制是165，但得到的l却大得离谱：16693，是我用错了，还是说需要在转换一下？


Question: 请教双链表是书上翻译错了还是我理解错误？

仅供参考//将c:\\tmp文件夹下的所有文件的内容全部放到用malloc分配的内存中 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> struct FB {     char fn[256];     size_t fl;     char *b;     struct FB *next;     struct FB *prev; } *fh,*fb,*ft; char ln[256]; char fpn[256]; FILE *af; FILE *f; int L,n; int main() {     system("dir /b /a-d c:\\tmp\\*.* >c:\\allfn.txt");     af=fopen("c:\\allfn.txt","r");     if (NULL==af) {         printf("Can not open file c:\\allfn.txt!\n");         return 1;     }     fh=NULL;     fb=NULL;     n=0;     while (1) {         if (NULL==fgets(ln,256,af)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) ln[L-1]=0;         printf("read %s\n",ln);         strcpy(fpn,"c:\\tmp\\");         strcat(fpn,ln);         ft=(struct FB *)malloc(sizeof(struct FB));         if (NULL==ft) {             printf("Can not malloc ft!\n");             fclose(af);             return 2;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]==%p\n",n,ft);         strcpy(ft->fn,fpn);         f=fopen(fpn,"rb");         if (NULL==f) {             printf("Can not open file %s!\n",fpn);             fclose(af);             return 3;//之前的malloc在main退出后由操作系统自动free         }         ft->fl=_filelength(fileno(f));         ft->b=malloc(ft->fl);         if (NULL==ft->b) {             printf("Can not malloc ft->b!\n");             fclose(f);             fclose(af);             return 4;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]->b==%p\n",n,ft->b);         if (ft->fl!=fread(ft->b,1,ft->fl,f)) {             printf("fread error!\n");             fclose(f);             fclose(af);             return 5;//之前的malloc在main退出后由操作系统自动free         }         fclose(f);         ft->next=NULL;          if (NULL==fh) {             ft->prev=NULL;             fh=ft;         } else {             fb->next=ft;             ft->prev=fb;         }         fb=ft;         n++;     }     fclose(af);     printf("-----list-----\n");     for (ft=fh;NULL!=ft;ft=ft->next) {         printf("%8d %s\n",ft->fl,ft->fn);         if (NULL!=ft) fb=ft;     }     printf("-----free-----\n");     n--;     if (NULL!=fh) {         for (ft=fb->prev;NULL!=ft;ft=ft->prev) {             if (NULL!=ft->next->b) {                 printf("ft[%d]->b==%p\n",n,ft->next->b);                 free(ft->next->b);             }             if (NULL!=ft->next) {                 printf("ft[%d]==%p\n",n,ft->next);                 free(ft->next);             }             n--;         }         if (NULL!=fh->b) {             printf("ft[0]->b==%p\n",fh->b);             free(fh->b);         }         printf("ft[0]==%p\n",fh);         free(fh);     }     return 0; } //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //找不到文件 // //C:\tmp\tmp\Debug>tmp //找不到文件 //-----list----- //-----free----- // //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //2011-06-30  18:04            44,840 my_c.rar //2011-06-30  17:18             1,036 err.frm //2011-06-30  14:32            14,243 出租.txt //2011-06-28  12:08            23,681 MSDN98书签.txt //             4 个文件         83,800 字节 //             0 个目录 17,041,870,848 可用字节 // //C:\tmp\tmp\Debug>tmp //read my_c.rar //ft[0]==00421800 //ft[0]->b==00520068 //read err.frm //ft[1]==00421670 //ft[1]->b==0052AFC0 //read 出租.txt //ft[2]==00421530 //ft[2]->b==00378F28 //read MSDN98书签.txt //ft[3]==004213F0 //ft[3]->b==0052B3F8 //-----list----- // 44840 c:\tmp\my_c.rar //  1036 c:\tmp\err.frm // 14243 c:\tmp\出租.txt // 23681 c:\tmp\MSDN98书签.txt //-----free----- //ft[3]->b==0052B3F8 //ft[3]==004213F0 //ft[2]->b==00378F28 //ft[2]==00421530 //ft[1]->b==0052AFC0 //ft[1]==00421670 //ft[0]->b==00520068 //ft[0]==00421800 // //C:\tmp\tmp\Debug>

zhao4zhong1描述：将data指向的新元素插入到双向链表list中element指向的元素之后。当插入前list为空时，element无用，此时最好取值NULL。在插入完成后，不要释放data所指向的内存，因为该函数内部实现不拷贝data所指向的内存。

template <class T> struct ListNode {   struct ListNode *prev, *next;   T *data; }; 链表的目的是什么？是为了线性并动态地存储数据，指向数据的指针，那么肯定是一个指针，你管它数据(data)是什么类型的。反正data的类型是使用链表的人确定的。


Question: 帮忙看下啊

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

对不起，说错了。 你用int指针指向字符串，每次拿4个字符做int，当然不是97。

97就是'a'，想打字符用%c

#include <stdio.h> int main() { int *a; char *c="and"; int b; b=(int)c[0]; a=&b; printf("%d",*a);//97 return 0; }

还有一个a=c;忘了打了，帮看一下到底什么情况啊


Question: 3DES加密之后的乱码处理

同求.....

加密后的数据是二进制数据，不是字符串，如果想转成字符串，可考虑base64编码

字符串加密之后的数据就不是正常的字符串； 当成字符串就会是空或者乱码；

3DES加密是按二进制加密的，不用处理的

使用HexDump函数显示字节流。

加密后已经成了字节流了，你按printf("%02X ", buf[0]);这种把buf里的内容打出来就可以了

引用 3 楼 MisteryMethod 的回复:是这样加密完后的密码不能当字符串来使用，只能当char *来使用，因为是块长度是固定的。 因为有很多不可见字符，所以需要一个字符一个字符的打印。 可以输出成0xFF这种形式的，每一个CHAR 进行一次取值，强转，16进制换算进行打印   求代码  别的项目对888888进行3DES加密（key是16位），结果是16位数字+大写字母 我该怎么也转换成这样？

引用 1 楼 zhao4zhong1 的回复:仅供参考： #include <stdio.h> #include <string.h> FILE *f; char buffer[4096]; int r,a; void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } } int main(int argc,char **argv) {     if (argc<2) {         fprintf(stderr,"Usage: %s filename.ext\n",argv[0]);         return 2;     }     f=fopen(argv[1],"rb");     if (NULL==f) {         fprintf(stderr,"Can not open file [%s]!\n",argv[1]);         return 1;     }     a=0;     while (1) {         r=fread(buffer,1,4096,f);         HexDump(buffer,r,a);         a+=r;         if (r<4096) break;     }     fclose(f);     return 0; }   我把加密之后的密码当作字符串（%s）打印出来时是4个字符的乱码，长度8。这个乱码我可以直接拿来正确的解密，但调用接口的时候乱码肯定不行，该怎么弄？ 麻烦说清楚点，我是搞java的………………


Question: 为什么是unsigned int？

引用 13 楼 zjq9931 的回复:16进制的写法，就是无符号类型的数。 不是这样的，我说的规则来自C规范。 详情请参考我的博客（常整型部分） http://www.cnblogs.com/edward-bian/p/3870679.html

引用 13 楼 zjq9931 的回复:16进制的写法，就是无符号类型的数。 觉得这个说法合理

16进制的写法，就是无符号类型的数。

理解和讨论之前请先学会如何观察！

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

根据C的标准，在32位环境下0x80000000当然是unsigned int啊  3.1.3.2 Integer constants  Syntax            integer-constant:                   decimal-constant integer-suffix<opt>                   octal-constant integer-suffix<opt>                   hexadecimal-constant integer-suffix<opt>            decimal-constant:                   nonzero-digit                   decimal-constant digit            octal-constant:                   0                    octal-constant octal-digit            hexadecimal-constant:                   0x  hexadecimal-digit                   0X  hexadecimal-digit                   hexadecimal-constant hexadecimal-digit            nonzero-digit: one of                   1  2  3  4  5  6  7  8  9            octal-digit: one of                   0  1  2  3  4  5  6  7            hexadecimal-digit: one of                   0  1  2  3  4  5  6  7  8  9                   a  b  c  d  e  f                   A  B  C  D  E  F            integer-suffix:                   unsigned-suffix long-suffix<opt>                   long-suffix unsigned-suffix<opt>            unsigned-suffix: one of                   u  U            long-suffix: one of                   l  L  Description     An integer constant begins with a digit, but has no period or exponent part.  It may have a prefix that specifies its base and a suffix that specifies its type.     A decimal constant begins with a nonzero digit and consists of a sequence of decimal digits.  An octal constant consists of the prefix 0 optionally followed by a sequence of the digits 0 through 7 only.  A hexadecimal constant consists of the prefix 0x or 0X followed by a sequence of the decimal digits and the letters a (or A ) through f (or F) with values 10 through 15 respectively.  Semantics     The value of a decimal constant is computed base 10; that of an octal constant, base 8; that of a hexadecimal constant, base 16.  The lexically first digit is the most significant.     The type of an integer constant is the first of the corresponding list in which its value can be represented.  Unsuffixed decimal: int, long int, unsigned long int; unsuffixed octal or hexadecimal: int, unsigned int, long int, unsigned long int; suffixed by the letter u or U: unsigned int, unsigned long int; suffixed by the letter l or L: long int, unsigned long int; suffixed by both the letters u or U and l or L: unsigned long int .  32为环境下0x80000000是不能用int表示的，但是可以用unsigned int表示，所以就是unsigned int类型呀

引用 楼主 u013491662 的回复: #include <stdio.h> int main() { 	printf("%d", 0x80000000 >> 31); 	return 0; }  为什么0x80000000是unsigned int类型？它不应该是最小的int数吗？ 要是0x8000就是int型？  电脑没有说它是unsigned int类型，它就是一个二进制数字，你怎么看得出电脑说它是什么类型了？  你其实是想问你的移位计算结果吧。

#define is_unsigned(a) ( (a) >= 0 && ~(a) >= 0 ) int main() { 	printf("%d",is_unsigned(0x80000000)); }

写错了 2. 如果从signed开始尝试且为10进制，则跳过unsigned。

常整型的类型定义规则： 1. 从signed int 或指定类型（比如UL）向上尝试； 2. 如果从signed开始尝试且为10进制，则通过unsigned。  0x80000000从signed int 开始尝试，放不下且是16进制，则尝试unsigned int，成功。

int最大表示2 147 483 647，0x80000000是十进制的2 147 483 648，已超出范围，在右移之前，要用更大的范围的整数类型表示0x80000000，这是我的理解，不对了欢迎指出来

引用 8 楼 user-10 的回复:他本来就是int型啊 32为环境下0x80000000是unsigned int  程序为证明  #include <stdio.h>  int main(int argc, char *argv[]) {     int n = 0x80000000;     unsigned int u = 0x80000000;      printf("0x%08x 0x%08x 0x%08x\n", n >> 8, u >> 8, 0x80000000 >> 8);      return 0; } /* 输出: 0xff800000 0x00800000 0x00800000 */  虽然C89上说负数的右移操作结果implementation-defined的, gcc对负数的右移是带符号的右移, 这个结果足以说明 0x80000000是unsigned int     The result of E1 >> E2 is E1 right-shifted E2 bit positions.  If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity, 2 raised to the power E2 .  If E1 has a signed type and a negative value, the resulting value is implementation-defined.

引用 7 楼 misskissC 的回复:Integer Promotion:凡是可以使用int或unsigned int类型作右值的地方也都可以使用有符号或无符号的char型、short型及Bit-field。如果原始类型类型范围能用int型表示，则其类型被提升为int，如果int表示不了则提升为unsigned int. 这个和integer promotions提升没有关系吧，

他本来就是int型啊


Question: 动态数组插入问题

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

引用 1 楼 Idle_ 的回复:insert时没有增加cnt  真的，谢谢~~

insert时没有增加cnt


Question: 字符串的替换问题

因为str 跟 q 的地址重复了， 因此 strcat失败  str跟r连接之后变成了 123efg456   因为efg跟456 之间没有 字符串结束符\0，因此str要到  456之后才算结束  这样就跟 4开始的q字符串 地址重复了。  失败

#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //


Question: 咨询一个glibc中strcat的实现的一个疑问

Obsolete Forms of Function Declarations and Definitions The old-style function declarations and definitions use slightly different rules for declaring parameters than the syntax recommended by the ANSI C standard. First, the old-style declarations don’t have a parameter list. Second, in the function definition, the parameters are listed, but their types are not declared in the parameter list. The type declarations precede the compound statement constituting the function body. The old-style syntax is obsolete and should not be used in new code. Code using the old-style syntax is still supported, however. This example illustrates the obsolete forms of declarations and definitions:    double old_style();           /* Obsolete function declaration */  double alt_style( a , real )  /* Obsolete function definition */     double *real;      int a;  {     return ( *real + a ) ; }  Functions returning an integer or pointer with the same size as an int are not required to have a declaration although the declaration is recommended.   To comply with the ANSI C standard, old-style function declarations using an ellipsis now generate an error when compiling with the /Za option and a level 4 warning when compiling with /Ze. For example:  void funct1( a, ... )  /* Generates a warning under /Ze or */ int a;                 /* an error when compiling with /Za */ { }  You should rewrite this declaration as a prototype:  void funct1( int a, ... ) { }  Old-style function declarations also generate warnings if you subsequently declare or define the same function with either an ellipsis or a parameter with a type that is not the same as its promoted type.   The next section, C Function Definitions, shows the syntax for function definitions, including the old-style syntax. The nonterminal for the list of parameters in the old-style syntax is identifier-list.

不要纠结了，这是二十多年前的语法，早就淘汰了。 int strhhh (a)      int *a; { ...... 这个相当于 int strhhh (int *a) { ...


Question: GCC编译参数问题

搜“跟我一起写makefile”

一楼的回答很好，编译器无法改变代码的内容， 除非选择条件编译 具体事例是什么呢

你的具体需求是什么？ 1楼说的是一个方法

编译时修改值不太可能。 可能的做法是根据不同的编译参数，选择不同的值。 例如： int a=0; #if defined ( D1)      a=1; #elif defined(D2)      a=2; #endif


Question: 已在struct与typedef迷惑求解

一言以蔽之：typedef就是为某个自定义类型起了个名字而已罢了。

struct 定义结构体； typedef 为类型（包括结构体，类）定义别名；  struct  A { };  typedef A AA；

struct 是定义结构体，但是声明时需要struct XXX enployee;才能使用 typedef 为复杂的声明定义简单的别名  typedef struct xxx { }AAA; 这样就可以使用AAA 直接定义 AAA enployee;


Question: 新人问题求助

我知道了，因为pow不能随便做函数名。。


Question: 静态库 头文件问题

《程序员的自我修养——链接、装载与库》

从语法来说不一定需要，c语言对函数声明的要求不严格，即使不声明也能调用。但是还是声明一下比较清楚规范。 比如，不包含string.h也能使用memset等库函数，但是应该声明。

如果不在头文件里声明，其他人如何知道你提供了哪些接口？所以头文件里包含的是所有你提供接口的声明。链接期间链接器处理的是中间文件（*.o或*.obj），它看不到h和c源文件。

建议包含头文件。虽然说 strcpy、memset 之类的不用 stdio、stdlib 都一样调用，并且会提示，但能编译过去，因为是标准 C 的。你试试不包含 windows.h 来调用 Windows API？肯定么没玩没了的报错。


Question: c 程序监控mysql 表数据变化

引用 5 楼 zhao4zhong1 的回复:我的意思是你不要去做Java或C#转为C的无用功。 赵老师可能误解我意思了， 类似帖子如下： Java程序监控MySQL数据库更新的问题 http://bbs.csdn.net/topics/370148351 C#监控MySQL数据库/表变化 http://bbs.csdn.net/topics/390661071 这两个链接可忽略不看的，我这里说的是其他语言监控mysql的类似帖子，而我这里是C的，不是要将Java或C#转为C哈吗，场景见4楼我的回复。 C程序监控mysql应该不涉及语言之间的转化吧

我的意思是你不要去做Java或C#转为C的无用功。

引用 2 楼 zhao4zhong1 的回复:不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·…… 谢谢，不知道赵老师可以回复得通俗些，接地气些么，呵呵 场景是这样的，用户---【操作】---》客户端网站---【增删改】---》mysql数据库---【数据表中数据变化】《------》C 程序获知数据变化------》根据逻辑条件do something 按你说的A将请求数据写到文件a.txt，写完后改名为aa.txt，我这边是操作不了A的，只能操作B 网上基本两种建议：1 触发器 ，2 监控binlog

引用 1 楼 user-2 的回复:你研究一下mysql提供的C API就可以了，应该不麻烦 谢谢，我看看...

你研究一下mysql提供的C API就可以了，应该不麻烦

你就不能等Java或C#的弄出来后，用管道或共享文本文件的方法调用它们吗？ 实在不想等的话，自己搜“监控mysql C源代码”


Question: C中socket通信关于断线重连的问题

搜“VC 心跳包 源代码”

这个心跳包属于长链接，需要后台支持的！

引用 1 楼 lovesmiles 的回复:服务器端定时发一个包给客户端，客户端在规定时间内检查有没有收到这个包，没有就是断线了，重连接。  可以用clock函数实现计时。 服务器哪边怎么写的我不知道......发这个包有没有返回呢？？要不要select监听？如果断开我是需要再重新创建套接字进行连接？那我的套接字就变了？是不是套接字也要设定为动态的？

引用 3 楼 liuxingyu0502 的回复:这个心跳包属于长链接，需要后台支持的！能不能再说详细点？后台怎么支持的呢？


Question: 请问如何得到一个文件除去最后64位的部分。

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

自问自答了，前面打开文件那里，用==比较了string，所以文件没有打开。

引用 7 楼 Idle_ 的回复:[quote=引用 6 楼 u011336497 的回复:] [quote=引用 3 楼 Liu_peiqi 的回复:] 在c/c++程序中，约定俗成，n表大小，0->n-1表索引。 大神帮我看下为什么一个fseek都能出现segmentation fault。[/quote]  那就是有可能fseek前的语句中有溢出。检查一下前面grcp_xxxx传递的参数是否都正确[/quote] 可是把fseek注释掉就没问题了。

引用 6 楼 u011336497 的回复:[quote=引用 3 楼 Liu_peiqi 的回复:] 在c/c++程序中，约定俗成，n表大小，0->n-1表索引。 大神帮我看下为什么一个fseek都能出现segmentation fault。[/quote]  那就是有可能fseek前的语句中有溢出。检查一下前面grcp_xxxx传递的参数是否都正确

引用 3 楼 Liu_peiqi 的回复:在c/c++程序中，约定俗成，n表大小，0->n-1表索引。 大神帮我看下为什么一个fseek都能出现segmentation fault。

引用 2 楼 robertbo 的回复:fseek是从0开始的，ftell得到的是n，比如fseek(fTmp, 100L, SEEK_SET);后，ftell大小得到的是（100-0）的值，所以是n。 大神帮我看下为什么一个fseek都能出现segmentation fault。

引用 1 楼 user-5 的回复:是从0开始吧. 其实只要写一个程序跑一下就行了. 好郁闷，我fseek一下都segmentation fault.  #include <stdio.h> #include <stdlib.h> #include <gcrypt.h> void replace_newline(char *password, size_t length){ 	int i; 	for(i=0; i<length; i++){ 		if(password[i]=='\n'){ 			password[i]='\0'; 		} 	} }   void trim_filename(char *filename){ 	int i; 	for(i=0; i<30; i++){ 		if(filename[i]=='\0'){ 			filename[i-3]='\0'; 			break; 		} 	} } int main(int argc, char* argv[]){ 	if(argc<3){ 		printf("Please input enough parameters."); 	}     if(!gcry_check_version(GCRYPT_VERSION)){         fputs("libgcrypt version mismatch\n", stderr);         exit(2);     } 	/*Disable secure memory.*/ 	gcry_control(GCRYCTL_DISABLE_SECMEM, 0); 	/*Loading complete*/ 	gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 	printf("Initialization finished\n"); 	 	FILE *fp, *fpout; 	char *filename; 	char password[256]; 	char *salt="NaCl"; 	char key[64]; 	int initial_vector[4]={5, 8, 4, 4}; 	int filesize; 	char mac_buffer[64]; 	char mac_buffer_new[64]; 	int i; 	unsigned char cur; 	gcry_cipher_hd_t hd; 	gcry_md_hd_t hdmac; 	filename=argv[1]; 	if(argv[2]=="l"){ 		fp=fopen(argv[1],"r+"); 		trim_filename(filename); 		if(fp==NULL){ 			printf("Fail to open file."); 			exit(1); 		} 		 	}else{ //		receive_file(); 		fp=fopen("temp", "r"); 	}  	if(fopen(filename, "r")==NULL){ 		printf("File exists."); 		exit(33); 	}  	fpout=fopen(filename, "w"); 	 	printf("Password:"); 	fgets(password, 256, stdin); 	replace_newline(password, 256); 	gcry_kdf_derive(password, strlen(password), GCRY_KDF_PBKDF2, GCRY_MD_SHA512, salt, strlen(salt), 4096, 64, key); 	for(i=0; i<64; i++){ 		printf("%02X ", (unsigned char) key[i]); 	} 	printf("\n"); /*Get the last 64 bytes which is the HMAC. And verify it.*/ 	gcry_md_open(&hdmac, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); 	gcry_md_setkey(hdmac, key, 64); 	fseek(fp, 0, SEEK_END); /*	filesize=ftell(fp); 	fseek(fp, 0L, SEEK_SET); 	 	fseek(fp, filesize-64, SEEK_SET); 	fread(mac_buffer, 64, 1, fp);//Get the last 64 bytes which is HMAC. 	fseek(fp, 0L, SEEK_SET); 	i=0; 	while(i<filesize-64){ 		cur=fgetc(fp); 		gcry_md_putc(hdmac, cur); 		i++; 	} 	mac_buffer_new=gcry_md_read(hdmac, GCRY_MD_SHA512); 	for(i=0; i<64; i++){ 		if(mac_buffer[i]!=mac_buffer_new[i]){ 			printf("HMAC doesn't match."); 		} 	} */      }

在c/c++程序中，约定俗成，n表大小，0->n-1表索引。

是从0开始吧. 其实只要写一个程序跑一下就行了.


Question: 怎么把一段字符串插入到另一段字符串

以下代码的任务是将ch2插入到ch1的第m个字符之后，并将结果放在ch3中，这里需保证m不能大于ch1的总长度，否则ch2无法插入。仅供参考，大神勿喷 	char ch1[30] = {0}; 	char ch2[30] = {0}; 	char ch3[100] = {0}; 	int m;			// 在ch1中第m个字符之后插入ch2,不应该大于ch1的总长度  	printf("please input ch1:\n"); 	scanf("%s",ch1); 	printf("please input ch2:\n"); 	scanf("%s",ch2); 	printf("please input m:\n"); 	scanf("%d",&m);  	char *p1 = ch1; 	char *p2 = ch2; 	char *p3 = ch3; 	int nTemp = 0; 	while (*p1 != '\0') 	{ 		if (nTemp < m) 		{ 			*p3++ = *p1++; 		} 		else 		{ 			if (*p2 == '\0') 			{ 				*p3++ = *p1++; 			} 			else 			{ 				*p3++ = *p2++; 			} 		} 		nTemp++; 	}   	printf("str1:%s\nstr2:%s\n%d\n" ,ch1,ch2,m); 	printf("%s\n",ch3);

代码很乱啊，第二个循环中ch2[i]就不对吧，这个i应该是从0开始吧（或者这里应该是一个从0开始的j）

仅供参考#include <stdio.h> #include <string.h> #include <locale.h> char s[256]; char *p; int r,n,i; int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //

写成函数不好吗？  #include <stdio.h> #include <string.h>   /**   * @brief insert s2 into s1 at position n  *   * @param s1  * @param s2  * @param n   *   * @return s1  */ char *strins(char *s1, const char *s2, size_t n) {     size_t n1, n2;      n1 = strlen(s1);     if (n > n1)         n = n1;      n2 = strlen(s2);     memmove(s1 + n + n2, s1 + n, n1 - n + 1);     memcpy(s1 + n, s2, n2);      return s1; }  int main(int argc, char *argv[]) {     char s1[1024];     char s2[] = "abc";      strcpy(s1, "0123456789");     strins(s1, s2, 3);     printf("%s\n", s1);      strcpy(s1, "0123456789");     strins(s1, s2, 0);     printf("%s\n", s1);      strcpy(s1, "0123456789");     strins(s1, s2, 10);     printf("%s\n", s1);      strcpy(s1, "0123456789");     strins(s1, s2, 15);     printf("%s\n", s1);      return 0; }  /* output: 012abc3456789 abc0123456789 0123456789abc 0123456789abc */

其实LZ是想把ch1和ch2组合成一个新的字符数组，但是不是strcat那样直接把ch2添加到ch1尾部，而是把ch2内容插到ch1第m个元素的后面。

什么把ch2插入到ch1，又分段存储到ch3中？不明白你的意思了……你那个m怎么理解？如果我输入101？怎么办？还有记住数组的初始化、sizeof和strlen的区别……

strcat函数，连接两个字符串 http://blog.csdn.net/u012421456/article/details/38645335#t7


Question: 分享一下我的C笔记

写的不错哦  赞一个

So many books

膜拜楼主

这笔记更像是对c的介绍

小白在此感谢楼主……

学习学习，

对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！

不错呀！谢谢分享

寫得太好了 頂!!!

这个笔记不太适合初学者

很好   刚开始学习C   正好学习一下  谢了你的分享


Question: 为什么C程序的结果会是这样的？

引用-789.124023 后面小数023哪来的？ 浮点数的规格化问题

认真复习一下printf format实参的意义。

1. 浮点数都是2进制表示的，不能精确表示所有数； 2. printf 的格式为%[flags][width][.precision][length]type，小数点前是最小长度，小数点后表示精度

1.计算机无法精确的区分浮点数，所以后面那几位数是无效的，可以不理会 2.你指的位宽是什么？是总共输出的位数，还是小数点后数字的个数。如果数字位数大于指定的位数，会全部输出，小于，则对齐。小数后指定位数的格式是“%.2f”，这样只会保留2位小数


Question: 不知是哪里出错了,将“log.txt”读入结构体数组,搜索结构体内某个成员并将该成员所在结构体数组的flowin&flowout取负值.

我感觉被骗了，一直在用code block 大叔你是说用visual stdio吗

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 关于结构体里指针的指针赋值问题

引用 7 楼 cl781121 的回复:[quote=引用 6 楼 xusen1013 的回复:] [quote=引用 2 楼 cl781121 的回复:] 那应该怎么样写呢？ struct _pic_data { unsigned char **rgba; }; ....... void main() { pic_data* poutdata=new pic_data; poutdata->rgba = (unsigned char**) malloc(1024); poutdata->rgba[0] = 0; } 这样就OK了[/quote]    可是我的项目里一定要poutdata->rgba[0][0]这样的方式去赋值，我应该怎么写？[/quote] 你的什么项目要用这种方式赋值？ 你可以把 poutdata->rgba 当成一个指向指针数组的指针。 poutdata->rgba = (unsigned char**) malloc(sizeof(unsigned char*)*4);  4个指针就够了，因为只需要用到4个内存空间存R、G、B、A这4个通道的像素数据。 上面是为指针数组分配了空间，下面为指针数组中的4个指针分配空间：  poutdata->rgba[0] = (unsigned char*)malloc(sizeof(unsigned char)*size); poutdata->rgba[1] = (unsigned char*)malloc(sizeof(unsigned char)*size); poutdata->rgba[2] = (unsigned char*)malloc(sizeof(unsigned char)*size); poutdata->rgba[3] = (unsigned char*)malloc(sizeof(unsigned char)*size);  size 值为多少，需要看你的图片尺寸有多大，一般是图片的宽x高，这4段内存空间是用来分别存R、G、B、A通道的数据的。

引用 6 楼 xusen1013 的回复:[quote=引用 2 楼 cl781121 的回复:] 那应该怎么样写呢？ struct _pic_data { unsigned char **rgba; }; ....... void main() { pic_data* poutdata=new pic_data; poutdata->rgba = (unsigned char**) malloc(1024); poutdata->rgba[0] = 0; } 这样就OK了[/quote]    可是我的项目里一定要poutdata->rgba[0][0]这样的方式去赋值，我应该怎么写？

引用 2 楼 cl781121 的回复:那应该怎么样写呢？ struct _pic_data { unsigned char **rgba; }; ....... void main() { pic_data* poutdata=new pic_data; poutdata->rgba = (unsigned char**) malloc(1024); poutdata->rgba[0] = 0; } 这样就OK了

简单说你rgba指向的是数组，而不是指针。 你可以把rgba定义为unsigned char[N]* N如果不是常数，则只好一维化或再申请一个指针数组

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

行数可以没有，列数得有吧

那应该怎么样写呢？

poutdata->rgba[0][0] = 0; 是因为你想模拟二位数组，但你告诉系统你的行数，也没有列数，所以系统没法处理


Question: C语言编程：用二进制打开一个*dat文件，取出1K

楼上正解啊，不难

谢邀，已经有解，露个脸^_^

把你自己 写的代码拿出来看看.  比如文件大小为8K，要取出从第6.5K，到7.5K的1K。 fread fseek(pFile, 6.5*1024, SEEK_SET); //从文件起始位置移动6.5k, 当然, 你自己计算的时候, 要写成字节 fread(buf, 1,  1*1024, pFile); //读取1K数据到buf中. fclose

不判断每个函数的返回值≡作死

引用 9 楼 mujiok2003 的回复:[quote=引用 6 楼 helloya123 的回复:] 你这个代码我怎么看不懂啊？ 比如文件大小为8K，要取出从第6.5K，到7.5K的1K。 直接调用吧: demo.exe 6500 [/quote] demo.exe 6656

引用 6 楼 helloya123 的回复:你这个代码我怎么看不懂啊？ 比如文件大小为8K，要取出从第6.5K，到7.5K的1K。 直接调用吧: demo.exe 6500

楼上回复太复杂了。应该用fopen、fseek、fread就能解决吧。我没调试通，请教各位前辈。

#include <sys\stat.h> #include <io.h> #include <fcntl.h> #include <share.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <string.h> #define MAX_CLU_BYTES 65536 FILE *fo; int fh; __int64 offs,offs1; __int64 rvi64; int rv,wrv; unsigned char buf[MAX_CLU_BYTES]; char ofn[_MAX_PATH]; char offstr[80]; void strcpybutcomma(char *t,char *s) {     char c;      while (1) {         c = *s++;         if (','!=c) *t++ = c;         if (0==c) break;     } } void main(int argc,char **argv) {     if (argc<3) {         printf("Copy File Tail.\n");         printf("Usage:\n");         printf("    cft filename.ext offset_begin[-offset_end]\n");         printf("Copy filename.ext offset_begin[-offset_end] to offset_begin[-offset_end]-filename.ext\n");         printf("Note: Byte at offset_end is NOT included.\n");         printf("Example:\n");         printf("    cft abc.rar 12345\n");         printf("Copy abc.rar offset 12345-end to 12345-abc.rar\n");         printf("    cft abc.rar 123-12345\n");         printf("Copy abc.rar offset 123-12345 to 123-12345-abc.rar\n");         printf("    cft abc.rar 0xAB-0xCD\n");         printf("Copy abc.rar offset 0xAB-0xCD to 0xAB-0xCD-abc.rar\n");         return;     }     strcpybutcomma(offstr,argv[2]);     rv=sscanf(offstr,"%I64i-%I64i",&offs,&offs1);     if (rv==0) {         printf("offset %s is not number\n",argv[2]);         return;     }     fh=_sopen(argv[1],_O_BINARY|_O_RDONLY|_O_RANDOM,_SH_DENYNO);     if (fh==-1) {         printf("_sopen %s errno=%d\n",argv[1],errno);         return;     }     if (rv==1) {         offs1=_filelengthi64(fh);         if (offs1==-1i64) {             printf("%I64=_filelengthi64 errno=%d\n",offs1,errno);             _close(fh);             return;         }     } else {//rv==2         if (offs1<offs) {             printf("%s offset_begin>offset_end error\n",argv[2]);             _close(fh);             return;         }     }     rvi64=_lseeki64(fh,offs,SEEK_SET);     if (rvi64!=offs) {         printf("%I64u=_lseeki64 %I64u errno=%d\n",rvi64,offs,errno);         _close(fh);         return;     }     sprintf(ofn,"%s-",offstr);     strcat(ofn,argv[1]);     fo=fopen(ofn,"wb");     if (fo==NULL) {         _close(fh);         printf("fopen %s error\n",ofn);         return;     }     cprintf("\n%I64u\r",offs);     while (1) {         rv=_read(fh,buf,(unsigned int)__min(offs1-offs,MAX_CLU_BYTES));         if (rv==0) break;//         if (rv<0) {             fclose(fo);             _close(fh);             printf("_read %s offset %I64u error\n",argv[1],offs);             return;         }         wrv=fwrite(buf,1,rv,fo);         if (wrv!=rv) {             fclose(fo);             _close(fh);             printf("fwrite %s error\n",ofn);             return;         } else {             offs+=rv;             cprintf("%I64u\r",offs);             if (offs>=offs1) break;//         }     }     fclose(fo);     _close(fh);     printf("Copy %s offset %s to %s OK.\n",argv[1],argv[2],ofn); }

从test.pdb读，写入out.dat,  offset有命令参数提供， 如果没有则从头开始读入 #include <stdio.h>  int main(int argc, char*argv[]) {   freopen("test.pdb", "rb", stdin);   freopen("out.dat", "wb", stdout);   unsigned int  offset = 0, length = 1024, rdbytes = 0, total = 0, wtbytes = 0;   if (argc == 2){     sscanf(argv[1], "%u", &offset);   }   char buf[1024];   while (0 == ferror(stdin))   {     rdbytes = fread(buf, 1, 1024, stdin);     total += rdbytes;     if (total >= offset)     {       break;     }   }   if (total > offset){     wtbytes = fwrite(buf + rdbytes - (total - offset), 1, total - offset, stdout);   }   rdbytes = fread(buf, 1, 1024, stdin);   if (rdbytes > 0){     if (rdbytes > length - wtbytes)       rdbytes = length - wtbytes;     wtbytes += fwrite(buf, 1, rdbytes, stdout);   }   return 0; }

fopen fread fwrite fclose 就这几个函数，自己查查先。

回复错了， 抱歉。

Debug->Exceptions->break when an exception is


Question: gcrypt为什么这样对我。。。

引用 7 楼 user-3 的回复:https://www.gnupg.org/documentation/manuals/gcrypt/ 根据这个文档推测gcrypt是带测试代码的。 我有在tests下找到一个叫fipsdrv.c的文件，里面的代码应该有参考性。

#include <cstdlib> #include <iostream> #include <string> #include <gcrypt.h>  using namespace std;  #define GCRY_CIPHER GCRY_CIPHER_AES128   // Pick the cipher here #define GCRY_MODE GCRY_CIPHER_MODE_ECB // Pick the cipher mode here  void aesTest(void) {     gcry_cipher_hd_t handle;     size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);      string txtBuffer ("123456789 abcdefghijklmnopqrstuvwzyz ABCDEFGHIJKLMNOPQRSTUVWZYZ");     size_t txtLength = txtBuffer.size() +1; // string plus termination     char * encBuffer = (char *)malloc(txtLength);     char * outBuffer = (char *)malloc(txtLength);      char * key = "one test AES key"; // 16 bytes      gcry_control (GCRYCTL_DISABLE_SECMEM, 0);      gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);      gcry_cipher_open(&handle, GCRY_CIPHER, GCRY_MODE, 0);      gcry_cipher_setkey(handle, key, keyLength);      gcry_cipher_encrypt(handle, encBuffer, txtLength, txtBuffer.c_str(), txtLength);      gcry_cipher_decrypt(handle, outBuffer, txtLength, encBuffer, txtLength);      size_t index;     printf("encBuffer = ");     for (index = 0; index<txtLength; index++)         printf("%c", encBuffer[index]);     printf("\n");      printf("outBuffer = %s\n", outBuffer);      gcry_cipher_close(handle);     free(encBuffer);     free(outBuffer); }   int main() {     aesTest();     return 0; }   https://stackoverflow.com/questions/26189967/aes128-in-libgcrypt-not-encrypting

没人懂么。。网上也基本没有程序例子。。

引用 4 楼 user-3 的回复:LZ有读参考手册么？ 有啊。。。读了才知道怎么写的。

LZ有读参考手册么？

有人懂gcrypt嘛~~

虽然我后面有几个0没处理，但前面的内容应该正常显示啊。。

于是就打印出来一堆乱码。加密马上解密都不可以。


Question: 不用matlab和opencv，只是用简单的C语言，能实现高斯滤波吗

引用 8 楼 u013931282 的回复:[quote=引用 7 楼 lovesmiles 的回复:] [quote=引用 6 楼 u013931282 的回复:] [quote=引用 5 楼 lovesmiles 的回复:] [quote=引用 4 楼 u013931282 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！[/quote] K是RGB三色通道。看你是对彩图还是灰度图操作。对灰度图操作，这个代码要改一下。[/quote] 我的是对灰度图像操作，是将K去掉就可以了吗？高斯滤波结束后，图像的像素有什么规律吗，我怎么判断我的结果是否正确？谢啦！嘿嘿[/quote]  怎么判断你的结果是不是正确的，这个真是个难题，只能用同样的算法在matlab上面跑一下两个结果是不是一致。 话说你对高斯滤波的意义和算法步骤理解透彻没有？你说的结果正确是什么概念？[/quote] 老师让我自己看，查高斯滤波的代码，我在网上查到的，高斯滤波就是用邻域内像素的加权平均值代替邻域中心的像素值，先要通过公式产生一个模板，然后用这个模板和图像矩阵做卷积运算。我理解的是把卷积运算后的结果赋值给原图像，然后原图像就改变了，是这样吗？我也是刚学，所以也不知道查的对不对。双边滤波是和高斯滤波的步骤差不多，只是产生模板的公式不一样吗？[/quote] 模板也有大小的。

引用 7 楼 lovesmiles 的回复:[quote=引用 6 楼 u013931282 的回复:] [quote=引用 5 楼 lovesmiles 的回复:] [quote=引用 4 楼 u013931282 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！[/quote] K是RGB三色通道。看你是对彩图还是灰度图操作。对灰度图操作，这个代码要改一下。[/quote] 我的是对灰度图像操作，是将K去掉就可以了吗？高斯滤波结束后，图像的像素有什么规律吗，我怎么判断我的结果是否正确？谢啦！嘿嘿[/quote]  怎么判断你的结果是不是正确的，这个真是个难题，只能用同样的算法在matlab上面跑一下两个结果是不是一致。 话说你对高斯滤波的意义和算法步骤理解透彻没有？你说的结果正确是什么概念？[/quote] 老师让我自己看，查高斯滤波的代码，我在网上查到的，高斯滤波就是用邻域内像素的加权平均值代替邻域中心的像素值，先要通过公式产生一个模板，然后用这个模板和图像矩阵做卷积运算。我理解的是把卷积运算后的结果赋值给原图像，然后原图像就改变了，是这样吗？我也是刚学，所以也不知道查的对不对。双边滤波是和高斯滤波的步骤差不多，只是产生模板的公式不一样吗？

引用 6 楼 u013931282 的回复:[quote=引用 5 楼 lovesmiles 的回复:] [quote=引用 4 楼 u013931282 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！[/quote] K是RGB三色通道。看你是对彩图还是灰度图操作。对灰度图操作，这个代码要改一下。[/quote] 我的是对灰度图像操作，是将K去掉就可以了吗？高斯滤波结束后，图像的像素有什么规律吗，我怎么判断我的结果是否正确？谢啦！嘿嘿[/quote]  怎么判断你的结果是不是正确的，这个真是个难题，只能用同样的算法在matlab上面跑一下两个结果是不是一致。 话说你对高斯滤波的意义和算法步骤理解透彻没有？你说的结果正确是什么概念？

引用 5 楼 lovesmiles 的回复:[quote=引用 4 楼 u013931282 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！[/quote] K是RGB三色通道。看你是对彩图还是灰度图操作。对灰度图操作，这个代码要改一下。[/quote] 我的是对灰度图像操作，是将K去掉就可以了吗？高斯滤波结束后，图像的像素有什么规律吗，我怎么判断我的结果是否正确？谢啦！嘿嘿

引用 4 楼 u013931282 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！[/quote] K是RGB三色通道。看你是对彩图还是灰度图操作。对灰度图操作，这个代码要改一下。

引用 1 楼 zhao4zhong1 的回复:搜“VC6 高斯滤波 源代码” int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements}  double conv[3][3];  double hg = 0;       //Convolution kernel for(i=0; i<3;i++) { for(j=0;j<3;j++) { int u=i-1; //subtract from centre element index in 3*3 (1,1) int v=j-1; conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  hg += conv[i][j]; } } for(int i=0; i<3;i++) { for(int j=0;j<3;j++) {                 conv[i][j] = conv[i][j] / hg; } }      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights for(int i =0; i < height ; i++) { for(int j =0; j < width ; j++) { for(int k =0; k < 3 ; k++) { double val = 0; double valw =0; if(j-1 > 0  && i-1 > 0) { val += conv[0][0] * XImage[i-1][j-1][k]; valw += conv[0][0]; } if(i-1 > 0 ) { val += conv[0][1] * XImage[i-1][j][k]; valw += conv[0][1];                                                                  } if(i-1 > 0 && j+1 < width) { val += conv[0][2] * XImage[i-1][j+1][k]; valw += conv[0][2]; }  if(j-1 > 0 ) { val += conv[1][0] * XImage[i][j-1][k]; valw += conv[1][0]; }  val += conv[1][1] * XImage[i][j][k]; valw += conv[1][1];                                                                 if(j+1 < width) { val += conv[1][2] * XImage[i][j+1][k]; valw += conv[1][2]; }  if(j-1 > 0  && i+1 < height) { val += conv[2][0] * XImage[i+1][j-1][k]; valw += conv[2][0]; } if(i+1 < height) { val += conv[2][1] * XImage[i+1][j][k]; valw += conv[2][1]; } if(j+1 < width  && i+1 < height) { val += conv[2][2] * XImage[i+1][j+1][k]; valw += conv[2][2]; }       	sXImage[i][j][k] = val / valw;    } }  }   return( sXImage);   } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！

引用 楼主 u013931282 的回复:如题，初学者，都还不懂，求知道的朋友指导一下！ 用visual c++ 6.0，C语言实现 怎么看高斯滤波产生的结果对不对呢

引用 楼主 u013931282 的回复:如题，初学者，都还不懂，求知道的朋友指导一下！ 用visual c++ 6.0，C语言实现 int*** SmoothImage(int ***XImage ,int width, int height, int channel) {         double sigma =  1.85; //(n/2 -1)*0.3 +0.8  { n = 9 ,no. of elements} 	 double conv[3][3]; 	 double hg = 0;       //Convolution kernel 	for(i=0; i<3;i++) 	{ 		for(j=0;j<3;j++) 		{ 			int u=i-1; //subtract from centre element index in 3*3 (1,1) 			int v=j-1; 			conv[i][j] =exp ( - ((u*u) + (v*v)) / (2*sigma*sigma) );  			hg += conv[i][j]; 		} 	} 	for(int i=0; i<3;i++) 	{ 		for(int j=0;j<3;j++) 		{                 conv[i][j] = conv[i][j] / hg; 		} 	}      int*** sXImage = 0;      sXImage =  CreateImageMatrix( sXImage , width , height , channel );// allocating a 3d array       //Assigning weights 	for(int i =0; i < height ; i++) 		{ 			for(int j =0; j < width ; j++) 			{ 			for(int k =0; k < 3 ; k++) 				{ 					double val = 0; 					double valw =0; 					if(j-1 > 0  && i-1 > 0) 								{ 									val += conv[0][0] * XImage[i-1][j-1][k]; 									valw += conv[0][0]; 								} 								if(i-1 > 0 ) 								{ 									val += conv[0][1] * XImage[i-1][j][k]; 									valw += conv[0][1];                                                                  } 								if(i-1 > 0 && j+1 < width) 								{ 									val += conv[0][2] * XImage[i-1][j+1][k]; 									valw += conv[0][2]; 								}  								if(j-1 > 0 ) 								{ 									val += conv[1][0] * XImage[i][j-1][k]; 									valw += conv[1][0]; 								}  								val += conv[1][1] * XImage[i][j][k]; 								valw += conv[1][1];                                                                 if(j+1 < width) 								{ 									val += conv[1][2] * XImage[i][j+1][k]; 									valw += conv[1][2]; 								}  								if(j-1 > 0  && i+1 < height) 								{ 									val += conv[2][0] * XImage[i+1][j-1][k]; 									valw += conv[2][0]; 								} 								if(i+1 < height) 								{ 									val += conv[2][1] * XImage[i+1][j][k]; 									valw += conv[2][1]; 								} 								if(j+1 < width  && i+1 < height) 								{ 									val += conv[2][2] * XImage[i+1][j+1][k]; 									valw += conv[2][2]; 								} 								 						 							 					   	sXImage[i][j][k] = val / valw;  					 						 				} 			} 	 }   			return( sXImage); 		 		 } 我还想问一下，嘿嘿！这个是我在网上找到的，前半部分差不多懂了，是生成滤波模板，后面红色的部分，k是做什么的呢？拜托了，看不太懂！

搜“VC6 高斯滤波 源代码”