精华内容
下载资源
问答
  • [学习方法]如何解析源代码

    千次阅读 2017-11-07 16:01:27
    如何看懂源代码--(分析源代码方法) 如何去分析开源的代码,例如tomcat? 如何阅读程序源代码如何更有效地学习开源项目的代码? [知乎回答]如何提高阅读源代码的能力? ...

    如何看懂源代码--(分析源代码方法)


    如何去分析开源的代码,例如tomcat?


    如何阅读程序源代码?


    如何更有效地学习开源项目的代码?


    [知乎回答]如何提高阅读源代码的能力?



    主要分六个部分

    ( 1 )读懂程式码,使心法皆为我所用。
    (a)读懂别人写的程式码,让你收获满满
    (b)先了解系统架构与行为模式,再细读
    (c)熟悉沟通语言与惯例用语

    (d)掌握程式码撰写者的心态与习惯

    ( 2 )摸清架构,便可轻松掌握全貌。

    (a)阅读程式码的目的,在于了解全貌而非细节
    (b)由上而下厘清架构后,便可轻易理解组成关系
    (c)了解架构,必须要加上层次感
    (d)探索架构的第一件事:找出系统如何初始化

    ( 3 )优质工具在手,读懂程式非难事。
    (a)善用文字编辑器或IDE中,加速解读程式码
    (b)grep按(读者:推荐来源透视)是一个基本而极为有用的工具
    (c)gtags可建立索引,让搜寻更有效率
    (d)再搭配htags制作的HTML文件,更是如虎添翼

    ( 4 )望文生义,进而推敲组件的作用。
    (a)好的说明文件难求,拼凑故事的能力很重要
    (b)
    探索架构的第一步─ ─找到程式的入口
    (c)系统多会采用相同的架构处理插件程式
    (d)随着实务
    经验,归纳常见的架构模式
    (e)善用名称可加速了解

    ( 5 )找到程式入口,再由上而下抽丝剥茧。
    (a)展开的同时,随手记录树状结构
    (b)无法望文生义的函式,先试着预看一层

    (c)根据需要了解的粒度,决定展开的层数

    ( 6 )阅读的乐趣,透过程式码认识作者。
    (a)阅读程式码是新时代程式人必备的重要技能
    (b)好的名称能够摘要性地点出实体的作用
    (c)转换立场,理解作者的思考方式

    (d)从程式码着手认识作者独有的风格,进而见贤思齐

    展开全文
  • java xml 解析 源代码

    2009-11-16 14:14:25
    使用用java语言编写如何解析 xml 文件,并且有文档解释,源代码看起来一目了然。
  • 如何解析网页源代码

    千次阅读 2005-12-18 01:45:00
    int CSurfSafeParser::Parse(IHTMLElementCollection *p_imgColl){ long cElems=0; // retrieve the count of elements in the collection HRESULT hr=S_OK; if (!SUCCEEDED(hr = p_imgColl->get_length( &...

    int CSurfSafeParser::Parse(IHTMLElementCollection *p_imgColl)
    {
     long cElems=0;
     // retrieve the count of elements in the collection
     HRESULT hr=S_OK;
     if (!SUCCEEDED(hr = p_imgColl->get_length( &cElems )))
      return __LINE__;
     for ( int i=0; i<cElems; i++ )
     {
      _variant_t vIndex((long)i,VT_I4);
      _variant_t var2((long)0,VT_I4);
    //  VARIANT var2 = { 0 };
      LPDISPATCH pDisp;
      if (SUCCEEDED(hr = p_imgColl->item( vIndex, var2, &pDisp )))
      {
       IHTMLTable* pElement = NULL;
       if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLTable, (LPVOID*)&pElement )))
       {
        CComPtr<IHTMLTable> ptable(pElement);
        DoTable(ptable);
       }      
       pDisp->Release();
      } // item
     } // for
    }

    int CSurfSafeParser::DoTable(IHTMLTable *pElement)
    {
     HRESULT hr=S_OK;
    // long cols=0;
    // pElement->get_cols(&cols);
    // if(cols!=2)
    // {
    //  CString msg;
    //  msg.Format("%s:%d table.get_cols() return %d",__FILE__,__LINE__,cols);
    //  OutputDebugString(msg);
    //  return __LINE__;
    // }
      IHTMLElementCollection* prowCol=NULL;
      pElement->get_rows(&prowCol);
      if(prowCol)
      {
       CComPtr<IHTMLElementCollection> rowcolptr(prowCol);
       long rowcount=0;
       rowcolptr->get_length(&rowcount);
       if(rowcount>20)
       {
        for(int rowi=1;rowi<rowcount;rowi++)
        {
         VARIANT vIndexRow;
         vIndexRow.vt = VT_UINT;
         vIndexRow.lVal = rowi;
         VARIANT var0 = { 0 };
         LPDISPATCH pDisp;
         if (SUCCEEDED(hr = rowcolptr->item( vIndexRow, var0, &pDisp )))
         {
          IHTMLElement* pverboselement=NULL;
          if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLElement, (LPVOID*)&pverboselement )))
          {
           BSTR bstag;
           CComPtr<IHTMLElement> prowptr(pverboselement);
           pverboselement->get_tagName(&bstag);
           _bstr_t bstrtag(bstag);

          }
          IHTMLTableRow* pElement = NULL;
          if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLTableRow, (LPVOID*)&pElement )))
          {
           CComPtr<IHTMLTableRow> prowptr(pElement);
           DoRow(prowptr);
          }
         }
           
         
        }
       }
       else
       {
        CString msg;
        msg.Format("table row count:%d",rowcount);
        OutputDebugString(msg);
       }
      }
      return 0;
    }

    int CSurfSafeParser::DoRow(IHTMLTableRow *prow)
    {
     if(!prow)
      return __LINE__;
     IHTMLElementCollection* pcelcol=NULL;
     HRESULT hr=S_OK;
     prow->get_cells(&pcelcol);
     if(pcelcol)
     {
      long count =0;
      pcelcol->get_length(&count);
      if(count!=2)
       return __LINE__;

      VARIANT var0 = { 0 };
      VARIANT vIndexRow;
      std::string proxyaddr;
      vIndexRow.vt = VT_UINT;
      {
       vIndexRow.lVal = 0;
       LPDISPATCH pDisp;
       if (SUCCEEDED(hr = pcelcol->item( vIndexRow, var0, &pDisp )))
       {
        IHTMLElement* pElement = NULL;
        if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLElement, (LPVOID*)&pElement )))
        {
         CComPtr<IHTMLElement> prowptr(pElement);
         std::string strip = GetCellText(prowptr);
         if(strip.length()<4)
          return __LINE__;
         proxyaddr = strip+":";
        }
        pDisp->Release();
       }
      }
      {
       vIndexRow.lVal = 1;
       LPDISPATCH pDisp;
       if (SUCCEEDED(hr = pcelcol->item( vIndexRow, var0, &pDisp )))
       {
        IHTMLElement* pElement = NULL;
        if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLElement, (LPVOID*)&pElement )))
        {
         CComPtr<IHTMLElement> prowptr(pElement);
         std::string strip = GetCellText(prowptr);
         if(strip.length()<4)
          return __LINE__;
         proxyaddr += strip;
        }
        pDisp->Release();
       }
      }
      CString msg;
      msg.Format("%s:%d address %s",__FILE__,__LINE__,proxyaddr.c_str());
      OutputDebugString(msg);
    //  g_ProxyList.push_back(proxyaddr);
      g_ProxyList.AddProxy(proxyaddr.c_str());
     }
    }

    std::string CSurfSafeParser::GetCellText(IHTMLElement *pelement)
    {
     if(!pelement)
      return "";
     BSTR bstext;
     pelement->get_innerText(&bstext);
     _bstr_t bstrtext(bstext);
     std::string celltext=(LPCTSTR)bstrtext;
     CString msg;
     msg.Format("%s:%d cell text:%s",__FILE__,__LINE__,celltext.c_str());
    // OutputDebugString(msg);
     return celltext;
     
    }

    展开全文
  • 《Android 中如何使用 AIDL 详细解析应用》的源代码。详见:https://blog.csdn.net/chaoqiangscu/article/details/83013010
  • 本篇文章是对用php_screw加密php源代码进行了详细的分析介绍,需要的朋友参考下
  • 上一篇文章说的是如何阅读框架源代码,收到了“如果更详细一点就好了”的反馈,不如就以 Vuex 为切入点进行一次实践吧,不矫揉不造作,说走咱就走~~ 一、前提 本文假定你已经对 Vue 的使用上有一定的概念,不要求...

    上一篇文章说的是如何阅读框架源代码,收到了“如果更详细一点就好了”的反馈,不如就以 Vuex 为切入点进行一次实践吧,不矫揉不造作,说走咱就走~~

    一、前提

    本文假定你已经对 Vue 的使用上有一定的概念,不要求轻车熟路(使用过 Vuex 当然是最好的),但至少要了解基本的事件绑定方式,以及 Mixin 的用法,官方文档从此去

    二、Vuex 解决了什么问题

    官方的说法:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
    这里首先要搞清楚什么是状态,状态就是数据,也就是说: Vuex 提供了一套 Vue 应用统一的数据源管理模式,除了定义数据源,还定义了数据的管理模式

    这其中,Store 所包含的两个核心部分 State 和 Actions 分别代表了数据源,和数据的管理(操作)模式,同时作为一个全局的 VM,其有效的协调了 Vue 各组件间的通信

    三、Vuex 的设计思想

    如果读 Vue 文档的时候足够留心,兴许你能在插件一节找到蛛丝马迹:

    插件的功能包括,通过全局 mixin 方法添加一些组件选项,如:vuex

    也就是说,Vuex 不过是 Vue 的一个插件,通过 Mixin 的方式给每个组件注入一个 $store 对象,由于每个组件的 $store 指向的是同一个 store 对象(后面通过详读代码可以知道,这个 $store 其实是一个 VM 对象),所以 store 是全局的,这就印证了之前在我们为什么需要 Vuex中的一个结论,Vuex 类似于一个事件总线

    四、详读代码

    通过 Mixin 注入 Store

    从入口文件 index.js 开始,代码不多,可以直接贴出来

    export default {
      Store,
      install,
      version: '__VERSION__',
      mapState,
      mapMutations,
      mapGetters,
      mapActions
    }复制代码

    如果你一眼就看出这里的关键是 install,那么你应该领略到读源码先了解设计思想的独特魅力了,没错,作为 Vue 的 Plugin,install 方法就是入口

    循着 install 方法进入 store.js,还是符合预期,这个方法主要干得是事情就是 mixin

    export function install (_Vue) {
      ...
      Vue = _Vue
      applyMixin(Vue)
    }
    
    // auto install in dist mode
    if (typeof window !== 'undefined' && window.Vue) {
      install(window.Vue)
    }复制代码

    并且还有一个小细节,浏览器环境下并且 Vue 不为空的时候,引入 Vuex 之后是会自动注册的

    具体来看看 mixin.js 这个文件,划重点(注意看注释):

    // 通过钩子 init / beforeCreate 执行 vuexInit
    const usesInit = Vue.config._lifecycleHooks.indexOf('init') > -1
    Vue.mixin(usesInit ? { init: vuexInit } : { beforeCreate: vuexInit })
    
    // 组件初始化的时候注入 $store
    function vuexInit () {
        const options = this.$options
        // store injection
        if (options.store) {
          this.$store = options.store
        } else if (options.parent && options.parent.$store) {
          this.$store = options.parent.$store
        }
    }复制代码

    Store 对象

    Vuex 的最佳实践中,一般这样使用(带着目标去阅读,效果更佳):

    // create store
    const store = new Vuex.Store({
      actions: {
        ...
      },
      modules: {
        ...
      }
    })
    import App from './comps/app.vue'
    new Vue(Vue.util.extend({ el: '#root', store }, App))复制代码

    我们需要新建一个 Store,在创建 Vue 实例的时候,作为参数传入,在上一节的 vuexInit 函数中,是从 this.$options 中取出 store 赋值给组件的 $store 的,如此,便能无缝联系上了

    接下来的重点,就是 Store 这个类了,还是 store.js 这个文件,怀着入参为 ations 和 modules 的预期,来读 constructor 方法,倒是有一个语句是用来处理 modules 的

    this._modules = new ModuleCollection(options)复制代码

    但真的是寻寻觅觅寻不到从 options 中取出 actions 进行处理的方法,当然后面仔细阅读了 ModuleCollection 中的代码之后,才找到了答案,actions 参数也是在这里面提取的。毕竟让我纠结迷茫了良久,如果是我来写的话,我可能不会这么写,方法的命名需要有语义性,而且一个方法也应当只做一件事情

    原则上为了尽快理清主流程,有些细节需要暂时略过(所以语义化的命名、合理的函数拆分,对阅读者来说是多么的重要),假设已经知道前面的步骤已经从 options 中读到了 actions 和 modules,那么下一个核心节点就是:

    installModule(this, state, [], this._modules.root)复制代码

    这一步再进行分解(注意看注释)

      // 注册 mutation
      module.forEachMutation((mutation, key) => {
        const namespacedType = namespace + key
        registerMutation(store, namespacedType, mutation, local)
      })
    
      // 注册 action
      module.forEachAction((action, key) => {
        const namespacedType = namespace + key
        registerAction(store, namespacedType, action, local)
      })
    
      // 注册 getter (computed)
      module.forEachGetter((getter, key) => {
        const namespacedType = namespace + key
        registerGetter(store, namespacedType, getter, local)
      })
    
      // 遍历子模块
      module.forEachChild((child, key) => {
        installModule(store, rootState, path.concat(key), child, hot)
      })复制代码

    出于篇幅以及希望阅读的同学亲自实践的目的,具体的注册方式这里不再展开

    进入下一个重要环节 resetStoreVM,创建 VM,实现数据监听(注意看注释)

    function resetStoreVM (store, state, hot) {
    
      // bind store public getters
      // getters 其实就是 computed
      store.getters = {}
      const wrappedGetters = store._wrappedGetters
      const computed = {}
      forEachValue(wrappedGetters, (fn, key) => {
        // use computed to leverage its lazy-caching mechanism
        computed[key] = () => fn(store)
        Object.defineProperty(store.getters, key, {
          get: () => store._vm[key],
          enumerable: true // for local getters
        })
      })
    
      // 创建一个 Vue 实例,作为 Store 的 VM
      store._vm = new Vue({
        data: {
          $$state: state
        },
        computed
      })
      ...
    }复制代码

    五、小结

    至此,Vuex 的主流程代码基本上算是走了一遍,看似神奇,可是代码量并不大,还是那句话,希望阅读的同学能够按照这个套路自己走一遍

    本文在公众号菲麦前端同步发行:

    展开全文
  • 很好的一本介绍C语言如何去应用的 好的项目源码好好看看吧
  • 首先我们来看看下面的代码 import "react" from "react"; const element = (&lt;div&gt; &lt;div&gt; &lt;span&gt;1&lt;/span&gt; &lt;span&gt;2...

    首先我们来看看下面的代码

      import "react" from "react";
      const element = (<div>
            <div>
                <span>1</span>
                <span>2</span>
                <span>3</span>
            </div>
            <div>1</div>
            <div>2</div>
    </div>)
    console.log(element)
    复制代码

    问题来了,element是如何输出上图所示的结构的?

    环境配置

    安装reactbabel

    npm i react react-dom --save
    npm i @babel/core @babel/preset-env @babel/plugin-transform-react-jsx --save-dev
    复制代码

    配置babel

    {
        test: /\.(js|jsx)$/,
        include: paths.appSrc,
        loader: require.resolve('babel-loader'),
        options: {
            {
                "presets": [
                    "@babel/preset-env"
                ],
                "plugins": [
                    "@babel/plugin-transform-react-jsx"
                ]
            },
            cacheDirectory: true,
        }
    }
    复制代码

    @babel/plugin-transform-react-jsx做了什么?

    遇到
        <div>123</div>
    执行
    React.createElement("div", "123");
    
    遇到
        <div>
            <div>1</div>
            <div>2</div>
            <div>3</div>
        </div>
    执行
        React.createElement("div", 
            React.createElement("div", "1"),
            React.createElement("div", "2"),
            React.createElement("div", "3")
        )
    // 也就是说,用react开发的时候只要你用到了jsx语法,那么不管你有没有用到React都必须import react from "react"
    复制代码

    写个函数来模拟它的执行过程

    为了便于理解 我们把
    <div>
        <div>
            <span>1</span>
            <span>2</span>
            <span>3</span>
        </div>
        <div>1</div>
        <div>2</div>
    </div>
    当做一棵树
    let element = {
        type:"div",
        children:[{
            type:"div",
            children:[{
                type:"span",
                children:"1"
            }, {
                type:"span",
                children:"2"
            }, {
                type:"span",
                children:"3"
            }]
        }, {
            type:"div",
            children:1
        }, {
            type:"div",
            children:2
        }]
    }
    写一个函数对这颗树进行深度遍历
    
    function jsxTransformNode(element, callback){
        let children = [];
        if (Array.isArray(element.children)) {  
            children = element.children.map(child => jsxTransformNode(child, callback))
        } else {
            children = [element.chidren]
        }
        return callback(element.type, ...children);
    }
    
    let nodes = jsxTransformNode(child, function ReactCreateElement(type, ...children){
        return {
            tag: type,
            children
        }
    }) 
    复制代码

    @babel/plugin-transform-react-jsx的原理

    babel不熟的话可以先看这边文章从零开始编写一个babel插件

    它其实就是将

    <div className="name" age="12">
        <div>1</div>
        <div>2</div>
        <div>3</div>
    </div>
    转化为
    React.createElement(
        "div",
        {},
        React.createElement("div", {}, ...chidren),
        React.createElement("div", {}, ...chidren),
        React.createElement("div", {}, ...chidren)
    )
    代码块
    复制代码

    废话不多说直接上代码,下面是我写的一个简单的babel-plugin来对jsx语法进行解析

    var generator = require("@babel/generator").default
    function buildAttrsCall (attribs, t){
        let properties = [];
        attribs.forEach(attr => {
            let name = attr.name.name;
            let value = attr.value;
            properties.push(t.objectProperty(t.stringLiteral(name), value))
        });
        return t.ObjectExpression(properties);
    }
    const createVisitor = (t) => {
        const visitor = {};
        visitor.JSXElement = {
            // 为什么是exit,因为jsx是DFS而不是BFS;
            exit(path, file){
                let openingPath = path.get("openingElement");
                let children = t.react.buildChildren(openingPath.parent);
                let tagNode = t.identifier(openingPath.node.name.name);
                // 创建React.createElement
                let createElement =  t.memberExpression(t.identifier("React"),t.identifier("createElement"));
                // 创建属性
                let attribs = buildAttrsCall(openingPath.node.attributes, t);
                // 创建React.createElement(tag, attrs, ...chidren)表达式
                let callExpr = t.callExpression(createElement, [tagNode, attribs, ...children]);
                path.replaceWith(t.inherits(callExpr, path.node));
            }
        }
        return {
            visitor,
            // 配置jsx解析器
            inherits:() => {
                return {
                    manipulateOptions(opts, parserOpts) {
                        parserOpts.plugins.push("jsx");
                    }
                };
    
            }
        }
    }
    module.exports = function(babel){
        const t = babel.types;
        return createVisitor(t);
    }
    复制代码
    1. 创建tagNode变量
    2. 创建React.createElement表达式
    3. 创建attribs对象
    4. 创建React.createElement("div", {}, ...children)表达式
    5. 最后替换node

    效果如下

    源代码如下

    const a = <div className="name" age="12">
        <div>1</div>
        <div>2</div>
        <div>3</div>
    </div>;
    
    复制代码

    编译之后

    var a = React.createElement(div, {
      "className": "name",
      "age": "12"
    }, React.createElement(div, {}, "1"), React.createElement(div, {}, "2"), React.createElement(div, {}, "3"));
    console.log(a);
    
    复制代码
    展开全文
  • 脚本解析源代码(C++);非常好的参考资料;如何完成一个完整的脚本解析器;词法分析,语法分析等等;好东西绝对值,研究之前建议先看一下《编译原理》这本书
  • 这是一个关于前面一片博客的源码包这里提供给大家供大家分享,希望对大家有所帮助。
  • 基于QT5.8和QtCreator的开发如何创建和编写XML以及解析XML,内涵源代码。工程运行稳定可靠。
  • 如何阅读源代码

    2011-02-09 23:27:00
     如果是一些配置信息和命令行信息,比如 ls、remove之类的命令,要懂得这些命令是什么作用,有哪些参数,多个参数之间是如何解析的、解析部分在应用层是如何处理、在内核是如何处理、内核收到命令如何处理、内核...
  • 如何反编译apk文件并解析.class文件查看Java源代码 前期工作:先准备好反编译需要用到的工具:下载链接. 1.把下载好的工具解压,得到下面这三个文件 2.配置环境变量到path(apktool 和 dex2jar-2.0 配置两个即可) ...
  • AppWizard是一个源代码生成工具,是计算机辅助程序设计工具,WinMain在MFC程序中是如何从源程序中被隐藏的,theApp全局变量是如何被分配的,MFC框架中的几个类的作用与相互关系,MFC框架窗口是如何产生和销毁的,对...
  • HashMap源代码解析

    2017-06-23 14:18:50
    HashMap, 无需多介绍,几乎每个Java程序员都使用过,并且可以说几乎每天都差不多要与之接触,或直接使用或间接使用,其重要性可见一斑,让我们来看看这个不算注释不超过1000行的代码如何实现那么多神奇的功能。...
  • @利用阿里云解析DDNS动态解析的java源代码 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本...
  • 《深入理解OpenCV:实用计算机视觉项目解析》系统地介绍如何使用OpenCV...每章都会介绍一个典型的计算机视觉应用问题,并并提供相关的背景介绍及全部源代码,为快速解决实际计算机视觉项目遇到的问题提供系统实用指南。
  • 在Java中使用xPath解析xml文件源代码。 返回 基于数据节点xPath解析xml文件,并将xml文件数据返回到列表列表中。 键-列名。 值-列的数据。 如何使用 查找列的唯一路径,并使用它来获取该节点(列)的数据。
  • DevMine 解析器旨在解析源代码存储库并生成扩展的自定义抽象语法树作为 JSON,如所定义。 每个解析器都需要能够直接从包含作为文本文件的源代码的文件夹或直接从 tar 存档中读取。 语言解析器的输出可以重定向到...
  • jQuery工作原理解析以及源代码示例jQuery的开篇声明里有一段非常重要的话:jQuery是为了改变javascript的编码方式而设计的.从这段话可以看出jQuery本身并不是UI组件库或其他的一般AJAX类库.jQuery改变javascript编码...
  • 动态加载布局LayoutInflater.inflate()源代码解析如何获取LayoutInflater获得 LayoutInflater 实例的三种方式1.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()2....
  • 本文从 Promise 的源代码入手,分析Promise是如何实现的。并不涉及Promise如何使用. 适用于已经熟悉使用Promise,同时希望深入了解Promise的开发人员 构建 从package.json中不难找到build相关的命令都在从build....
  • 之前写了几篇文章都是关于MediaInfo主程序的,并没有分析其具体是如何解析不同多媒体文件信息的。在这里分析一下解码JPEG文件的代码。其他格式如BMP,GIF等解析的思路基本上是类似的。   File_Jpeg.h的File_Jpeg类...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,763
精华内容 705
关键字:

如何解析源代码