Question: 一个小问题关于自动关机函数

引用 3 楼 zhao4zhong1 的回复:dir /b c:\windows\system32\*.exe C:\>dir /w c:\windows\system32\*.exe  驱动器 C 中的卷是 C_HD5_1  卷的序列号是 1817-D526   c:\windows\system32 的目录  accwiz.exe             AcSignOpt.exe          actmovie.exe           ahui.exe               alg.exe append.exe             arp.exe                asr_fmt.exe            asr_ldm.exe            asr_pfu.exe at.exe                 ati2evxx.exe           Ati2mdxx.exe           atiapfxx.exe           atibtmon.exe ATIODCLI.exe           ATIODE.exe             atmadm.exe             attrib.exe             auditusr.exe AUTMGR32.EXE           autochk.exe            autoconv.exe           autofmt.exe            autolfn.exe azrlreg.exe            BocomSetupCmd.exe      bocomuninst.exe        bootcfg.exe            cacls.exe calc.exe               cd2chain.exe           certreq.exe            certutil.exe           change.exe charmap.exe            chglogon.exe           chgport.exe            chgusr.exe             chkdsk.exe chkntfs.exe            choice.exe             cidaemon.exe           cipher.exe             cisvc.exe ckcnv.exe              cleanmgr.exe           cliconfg.exe           clip.exe               clipbrd.exe clipsrv.exe            clspack.exe            cluster.exe            cmd.exe                cmdkey.exe cmdl32.exe             cmmon32.exe            cmstp.exe              comclust.exe           comp.exe compact.exe            conime.exe             control.exe            convert.exe            cprofile.exe cscript.exe            csrss.exe              csvde.exe              ctfmon.exe             ctfmon_old.exe cys.exe                dcgpofix.exe           dcomcnfg.exe           dcphelp.exe            dcpromo.exe ddeshare.exe           debug.exe              defrag.exe             dfrgfat.exe            dfrgifc.exe dfrgntfs.exe           dfscmd.exe             dfsinit.exe            dfssvc.exe             dhcpwiz.exe diantz.exe             diskpart.exe           diskperf.exe           diskraid.exe           dllhost.exe dllhst3g.exe           dmadmin.exe            dmremote.exe           dnswiz.exe             doskey.exe dosx.exe               dplaysvr.exe           dpnsvr.exe             dpvsetup.exe           driverquery.exe drmupgds.exe           drwatson.exe           drwtsn32.exe           dsadd.exe              dsget.exe dsmod.exe              dsmove.exe             dsquery.exe            dsrm.exe               dumprep.exe dvdplay.exe            dvdupgrd.exe           dwwin.exe              dxdiag.exe             edlin.exe esentutl.exe           eudcedit.exe           eventcreate.exe        eventtriggers.exe      eventvwr.exe exe2bin.exe            expand.exe             extrac32.exe           fastopen.exe           fc.exe femgrate.exe           find.exe               findstr.exe            finger.exe             fixmapi.exe FlashPlayerApp.exe     flattemp.exe           fltmc.exe              fontview.exe           forcedos.exe forfiles.exe           freedisk.exe           fsutil.exe             ftp.exe                gdi.exe getmac.exe             gettype.exe            gpresult.exe           gpupdate.exe           grpconv.exe help.exe               hostname.exe           HP1100SM.EXE           icacls.exe             icardagt.exe ie4uinit.exe           ieudinit.exe           iexpress.exe           imapi.exe              insrepim.exe inuse.exe              ipconfig.exe           ipsec6.exe             ipxroute.exe           ismserv.exe java.exe               javaw.exe              javaws.exe             jdbgmgr.exe            jetconv.exe jview.exe              krnl386.exe            label.exe              lcwiz.exe              ldifde.exe licmgr.exe             llsmgr.exe             llssrv.exe             locator.exe            lodctr.exe logagent.exe           logman.exe             logoff.exe             logonui.exe            lpq.exe lpr.exe                lsass.exe              LVComS.exe             macfile.exe            magnify.exe makecab.exe            MDM.EXE                mem.exe                mmc.exe                mmcperf.exe mnmsrvc.exe            mobsync.exe            mountvol.exe           mplay32.exe            mpnotify.exe mqbkup.exe             mqdssvc.exe            mqmig.exe              mqsvc.exe              mqtgsvc.exe mrinfo.exe             MRT.exe                mscdexnt.exe           msdtc.exe              msfeedssync.exe msg.exe                mshta.exe              msiexec.exe            mspaint.exe            msppcnfg.exe msswchx.exe            mstinit.exe            mstsc.exe              narrator.exe           nbtstat.exe nddeapir.exe           net.exe                net1.exe               netdde.exe             netset03.exe netsh.exe              netstat.exe            nlb.exe                nlbmgr.exe             nlsfunc.exe notepad.exe            nslookup.exe           ntbackup.exe           ntdsutil.exe           ntfrs.exe ntfrsutl.exe           ntkrnlpa.exe           ntoskrnl.exe           ntsd.exe               ntvdm.exe nw16.exe               nwscript.exe           odbcad32.exe           odbcconf.exe           oobechk.exe openfiles.exe          osk.exe                packager.exe           pathping.exe           pentnt.exe perfmon.exe            ping.exe               powercfg.exe           PresentationHost.exe   print.exe progman.exe            proquota.exe           proxycfg.exe           qappsrv.exe            qprocess.exe query.exe              quser.exe              qwinsta.exe            r2repair.exe           RACMGR32.EXE rasautou.exe           rasdial.exe            rasphone.exe           rcimlby.exe            rcp.exe rdpclip.exe            rdsaddin.exe           rdshost.exe            recover.exe            redir.exe redircmp.exe           redirusr.exe           reg.exe                regedt32.exe           regini.exe register.exe           regsvr32.exe           regwiz.exe             relog.exe              remrras.exe replace.exe            reset.exe              rexec.exe              route.exe              routemon.exe rraswiz.exe            rsh.exe                rsm.exe                rsmmllsv.exe           rsmsink.exe rsmui.exe              rsnotify.exe           rsopprov.exe           rtcshare.exe           runas.exe rundll32.exe           runonce.exe            rwinsta.exe            sacsess.exe            savedump.exe sc.exe                 scardsvr.exe           schtasks.exe           schupgr.exe            sdbinst.exe secedit.exe            services.exe           sessmgr.exe            sethc.exe              setup.exe setupn.exe             setver.exe             setx.exe               sfc.exe                sfmprint.exe sfmpsexe.exe           sfmsvc.exe             shadow.exe             share.exe              shmgrate.exe shrpubw.exe            shutdown.exe           sigverif.exe           skeys.exe              smbinst.exe smlogsvc.exe           smss.exe               sndrec32.exe           sndvol32.exe           sort.exe spoolsv.exe            sprestrt.exe           spupdsvc.exe           subst.exe              svchost.exe syncapp.exe            sysedit.exe            syskey.exe             sysocmgr.exe           systeminfo.exe systray.exe            takeown.exe            tapicfg.exe            taskkill.exe           tasklist.exe taskmgr.exe            tcmsetup.exe           tcpsvcs.exe            telnet.exe             timeout.exe tlntadmn.exe           tlntsess.exe           tlntsvr.exe            tlsbln.exe             tracerpt.exe tracert.exe            tsadmin.exe            tscon.exe              tscupgrd.exe           tsdiscon.exe tsecimp.exe            tskill.exe             tsprof.exe             tssdis.exe             tsshutdn.exe TsWpfWrp.exe           typeperf.exe           tzchange.exe           unlodctr.exe           upg351db.exe ups.exe                user.exe               userinit.exe           utilman.exe            uwdf.exe vds.exe                vdsldr.exe             verclsid.exe           verifier.exe           vsjitdebugger.exe vssadmin.exe           vssvc.exe              vwipxspx.exe           w32tm.exe              waitfor.exe wdfmgr.exe             wextract.exe           where.exe              whoami.exe             wiaacmgr.exe winchat.exe            WINDBVER.EXE           WinFXDocObj.exe        winhlp32.exe           winlogon.exe winmsd.exe             winspool.exe           winver.exe             WISPTIS.EXE            wjview.exe wlbs.exe               wowdeb.exe             wowexec.exe            wpabaln.exe            wpnpinst.exe write.exe              wscript.exe            wuauclt.exe            wuauclt1.exe           wupdmgr.exe xcopy.exe              ZSHP1020.EXE              412 个文件    121,608,256 字节                0 个目录  7,938,596,864 可用字节

Windows XP快捷键和命令行大全 http://blog.163.com/tab_98/blog/static/1192409720159892410983

windows下有API函数，使用C或者C++都可以，不过忘了是什么了。你可以百度一下，只记得要引用windows.h头文件。 给你找了一篇blog，参考一下吧。 http://blog.csdn.net/dragon101788/article/details/7312815

引用 1 楼 user-7 的回复:shutdown.exe -a　取消关机 　　shutdown.exe -s 关机 　　shutdown.exe -f　强行关闭应用程序 　　shutdown.exe -m \\计算机名　控制远程计算机 　　shutdown.exe -i　显示“远程关机”图形用户界面，但必须是Shutdown的第一个参数 　 　　shutdown.exe -l　注销当前用户 　　shutdown.exe -r　关机并重启 　　shutdown.exe -s -t 时间　设置关机倒计时 　　shutdown.exe -h 休眠

system 本质上调用命令行来执行，所以你只需要看 cmd 里能执行什么他都能执行。 不过前提是你的程序是命令行程序，否则也没用。

楼主是不是想用自己的双手成就优化使用的梦想？ 看看脚本语言吧，我当时也是自己想做个便捷实用的游戏选择器什么的，结果用脚本只弄成了字符版本，后来还是用高级语言写的图形化版本

dir /b c:\windows\system32\*.exe

shutdown -s -t 1，表示1s后关机 shutdown -s，没有指定时间的话，默认30s后关机


Question: C语言txt文件中内容字符串查找问题求助

//in.txt文件内容如下: //A->B //hello everybody haha hehe //B->A //world is big //A->B //impossible is nothing //B->A //just do it //需求： //首先查找字符串hello，找到后提取其上一行字符串A->B，然后依次查找下一个A->B或者B->A（两个都可以）， //提取出其下一行第一个字符串，也就是world ,impossible ,just 然后把hello,world,impossible,just放到一个数组里。 #include <stdio.h> #include <string.h> #include <stdlib.h> FILE *f; char ln1[80],ln2[80],ln[80]; char A[40],B[40]; char key1[82]; char key2[82]; long offset; char arr[100][80]; char *p; int n,i; int main() {     f=fopen("in.txt","rb");     if (NULL==f) {         printf("Can not open file in.txt!\n");         return 1;     }     ln1[0]=0;     while (1) {         if (NULL==fgets(ln2,80,f)) break;         offset=ftell(f);         if (strstr(ln2,"hello")) {             if (ln1[0]) {                 p=strstr(ln1,"->");                 if (p) {                     n=__min(39,p-ln1);                     strncpy(A,ln1,n);A[n]=0;                     n=__min(39,strlen(p+2));                     strncpy(B,p+2,n);                     n--;                     while (1) {                         if (B[n]==0) break;                         if (B[n]=='\r' || B[n]=='\n') B[n]=0;                         n--;                     }                     sprintf(key1,"%s->%s",A,B);                     sprintf(key2,"%s->%s",B,A);                     i=0;                     while (1) {                         if (i==0) {                             strcpy(ln,ln2);                         } else {                             if (NULL==fgets(ln,80,f)) break;                         }                         if (1==sscanf(ln,"%79s",arr[i])) {                             i++;                             if (i>=100) break;                             if (NULL==fgets(ln,80,f)) break;                             if (!(strstr(ln,key1) || strstr(ln,key2))) break;                         } else break;                     }                     n=i;                     for (i=0;i<n;i++) printf("[%d] \"%s\"\n",i,arr[i]);                 }             }         }         strncpy(ln1,ln2,79);ln1[79]=0;         fseek(f,offset,SEEK_SET);     }     fclose(f);     return 0; } //[0] "hello" //[1] "world" //[2] "impossible" //[3] "just" //

4KB、4KB地把文件读取到缓冲区，然后每次查找一行（直到查到行末尾的换行符，就是到达了末尾了），这样就得到了这一行的字符串内存，然后再逐个字符逐个字符地取，若取到的字符是A，则向后取3位，看看后3位是不是"->B"这样的字符，如果是，就表示你已经取到了。 如此循环往复即可

如果内容不多，就直接全部读到Buff里面。安String来处理。 如果内容比较多，建议是写专门的操作来做，你的需求已经可以分解成对应的Function了。

如果你的格式就是这样,每行判断一下就好了,比如大写字母,不是A就是B,小写字节就只有hwij

求助啊求助啊求助啊求助


Question: C语言编写自动关机程序

因为用time_t这类函数，输出的结果会包含月份、日期、具体时间和年份， 我的思路是利用 strcmp("18-30-00", "23-30-00")这个函数来比较时、分、秒，在用system（“shutdown -s -t 10”）来关机，您看这个可行吗？

仅供参考：#include <stdio.h> #include <string.h> #include <time.h> #include <time.h> #include <sys/timeb.h>  struct tm st; time_t tt; char mon[4]; char mn[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int i; char timstr[27]; char tmpbuf[128]; struct _timeb tb; int tz; char c;  void main() {     strcpy(timstr,"08/Dec/2011:15:25:03 +0800");     sscanf(timstr,"%2d/%3s/%4d:%2d:%2d:%2d",&st.tm_mday,mon,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec);     for (i=0;i<12;i++) if (0==stricmp(mn[i],mon)) {st.tm_mon=i; break;}     st.tm_year-=1900;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S\n",localtime(&tt));         printf(tmpbuf);//2011-12-08 15:25:03     } else {         printf("[%s] is Invalid time string!\n",timstr);     }      _ftime(&tb);     strftime(tmpbuf,128,"%m/%b/%Y:%H:%M:%S",localtime(&tb.time));     tz=-tb.timezone;     c=(tz>0)?'+':'-';     tz=(tz>0)?tz:-tz;     sprintf(tmpbuf,"%s %c%02d%02d\n",tmpbuf,c,tz/60,tz%60);     printf(tmpbuf);//12/Dec/2011:17:36:41 +0800 }   C:\>shutdown /? 用法: shutdown [/i | /l | /s | /r | /a | /p | /h | /e] [/f]     [/m \\computer][/t xxx][/d [p:]xx:yy [/c "comment"]]      没有参数   显示帮助。这与键入 /? 是一样的     /?         显示帮助。这与不键入任何选项是一样的     /i         显示图形用户界面(GUI)。                这必须是第一个选项     /l         注销。这不能与 /m 或 /d 选项一起使用     /s         关闭计算机     /r         关闭并重启动计算机     /a         放弃系统关闭。                这只能在超时过程中使用     /p         关闭本地计算机，没有超时或警告。                这只能与 /d 选项一起使用     /h         休眠本地计算机。                这只能与 /f 选项一起使用     /e         将计算机的意外关闭原因记入文档     /m \\computer 指定目标计算机     /t xxx     设置关闭前的超时为 xxx 秒。                有效范围是 0-600，默认为 30     /c "comment" 重启动或关闭的原因的注释。                最大允许 127 个字符     /f         强制正在运行的应用程序关闭而不事先警告用户     /d [p:]xx:yy  提供重启动或关闭的原因                p 表明重启动或关闭是计划内的                xx 是主要原因号(小于 256 的正整数)                yy 是次要原因号(小于 65536 的正整数)

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……

这个还要编程？直接输入at命令不就行了？ 写个bat  at 23:30:00 shutdown -s   然后吧这个bat放入启动组，ok 编程也简单啊，一句system()就行了，只不过觉得这个纯粹调用系统命令好像没有什么必要编程了。哦，编程可能要方便点，可以自动设置自动启动，或者搞成自动启动服务啥的都可以，也是具有一定逻辑的，也不能说完全没有什么必要，看你了，功能实现就是调用系统命令，你看是否需要编程，从某个角度完全钓鱼系统命令行，已经没什么必要编程了，从某个角度又可以编程，实现自动启动这种特殊的逻辑，或者把他封装成exe，定时启动，这样可能看起来也比bat爽一点，还可以后台运行。

比较和计算时间间隔请用： difftime Finds the difference between two times.  double difftime( time_t timer1, time_t timer0 );  Routine Required Header Compatibility  difftime <time.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  difftime returns the elapsed time in seconds, from timer0 to timer1. The value returned is a double-precision floating-point number.  Parameters  timer1  Ending time  timer0  Beginning time  Remarks  The difftime function computes the difference between the two supplied time values timer0 and timer1.  Example   /* DIFFTIME.C: This program calculates the amount of time  * needed to do a floating-point multiply 10 million times.  */  #include <stdio.h> #include <stdlib.h> #include <time.h>  void main( void ) {    time_t   start, finish;    long loop;    double   result, elapsed_time;     printf( "Multiplying 2 floating point numbers 10 million times...\n" );        time( &start );    for( loop = 0; loop < 10000000; loop++ )       result = 3.63 * 5.27;     time( &finish );     elapsed_time = difftime( finish, start );    printf( "\nProgram takes %6.0f seconds.\n", elapsed_time ); }   Output  Multiplying 2 floats 10 million times...  Program takes      2 seconds.   Floating-Point Support Routines |  Time Management Routines  See Also   time


Question: 多项式相乘

顶起来一下，帮我解答一下呀

我能说我是菜鸟吗，一点都看不懂，头文件里面的定义都没有看懂


Question: matlab转C语言

引用 8 楼 zhao4zhong1 的回复:OpenCV是开源的。 《学习OpenCV（中文版）》 这位老师，opencv的c++图像处理方法编程你懂不懂的，我现在急需一位有这方面经验的人来指导，如果你懂，可不可以给我下联系方式，有偿指导也行

我原来也做过楼主类似的工作，这方面的资料网上比较少，建议楼主看：《matlab与c/c++混合编程》 这本书

OpenCV是开源的。 《学习OpenCV（中文版）》

引用 5 楼 zhao4zhong1 的回复:图像处理的C语言代码虽然比较复杂；但OpenCV自带的C语言图像处理例子代码和例子中调用的函数对应的源代码还是比较简单的。 老师可不可以给我你的联系方式，QQ微信都可以  方便问答

引用 5 楼 zhao4zhong1 的回复:图像处理的C语言代码虽然比较复杂；但OpenCV自带的C语言图像处理例子代码和例子中调用的函数对应的源代码还是比较简单的。 那如果要导入DSP中  还是需要将他的所有函数库一起导入进去吗

引用 3 楼 zhao4zhong1 的回复:所以楼主的想法是行不通的。 只能直接使用C实现图像处理功能。可以参考OpenCV源代码片断。 关键现在还不知道用什么方法处理图像能获得理想效果，而C语言代码又过于复杂，所以我想先用matlab找到对应方法后再用C语言编写，不知道老师这里有没有对应matlab图像处理函数的C代码

引用 1 楼 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不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！可是老师，我这边是要将程序导入DSP，必须是用C语言，而且是要脱离电脑，您的这种方法是不是不太适合我的应用条件呢


Question: eclipse C语言环境问题

指明库路径。

mingw修复bug很慢， 还是用vc++ (windows)或g++(Linux/Unix)吧。


Question: 电影院售票系统 c语言制作 请教 文件读取 写入问题

可以结贴了，给我点分吧

引用 9 楼 赵4老师的回复:不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 Editplus不就可以查看吗？查看16进制

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

...... FILE *in; char ch;  ...... ch=fgetc(in);    //#1 while(!feof(in)) {     // 语句；     ch=fgetc(in); }   //当执行完语句#1后，指针已自动向后移一位，feof()判断的是后一位的情况。 //当吸走最后一个有效字符后，指针移到最后有效字符再往后一位，由前面分析已知，feof()判断结果为0，会再行//循环一次，正好处理完最后一个有效字符后循环结束。 可以先读取一个节点，然后文件指针不就自动后移了一下，然后把判断条件写到while里面。这也不就避免了多都一次的问题。 百度一下解决方法很多的，这只是一种！！！

引用 5 楼 qianghaohao 的回复:没修改之前，查询电影票后再买票直接程序就奔溃了！！！多都一个节点是你那个while条件问题，建议看看fefo函数的详细用法！！！结贴吧，问题基本都说了！！！确实是feof函数不会用，在while（！feof（fp））循环里面放上fread函数以后，就算文件是空的也会循环一次。有没有什么办法能改掉这个结构。

引用 3 楼 cqh963852 的回复:[quote=引用 1 楼 qianghaohao 的回复:] #include<stdio.h> #include<stdlib.h> #include<string.h> #include<windows.h>  void new_mv(); void save_mv(); int judge(); void read_data();// void show();// void menu_print(); void guanli_menu(); void guanli(); void youke_menu(); void youke(); void buy_mv(); void leave_mv(); void add_mv();  typedef struct movie {     char name[20];     int money;     int ticket;     struct movie *next; }mv; mv * head = NULL;  int main() {     int k = 1;     int switch_count=0;     do     {         menu_print();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)//分支里面的函数用处理过后的函数，用 judge与其他函数组合出来的函数。         {         case 0:             k = 0;             break;         case 1:             system("cls");             guanli();             break;         case 2:             if(head == NULL)             {                 read_data();             }             system("cls");             youke();             break;         default:;         }         system("cls");     }while(k != 0);     return 0; }  void new_mv() {     int k = 0;     mv * add, * prev;     prev = head; //*****************修改***************     do     {          add = (mv *)malloc(sizeof(mv));          printf("请输入影片:\n");         scanf("%s",add->name);         printf("价格:\n");         scanf("%d",&add->money);         printf("票数:\n");         scanf("%d",&add->ticket);          if(head == NULL)         {             head = add;         }         else         {             prev->next = add;         }         add->next = NULL;         prev = add;           k = judge();     }while(k == 1); } void save_mv() {     FILE *fp;     mv * temp;     temp = head;       if((fp=fopen("mv.txt","wb"))==NULL)     {         printf("open file error!\n");         getchar();         exit(0);     }      do     {         fwrite(temp,sizeof(mv),1,fp);         printf("%d\n",temp);//测试使用，输出地址         temp = temp->next;     }     while(temp);      head = NULL;//////////////////////     fclose(fp); }  int judge() {     char c;     int a=1;     do     {         getchar();         printf("continue?<y\\n>");         scanf("%c",&c);         if(c=='y')         {             a=1;             break;//跳出判断函数。继续执行外层循环。         }         else         if(c=='n')         {             a=0;             break;//使外层do while 循环终止         }         else         {             a=1;//继续循环判断函数；         }     }while(a==1);     return a; }  void read_data() {     FILE * fp;     mv * temp;     mv * prev;      prev = head; //****************修改******prev要有指向的节点****************      if((fp=fopen("mv.txt","r"))==NULL)     {         printf("open file error!\n");         getchar();         exit(0);     }     while(!feof(fp))     {         temp = (mv *)malloc(sizeof(mv));         if(head == NULL)         {             head = temp;         }         else         {             prev->next = temp;         }         fread(temp,sizeof(mv),1,fp);         temp->next = NULL;         prev = temp;     }  }  void show()//展示 {     mv *temp;     temp = head;     while(temp->next)     {         printf("name:%s,noney:%d\n",temp->name,temp->money);         temp=temp->next;     } }  void menu_print() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.管理员登录\t\t\t\t|\n");     printf("|\t\t\t\t2.用户登录\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void guanli_menu() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.新建电影信息\t\t\t\t|\n");     printf("|\t\t\t\t2.增加电影信息\t\t\t\t|\n");     printf("|\t\t\t\t3.删除电影信息\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void guanli() {     int k = 1;     int switch_count=0;     do     {         guanli_menu();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)         {             {             case 0:                 k = 0;                 break;             case 1:                 new_mv();                 save_mv();                 break;             case 2:                 add_mv();                 break;             default:;             }         }     }while(k != 0); }  void youke_menu() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.查询当前电影\t\t\t\t|\n");     printf("|\t\t\t\t2.购票\t\t\t\t\t|\n");     printf("|\t\t\t\t3.退票\t\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void youke() {     int k = 1;     int switch_count = 0;     do     {         youke_menu();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)         {             {             case 0:                 k = 0;                 break;             case 1:                 show();                 //head = NULL; //****************查询完不该把头指针丢掉啊，                                 //否则接下来买票就找不到头指针从而导致错误                 break;             case 2:buy_mv();                 break;             default:leave_mv();             }         }     }while(k != 0); }  void buy_mv() {     int flag = 0;     char a[20] = {0};     mv *temp;     show();     temp = head;     printf("请输入你想买的电影的名字:");     scanf("%s",a);     while(temp)     {         if(strcmp(temp->name,a) == 0)         {             flag = 1;             printf("已经找到\n");             if(judge() == 0)             {                 break;             }             temp->ticket--;             printf("余票：%d",temp->ticket);             break;         }         else         {             temp = temp -> next;         }     }     if(flag == 0)     {         printf("没有找到你所找的电影：\n");     }      Sleep(1000);     system("cls"); }   void leave_mv() {     int flag=0;     char a[20];     mv *temp;     show();     temp=head;     printf("请输入你想退的票：");     scanf("%s",a);     while(temp)     {         if(strcmp(temp->name,a) == 0)         {             flag = 1;             printf("已经找到\n");             judge();             temp->ticket++;             printf("余票：%d",temp->ticket);             break;         }         else         {             temp = temp -> next;         }     }     if(flag == 0)     {         printf("没有找到你所找的电影：\n");     }      Sleep(2000);     system("cls"); }  void add_mv() {      int k = 0;     mv * add, * prev;      read_data();      prev = head;     do     {          add = (mv *)malloc(sizeof(mv));          printf("请输入影片:\n");         scanf("%s",add->name);         printf("价格:\n");         scanf("%d",&add->money);         printf("票数:\n");         scanf("%d",&add->ticket);           while(prev->next)         {             printf("name:%s,noney:%d\n",prev->name,prev->money);             prev = prev->next;         }         prev = add;         prev->next = NULL;          k = judge();     }while(k == 1);     save_mv();      //head = NULL; //************修改****给链表增加了一个节点不该把头节点    //                               空置啊******************** }                    修改的地方都在注释中，注意头节点呀，还有prev指针的指向，总感觉LZ指针乱指，以后多多注意一下！！！这种问题调试一下便出来了，还有让别人看代码，把注释写上呀，啥注释都没有。。。真心不是这个意思。问题出在read_data();函数上面，总是会多读一个节点。头结点是故意滞空的。应该是之前程序思路问题，以前没有做比较长的代码。链表也是第一次用，还麻烦再帮解决下。[/quote]头节点指向确实需要修改。。。但是现在函数都有问题。所以想先修改read_data();函数，至少能让函数正常了。。。

引用 1 楼 qianghaohao 的回复:#include<stdio.h> #include<stdlib.h> #include<string.h> #include<windows.h>  void new_mv(); void save_mv(); int judge(); void read_data();// void show();// void menu_print(); void guanli_menu(); void guanli(); void youke_menu(); void youke(); void buy_mv(); void leave_mv(); void add_mv();  typedef struct movie {     char name[20];     int money;     int ticket;     struct movie *next; }mv; mv * head = NULL;  int main() {     int k = 1;     int switch_count=0;     do     {         menu_print();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)//分支里面的函数用处理过后的函数，用 judge与其他函数组合出来的函数。         {         case 0:             k = 0;             break;         case 1:             system("cls");             guanli();             break;         case 2:             if(head == NULL)             {                 read_data();             }             system("cls");             youke();             break;         default:;         }         system("cls");     }while(k != 0);     return 0; }  void new_mv() {     int k = 0;     mv * add, * prev;     prev = head; //*****************修改***************     do     {          add = (mv *)malloc(sizeof(mv));          printf("请输入影片:\n");         scanf("%s",add->name);         printf("价格:\n");         scanf("%d",&add->money);         printf("票数:\n");         scanf("%d",&add->ticket);          if(head == NULL)         {             head = add;         }         else         {             prev->next = add;         }         add->next = NULL;         prev = add;           k = judge();     }while(k == 1); } void save_mv() {     FILE *fp;     mv * temp;     temp = head;       if((fp=fopen("mv.txt","wb"))==NULL)     {         printf("open file error!\n");         getchar();         exit(0);     }      do     {         fwrite(temp,sizeof(mv),1,fp);         printf("%d\n",temp);//测试使用，输出地址         temp = temp->next;     }     while(temp);      head = NULL;//////////////////////     fclose(fp); }  int judge() {     char c;     int a=1;     do     {         getchar();         printf("continue?<y\\n>");         scanf("%c",&c);         if(c=='y')         {             a=1;             break;//跳出判断函数。继续执行外层循环。         }         else         if(c=='n')         {             a=0;             break;//使外层do while 循环终止         }         else         {             a=1;//继续循环判断函数；         }     }while(a==1);     return a; }  void read_data() {     FILE * fp;     mv * temp;     mv * prev;      prev = head; //****************修改******prev要有指向的节点****************      if((fp=fopen("mv.txt","r"))==NULL)     {         printf("open file error!\n");         getchar();         exit(0);     }     while(!feof(fp))     {         temp = (mv *)malloc(sizeof(mv));         if(head == NULL)         {             head = temp;         }         else         {             prev->next = temp;         }         fread(temp,sizeof(mv),1,fp);         temp->next = NULL;         prev = temp;     }  }  void show()//展示 {     mv *temp;     temp = head;     while(temp->next)     {         printf("name:%s,noney:%d\n",temp->name,temp->money);         temp=temp->next;     } }  void menu_print() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.管理员登录\t\t\t\t|\n");     printf("|\t\t\t\t2.用户登录\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void guanli_menu() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.新建电影信息\t\t\t\t|\n");     printf("|\t\t\t\t2.增加电影信息\t\t\t\t|\n");     printf("|\t\t\t\t3.删除电影信息\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void guanli() {     int k = 1;     int switch_count=0;     do     {         guanli_menu();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)         {             {             case 0:                 k = 0;                 break;             case 1:                 new_mv();                 save_mv();                 break;             case 2:                 add_mv();                 break;             default:;             }         }     }while(k != 0); }  void youke_menu() {     printf("*************************欢迎来到逗逼电影俱乐部**************************\n");     printf("|\t\t\t\t请输入选项\t\t\t\t|\n");     printf("|\t\t\t\t0.退出\t\t\t\t\t|\n");     printf("|\t\t\t\t1.查询当前电影\t\t\t\t|\n");     printf("|\t\t\t\t2.购票\t\t\t\t\t|\n");     printf("|\t\t\t\t3.退票\t\t\t\t\t|\n");     printf("*************************************************************************\n"); }  void youke() {     int k = 1;     int switch_count = 0;     do     {         youke_menu();         printf("\t\t\t请选择<0-3>:");         scanf("%d",&switch_count);         switch(switch_count)         {             {             case 0:                 k = 0;                 break;             case 1:                 show();                 //head = NULL; //****************查询完不该把头指针丢掉啊，                                 //否则接下来买票就找不到头指针从而导致错误                 break;             case 2:buy_mv();                 break;             default:leave_mv();             }         }     }while(k != 0); }  void buy_mv() {     int flag = 0;     char a[20] = {0};     mv *temp;     show();     temp = head;     printf("请输入你想买的电影的名字:");     scanf("%s",a);     while(temp)     {         if(strcmp(temp->name,a) == 0)         {             flag = 1;             printf("已经找到\n");             if(judge() == 0)             {                 break;             }             temp->ticket--;             printf("余票：%d",temp->ticket);             break;         }         else         {             temp = temp -> next;         }     }     if(flag == 0)     {         printf("没有找到你所找的电影：\n");     }      Sleep(1000);     system("cls"); }   void leave_mv() {     int flag=0;     char a[20];     mv *temp;     show();     temp=head;     printf("请输入你想退的票：");     scanf("%s",a);     while(temp)     {         if(strcmp(temp->name,a) == 0)         {             flag = 1;             printf("已经找到\n");             judge();             temp->ticket++;             printf("余票：%d",temp->ticket);             break;         }         else         {             temp = temp -> next;         }     }     if(flag == 0)     {         printf("没有找到你所找的电影：\n");     }      Sleep(2000);     system("cls"); }  void add_mv() {      int k = 0;     mv * add, * prev;      read_data();      prev = head;     do     {          add = (mv *)malloc(sizeof(mv));          printf("请输入影片:\n");         scanf("%s",add->name);         printf("价格:\n");         scanf("%d",&add->money);         printf("票数:\n");         scanf("%d",&add->ticket);           while(prev->next)         {             printf("name:%s,noney:%d\n",prev->name,prev->money);             prev = prev->next;         }         prev = add;         prev->next = NULL;          k = judge();     }while(k == 1);     save_mv();      //head = NULL; //************修改****给链表增加了一个节点不该把头节点    //                               空置啊******************** }                    修改的地方都在注释中，注意头节点呀，还有prev指针的指向，总感觉LZ指针乱指，以后多多注意一下！！！这种问题调试一下便出来了，还有让别人看代码，把注释写上呀，啥注释都没有。。。真心不是这个意思。问题出在read_data();函数上面，总是会多读一个节点。头结点是故意滞空的。应该是之前程序思路问题，以前没有做比较长的代码。链表也是第一次用，还麻烦再帮解决下。


Question: linux 多大程度 保证收发数据的实时性

引用 5 楼 ForestDB 的回复:我所谓的业务，就是这个3ms从何而来？   是因为有一个协议要求 3ms 内完成响应。当然这个协议是暂定的。如果不能实现，就使用这个协议了。

啥叫实时性？

我所谓的业务，就是这个3ms从何而来？

引用 2 楼 ForestDB 的回复:对响应时间有要求的，请考虑实时操作系统。  当然LZ可以说说具体的业务，看看业务是否对响应时间有要求。  另： 所谓“实时”，并不是指它有多快，而是指它一定会在指定的时间内完成动作。    具体的业务就是 接收到请求，然后组包， 然后发送数据。过程比较简单。只是这个过程能否保证 在 3ms 内完成 ？

不管多 "硬" 的操作系统都无法保证。  业务是确定的(请求),做个压测测出服务器(组)可以负载多少并发。 再做平衡负载，旁路什么的，这样就算不能100%,起码也有99.999%


Question: popen获取nginx版本失败

问题解决了，nginx在执行-v 命令时会把结果输出到stderr而不是stdout 只需要把stderr重定向到stdout就可以了

哪位大神帮忙看下啊

使用这个函数执行诸如 ps/ls之类的命令可以正确获得输出，只有nginx -v没有办法


Question: 子线程执行（汇编调c函数）程序，join之后被挂起，子线程未退出

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


Question: 关于获取数组首地址的一个问题

请参考K&R第二版附录A7.1 指针转换  对于某类型T，如果某表达式或子表达式的类型为“T类型的数组”，则此表达式的值是指向数组中第一个对象的指针，并且此表达式的类型将被转换为“指向T类型的指针“。如果此表达式是一元运算符&或sizeof，则不会进行转换。

参看：  对数组名取地址在 C 标准里面是未定义的。这个表达式曾经引起过争论，焦点在于对一个 右值取地址的合法性。 C89 规定&运算符的操作数必须具有具体的内存空间，换言之就是一 个左值，但数组名却是一个右值，按照&运算符的要求，这是非法行为。因此，早期的编译 器通常规定&a 是非法的。但不知道什么原因，现在的编译器都把&a 人为地定义成一个比 a 高一级而地址值跟 a 一样的地址，但作为比 a 高一级的地址，有一个行为却非常怪诞， sizeof(&a)的结果跟 sizeof(a)相同，这也是人为的痕迹。笔者倾向于把&a 定义为非法，应该 维护&运算符的权威性，而不是在规定对某个右值取地址为非法的同时，又允许对另一个右 值取地址，这是互相矛盾的。

你这个问题恐怕要参考C标准了。    int testfun(unsigned char* buf, int len) {   unsigned char arry[10] = {0};     if( buf == NULL ) return -1;   if( len <= 0 )return -1;    if (len>10) len=10;//小心驶得万年船   memcpy(arry, buf, len);//方式1   memcpy(&arry, buf, len);//方式2   return 0; }

printf("%p" 就可以看到了,同一地址,只是类型不同


Question: 大家帮忙看下这个程序哪里出错了，新手求教！！！

for (i = 0; i < lim - 1 && (c = getchar()) != EOF) && c != '\n' ; ++i) 这里你仔细看一下，真的是正确的吗。 几个括号的匹配。

#include <stdio.h> #define MAXLINE 1000 int mygetline (char line[], int maxline); void mycopy (char to[], char from[]);  int main() { 	int len; 	int max; 	char line [MAXLINE]; 	char longest [MAXLINE]; 	max = 0; 	while ((len = mygetline(line, MAXLINE)) > 0) 	{ 		if (len > max) 		{ 			max = len; 			mycopy(longest, line); 		} 		if (max > 0) 			printf("%s\n", longest); 	} 	return 0;  }  int mygetline (char s[], int lim) { 	int c; 	int i; 	for (i = 0; i < lim - 1 && ((c = getchar()) != EOF) && c != '\n' ; ++i) 	{ 	//	printf("c = %d %c\n", c, c); 		s[i] = c; 	} 	s[i] = '\0'; 	return i; }  void mycopy (char to[], char from[]) { 	int i= 0;  	while ( from[i] != '\0') 	{ 		to[i] = from[i]; 		++i; 	} 	to[i]='\0'; }

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


Question: C语言,使用共用体和结构体 查看int型的bit分布

有符号数，是所谓的补码数 最高位表示符号， 若最高位为0，表示正数，其绝对值为所有位包括符号位的原码对应二进制数 若最高位为1，表示负数，其绝对值为所有位包括符号位全部按位取反，再末尾加一后对应的二进制数

位段的数据类型，只是表示该位段参与+-*/等算术运算时， 当作什么类型的整数使用， 以及最多占有多少 Bits，有无符号等等。 最终还是要按照实际占有 Bits多少，来表示和解释的。

位段，按照所有位数计算，最高位是其所有位数中的最高位，而不是类型的最高位。 short  本身是 16Bits，但是你这里 因为是位段，只占1 bit .这个1bit 就是最高位了 由于 没有数据位，只有符号位，所以只能表示 0，-1 两个数   有符号数，是所谓的补码数，最高位 表示符号， 其它位： 正数 用原码， 负数用补码（反码加一）表示。  位段的位数，只要不等于， 类型位数本身， 那么 最高位就只是位段，所有位中的最高位，而不是类型的最高位。  位段的表示方法，和有符号数表示方法，在这点上略有不同，因为位段 和有符号数的位数往往不同。 往往要比有符号数本身的位数少。

如果依然按照 16Bits short 来表示的话，那就永远没有符号位了 所以 ，有符号位段，实际上是按照位段的位数表示的有符号数， 不是C语言的内部数据类型的有符号数

引用 12 楼 yikoumeishuidekujing 的回复:[quote=引用 11 楼 SXJIAKE 的回复:] [quote=引用 10 楼 yikoumeishuidekujing 的回复:] [quote=引用 8 楼 yikoumeishuidekujing 的回复:] [quote=引用 7 楼 SXJIAKE 的回复:] short 拿到的结果应该是 0xFFFF 所以实际上显示为 -1…… 像这种结构体位域最好用无符号的 你的回答是错误的,按你的说法,则 b0到b1都应该是-1,而不是只有b0到b7是1了[/quote]  写错了,应该是"则 b0到b31都应该是-1,而不是只有b0到b7是1了"[/quote]你赋值只给了个 255 ，才 1 个字节，8 位，怎么可能全都是 -1？[/quote]  所以说 一个short 只拿到一个 1,而不是 0xFFFF [/quote]算了，我说的你没看懂，不想解释了。

引用 11 楼 SXJIAKE 的回复:[quote=引用 10 楼 yikoumeishuidekujing 的回复:] [quote=引用 8 楼 yikoumeishuidekujing 的回复:] [quote=引用 7 楼 SXJIAKE 的回复:] short 拿到的结果应该是 0xFFFF 所以实际上显示为 -1…… 像这种结构体位域最好用无符号的 你的回答是错误的,按你的说法,则 b0到b1都应该是-1,而不是只有b0到b7是1了[/quote]  写错了,应该是"则 b0到b31都应该是-1,而不是只有b0到b7是1了"[/quote]你赋值只给了个 255 ，才 1 个字节，8 位，怎么可能全都是 -1？[/quote]  所以说 一个short 只拿到一个 1,而不是 0xFFFF

引用 10 楼 yikoumeishuidekujing 的回复:[quote=引用 8 楼 yikoumeishuidekujing 的回复:] [quote=引用 7 楼 SXJIAKE 的回复:] short 拿到的结果应该是 0xFFFF 所以实际上显示为 -1…… 像这种结构体位域最好用无符号的 你的回答是错误的,按你的说法,则 b0到b1都应该是-1,而不是只有b0到b7是1了[/quote]  写错了,应该是"则 b0到b31都应该是-1,而不是只有b0到b7是1了"[/quote]你赋值只给了个 255 ，才 1 个字节，8 位，怎么可能全都是 -1？

引用 8 楼 yikoumeishuidekujing 的回复:[quote=引用 7 楼 SXJIAKE 的回复:] short 拿到的结果应该是 0xFFFF 所以实际上显示为 -1…… 像这种结构体位域最好用无符号的 你的回答是错误的,按你的说法,则 b0到b1都应该是-1,而不是只有b0到b7是1了[/quote]  写错了,应该是"则 b0到b31都应该是-1,而不是只有b0到b7是1了"

引用 6 楼 zhao4zhong1 的回复:不是“除了符号位什么都没有了,勉为其难 解释为-1”； 而是“其符号位为1，表示负数。其绝对值为按各位（即所有位包括符号位）取反后再末位＋1，即1取反后为0，0＋1=1。”  懂了,十分感谢!!!

引用 7 楼 SXJIAKE 的回复:short 拿到的结果应该是 0xFFFF 所以实际上显示为 -1…… 像这种结构体位域最好用无符号的 你的回答是错误的,按你的说法,则 b0到b1都应该是-1,而不是只有b0到b7是1了

引用 3 楼 zhao4zhong1 的回复:1 （补码）用来表示1位有符号数，其符号位为1，表示负数。其绝对值为按各位取反后再末位＋1，即1取反后为0，0＋1=1。 综上所述，1 （补码）用来表示1位有符号数，对应-1  按你的解释是合理的,  不过一个bit位也能表示负数,我需要再消化消化 当一个bit位是 无符号数时,能填入1或0,分别表示1和0 当一个bit位是 有符号数时,能填入1或0,接着系统根据第一个bit判断正负 遇到0时,判断其是正数,由于除了符号位什么都没有了,勉为其难 解释为0 遇到1时,判断其是负数,由于除了符号位什么都没有了,勉为其难 解释为-1  n个比特位可以表示有符号整数的范围是 -2^(n-1) ~ 2^(n-1)-1 这样就统一了 1个比特能表示的范围是 -1 ~ 0,即-1和0  OK! Thank you~~

内存里都是一个 bit 的 1 只是这个 1 按有符号数来解释的话最高位是符号位，这里的最高位就是这个唯一的位了，它是 1 就表示是负数，至于负的多少就是按楼上的补码算法来确定的

引用 1 楼 adlay 的回复:定义成 unsigned short 就是 1 了  的确是的,不过我想知道为什么 short情况下是-1呢 当定义成unsigned short时, 以bit0为例,其获得的值为1,所以是1 其补码形式是 0000000000000001  按理说 赋值给 short 也应该是1啊,为什么会是-1呢

定义成 unsigned short 就是 1 了


Question: 求助！帮忙看看，字符串数组指针作为函数的参数，哪里出错了？

printf("%s",*(pS+i)); 	}  	char*pstr=NULL; 	pstr=(char*)malloc(200*sizeof(char)); 	shuchu_zifuchuan(pS); 	return 0; 	 } void shuchu_zifuchuan(char**pS) { 	for(int i=0;i<3;++i) 	{ 		printf("\n%s",*(pS+i)); 	} }   我把定义的函数改变了，改成输出字符串数组。但是还是出错，怎么办？

不是这个问题。该了之后还是不行。

printf("%d %s",*(pS+i));//改为if(NULL != *(pS+i))  printf("%d %s\n",i,*(pS+i));

//定义一个函数，他的参数是字符串数组指针，返回一个将所有字符串合并起来的字符串指针，每个字符串都用换行符来终止。 //如果输入数组中的原字符串将换行符作为最后一个字符,函数就不能给字符串添加另一个换行符。 //编写一个程序，从键盘读入几个字符串，用这个函数输出合并后的字符串。 #include<stdio.h> #include<string.h> #include<stdlib.h> #define GESHU 5 #define BUF_len 200 size_t str_count=GESHU; char* hb_zifuchuan(char**); int main(void){     char buf[BUF_len];     char **pS=NULL;     pS=(char **)malloc(str_count*sizeof(char *));     int i=0;     while (true) {         if (!(gets(buf))) {     //读入字符串，并检验字符串是否输入正常             printf("\n shuru cuo wu.");             free(pS);             pS=NULL;             break;         }         if (strlen(buf)==0) break; //循环中断条件，是字符串长度为空         if ((i+1)==str_count) {       //如果读入字符串个数达到上限，增加上限             str_count+=GESHU;             pS=(char **)realloc(pS,str_count*sizeof(char *)); //重新扩展内存分配         }         int str_len=strlen(buf)+1;         *(pS+i)=(char *)malloc(str_len*sizeof(char)); //给字符串指针分配内存空间         strcpy(*(pS+i),buf);                         //将字符串读入指针空间中         ++i;     }     printf("\n");     for(int i=0;i<str_count;++i) {           //+++在这里我验证了，pS的内容。证明它确实是字符串数组的指针。         printf("%d %s\n",i,*(pS+i));     }     char *pstr=hb_zifuchuan(pS);     printf("\n shuchu zuihou de zifuchuan:%s",pstr);     return 0; } char *hb_zifuchuan(char **pS) {     char *p=(char *)malloc(BUF_len*str_count*sizeof(char));     printf("\n");     for(int i=0;i<str_count;++i) {                    //+++为什么在这函数就不能读出字符串数组呢？？         printf("%d %s",*(pS+i));     }     size_t char_cnt=0;     size_t zong=0;     for(int i=0;i>0;++i) {         size_t str_len=strlen(*(pS+i));   //定义字符串数组中每个字符串的长度，及其长度是多少？         if (*(pS+i)=NULL) break; //如果字符串长度为0，那么终止循环，         ++char_cnt; //每循环一次char_cnt的数目加1 ，即用来计算有几个字符串         *(*(pS+i)+str_len)='\n'; //给字符串最后换成\n         *(*(pS+i)+str_len+1)='\0'; //给字符串添加\0         char *pT=NULL;         zong+=str_len+2*char_cnt;         pT=(char *)realloc(p,zong*sizeof(char));         if(!pT) {             printf("\n kuozhan chu cuo le.");             free(p);             p=NULL;             break;         }         p=pT;         strcat(p,*(pS+i));     }     return p; }

你能不能打空格，我看的很累

说错了，换行


Question: 请问这个声明的具体含义

//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

引用 5 楼 jiqiang01234 的回复:typedef void (*P)(); typedef void (*F)(P); F[10]; 应该是这样吧：typedef void (*P)(); typedef void (*F)(P); F b[10];声明一个函数指针数组，该数组的元素类型为指向如下函数原型的函数地址： void func1(void (*)(void)); 该函数的参数是一个指向如下函数类型的函数指针： void func2(void); 所以，调用 func1 这样的函数时，应该是这样的语法： func1(func2); 对于如上声明，给数组赋值如下： F b[10]; b[0] = func1; 通过指针调用函数： b[0](func2);

声明的这个函数指针还是个数组，有10个如上所述的元素

声明一个的是一个函数指针，指向返回值为void类型、参数为又一个函数指针的函数  其中参数的那个函数指针是返回void类型的无参函数

引用 1 楼 cjqpker 的回复:void (*b[10]) (void (*)());  声明了一个函数指针数组吧 指针指向这样的函数 ： 无返回值，有一个函数指针类型的参数，这个类型描述为void (*)()  是“定义”，不是声明。


Question: C怎么处理matlab的mat数据

参看：  http://blog.csdn.net/left_la/article/details/8206645 http://wenku.baidu.com/link?url=xSIdthvnyJjzR45PhzLf0sxtoVGKLGvOtuI41wonZfc-pfFEtTOGbgr1X3nygZFPnOav8oeUoqC91TSlpRyrcfQVbKRwItrBbfg8_Q3Bsoi

我觉得你在MATLAB里读入mat，然后把数据输出到c可以读的纯文本文件中更简单省事。 就是不知道MATLAB能不能生成和读写文本文件，我猜应该可以吧。

不要做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不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！


Question: 关于zhang细化算法的问题，为什么要进行两步？

好吧 自问自答。。。应该是防止只有两个点的时候都删除造成断点吧


Question: 求此crc8校验计算法源码的详细注释

楼主，你好，我想知道这个算法正确吗，我算出来的跟CRC calculator计算的结果不一样啊。

引用 1 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。 引用 1 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。    多谢赵4老师的教诲，但是现在问题不是需要我断点、调试的问题，发帖前我已经实验了不知多少次了，学习的道理我知道，但至少对于解决这个问题没有帮助，对于crc校验我搜集了网上的很多资料，但是仍然有不懂的地方，因此想通过这个源代码的注释来点破我理解上的困难，您如果知道如何理解，请您写出注释为我指点迷津，谢谢。


Question: socket 断开自动重连

引用 11 楼 hnwyllmm 的回复:我是分两种情况的：（前提是我已经有心跳包 正常运行）  1： 服务器 掉电重启， 过一会儿 客户端检测到 失联， 于是 尝试重新连接 （先 shutdown  然后  close（socket）， 然后 重新创建 socket  然后  connect）  ，  因为 服务器 重启，所以服务器 也会进入  accept 状态 （我试过 accept 之前 服务器 也需要 shutdown   和  close  与 客户端 连接的 socket ，  否则重连不上 ）   2： 如果 客户端掉电 重启，  应该 怎么处理 比较方便 ？     1. 调用close就不用调用shutdown了，这些知识楼主回头找找资料看下，不过楼主的做法还是可行的 2. 既然客户端可以使用心跳，服务端也一样也有心跳机制检测了吗？   服务器也可以检测心跳，如果失联，也可以检测到。

当然是“accept 后 与 客户端 连接的 socket”了。 参考MSDN98中的例子代码。MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

引用 3 楼 hnwyllmm 的回复:[quote=引用 2 楼 teachin88 的回复:] [quote=引用 1 楼 hnwyllmm 的回复:] 第一个 只是连接上，但是服务器端并没有接受这个连接，收发数据肯定有问题吧 第二个，先shutdown关闭连接再调用connect试试 第三个，如果上面那个不行，就close再重连，应该可以的   也就是说 客户端 connect 重连的时候，  服务器 必须到  accept 状态 ，否则就算连上 也不能正常 通信 是吧？[/quote]  也许对于操作系统来说没有accept也可以正常建立TCP的连接，但是没有accept，这个连接对程序来说是不可用的 [/quote]    这么说，对于 一对一 的 客户端 --服务器 ，    服务器也必须  通过 心跳 超时 检测 是否 断开， 如果断开， 服务器必须 跳转到 accept 去 等待连接 ？   ps：  服务器 有两个 socket，  一个是 创建 的服务端 socket ，  另一个是  accept 后 与 客户端 连接的 socket ，  你说 的 shutdown 和 close  是针对哪个socket 的 ？

引用 9 楼 hnwyllmm 的回复:[quote=引用 7 楼 teachin88 的回复:] [quote=引用 3 楼 hnwyllmm 的回复:] [quote=引用 2 楼 teachin88 的回复:] [quote=引用 1 楼 hnwyllmm 的回复:] 第一个 只是连接上，但是服务器端并没有接受这个连接，收发数据肯定有问题吧 第二个，先shutdown关闭连接再调用connect试试 第三个，如果上面那个不行，就close再重连，应该可以的   也就是说 客户端 connect 重连的时候，  服务器 必须到  accept 状态 ，否则就算连上 也不能正常 通信 是吧？[/quote]  也许对于操作系统来说没有accept也可以正常建立TCP的连接，但是没有accept，这个连接对程序来说是不可用的 [/quote]    这么说，对于 一对一 的 客户端 --服务器 ，    服务器也必须  通过 心跳 超时 检测 是否 断开， 如果断开， 服务器必须 跳转到 accept 去 等待连接 ？   ps：  服务器 有两个 socket，  一个是 创建 的服务端 socket ，  另一个是  accept 后 与 客户端 连接的 socket ，  你说 的 shutdown 和 close  是针对哪个socket 的 ？[/quote] 最好是有心跳机制检测是否客户端已经断开连接，否则如果客户端down机，可能要很久才能知道客户端不在了。 我说的shutdown是客户端的socket，这个动作可以关闭连接，但是close是关闭套接字，虽然它也可能直接调用shutdown[/quote]    我是分两种情况的：（前提是我已经有心跳包 正常运行）  1： 服务器 掉电重启， 过一会儿 客户端检测到 失联， 于是 尝试重新连接 （先 shutdown  然后  close（socket）， 然后 重新创建 socket  然后  connect）  ，  因为 服务器 重启，所以服务器 也会进入  accept 状态 （我试过 accept 之前 服务器 也需要 shutdown   和  close  与 客户端 连接的 socket ，  否则重连不上 ）   2： 如果 客户端掉电 重启，  应该 怎么处理 比较方便 ？

每次重连请至少间隔10秒。

当连接池由于来自某个IP的频繁多次重连被一堆无效连接占满时，需要断开来自该IP的所有连接并清空其相关连接池。

判断连接可用的唯一标准是双方各收发一次心跳包。

引用 2 楼 teachin88 的回复:[quote=引用 1 楼 hnwyllmm 的回复:] 第一个 只是连接上，但是服务器端并没有接受这个连接，收发数据肯定有问题吧 第二个，先shutdown关闭连接再调用connect试试 第三个，如果上面那个不行，就close再重连，应该可以的   也就是说 客户端 connect 重连的时候，  服务器 必须到  accept 状态 ，否则就算连上 也不能正常 通信 是吧？[/quote]  也许对于操作系统来说没有accept也可以正常建立TCP的连接，但是没有accept，这个连接对程序来说是不可用的

引用 1 楼 hnwyllmm 的回复:第一个 只是连接上，但是服务器端并没有接受这个连接，收发数据肯定有问题吧 第二个，先shutdown关闭连接再调用connect试试 第三个，如果上面那个不行，就close再重连，应该可以的   也就是说 客户端 connect 重连的时候，  服务器 必须到  accept 状态 ，否则就算连上 也不能正常 通信 是吧？

引用 7 楼 teachin88 的回复:[quote=引用 3 楼 hnwyllmm 的回复:] [quote=引用 2 楼 teachin88 的回复:] [quote=引用 1 楼 hnwyllmm 的回复:] 第一个 只是连接上，但是服务器端并没有接受这个连接，收发数据肯定有问题吧 第二个，先shutdown关闭连接再调用connect试试 第三个，如果上面那个不行，就close再重连，应该可以的   也就是说 客户端 connect 重连的时候，  服务器 必须到  accept 状态 ，否则就算连上 也不能正常 通信 是吧？[/quote]  也许对于操作系统来说没有accept也可以正常建立TCP的连接，但是没有accept，这个连接对程序来说是不可用的 [/quote]    这么说，对于 一对一 的 客户端 --服务器 ，    服务器也必须  通过 心跳 超时 检测 是否 断开， 如果断开， 服务器必须 跳转到 accept 去 等待连接 ？   ps：  服务器 有两个 socket，  一个是 创建 的服务端 socket ，  另一个是  accept 后 与 客户端 连接的 socket ，  你说 的 shutdown 和 close  是针对哪个socket 的 ？[/quote] 最好是有心跳机制检测是否客户端已经断开连接，否则如果客户端down机，可能要很久才能知道客户端不在了。 我说的shutdown是客户端的socket，这个动作可以关闭连接，但是close是关闭套接字，虽然它也可能直接调用shutdown


Question: 【求助】大神求帮忙 java转换为C语言

希望楼上在此生弥留之际后悔没照我这段话做，浪费了很多大好青春。

引用 3 楼 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不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！ 哈哈哈，我一看到标题就知道我又能看到这一段话了。。

引用 8 楼 u013550545 的回复:引用 6 楼 SXJIAKE 的回复:引用 5 楼 u013550545 的回复:C语言吧贴吧的那个贾可?头像都一样，肯定是我了。晕，忘了我早换了头像，以前是 VIM 这个头像……不过在这里讨论这个没意义吧

引用 4 楼 SXJIAKE 的回复:#include <stdio.h> #include <stdlib.h>  static int exchange(char chs[], int n, char ch);  int main(int argc, char *argv[]) {     int n = 0;     while (scanf("%d\n", &n) != EOF) {         int count[26] = { 0 };         char ch = '0';         int oddchar = 0;          char chs[256] = { 0 };         scanf("%s\n", chs);          int len = strlen(chs);          for (int j = 0; j < len; j++) {             int index = chs[j] - 'a';             count[index]++;         }          for (int i = 0; i < 26; i++) {             if (count[i] % 2 != 0) {                 oddchar++;                 ch = (char)(i + 'a');             }         }          if (oddchar > 1) {             printf("Impossible\n");         } else {             int result = exchange(chs, n, ch);             printf("%d\n", result);         }     }     return 0; }  static int exchange(char chs[], int n, char ch) {     int i;     int j;     int k;     int count = 0;     for (i = 0; i < n / 2; i++) {         if (chs[i] == ch) {             for (j = i; j < n - i - 1; j++) {                 if (chs[j] == chs[n - i - 1]) {                     break;                 }             }             count += j - i;              for (k = j; k > i; k--) {                 chs[k] = chs[k - 1];             }             chs[i] = chs[n - i - 1];         } else {             for (j = n - i - 1; j >= i; j--) {                 if (chs[j] == chs[i]) {                     break;                 }             }             count += n - i - 1 - j;              for (k = j; k < n - i - 1; k++) {                 chs[k] = chs[k + 1];             }             chs[n - i - 1] = chs[i];         }     }     return count; }C语言吧贴吧的那个贾可?

#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXLENGTH 100  int exchange(char chs[], int n, char ch)  {     int count = 0, i, j, k;     for (i = 0; i < n / 2; i++)  	{ 		if (chs[i] == ch)  		{ 			for (j = i; j < n - i - 1; j++)  			{ 				if (chs[j] == chs[n - i - 1])  				{ 					break; 				} 			} 			 			count += j - i; 			 			for (k = j; k > i; k--)  			{ 				chs[k] = chs[k - 1]; 			} 			chs[i] = chs[n - i - 1]; 			 		} else  		{ 			for (j = n - i - 1; j >= i; j--)  			{ 				if (chs[j] == chs[i])  				{ 					break; 				} 			} 			 			count += n - i - 1 - j; 			 			for (k = j; k < n - i - 1; k++)  			{ 				chs[k] = chs[k + 1]; 			} 			chs[n - i - 1] = chs[i]; 		}     }     return count;   }  int main() { 	char chs[MAXLENGTH]; 	while(gets(chs) != NULL) 	{ 		int count[26]; 		char ch = '0'; 		int oddchar = 0; 		int n; 		int i, j; 		if((strlen(chs)) == 0) 			break; 		n = atoi(chs); 		gets(chs); 		for (j = 0; chs[j] != '\0'; j++)  		{ 			int index = chs[j] - 'a'; 			count[index]++; 		} 		 		for (i = 0; i < 26; i++) 		{ 			if (count[i] % 2 != 0)  			{ 				oddchar++; 				ch = (char) (i + 'a'); 			} 		} 		 		if (oddchar > 1)  		{ 			printf("Impossible\n"); 		} else  		{ 			int result = exchange(chs, n, ch); 			printf("%d\n",result); 		} 	} 	return 0; }

转成C不是很方便，C++就完全没问题： import和class->去掉 scanner->std::cin hasNext->std::cin::operator bool nextLine->std::getline toCharArray->不需要，直接在字符串上操作 new int[26]->记得填0，或者直接分配在栈上填零int count[26] = {0}; System.out.println->std::cout exchange(char[]...->如果用std::string，那么改成std::string&即可 以上C++元素在C中都有替代，就是getline比较麻烦（需要缓冲大小自动调整），剩下的直接抄


Question: bool关键字错误

非常感谢，问题以及解决，但是CB里说没有True以及False的声明以及实现....（我自己宏定义了TRUE FALSE）

#include <stdbool.h>


Question: c程序 报错诸多 求解答

引用 4 楼 sonnig_8 的回复:谢谢楼三的程序（真的比我写的简单多了，惭愧Ing），楼二老师的方法我也用过，但是确实不太懂怎么修改，遇到错的地方直接删掉反而可以运行 错误代码如下（有点多...）： 200	3 [Warning] passing argument 1 of 'daochu2' from incompatible pointer type [enabled by default] 218	3 [Warning] passing argument 1 of 'daochu3' from incompatible pointer type [enabled by default] 262	3 [Warning] passing argument 1 of 'dayin2' from incompatible pointer type [enabled by default] 373	5 [Warning] passing argument 1 of 'shuru2' from incompatible pointer type [enabled by default] 374	5 [Warning] passing argument 1 of 'shuru3' from incompatible pointer type [enabled by default] 378	5 [Warning] passing argument 1 of 'dayin2' from incompatible pointer type [enabled by default] 384	4 [Warning] passing argument 1 of 'paixu' from incompatible pointer type [enabled by default] 391	4 [Warning] passing argument 1 of 'daochu2' from incompatible pointer type [enabled by default] 392	4 [Warning] passing argument 1 of 'daochu3' from incompatible pointer type [enabled by default] 	   [Error] ld returned 1 exit status 你在你代码最开头加/*,最后加*/，编译，通过。 然后将你代码中你认为不可能出错的部分放在/*...*/外，其余括在/*...*/里面，编译，若通过，逐步减少被/*...*/括住的内容；若不通过，逐步增加被/*...*/括住的内容，……

我大一时写的代码。 与你的需求应该大体相同。 可以参考一下： http://download.csdn.net/detail/zidane_2014/9029619

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

楼主，错误信息贴一下


Question: 应该怎么修改宏定义

引用 33 楼 eseses455250704 的回复:[quote=引用 31 楼 adlay 的回复:] 不对啊，你原来的代码怎么通过编译的。。。 你的 printf("\n----------- Begin Unit Test ----------\n"); Test_LinkTable( ); char *result = all_tests(); 也存在变量定义出现在语句之后了的吗     警告怎么消除啊？ 哥们[/quote]  你是 64 位的系统吗？ 把 “%d" 改成 "%ld" 试试呢

引用 30 楼 adlay 的回复:你用的 VC6 吗？ main 改成这样吧  int main(int argc, char **argv) {     int passed = 0;     int failed = 0;     int i = 0;           BEGIN_TEST         test_replace(),         test_remove()     END_TEST       printf("\n----------- Begin Unit Test ----------\n");     printf("Tests run: %d\n", sizeof(testResults) / sizeof(char*));       for(i = 0; i < sizeof(testResults) / sizeof(char*); ++i)     {         if(testResults[i])         {             printf("TEST %d Error: %s\n", i, testResults[i]);             ++passed;         }         else         {             ++failed;             printf("TEST %d Passed", i);         }     }       printf("\n------------End Unit Test -------------\n");     printf("Passed: %d 个 \n",passed);     printf("Failed: %d 个 \n",failed);     printf("\n----------------------------------------\n");     return 0; }     谢谢您   现在想消除这个警告  怎么改正下呢  warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]      printf("Tests run: %d\n", sizeof(testResults) / sizeof(char*));      ^

引用 31 楼 adlay 的回复:不对啊，你原来的代码怎么通过编译的。。。 你的 printf("\n----------- Begin Unit Test ----------\n"); Test_LinkTable( ); char *result = all_tests(); 也存在变量定义出现在语句之后了的吗     警告怎么消除啊？ 哥们

引用 31 楼 adlay 的回复:不对啊，你原来的代码怎么通过编译的。。。 你的 printf("\n----------- Begin Unit Test ----------\n"); Test_LinkTable( ); char *result = all_tests(); 也存在变量定义出现在语句之后了的吗    没有  用的gcc  照着你给我说的又编译了一下 看看还是有点警告和错误 UnitTest.c:188:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]  printf("Tests run: %d\n", sizeof(testResults) / sizeof(char*));  ^ UnitTest.c:206:1: error: expected declaration or statement at end of input  }  ^ make: *** [UnitTest.o] 错误 1

引用 27 楼 adlay 的回复:在保留测试函数形式的情况下，最简单的例子  #include <stdio.h>  #define tcut_assert(what, test) do { if (!(test)) return what;} while (0)   static char * test_replace() { 	int number4 = 2; 	tcut_assert("error, number4 != 1", number4 == 1); 	return 0; }   static char * test_remove() { 	int number5 = 1; 	tcut_assert("error, number5 != 1", number5 == 1); 	return 0; }   //static char * all_tests() //{ //	tcut_run_test(test_replace); //	tcut_run_test(test_remove); //	return 0; //}  #define BEGIN_TEST  char* testResults[] = { #define END_TEST };    int main(int argc, char **argv) { 	printf("\n----------- Begin Unit Test ----------\n"); 	 	BEGIN_TEST 		test_replace(), 		test_remove() 	END_TEST   	int passed = 0; 	int failed = 0;  	printf("Tests run: %d\n", sizeof(testResults) / sizeof(char*));  	for(int i = 0; i < sizeof(testResults) / sizeof(char*); ++i) 	{ 		if(testResults[i]) 		{ 			printf("TEST %d Error: %s\n", i, testResults[i]); 			++passed; 		} 		else 		{ 			++failed; 			printf("TEST %d Passed", i); 		} 	}  	printf("\n------------End Unit Test -------------\n"); 	printf("Passed: %d 个 \n",passed); 	printf("Failed: %d 个 \n",failed); 	printf("\n----------------------------------------\n"); 	return 0; }    如果要收集更多的信息，比如打印出哪个测试函数出错等，可以 char* 数组改成一个包含更多信息的结构数组，吧 test_replace() 函数调用再包装到宏里面        拿着您写的这个   编译之后为什么好多错误，怎么消除这些错误啊？   UnitTest.c: In function ‘main’: UnitTest.c:177:13: error: parameter ‘testResults’ is initialized              BEGIN_TEST              ^ UnitTest.c:179:13: warning: initialization from incompatible pointer type [enabled by default]              test_constains()              ^ UnitTest.c:179:13: warning: (near initialization for ‘testResults’) [enabled by default] UnitTest.c:179:13: error: expected ‘}’ before ‘test_constains’ UnitTest.c:185:13: error: parameter ‘passed’ is initialized              int passed = 0;              ^ UnitTest.c:186:13: error: parameter ‘failed’ is initialized              int failed = 0;              ^ UnitTest.c:187:13: error: expected declaration specifiers before ‘printf’              printf("Tests run: %d\n", sizeof(testResults) / sizeof(char*));              ^ UnitTest.c:188:13: error: expected declaration specifiers before ‘for’              for(int i = 0; i < sizeof(testResults) / sizeof(char*); ++i;)              ^ UnitTest.c:188:28: error: expected declaration specifiers before ‘i’              for(int i = 0; i < sizeof(testResults) / sizeof(char*); ++i;)                             ^ UnitTest.c:188:69: error: expected declaration specifiers before ‘++’ token              for(int i = 0; i < sizeof(testResults) / sizeof(char*); ++i;)                                                                      ^ UnitTest.c:188:73: error: expected declaration specifiers before ‘)’ token              for(int i = 0; i < sizeof(testResults) / sizeof(char*); ++i;)                                                                          ^ UnitTest.c:176:17: error: old-style parameter declarations in prototyped function definition              int main(int argc, char **argv)                  ^ UnitTest.c:205:1: error: expected ‘{’ at end of input  }  ^ UnitTest.c: In function ‘main’: UnitTest.c:205:1: error: expected declaration or statement at end of input make: *** [UnitTest.o] 错误 1

#define tcut_assert(what, test) do { if (!(test)) {printf("%s\n", what); return what;}} while (0) } 少了一个;  抱歉  #define tcut_run_test(test) do { char *what = test(); nr_tests++; if (what != 0) mark = false; } while (0） 这个应该是！=  楼主 你再试试

引用 19 楼 ant2012 的回复:[quote=引用 17 楼 eseses455250704 的回复:] [quote=引用 15 楼 ant2012 的回复:] 忘了说了，主函数也得改 char *result = all_tests(); bool result = all_tests(); if (!result) { printf("Error:The test doesn't pass normal"); }   就是宏里面return那里  结束了函数的运行，不再执行下一个语句了   应该怎么改下那里呢[/quote]  #define tcut_assert(what, test) do { if (!(test)) {printf("%s\n", what); return what}} while (0) } #define tcut_run_test(test) do { char *what = test(); nr_tests++; if (what == 0) mark = false; } while (0） 改成这个不行么[/quote]    这个不行啊  我照着你的改了 不能运行   哥们   就是宏里面return那里  结束了函数的运行，不再执行下一个语句了   应该怎么改下那里呢[/quote]   有没有别的写法

引用 17 楼 eseses455250704 的回复:[quote=引用 15 楼 ant2012 的回复:] 忘了说了，主函数也得改 char *result = all_tests(); bool result = all_tests(); if (!result) { printf("Error:The test doesn't pass normal"); }   就是宏里面return那里  结束了函数的运行，不再执行下一个语句了   应该怎么改下那里呢[/quote]  #define tcut_assert(what, test) do { if (!(test)) {printf("%s\n", what); return what}} while (0) } #define tcut_run_test(test) do { char *what = test(); nr_tests++; if (what == 0) mark = false; } while (0） 改成这个不行么

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

引用 15 楼 ant2012 的回复:忘了说了，主函数也得改 char *result = all_tests(); bool result = all_tests(); if (!result) { printf("Error:The test doesn't pass normal"); }   就是宏里面return那里  结束了函数的运行，不再执行下一个语句了   应该怎么改下那里呢

引用 15 楼 ant2012 的回复:忘了说了，主函数也得改 char *result = all_tests(); bool result = all_tests(); if (!result) { printf("Error:The test doesn't pass normal"); } 宏那里应该怎么改下  不改的话还是老样子啊

引用 11 楼 ant2012 的回复:错了，将 static char * all_tests() {  tcut_run_test(test_replace); tcut_run_test(test_remove); return 0; } 改成 bool all_tests() {  tcut_run_test(test_replace); tcut_run_test(test_remove); return 0; }          哥们  这么写也不对啊  编译都出错的？

引用 25 楼 adlay 的回复:试试  #define tcut_run_test(test) do { char *what = test(); nr_tests++;} while (0）  你要想遇到错误还继续，就不能用一个返回值来返回所有的错误信息，需要用更多的结构来记录每一个测试的运行情况。  具体说下如果用更多的结构来记录每一个测试的运行情况  该怎么写呢

引用 23 楼 ant2012 的回复:编译错误信息是什么 我得出这样的结果 是这样    Tests run: 5 error, number4 != 1 Error:The test doesn't pass normal ------------End Unit Test ------------- Passed: 4 个  Failed: 1 个  编译过了  但是发现没有执行第6个函数 因为第五个就return了    怎么写能把第六个也执行了呢？  就是passed变为5个 ----------------------------------------

编译错误信息是什么


Question: 关于c语言中字符串和指针的一点困惑，求指教！

引用 21 楼 zhao4zhong1 的回复:[quote=引用 20 楼 zhangxiangDavaid 的回复:] 眼见为实：  #include <stdio.h> int main() { 	char notes[] = "See you at the snack bar."; 	char * ptr;  	ptr = notes; 	puts(++ptr); 	notes[7] = '\0'; 	puts(++ptr);  	return 0; } //ee you at the snack bar. //e you  些微侵犯了zhao4zhong1的将代码运行结果作为注释放在代码尾部的专利（还没申请）！[/quote] 我已经提前申请了。 zhangxiang：这是你的专利。 zhao4zhong1：不，这是你的专利！

引用 20 楼 zhangxiangDavaid 的回复:眼见为实：  #include <stdio.h> int main() { 	char notes[] = "See you at the snack bar."; 	char * ptr;  	ptr = notes; 	puts(++ptr); 	notes[7] = '\0'; 	puts(++ptr);  	return 0; } //ee you at the snack bar. //e you  些微侵犯了zhao4zhong1的将代码运行结果作为注释放在代码尾部的专利（还没申请）！

notes[7]='\0'; 表示7这个位置是字符串的结束位置  puts(++ptr) 就会输出e到u这个几个字符

这个问题，可以分步骤解释如下：  char notes[]="See you at the snack bar."; 这一句，字面串"See you at the snack bar."在程序转换阶段先是在末尾添加一个空字符'\0'，然后用于初始化一个不可见的静态数组。最后，C的实现用这个数组的内容初始化数组notes。  char * ptr; ptr = notes; 这两句，数组notes自动转换为指向其第一个元素的指针，并将这个指针赋给ptr。也就是说，ptr现在指向数组notes的首元素，也就是notes [0]。  puts(++ptr); 这一句，puts函数要求一个字符串。字符串是一个字符的序列，且以第一个遇到的空字符（'\0'）终止。字符串包括单字节字符的序列和多字节字符的序列，但应与宽字符的序列相区别。 不管怎么说，因为在传递给puts函数之前，表达式++ptr的效果是指向数组notes的第二个元素（notes [1]），所以输出的是 ee you at the snack bar.  notes[7]='\0'; 这一句，将数组的7号元素修改为空字符'\0'。此时，数组notes的元素是 See you\0at the snack bar.  puts(++ptr); 这一句，在进入puts函数之前，表达式++ptr的效果是指向数组notes的第三个元素（notes [2]），我们知道，puts函数输出一个字符串，但是，因为前面已经在数组中加入一个空字符'\0'，所以它指向的串，以入puts函数的输出实际上是 e you  以上的关键是搞清楚数组、指针和字符串这几个概念。再来看另一个例子： char keywords [] = "if\0else\0switch\0while"; 这是一个数组，从字符串的角度来看，它包含了4个字符串，可以这样输出它们： puts (keywords); puts (keywords + 3); puts (keywords + 8); puts (keywords + 15);

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

将指针传给puts()函数，而该指针也指向数组的首地址，因此修改的是同一块区域，楼主想的是两个不同地方是错误的

一个字符串的结束是\0，所以只要遇到\0该字符串就算结束

看看编译后的

改掉''\0' 不是多一位（字节），而是多了不确定位（字节）， 字符串长度，超过字符数组长度（超过数组定义的空间范围） puts 的时候，属于越界读。 这本来就是错误，用它来确定字符串长度是不对的  另外，C语言 数组越界，是可以操作的， 不是C语言层面上的错误。  只是程序逻辑错误。 C语言是不保证这种代码安全的。。。  一般来说，编译器不检查这种错误， 不过很多编译器，生成调试版本程序的时候， 可以一定程度的检测到这种错误。  聪明一点的编译器，也可能对某些错误，给出一些警告。 但这些都是不可靠的。关键还要自己掌握

"See you at"共十个字符， C语言给他加个'\0' ， 共十一个字符。   对于用字符串字面值， 初始化的字符数组（未定义数组元素个数）来说， 字面值的字节数，就是数组的元素个数。 字符串字面值，约定就是串内字符，所占字节，加上'\0' 所占字节。  第十一个字符恰恰就是 notes[10] ，第一个是notes[0] 你给改为 ‘a’ 以后，这个字符数组，就不在成为字符串了 但是puts函数是字符串输出函数，约定包含 '\0' 的，  puts(ptr); 没有找到‘\0' 他会继续找，找到之前的字符都会输出 至于这个'\0' 啥时候会出现，不确定， 不过一般来说，不论如何总能找到的， 程序空间不可能，一个字节为0值的内存，也没有。 除非最终找到某个不可读位置，程序报错， 程序总会输出些什么的。 但这是不可控的，输出的内容不是你希望输出的。

引用 9 楼 lm_whales 的回复:字符串，C语言中用字符数组表示（实现）。 只是字符串以 ‘\0’ 结束， 此后的字符，都不属于字符串了，字符串，不是C语言的数据类型。  字符数组，定义了多少元素，就有多少字节，就有多少个字符，是一个集合类型。 不管 ‘\0’ 在哪里，字符数组的元素数，都是定义时候的个数。  字符串的长度，随着‘\0’的位置而变化。 一个没有‘\0’的字符数组，不是一个字符串。 字符串字面值（串常量），实现上也是字符数组这一类的东西。  字符串，是C 语言不明确定义的数据类型，这个类型 不属于C语言。但是约定这么用，这么实现。  说的很对啊。都是很基本的东西。但是很有用的。借用的继续往下深究。如果没有\0，会出现什么情况：  #include <stdio.h> int main() {        char notes[]="See you at";      char * ptr;      ptr=notes;      notes[10]='a';      puts(ptr); 	 return 0; }  运行结果是：See you ata誑。数组不是11位吗（编译器自动给加了个\0），为什么改了\0，会多出一位。？？

你想法错误  其实是  先把数组首元素地址赋值给ptr

字符串和字符数组不是同一个东西吧，他们存储的地方不一样

最开始ptr执行的地址应该S所在的地址，第一个puts的输出应该是：ee you at the snack bar. 而此时ptr所指向的地址应该是第一个e所在的地址，但是notes指向的地址还是S所在的地址，notes[7]='\0';会将you后面的空格编程'\0'（字符串结束符)，第二puts输出时，是先将ptr的地址指向第二个e，然后再puts，所以是：e you

都是同一个字符串

引用 1 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？ 您说的很对，只有机器是说一不二的

该字符串最后被修改为： See you\0at the snack bar. 即第二个字符被清零。然而指针指向的是第三个字符 e，所以输出： e you

你口中的字符串和字符数组其实是同一个东西，不存在改变哪个没改变哪个的。


Question: 关于c编写Webservice

引用 3 楼 user-1 的回复:gsoap对于c/c++处理webservice，绝对是主流 好的谢谢

gsoap对于c/c++处理webservice，绝对是主流

因为就看到了gsoap，主要想知道一般c写的webservice主流都是用gsoap吗？还有其它选择吗，我怕如果太小众学习成本会很高

gsoap完全没问题


Question: C语言模拟密码输入(回显*),当没有输入内容,按退格键有蜂鸣声,如果有内容按退格键删掉最后那个字符

引用 3 楼 赵4老师的回复:将所有printf改为cprintf 为什么，不需要吧

将所有printf改为cprintf

楼主，你不实现了么

http://www.cplusplus.com/articles/E6vU7k9E/   这里有好多哦。


Question: 请问怎么用C语言访问像\\192.168.1.105这样的本地网络，并且读取里面的文件？

要不怎么叫“非法……”呢？

引用 10 楼 zhao4zhong1 的回复:不信的话，你在某个子目录下建一个junction指向自己的某一级父目录（这样就形成了一个死循环目录链），然后使用API和dir命令分别遍历该子目录试试看。 junction https://technet.microsoft.com/en-us/sysinternals/bb896768  这不是你自己处理有问题嘛？

引用 8 楼 jack960330 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 jack960330 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] system("net use y: \\192.168.1.105 password"); 应改为 system("net use y: \\\\192.168.1.105 password");  不是应该有网络邻居的API么[/quote] 用API不如用命令行简单、可靠。[/quote]  API更直接，可靠这个应该都差不多，为啥命令行就可靠，API就不可靠？[/quote] 参考下面： system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。

引用 7 楼 zhao4zhong1 的回复:[quote=引用 6 楼 jack960330 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] system("net use y: \\192.168.1.105 password"); 应改为 system("net use y: \\\\192.168.1.105 password");  不是应该有网络邻居的API么[/quote] 用API不如用命令行简单、可靠。[/quote]  API更直接，可靠这个应该都差不多，为啥命令行就可靠，API就不可靠？

效率再高，遇到意外而陷入死循环（比如楼上的循环目录链）或遇到数据量太大（比如所有文件数目达上千万）而导致溢出、崩溃、截短、……，我是不能忍受的。 至于有人能忍受，也是我管不了的。

引用 18 楼 adlay 的回复:这是一个代码重用的问题，使用 shell 命令是比使用 API 更高一个层次的重用， 层次越高，复杂度越低，效率也更低 （先生成文件再读文件就更低了，其实可以通过管道来获取输出的）  这就好比，用 C++ 能做的，C 也能做，  C 能做得，汇编也能做  汇编能做的，硬件也能做    这是一个方便和效率权衡的问题  你这说的什么跟什么，主要是API比较直接罢了

引用 15 楼 jack960330 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] [quote=引用 13 楼 jack960330 的回复:] [quote=引用 12 楼 zhao4zhong1 的回复:] 要不怎么叫“非法……”呢？  那你也不要建立什么快捷方式指向目录了，目录列表自动有一个名字是.和..的目录，如果 处理不当本来就会形成死循环，你处理肯定要做过滤的，哪有不过滤处理的[/quote] 那你试试过滤处理一下10楼所说的这种故意创建的非法目录结构。[/quote] 我一直觉得，shell命令能做的，基本上API就能做，问题在于怎么做，文件夹便利API不会自动遍历下级目录，是否选择遍历下级目录主要是你的遍历算法[/quote] 个人意见： 其实真正的不同在于： shell命令对各种意外的鲁棒性是经过无数先烈千锤百炼的结果； 而 API对各种意外的鲁棒性相比之下就至少差一个数量级了。  还可以参考一下这个帖子： http://bbs.csdn.net/topics/391817065

引用 14 楼 zhao4zhong1 的回复:[quote=引用 13 楼 jack960330 的回复:] [quote=引用 12 楼 zhao4zhong1 的回复:] 要不怎么叫“非法……”呢？  那你也不要建立什么快捷方式指向目录了，目录列表自动有一个名字是.和..的目录，如果 处理不当本来就会形成死循环，你处理肯定要做过滤的，哪有不过滤处理的[/quote] 那你试试过滤处理一下10楼所说的这种故意创建的非法目录结构。[/quote]  你那不就快捷方式么

引用 14 楼 zhao4zhong1 的回复:[quote=引用 13 楼 jack960330 的回复:] [quote=引用 12 楼 zhao4zhong1 的回复:] 要不怎么叫“非法……”呢？  那你也不要建立什么快捷方式指向目录了，目录列表自动有一个名字是.和..的目录，如果 处理不当本来就会形成死循环，你处理肯定要做过滤的，哪有不过滤处理的[/quote] 那你试试过滤处理一下10楼所说的这种故意创建的非法目录结构。[/quote] 我一直觉得，shell命令能做的，基本上API就能做，问题在于怎么做，文件夹便利API不会自动遍历下级目录，是否选择遍历下级目录主要是你的遍历算法

引用 13 楼 jack960330 的回复:[quote=引用 12 楼 zhao4zhong1 的回复:] 要不怎么叫“非法……”呢？  那你也不要建立什么快捷方式指向目录了，目录列表自动有一个名字是.和..的目录，如果 处理不当本来就会形成死循环，你处理肯定要做过滤的，哪有不过滤处理的[/quote] 那你试试过滤处理一下10楼所说的这种故意创建的非法目录结构。

引用 12 楼 zhao4zhong1 的回复:要不怎么叫“非法……”呢？  那你也不要建立什么快捷方式指向目录了，目录列表自动有一个名字是.和..的目录，如果 处理不当本来就会形成死循环，你处理肯定要做过滤的，哪有不过滤处理的

映射的一个磁盘，执行 net use y: \\192.168.1.105 password 后本地会多一个分区 Y

请问y:是什么意思呢？

引用 6 楼 jack960330 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] system("net use y: \\192.168.1.105 password"); 应改为 system("net use y: \\\\192.168.1.105 password");  不是应该有网络邻居的API么[/quote] 用API不如用命令行简单、可靠。

引用 5 楼 zhao4zhong1 的回复:system("net use y: \\192.168.1.105 password"); 应改为 system("net use y: \\\\192.168.1.105 password");  不是应该有网络邻居的API么

应该有读取网络邻居计算机的方法，这个 是网络邻居的格式

system("net use y: \\192.168.1.105 password"); f=fopen("y:\\test.txt","r"); ... fclose(f); system("net use y: /delete");


Question: c语言中,当局部变量的地址赋给指针时,为什么其生存周期可以延长至整个程序结束

肯定不行，出了作用域那块地址可能被从新写入其他数据。可以换成new。 int*fun(){         int* k = new int[12];         return k; } 这样把k的地址给出去，想什么时候释放就什么时候释放。

以地原子→以原子

菩萨保佑吧。

引用 8 楼 xiaohuh421 的回复:变量是在内存中分配的地址保存的,  生命周期到了, 这个变量的内存释放了, 但要注意, 释放, 只是告诉系统, 这块内存我不用了, 你自己收回去,   但并不代表这个地址都不存在了,   这地址是一直都在的,  通过指针, 当然可以继续访问.  但他的值是什么东西, 就要看系统有没有把它分配给其它变量了, 如果没有分配 , 可能是万年不变, 如果被分配了, 那就不知道是什么东西了.  参考下面的代码, 题目中的代码称作代码1,下面的代码称作代码2. 在代码1中,k的内存是动态分配的 在代码2中,a指向的内存也是动态分配的,它的内存的周期是整个程序, 直到遇到free为止 从这个角度来说,代码1中的k的内存也是整个程序. k的内存和a所指向的内存的 不同点在哪呢,应该是 一个在栈里,一个在堆里(写到这 我自己居然懂了)  #include<stdio.h> #include<stdlib.h>  int* fun(){ 	int *p = (int*)malloc(4); 	*p = 12; 	return p; } int main(){ 	int *p = fun(); 	printf("%d\n", *p);  	getchar(); 	free(p); 	return 0; }

引用 11 楼 zhao4zhong1 的回复:人的肉身是在物理上以地原子的形式存在的, 人的生命周期到了, 这个人的灵魂消失了, 但要注意,销魂, 只是告诉上帝, 这块肉身我不用了, 您老收回去,   但并不代表这堆原子都不存在了,   原子是一直都在的,  通过电子显微镜, 当然可以继续观察到这堆原子.  但它们是什么东西, 就要看上帝有没有把它分配给其它肉身了, 如果没有分配 , 可能是万年不变, 如果被分配了, 那就不知道是什么畜牲了.  楼下的看了不许笑哈！    我不笑,我赞赞赞呐~~~~~~~~~

肯定不正规，你都把房子卖了，虽然房子还在那，但你还不时地进去看看，那肯定不合法，只不过，偶尔悄悄地进去没被发现罢了

引用 2 楼 gss861225 的回复:应该是指针指向的地址还没有被其他数据覆盖的缘故吧。我也是这样想的,只是想知道这种写法是不是正规

只能说，有可能能访问，不是一定能访问。

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

野指针。。。

不仅可以访问，还可以修改，只不过这种访问是不确定的 局部变量的地址都是在程序自己的堆栈中，当局部变量结束后，只要没有将该局部变量的内存地址给别的变量，其值仍然存在。但如果修改的话，是比较危险的，因为这个内存地址可能给了程序的其它变量，通过指针强行修改的话，可能会引起程序崩溃

应该是指针指向的地址还没有被其他数据覆盖的缘故吧。


Question: 写一个宏定义函数

引用 12 楼 adlay 的回复:[quote=引用 10 楼 tzp118 的回复:] [quote=引用 7 楼 adlay 的回复:] [quote=引用 5 楼 tzp118 的回复:] [quote=引用 1 楼 adlay 的回复:] #define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088[/quote] 你确定你要的是 1088？ 不是补位到 16 的整数倍吗，怎么能减位呢？[/quote]  题目说的是扩展到 临近 的16的整数位啊  临近的[/quote] 是的啊，但是扩展的意思是增加，扩展到临近的就是增加最少的位 你 1089 变成 1088 是减少了，不是增加撒 在实际的图像中，图像一行有 1089 个 BYTE 的数据，你那样扩展成 1088 就丢掉了一个 BYTE 的数据了，是不会允许的 小学语文老师要哭了[/quote]  哦，我明白了，谢谢啊

引用 10 楼 tzp118 的回复:[quote=引用 7 楼 adlay 的回复:] [quote=引用 5 楼 tzp118 的回复:] [quote=引用 1 楼 adlay 的回复:] #define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088[/quote] 你确定你要的是 1088？ 不是补位到 16 的整数倍吗，怎么能减位呢？[/quote]  题目说的是扩展到 临近 的16的整数位啊  临近的[/quote] 是的啊，但是扩展的意思是增加，扩展到临近的就是增加最少的位 你 1089 变成 1088 是减少了，不是增加撒 在实际的图像中，图像一行有 1089 个 BYTE 的数据，你那样扩展成 1088 就丢掉了一个 BYTE 的数据了，是不会允许的 小学语文老师要哭了

所谓的临近起码你也得说清楚怎么个概念，比如说差值最小：1089 到 1088 的差值最小，而不是 1104。如果只是按指定位宽对其的话，只能往大不能小。如果要实现 1089 和 1087 都输出 1088 的话，最好还是写个函数。

#define EXTEND(value) ((value + 8) >> 4 << 4) 之前那个不符合你的要求，试试这个

引用 7 楼 adlay 的回复:[quote=引用 5 楼 tzp118 的回复:] [quote=引用 1 楼 adlay 的回复:] #define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088[/quote] 你确定你要的是 1088？ 不是补位到 16 的整数倍吗，怎么能减位呢？[/quote] 如果你不是要 “扩展到临近的16的倍数的整数” 只是想按四舍五入的方式找到临近的 16 的倍数的整数，那把 + 15 改成 + 8 吧

引用 7 楼 adlay 的回复:[quote=引用 5 楼 tzp118 的回复:] [quote=引用 1 楼 adlay 的回复:] #define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088[/quote] 你确定你要的是 1088？ 不是补位到 16 的整数倍吗，怎么能减位呢？[/quote]  题目说的是扩展到 临近 的16的整数位啊  临近的

引用 5 楼 tzp118 的回复:[quote=引用 1 楼 adlay 的回复:] #define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088[/quote] 你确定你要的是 1088？ 不是补位到 16 的整数倍吗，怎么能减位呢？

#define EXTEND(value) (value % 16 == 0 ? value : ((value >> 4) + 1) << 4)

引用 1 楼 adlay 的回复:#define EXTERN16BYTE(x)   ((x + 15) / 16 * 16)  可是我如果输入1089，按照您写的这个输出的是1104，可实际上需要输出的是1088

（x   + 15 ) & ~0xFu

要效率高一点还可以改成 (x + 15) & 0xFFFFFFF0

（x   + 15 ) & ~16U


Question: C语言中的 ...

引用 10 楼 iyomumx 的回复:gcc扩展，不是标准 引用To initialize a range of elements to the same value, write `[first ... last] = value'. This is a GNU extension. For example,       int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };  GCC的扩展，VS2013下不合法

大部分人这样写： char str[64] = { '\0' }; 我一般这样写： char str[64] = { 0 }; 你那种写法没见过，不过真的多余。上面这这两种写法也是全部置零。

语法糖越甜，编译调试查错越苦！ 把有限的生命浪费在品尝/品鉴无穷多种的语法糖中，我认为不值当。

指定范围初始化？

C99 以及以后的标准？

刚刚试了，确实是合法的

不是伪代码，是dhcp客户端实现的源码里的。。

表示真没见过这样写的，坐等大神回复

这不是伪代码吗?为什么不自己在编译器上验证一下呢. 看书的时候要从前言看起,里面会有一些代码约定.

这不会是伪代码吧，我从来都没见过


Question: C语言程序

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

同意一楼，楼主懂了吗？

a=077是8进制，即10进制的63，即16进制的0x3F，也即2进制的00111111 3的2进制提0x00000011。 b=a&3; 按位与： 00111111 00000011 ————— 00000011 结果b就是3。  然后b&=7，即b=b&7： 00000011 00000111 ————— 00000011 b还是3.


Question: 求组啊！帮帮我，我实在想不明白，为什么字符串会改变啊！怎么改都会变。帮帮忙。

我知道是strtok改变了源字符串。 我已经知道是怎么回事了。没复制正确。谢谢了。

http://www.cnblogs.com/cobbliu/p/3393177.html  strtok改变了你的字符串！


Question: 关于宏定义大神啊

如果 已经 #define 为宏了 或者已经是类型名，变量名，常量名，或者函数名了， 则#ifndef  为假，否为为真

一定是定义过

这样的写法保证此处 a 被定义，而且不会重复定义。

意思是 如果没有定义a 那么就定义a  所以，最终定义了a

引用 楼主 yff12321 的回复:#ifndef a     #define a  #endif 那么a有没有被宏定义过啊？是没有吗  肯定定义过，假如#ifndef a之前没有定义过a，那么这句话为真，则会执行 #define a，那就定义了a

#ifdef


Question: win7 64位驱动，编译后加载不成功

用WDK的人应该不算多，当初我也只是跟着例子模仿过，当初加载驱动都是用EzDriverInstaller，用DebugView看调试信息，使用VS2008编译，编译后能成功加载。建议你找个办法检测驱动文件的正确性，并且加载失败是否有相关错误码


Question: C语言递归问题求助

入栈的就是 临时变量 = n * 返回值

需要把调用该函数的后面那条指令的地址入栈 第二次以后是把n*fact(n-1);入栈，即递归结束后，接着执行乘法操作；你得把所有计算操作拆成原子操作，看看程序的汇编代码就知道了

按照你的逻辑，当然就是本次计算完fact之后的返回语句了，每次递归时都将返回语句压栈，然后再一层层返回

1) 返回地址入栈没错,c=2指令对应的地址入栈,不是指令本身 2) return (n * fact(n - 1))换一下写法 int t =fac(n-1); return n*t; 这就是你要的下一条指令的地址 如果只是学递归,没必要深究这个的,


Question: c语言求助，有关 学生成绩管理系统

自己百度，又不难写

为什么要将平时成绩、期中成绩、期末成绩又定义一个结构体呢？

其实是我不知道怎么用文件分类保存

struct student //结构体 { 	char name[20]; //姓名 	char number[20]; //学号 	char sex[2];//性别  	struct score 	{ 		double pinshi; //平时成绩      	double qizhong; //期中成绩     	double qimo; //期末成绩 	}score[5]; }s[60];  可以这么编吗，如果可以的话，那要肿么赋值诶

百度学生信息管理系统C语言源码啊，挺多的，找找看吧。

额额就是每门成绩又分别存有学生某门课的平时成绩、期中成绩和期末成绩，这个这个真心不太会啊

大神们，我百度过了，然后自己也有做一份，但是实在是不造怎么把学生信息、课程信息和学生选课成绩信息这几个结合到一块，求解答

一看就是课程设计，现在帮你实现了源码，不是在帮你……好好学习


Question: C语言 栈的问题求教

int DestroyStack(pLStack pLS) 这个函数不能改变pLS, 需要改为二级指针 如 int DestroyStack(pLStack *ppLS) {  *ppLS =NULL; } 这样, 如果是C++,改成引用 pLStack &pLS

主函数中测试如下：	 pLStack pLS; InitLStack(&pLS); ... .... DestroyStack(pLS); if(StackEmpty(pLS)) { 	printf(" 栈空\n"); }  没有在StackEmpty(pLS)函数中，出现但是没有出现      printf("栈不存在!" );      ？？ 调试过，但是不懂为什么？？


Question: 求指导，照着PPT上做怎么

#include<stdio.h> void sort(int a[],int n) {  int i,j,t;    for(i=0;i<n-1;i++)    for(j=i+1;j<n;j++)    if(a[i]>a[j]) {        t=a[i];       a[i]=a[j];       a[j]=t;}	 } main() { int x[5],i; for(i=0;i<5;i++)  scanf("%d",&x[i]); sort(x,5); for(i=0;i<5;i++)  printf("%4d",x[i]); } 暂没有发现其他问题~

1、{t=a[i];a[i]=a[j];a[j]=t}; 改为 {t=a[i];a[i]=a[j];a[j]=t;} 分号在大括号内 2、sort(x[],5); 改为 sort(x,5);


Question: 为何不能定义两个指针?

看变量的内存地址是要加上 & 来取址。

11楼说的有理

指针未初始化，内容是随机值的，说不定指到哪里去了

你就记住，指针必须被初始化 ----- NULL 或者 你直接用你定义的别的数据的地址 初始化   否则，这个指针的行为就是“未定义”的  如果此时这个指针指向了那些不允许显示的地址空间   就会报错  所以纠结为什么第一个可以第二个不行 是无意义的

指针未赋初值， 指向未知位置， 内容随机。

#include <stdio.h> int main() {         int *i;         int *j;         printf("%p, %p\n", i, j);         return 0; }  楼主的的指针变量只是定义了，而没有初始化 我在VS2010上试了下：编译会警告，调试会出错，截图如下：

#include <stdio.h>  int main(void) {     /* i和j指针没有初始化是没有意义的 */     int* i;     int* j;     /* 可以这样初始化指针 */     int a = 2;     int* k = &a;     /* 也可以这样初始化指针 */     int* m = (int*)malloc(sizeof(int));     *m = 5;     printf("%p, %p\n", i, j);     printf("%p, %p\n", k, m);     printf("%d, %d\n", *k, *m);     /* 释放指针 */     if(m != NULL)     {         free(m);     }     return 0; }

没有初始化的指针，值是随机的

没有初始化的指针 内容是随机的

引用 2 楼 user-10的回复:你只是定义一个指针，而没有对指针的值初始化，所以它可以是零值，也可以是任何值。 谢谢，理解了，不过为什么总是最后一个初始化成0

你只是定义一个指针，而没有对指针的值初始化，所以它可以是零值，也可以是任何值。

变成3个: #include <stdio.h>  int main() {         int *i;         int *j;         int *k;         printf("%p, %p, %p\n", i, j, k);         return 0; } 结果: 0x400440, 0x7fff208a9a70, (nil)


Question: 看不懂的指针，求大神解答

//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

上面的三位也说明的比较好了，这个就是一个函数指针，函数指针是存放的的某个函数地址的。这个一般在程序运行调用的时候会比较常用，因为调用某个函数其实就是要调到对应函数所在的内存地址。而这个地址就放在函数指针里。  flashi_nor_device * (*probe_fcn) (volatile word *probe_addr);  //这种方法是定义一个函数指针：返回值是flashi_nor_device *类型，并且参数是volatile word *这种类型的变量； typedef  flashi_nor_device * (*probe_fcn) (volatile word *probe_addr);    //这是定义一个函数指针类型~即probe_fcn就是一个指针函数类型，你可以通过probe_fcn定义上述的指针变量。

指向指针函数的函数指针，说白了，它是个指针，只不过它指向的是一个函数，而这个函数的返回值又是一个指针

flashi_nor_device * (*probe_fcn) (volatile word *probe_addr);  先把(*probe_fcn)  当作   funA 就是 flashi_nor_device * funA (volatile word *probe_addr);  这样子就认识了吧  而先把(*probe_fcn) 就是指针取值，probe_fcn是个函数指针。对于函数指针，可以去百度查查，到底是个什么东西就可以了

函数指针  比如  int add(int  a, int  b); int (*p)(int,int) = add;  下面的就是一个函数指针 再如  int * get(char * str)  对应的函数指针就是   int * (*p)(char * )


Question: 一个函数内，调用多个其他函数出错，怎么退出

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

c++的异常机制不是很好， 只能捕捉到自定义异常， 但是对系统异常没法捕捉（例如内存越界，野指针等） 所以， 好好用goto ，return， do..while();  出口多不是问题， 关键你要控制好逻辑， 定义自己的错误码等

是否可以添加打印信息，用于标注在哪个途径或者处理哪个函数里除了异常，然后直接调用exit退出程序。

可以 if else嵌套啊  如：  if （fun1 == xxx） {     if (fun2 == xxx)     {          //....     }     else     {     } } else { }

引用 2 楼 mylove94U 的回复:[quote=引用 楼主 mylove94U 的回复:] 各位好，我在一个函数中，调用多个函数，每个函数都可能出错，都需要进行判断，如果出错就退出程序，除了用do...while(0), goto语句外，还有什么好的方法呢。      do     {         queryCertStaus(status, certNo);         if(strncmp(status, ERR_CERT_ACTIVE,  2) != 0)         {             strcpy(retCode, status);             break; 	    //goto err;         }          if((pkLen = getPkFromDb(pkStr, certNo, identity)) == -1)         {             strcpy(retCode, ERR_NO_CERT);             break; 	    //goto err;         }          Base64Decode((unsigned char*)buf, &bufLen, signText);         sha1HMAC(hmac, (unsigned char*)buf, bufLen);  //对明文计算哈希          //公钥对哈希值进行加密         if (0 != (ret = RSA_PKEncrypt(tmp, &tmpLen, (unsigned char*)hmac, 20, (unsigned char*)pkStr, pkLen)))         {             trace_log(ERR, "RSA_PKEncrypt failure. Error message: %s", RSA_LastError(ret));             strcpy(retCode, ERR_SIGN_FAILURE);             break; 	    //goto err;         }          signLen = sizeof(signMsg);         Base64Encode(signMsg, &signLen, tmp, tmpLen);         flag = true;     }while(0); 引用 1 楼 cjqpker 的回复:如果不介意性能的话，可以抛异常 另外，处理好资源释放问题，可以随时return  嗯，return语句多了，感觉阅读起来有点费劲，出口有点多。[/quote]  所以才有 do while(0) 的方法出现。这个方法在统一出口、控制分支、清理资源方面，还是很有优势的，虽然看起来丑了点

引用 楼主 mylove94U 的回复:各位好，我在一个函数中，调用多个函数，每个函数都可能出错，都需要进行判断，如果出错就退出程序，除了用do...while(0), goto语句外，还有什么好的方法呢。      do     {         queryCertStaus(status, certNo);         if(strncmp(status, ERR_CERT_ACTIVE,  2) != 0)         {             strcpy(retCode, status);             break; 	    //goto err;         }          if((pkLen = getPkFromDb(pkStr, certNo, identity)) == -1)         {             strcpy(retCode, ERR_NO_CERT);             break; 	    //goto err;         }          Base64Decode((unsigned char*)buf, &bufLen, signText);         sha1HMAC(hmac, (unsigned char*)buf, bufLen);  //对明文计算哈希          //公钥对哈希值进行加密         if (0 != (ret = RSA_PKEncrypt(tmp, &tmpLen, (unsigned char*)hmac, 20, (unsigned char*)pkStr, pkLen)))         {             trace_log(ERR, "RSA_PKEncrypt failure. Error message: %s", RSA_LastError(ret));             strcpy(retCode, ERR_SIGN_FAILURE);             break; 	    //goto err;         }          signLen = sizeof(signMsg);         Base64Encode(signMsg, &signLen, tmp, tmpLen);         flag = true;     }while(0); 引用 1 楼 cjqpker 的回复:如果不介意性能的话，可以抛异常 另外，处理好资源释放问题，可以随时return  嗯，return语句多了，感觉阅读起来有点费劲，出口有点多。

如果不介意性能的话，可以抛异常 另外，处理好资源释放问题，可以随时return


Question: 新手请教printf("%t",a[i])输出的为什么是tttt

%t什么玩意

引用 1 楼 user-2 的回复:引用printf("%t",a[i]);  %t ????? 哦，了解了，应该是 printf("%d\t",a[i])

引用printf("%t",a[i]);  %t ?????


Question: 求解C相关

感谢各位，明白了

将16进制转成10进制, 除以2,  再转成word *型

base 是一个 word 类型的指针

& 取地址 高于 除 运算 (int) 类型强转  高于 除 运算 & 和 (int) 的运算结合方向是 从右到左  (int)&stamp_md5_hash/2  即 对stamp_md5_hash 这个变量取地址 ，将地址值强转为 int， 将这个int值 除以 2， 将除以2之后的值，做为一个(word *)指针

(int)&stamp_md5_hash 将stamp_md5_hash 地址转换成整型，接着除2取商，然后强制转换成word指针型，赋给base  楼主，你这是要做什么，为何这样操作，很危险


Question: 一个小小的关于指针的判断题

合法与不合法全看你前面a、b定义的是什么类型。。。   int** a; int b; *a = &b;   上面这种类型就是合法的

这个要看前面对这两个变量的定义，单单这个语句不能说对和错的

只是不合法，没有错误，只是阅读性差一些

《牛肉干》 C语言上机课，某女同学偷偷吃起牛肉干。 有一粒牛肉干掉到了键盘上，卡在7和8键之间。 女同学就在键盘上抠啊、抠啊、抠啊…… 程序里一行代码变成这个样子： int *pa=&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&a; 后来的结局是 ————程序顺利通过编译，运行结果正确！

*a=b 表示 a指针所指向的数据,等于b *a=&b 表示 a指针所指向的数据,等于b的地址

int main() { 	int* b; 	int**a=&b; 	int c=20; 	*a=&c;     cout<<"a:"<<a<<endl; 	cout<<"*a:"<<*a<<endl; 	cout<<"**a:"<<**a<<endl; 	system("pause"); } 运行一下这个你就明白了

int** a = new (int*); b = 000; *a = &b;

修正一下，以免使用未初始化的指针： int * c; int ** a = &c; int b = 0; *a = &b; 结果是将b的地址负值给c

int ** a; int b = 0; *a = &b;

你在定义指针并初始化 int b = 0；int * a = &b；  这么写可以！ 如果 你仅仅定义了 指针 int *a；  int b = 0；  *a = &b；  你的a都没有初始化 你用*a 肯定不合法！


Question: 实在看不懂的函数，指针与数组，求大神讲解

引用 5 楼 ant2012 的回复:建议楼主对指针的学习一步步来，别上来就一个指向指针函数的函数指针 还有，指针就是一个变量，只不过它和别的变量的区别在于，别的变量存放的是变量类型的数据，它存放的是存放数据的内存地址（因此，所有指针变量的大小都是一样大）  楼主可以理解为，内存就是一排排连续的柜子，每个变量拥若干个柜子，柜子里可能存放的是文件数据（普通变量），也可能存放的是文件所在柜子的编号（指针变量），通过这个编号就能找到文件存放的柜子 感谢感谢

引用 3 楼 yff12321 的回复:[quote=引用 1 楼 ant2012 的回复:] 楼主，prPtr = flash_nor_probe_table; 这句代码，你确定能编译通过？  prPtr为ProbeTbl结构体实例的对象，flash_nor_probe_table为包含多个ProbeTbl对象的数组的首地址，地址赋给对象？  应该将 ProbeTbl  prPtr; 改为 ProbeTbl  *prPtr;  //定义一个ProbeTbl类型指针，来承接数组的地址 对了ProbeTbl 不是这么弄的，是还有一个函数 typedef ProbeTbl *ProbeTbl_t; ProbeTbl_t prPtr; 这样合理了吗？[/quote]  这样可以 ProbeTbl_t是一个ProbeTbl的指针类型，声明出的变量即为指针

引用 1 楼 ant2012 的回复:楼主，prPtr = flash_nor_probe_table; 这句代码，你确定能编译通过？  prPtr为ProbeTbl结构体实例的对象，flash_nor_probe_table为包含多个ProbeTbl对象的数组的首地址，地址赋给对象？  应该将 ProbeTbl  prPtr; 改为 ProbeTbl  *prPtr;  //定义一个ProbeTbl类型指针，来承接数组的地址 对了ProbeTbl 不是这么弄的，是还有一个函数 typedef ProbeTbl *ProbeTbl_t; ProbeTbl_t prPtr; 这样合理了吗？

引用 1 楼 ant2012 的回复:楼主，prPtr = flash_nor_probe_table; 这句代码，你确定能编译通过？  prPtr为ProbeTbl结构体实例的对象，flash_nor_probe_table为包含多个ProbeTbl对象的数组的首地址，地址赋给对象？  应该将 ProbeTbl  prPtr; 改为 ProbeTbl  *prPtr;  //定义一个ProbeTbl类型指针，来承接数组的地址 会不会因为prPtr是结构体变量，而结构体的成员都是指针类型的所以默认prPtr也是指针类型的呢


Question: xcode 编程出现问题

引用 6 楼 qq_21362051 的回复:非常感谢，成功了，能不能给我讲下这个原理，我是菜鸟，求解，谢谢兄弟 饿，原理； 头文件的意义，就是重用，你两个.c文件都引用了那个头文件，编译的时候，两个.c编译为.o，里面都会有amount  accountBalance这两个变量的定义呢，且都是全局变量，所以在链接的时候会报 符号重复定义的错误"ld: 2 duplicate symbols for architecture x86_64"  这种错误，在c++等其他面向对象语言中一般不会发生， 你这里，因为两个.c应该是想要访问同一个变量amount；那么实际定义这个变量也就是申请其内存的地方只要一个就可以， 所以在头文件的定义中加上extern修饰(extern详情自己百度下吧)，这样所以通过transactions.h访问这俩变量的都是需要在链接的时候查找变量实际定义的，也就是transactions.c中没有加extern的 定义；

是不是一个变量在别处定义的，在另一个文件就得在前加上extern？

非常感谢，成功了，能不能给我讲下这个原理，我是菜鸟，求解，谢谢兄弟

amount  accountBalance 两个变量； transactions.h头文件中将变量定义 float 前面加上extern

这个是main.c #include "transactions.h"  int main(void) {     initializeAccount();     getBalance();     //Perform first transaction     askCustomer();     updateAccount(amount);     getBalance();     //Perform second transaction     askCustomer();     updateAccount(amount);     addGift(5.0);     getBalance();     //Perform third transaction     askCustomer();     updateAccount(amount);     addGift(2.0);     getBalance();     thankYou();     return EXIT_SUCCESS; } 这个是transactions.c #include <stdio.h> #include <stdlib.h>  float accountBalance, amount; void initializeAccount(void){     accountBalance = 0.0; }  void addGift(float giftAmount){     accountBalance += giftAmount;     printf("Congratulations! A gift of $%.2f has been added to your account\n",giftAmount); } void askCustomer(void){     printf("Next transaction please...\n");     printf("Enter amount to credit (positive) or debit (negative):");     scanf("%f",&amount); }  void getBalance(void){     printf("\nThe current balance in the account is $%.2f\n", accountBalance); }  void updateAccount(float amount){     accountBalance += amount;     printf("The account was updated with $%.2f\n",amount); }  void thankYou(void){     printf("------  Thank you!  ------"); } 这个是transactions.h #include <stdio.h> #include <stdlib.h> #ifndef TRANSACTIONS_H_ #define TRANSACTIONS_H_ float accountBalance, amount;  void initializeAccount(); void getBalance(void); void askCustomer(void); void updateAccount(float value); void addGift(float giftAmount); void thankYou(void);  #endif /* TRANSACTIONS_H_ */  代码是从教学视频上的，应该没问题

符号重定义，贴出你的代码

重建了还是不好使啊

重建所有


Question: KMP算法  完全看不懂唉

静下心好好分析

http://blog.csdn.net/yutianzuijin/article/details/11954939 这个建议楼主仔细看看   说的还是比较清楚的

求子串的Next数组 void getNext(char *str, int *next) { 	assert(str != NULL && next != NULL);  	int size = strlen(str); 	if(size == 0) 		return;  	int i = 0; 	int k = -1; 	next[0] = -1;  	while(i < size - 1) 	{ 		if(k == -1 || str[i] == str[k]) 		{ 			i++; 			k++; 			if(str[i] == str[k]) 			{ 				next[i] = next[k]; 			} 			else 			{ 				next[i] = k; 			} 		} 		else 		{ 			k = next[k]; 		} 	} }


Question: 新手求助   程序可以编译 但是无法运行

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

谢谢，谢谢。感谢你们

#include <stdio.h> //此函数判断质数 int prim(int u) { int i;     int prim = 1;  for (i = 0; i < u; i++)   // i不能为0 if ( u%i == 0 )  prim = 0;  return prim;  }     int main ()  {  	int u;  	int Pirm;  	  	scanf ("%d", &u );  	  	Pirm = prim(u);  	  	if ( Pirm == 1)  	 printf ("True");  	else  	 printf ("False");  	  	return 0;   }

引用 楼主 kqsz127 的回复:#include <stdio.h> //此函数判断质数 int prim(int u) { 	int i;     int prim = 1; 	 	for (i = 0; i < u; i++) 		if ( u%i == 0 )    ----------------> 这个地方0做除数了 			prim = 0; 		 	return prim;  }     int main ()  {  	int u;  	int Pirm;  	  	scanf ("%d", &u );  	  	Pirm = prim(u);  	  	if ( Pirm == 1)  		printf ("True");  	else  		printf ("False");  		  	return 0;   } 1.prime函数写的有问题 2.程序结束前，没有getchar，运行完直接退出

显示的啥错误？

没用 value返回255

int main ()   {    int u;    int Pirm;        scanf ("%d", &u );        Pirm = prim(u);        if ( Pirm == 1)    printf ("True");    else    printf ("False");    getchar();     //试试这个    return 0;    }

请汇报给微软！

运行之后（win10系统）显示出现问题，导致程序停止正常工作

在IDE中按F11键运行。

没有啊，没有360； 而且其他的程序可以编译

关闭UAC、防火墙、杀毒软件、……


Question: C语言的函数如何返回二维数组，并获取返回的二维数组大小

你加两个参数（定义为指针或引用）用来返回数组的宽度和维数不就行了

引用 2 楼 taoweiji2008 的回复:[quote=引用 1 楼 ant2012 的回复:] 你加两个参数（定义为指针或引用）用来返回数组的宽度和维数不就行了 我是从java过来的，不怎么会写C，希望你能够帮帮忙翻译一下。[/quote]  int** getInfo(int* height, int* length) { 	*height = 10; 	*length = 20; 	int **pp = (int**)malloc(*height * sizeof(int*)); 	for(int i = 0; i < *height; i++) 	{ 		pp[i] = (int*)malloc(*length * sizeof(int)); 	} 	return pp; }  int main() { 	int i, height, length; 	int** result = getInfo(&height, &length); 	printf("结果长度：%d\n", height); 	for(i = 0; i < height; i++) 	{ 		for(int j = 0; j < length; j++) 		{ 			printf("%d\n", result[i][j]); 		} 	} 	for(i = 0; i < height; i++) 	{ 		free(result[i]); 	} 	free(result); 	result = NULL; 	return 0; }

C语言没有JAVA那么灵活，像你的这个例子，如果用C语言实现还是很麻烦的，需要注意这几方面： 1、数组指针的传递； 2、数组的两个维度需要用单独的变量记录； 3、C语言动态申请的内存需要手动释放，而且动态二维数组的申请释放比较特殊；  因为这么搞比较麻烦，所以C语言一般不这么搞， 如果你的二维数组不大，还不如直接定义成全局变量。 没必要为了灵活，折腾死自己，写着费劲，也难以维护。  另外你的JAVA代码有一处似乎有问题，第二个for循环应该不能用result.length，而应该用result[0].length吧：  for (int j = 0; j < result[0].length; j++)

引用 1 楼 ant2012 的回复:你加两个参数（定义为指针或引用）用来返回数组的宽度和维数不就行了 我是从java过来的，不怎么会写C，希望你能够帮帮忙翻译一下。


Question: array[0]+i 和 array[0]+1 怎么理解？

引用 1 楼 ant2012 的回复:大哥，你在逗我么？ i是变量，1是常量 当然会出现这个结果了  散了吧…… a[0]  == 0, a[1]  == 1…… 原数组值特殊。一直误以为遍历了数组输出的，其实都是i的值。

大哥，你在逗我么？ i是变量，1是常量 当然会出现这个结果了