行例:
1. class XXX : public YYY, ZZZ {  //正常表达,其中class可为struct,public可为protected,部分空格可有可无,或为TAB,或随意换行。2. class XXX{ //不从任何父类继承3. class XXX:public YYY //:前后或没空格,或只一个父类,或大括号在下一行
{4. class XXX             //换行且加了空格
        : public YYY现在
    $fctx = file_get_contents ($f); //读入整个文件到一行了,用preg_match_all的话可以吗?

    $lines = file ($f);
    foreach ($lines as $ln)
    {
        if (!preg_match ('/\bclass\b/', $ln, $matches)) //??????这一行想极不知怎么写
        {
        }
    }

解决方案 »

  1.   

    如果只是判断匹不匹配,后面的$matches可以不要了。直接if (!preg_match ('/\bclass\b/', $ln))
      

  2.   

    要匹配的,要取出XXX,再如果有,取出YYY和ZZZ
      

  3.   

    你可以贴出$fctx的结果。 
      

  4.   

    因为是读的live555的cpp文件,内容很长的。下面是中间一部分:#ifndef _FRAMED_FILTER_HH
    #include "FramedFilter.hh"
    #endifclass ADUFromMP3Source: public FramedFilter {
    public:
      static ADUFromMP3Source* createNew(UsageEnvironment& env,
         FramedSource* inputSource,
         Boolean includeADUdescriptors = True);
    分析是想取出ADUFromMP3Source和FramedFilter 
      

  5.   

    试试。写的不好,等大牛优化。$fctx= <<<HTML
    #ifndef _FRAMED_FILTER_HH
    #include "FramedFilter.hh"
    #endifclass ADUFromMP3Source: public FramedFilter {
    public:
      static ADUFromMP3Source* createNew(UsageEnvironment& env,
    FramedSource* inputSource,
    Boolean includeADUdescriptors = True);
    HTML;
    preg_match_all('/class\s*([^\s:\{]*):\s*(?:public|protected)?\s*([^\s:\{]*)\s*\{/isU',$fctx,$m);
    print_r($m);Array
    (
        [0] => Array
            (
                [0] => class ADUFromMP3Source: public FramedFilter {
            )    [1] => Array
            (
                [0] => ADUFromMP3Source
            )    [2] => Array
            (
                [0] => FramedFilter
            ))
      

  6.   

    基本上可以了,只是还有些缺失,例如不是任何类的子类,即没有public行就找不出来
    function walkfile(&$file)
    {
            global $classes;
            global $all_cnt;
            global $allkeys;
            $pval = null;        $fctx = file_get_contents ($file);
            if (!preg_match_all('/class\s*([^\s:\{]*):\s*(?:public|protected)?\s*([^\s:\{]*)\s*\{/isU',$fctx,$m))
                    return;
            for ($i=0; $i<count($m[0]); $i++)
            {
                    $key = trim ($m[2][$i]); //parent class
                    $val = trim ($m[1][$i]); //subclass                //process parent class
                    if (isset ($allkeys[$key])) //found parent
                    {
                            if (!is_array ($allkeys[$key]))
                                    $allkeys[$key] = array ();
                            if (!isset($allkeys[$key][$val]))
                                $allkeys[$key][$val] = '';
                            $pval = &$allkeys[$key][$val];
                    }
                    else //not found parent
                    {
                            $classes[$key] = array ($val=>'');
                            $allkeys[$key] = &$classes[$key];
                            $pval = &$classes[$key][$val];
                    }
                    //process sub class
                    if (isset ($allkeys[$val])) //found subclass
                    {
                            if (is_array ($allkeys[$val])) //merge parent to this subclass array
                            {
                                    if (!is_array ($pval))
                                            $pval = array ();
                                    $pval = array_merge ($pval, $allkeys[$val]);
                            }
                            $allkeys[$val] = null;//set the old array to null
                            $allkeys[$val] = &$pval;//new refrence
                    }
                    else //not found subclass
                    {
                            $allkeys[$val] = &$pval;
                    }                printf ("class $val : public $key\r\n");
                    $all_cnt++;
            }
    }哪位帮忙优化一下呀,我写完程序也贴出来
      

  7.   

    还不完善。现在处理live555的目录只读出163个类,还差一些没子类的类没打出来。程序如下:#!/usr/bin/php
    <?php
    $all_cnt = 0;
    $classes = array ();// array('aa'=>null, 'bb'=>array('cc'=>'')) : null: has deleted. '': valid
    $allkeys = array ();//class=>addr eg. 'cc'=>&$classes['bb']['cc']function outtree (&$parent, $tab)
    {
            ksort ($parent);
            foreach ($parent as $left => &$right)
            {
                    if (is_null ($right)) continue;
                    printf ("$tab$left\r\n");
                    is_array ($right) && outtree ($right, $tab."\t");
            }
    }function walkfile(&$file)
    {
            global $classes;
            global $all_cnt;
            global $allkeys;
            $pval = null;        $fctx = file_get_contents ($file);
            if (!preg_match_all('/class\s*([^\s:\{]*):\s*(?:public|protected)?\s*([^\s:\{]*)\s*\{/isU',$fctx,$m))
                    return;
            for ($i=0; $i<count($m[0]); $i++)
            {
                    $key = trim ($m[2][$i]); //parent class
                    $val = trim ($m[1][$i]); //subclass                //process parent class
                    if (isset ($allkeys[$key])) //found parent
                    {
                            (!is_array ($allkeys[$key])) && ($allkeys[$key] = array ());
                            (!isset($allkeys[$key][$val])) && ($allkeys[$key][$val] = '');
                            $pval = &$allkeys[$key][$val];
                    }
                    else //not found parent
                    {
                            $classes[$key] = array ($val=>'');
                            $allkeys[$key] = &$classes[$key];
                            $pval = &$classes[$key][$val];
                    }
                    //process sub class
                    if (isset ($allkeys[$val])) //found subclass
                    {
                            if (is_array ($allkeys[$val])) //merge parent to this subclass array
                            {
                                    (!is_array ($pval)) && ($pval = array ());
                                    $pval = array_merge ($pval, $allkeys[$val]);
                            }
                            $allkeys[$val] = null;//set the old array to null
                            $allkeys[$val] = &$pval;//new refrence
                    }
                    else //not found subclass
                    {
                            $allkeys[$val] = &$pval;
                    }
                    //printf ("class $val : public $key\r\n");
                    $all_cnt++;
            }
    }function walkdir(&$dir)
    {
            if (!($h = opendir ($dir))) return;
            while (false !== ($f = readdir ($h)))
            {
                    if ($f=="." || $f=="..") continue;
                    $f = "$dir/$f";
                    is_dir ($f) && walkdir ($f);
                    !is_dir ($f) && preg_match ('/\.(h|hh|hpp|cpp|cxx)$/', $f) && walkfile ($f);
            }
            closedir ($h);
    }//function main ($argc, $argv)
    $argc != 2 && die ("need 2 args\n");
    walkdir ($argv[1]);
    outtree ($classes, "");
    printf ("allcnt=$all_cnt.\r\n");
    ?>
    奇怪,明明还提示可输入有XXX个字符,但又提示回复内容过长。
      

  8.   


    运行 ./class_tree.php /root/live的输出结果:BufferedPacket
            ADUBufferedPacket
            AMRBufferedPacket
            H264BufferedPacket
            JPEGBufferedPacket
            LATMBufferedPacket
            MPEG4GenericBufferedPacket
            QCELPBufferedPacket
            QTGenericBufferedPacket
    BufferedPacketFactory
            ADUBufferedPacketFactory
            AMRBufferedPacketFactory
            H264BufferedPacketFactory
            JPEGBufferedPacketFactory
            LATMBufferedPacketFactory
            MPEG4GenericBufferedPacketFactory
            QCELPBufferedPacketFactory
            QTGenericBufferedPacketFactory
    DelayQueueEntry
            AlarmHandler
            DelayQueue
    HashTable
            BasicHashTable
    Medium
            AVIFileSink
            DarwinInjector
            MPEG1or2Demux
            MPEG1or2FileServerDemux
            MPEG2TransportStreamIndexFile
            MediaSession
            MediaSink
                    BasicUDPSink
                    DummySink
                    FileSink
                            AMRAudioFileSink
                            H264VideoFileSink
                    RTPSink
                            MultiFramedRTPSink
                                    AudioRTPSink
                                            AC3AudioRTPSink
                                            AMRAudioRTPSink
                                            GSMAudioRTPSink
                                            MP3ADURTPSink
                                            MPEG1or2AudioRTPSink
                                            MPEG4LATMAudioRTPSink
                                    MPEG4GenericRTPSink
                                    SimpleRTPSink
                                    VideoRTPSink
                                            DVVideoRTPSink
                                            H263plusVideoRTPSink
                                            H264VideoRTPSink
                                            JPEGVideoRTPSink
                                            MPEG1or2VideoRTPSink
                                            MPEG4ESVideoRTPSink
                    TCPStreamSink
            MediaSource
                    FramedSource
                            AMRAudioSource
                                    AMRAudioFileSource
                                    AMRDeinterleaver
                            AudioInputDevice
                                    WAVAudioFileSource
                                    WindowsAudioInputDevice_common
                            BasicUDPSource
                            ByteStreamMemoryBufferSource
                            ByteStreamMultiFileSource
                            DeviceSource
                            FramedFileSource
                                    ADTSAudioFileSource
                                    ByteStreamFileSource
                                    MP3FileSource
                                            MP3HTTPSource
                            FramedFilter
                                    AC3AudioStreamFramer
                                    ADUFromMP3Source
                                    DVVideoStreamFramer
                                    EndianSwap16
                                    H263plusVideoStreamFramer
                                    H264FUAFragmenter
                                    HostFromNetworkOrder16
                                    MP3ADUTranscoder
                                    MP3ADUinterleaverBase
                                            MP3ADUdeinterleaver
                                            MP3ADUinterleaver
                                    MP3FromADUSource
                                            MP3Transcoder
                                    MPEG1or2AudioStreamFramer
                                    MPEG2IFrameIndexFromTransportStream
                                    MPEG2TransportStreamFramer
                                    MPEG2TransportStreamTrickModeFilter
                                    MPEGVideoStreamFramer
                                            H264VideoStreamFramer
                                                    H264VideoStreamDiscreteFramer
                                            MPEG1or2VideoStreamFramer
                                                    MPEG1or2VideoStreamDiscreteFramer
                                            MPEG4VideoStreamFramer
                                                    MPEG4VideoStreamDiscreteFramer
                                    NetworkFromHostOrder16
                                    PCMFromuLawAudioSource
                                    QCELPDeinterleaver
                                    uLawFromPCMAudioSource
                            JPEGVideoSource
                            MPEG1or2DemuxedElementaryStream
                            MPEG2TransportStreamMultiplexor
                                    MPEG2TransportStreamFromESSource
                                    MPEG2TransportStreamFromPESSource
                            RTPSource
                                    MultiFramedRTPSource
                                            AC3AudioRTPSource
                                            DVVideoRTPSource
                                            H261VideoRTPSource
                                            H263plusVideoRTPSource
                                            H264VideoRTPSource
                                            JPEGVideoRTPSource
                                            MP3ADURTPSource
                                            MPEG1or2AudioRTPSource
                                            MPEG1or2VideoRTPSource
                                            MPEG4ESVideoRTPSource
                                            MPEG4GenericRTPSource
                                            MPEG4LATMAudioRTPSource
                                            QuickTimeGenericRTPSource
                                            RawAMRRTPSource
                                            RawQCELPRTPSource
                                            SimpleRTPSource
            QuickTimeFileSink
            RTCPInstance
            RTSPClient
                    RTSPClientForDarwinInjector
            RTSPServer
                    RTSPServerSupportingHTTPStreaming
                            DynamicRTSPServer
            SIPClient
            ServerMediaSession
            ServerMediaSubsession
                    OnDemandServerMediaSubsession
                            FileServerMediaSubsession
                                    AC3AudioFileServerMediaSubsession
                                    ADTSAudioFileServerMediaSubsession
                                    AMRAudioFileServerMediaSubsession
                                    DVVideoFileServerMediaSubsession
                                    H263plusVideoFileServerMediaSubsession
                                    H264VideoFileServerMediaSubsession
                                    MP3AudioFileServerMediaSubsession
                                    MPEG1or2VideoFileServerMediaSubsession
                                    MPEG2TransportFileServerMediaSubsession
                                    MPEG4VideoFileServerMediaSubsession

    allcnt=163.
      

  9.   

    误会了吧,不需要完成很复杂的语法分析,只需要打个类派生树。
    只是最近常接触N万行的C++新工程,有感于C++软件都是过度设计的,不打个树出来我就要手工统计。所以才写这么个东西。
      

  10.   

    哪位懂正则的帮个忙想想啊,我这还有好几个CPP工程需要分析,都是几百个类的,实在不适合做手工统计。
    现在的情况是
    1.有派生的均有输出
    2.支持中间插任意空
    3.不支持多派生
    4.不支持没派生希望能支持没派生
      

  11.   

    令人恐惧的cpp..
    btw,你是说
    2. class XXX{ //不从任何父类继承
    这样的类没匹配到?
      

  12.   

    CPP就是易陷入过度设计,这live555还算是好的了。你看ACE的实现那才真是乱七八糟,更可怕的是很多人学好几年就以弄得复杂为水平体现。我是觉得C+PHP比CPP好太多了。
      

  13.   

    为了尽量不影响你原来的代码,你试下以下这个'/class\s*([^\s:\{]*)\s*(?:(?::\s*public|:\s*protected)([^\s:\{]*))?\s*\{/isU'
    $fctx= <<<HTML
    #ifndef _FRAMED_FILTER_HH
    #include "FramedFilter.hh"
    #endifclass ADUFromMP3Source:public aa,bb,cc{
    public:
      static ADUFromMP3Source* createNew(UsageEnvironment& env,
    FramedSource* inputSource,     
    Boolean includeADUdescriptors = True);class ADUFromMP3Source:protected xxx{
    public:
      static ADUFromMP3Source* createNew(UsageEnvironment& env,
    FramedSource* inputSource,
    Boolean includeADUdescriptors = True);class ADUFromMP3Source{
    public:
      static ADUFromMP3Source* createNew(UsageEnvironment& env,
    FramedSource* inputSource,
    Boolean includeADUdescriptors = True);HTML;
    preg_match_all('/class\s*([^\s:\{]*)\s*(?:(?::\s*public|:\s*protected)([^:\{]*))?\s*\{/isU',$fctx,$m);
    print_r($m);
      

  14.   

    上面贴错了,是这个'/class\s*([^\s:\{]*)\s*(?:(?::\s*public|:\s*protected)([^:\{]*))?\s*\{/isU'
      

  15.   

    少了\s好像不行,会匹配到其它地方去了。
    现在 用了你改的:'/class\s*([^\s:\{]*)\s*(?:(?::\s*public|:\s*protected)?\s*([^\s:\{]*))?\s*\{/sU'
    #!/usr/bin/php
    <?php
    $all_cnt = 0;
    $classes = array ();// array('aa'=>null, 'bb'=>array('cc'=>'')) : null: has deleted. '': valid
    $allkeys = array ();//class=>addr eg. 'cc'=>&$classes['bb']['cc']function outtree (&$parent, $tab)
    {
            ksort ($parent);
            foreach ($parent as $left => &$right)
            {
                    if (is_null ($right)) continue;
                    printf ("$tab$left\r\n");
                    is_array ($right) && outtree ($right, $tab."\t");
            }
    }function walkfile(&$file)
    {
            global $classes;
            global $all_cnt;
            global $allkeys;
            $pval = null;        $fctx = file_get_contents ($file);
            if (!preg_match_all('/class\s*([^\s:\{]*)\s*(?:(?::\s*public|:\s*protected)?\s*([^\s:\{]*))?\s*\{/sU',$fctx,$m))
                    return;
            //print_r ($m);// exit (0);
            for ($i=0; $i<count($m[0]); $i++)
            {
                    $key = trim ($m[2][$i]); //parent class
                    $val = trim ($m[1][$i]); //subclass
                    ($val=='') && ($val=$key) && ($key='ROOT'); //exchang key<==>value                //process parent class
                    if (isset ($allkeys[$key])) //found parent
                    {
                            (!is_array ($allkeys[$key])) && ($allkeys[$key] = array ());
                            (!isset($allkeys[$key][$val])) && ($allkeys[$key][$val] = '');
                            $pval = &$allkeys[$key][$val];
                    }
                    else //not found parent
                    {
                            $classes[$key] = array ($val=>'');
                            $allkeys[$key] = &$classes[$key];
                            $pval = &$classes[$key][$val];
                    }
                    //process sub class
                    if (isset ($allkeys[$val])) //found subclass
                    {
                            if (is_array ($allkeys[$val])) //merge parent to this subclass array
                            {
                                    (!is_array ($pval)) && ($pval = array ());
                                    $pval = array_merge ($pval, $allkeys[$val]);
                            }
                            $allkeys[$val] = null;//set the old array to null
                            $allkeys[$val] = &$pval;//new refrence
                    }
                    else //not found subclass
                    {
                            $allkeys[$val] = &$pval;
                    }
                    //printf ("class $val : public $key\r\n");
                    $all_cnt++;
            }
    }function walkdir(&$dir)
    {
            if (!($h = opendir ($dir))) return;
            while (false !== ($f = readdir ($h)))
            {
                    if ($f=="." || $f=="..") continue;
                    $f = "$dir/$f";
                    is_dir ($f) && walkdir ($f);
                    !is_dir ($f) && preg_match ('/\.(h|hh|hpp|cpp|cxx)$/', $f) && walkfile ($f);
            }
            closedir ($h);
    }//function main ($argc, $argv)
    $argc != 2 && die ("need 2 args\n");
    walkdir ($argv[1]);
    outtree ($classes, "");
    printf ("allcnt=$all_cnt.\r\n");
    ?>运行结果是264个类,检查过了是对的。哈,OK了,谢谢!
      

  16.   

    outtree一行应为outtree ($classes['ROOT'], "");以避免过多缩进