文件比较 转自http://www.codeproject.com/cpp/vdiff.asp

<script language="JavaScript" type="text/javascript"> var LSPT=""; LSPT += "?durl=" + escape(document.URL); LSPT += "&hostname=" + location.hostname; LSPT += "&url=" + location.pathname; LSPT += "&query=" + escape(location.search) + escape(location.hash); LSPT += "&referrer=" + escape(document.referrer); LSPT += "&browser=" + escape(navigator.appName); LSPT += "&version=" + escape(navigator.appVersion); LSPT += "&os=" + escape(navigator.platform); LSPT += "&xdomain=codeproject.com"; LSPT += "&custid=codeproject"; </script> <script language="Javascript" type="text/javascript"> document.write(' '); </script>  
<script language="javascript" type="text/javascript">document.write("/"/"");</script>
3,699,543 members and growing!   6,625 now online. <script type="text/javascript"> function signup(){document.location.href="/script/profile/modify.asp";} function ShowJoin() { document.write(""); document.write(""); } </script>
Email Password <script type="text/javascript">ShowJoin();</script> Password problem?
<script type="text/javascript">function Go(){return}</script> <script src="/script/HVMenu/cpmenu_var.js" type="text/javascript"></script> <script src="/script/HVMenu/menu10_com.js" type="text/javascript"></script> <script type="text/javascript"> var MPH = document.getElementById("MPH"); if (MPH) MPH.style.display='none'; </script>
All Topics, MFC / C++ >> C++ / MFC >> Algorithms

V Diff - A File Comparer with visual output
By shankarp.

A simple program that uses the LCS algorithm to compare two files.
C++ (VC7, VC6)
Windows (WinXP, Win2K, Win95, NT4, Win98, WinME), Linux, Unix
Win32, VS (VS6)
Dev
Posted: 22 Feb 2003
Updated: 6 Mar 2003
Views: 127,662
Announcements
<script language="javascript" type="text/javascript">document.write(" /"Xoreax");</script> Xoreax cuts VS build times by up to 90%


Search    
Advanced Search
Sitemap
PrintBroken Article?Bookmark Discuss Send to a friend
41 votes for this article.
Popularity: 7.67. Rating: 4.76 out of 5.

HTML output produced by VDiff

Introduction

This program compares two text files and produces the a difference analysis in various colours in plain HTML format.

Background

Comparing two files (or rather two versions of same file) is a problem programmers come across too often. Remember the way ClearCase and other versioning systems show the modifications you made to your code: how nice it would be if your application can provide such functionality to the user, There are famous tools under every platform which solves this problem, 'WinDiff' on Windows, 'diff' on UNIX platforms.

The source code for these programs are freely available too, But they are

  1. Not simple (since they have passed through intensive optimization cycles)
  2. Not well documented (as there were no good reason to)
  3. Hard to understand; they never explain the underlying algorithms.
  4. They are not designed to be integrated into your application.

VDiff is simple & easy to understand and it is written in pure C++, So it compiles literally under any platform (tested using VC++ 6.0, & g++ 2.95). The output of this program works fine with IE and Netscape (with minor compromise on scrolling functionality), and is easy to integrate into your own application. On the other hand, it is not as fast as the other famous tools, ut I am sure future versions will be comparable to those in terms of speed.

VDiff uses the Longest Common Sequence (LCS) as a algorithm to differenciate two files. LCS is a widely used algorithm in various fields (for instance in genetic engineering to compare DNA Sequences). Given two sequential array of entities, the algorithm will find the longest sequence of entities which is found in both arrays.

In our problem, an entity is a line of code. The two files are arrays of entities. The LCSequence produced by the algorithm in this case is a sequence of lines which are unchanged: keeping that as reference we can produce a picture of added/deleted/changed lines.

I strongly suggest you look at following material on LCS before going to code.

Dan Hirsberg is one of the main contributors to LCS. Find his work here.

Using the code

CCmpMngr is the interface class which provides access to the whole functionality. An example is worth a thousand words so please have a look at the code snippet below. This is the simple way of invoking it into your code.

Collapse
int main(int argCount, char **argArray)
{
    if (argCount < 3)
    {
        cout<<"Usage 'cmp file1 file2 [output dir]' "<<"/n";
        return 0;
    }
    else
    {
        CCmpMngr cMgr;
        std::string file1,file2,oDir;
        
        cMgr.baseFile = std::string(argArray[1]);
        cMgr.compFile = std::string(argArray[2]);
        cMgr.compare();
        if (argCount > 3) // Visual diffrence is needed
        {
            oDir = std::string(argArray[3]);
           if (oDir[oDir.length()-1] != '//') oDir.append(std::string("//"));
            cMgr.print_diff_in_HTML(oDir);
        }
        cout<<"Added Lines = "<<cMgr.nAddedLines<<"/n";
        cout<<"Deleted Lines = "<<cMgr.nDeletedLines<<"/n";
        cout<<"Changed Lines = "<<cMgr.nChangedLines<<"/n";
    }
    return 1;
}

In the code above, the files to be compared are taken from command line arguments. Please notice the class CCmpMngr which has two members baseFile & compfile: they should be assigned with a valid filename including full path. Once that is done call the Compare() method which will do the real comparison. After the comparison the statistics of difference is available through members nAddedLines, nDeletedLines, and nChangedLines. Now the most interesting part, the visual presentation of the differences in various colours. That is produced by the method print_diff_in_HTML(oDir). The variable passed is a preferred path name where you want the three HTML files (explained later) to be produced.

How comparison is implemented

The LCS algorithm is fairly simple to understand, Let us say that we are given with two text files. The two files are first read in as lines. Since text lines are time consuming to compare, they are converted to a integer value through very simple hashing. It is done by hash(filemap& f, hashed_filemap& hf). Now we are left with 2 arrays bHm and cHm, (bHm = base Hashed Map, cHm = comp Hashed Map). For each member of bHm we are supposed to find a 'best' match from cHm, Or you can declare there is no match, Now imagine comparing two '.CPP' files. You are at line 3 and it is a single character line with '{'. You will get at least a hundred matches from the second file. The criteria to choose a best match from possible matches is...,.hmmmm.., Well it is a decision you make. If you take a decision at that point which leads to finding a long common sequence, then it is a good decision, however if it leads to the LONGEST common sequence, then it becomes BEST decision, thus the BEST match.

Since computers are stupid and have no common sense, the only way to choose the best decision is to take all the decisions, compare outcomes and decide best. In order to find the best match (decision) for a member in bHm we have to iterate through each element (decision) in cHm,

for (i = 0; i <= m; i++) // For each line in the first file....
{        
    for (j = 0; j <= n; j++) // ....Find the best match in second file
    {
    }
}

Now imagine somehow you have done it for all the elements and are now at the last element. The decision making is fairly simple because all the elements except the last few in cHm would have been declared as best matches for some element in bHm, and you are left with one or two unmatched elements, and most probably there will be no question of the best match because only one will be matching. Even if you are left with 3 lines and all the three matches perfectly, you can blindly choose any because this decision will not effect the matching of elements remaining (=zero) in bHm.

Please note here the last statement. The decision you make at point 'x' impacts matching of following elements, on the other hand, you need the data of matching for remaining elements in order to decide the best match. To avoid this mutual dependency, we can start from last element that had no elements following, thus no data is required.

for (i = m; i >= 0; i--) // For each line in the first file....
{
    for (j = n; j >= 0; j--) // ....Find the best match in second file
    {
    }
}

Inside the loop we prepare a matrix where row and column represent the elements in first and second sequence. The matrix is composed of lengths of the longest common subsequence for each match. Please note that for each match the length of best available LCS is increased by one, otherwise the the best LCS remains the same.

if (bHm[i].second == cHm[j].second) // match
{
    LCSMatrix(i,j) = 1 + LCSMatrix(i+1, j+1); // Increment
}
else 
{
    // retain the best among available LCS
    LCSMatrix(i,j) = max(LCSMatrix(i+1, j), LCSMatrix(i, j+1));
}

Please note the matrix LCSMatrix is very memory consuming if you are comparing big files (i.e. if you are comparing files with 30000 lines each then you need 3.3GB of memory). Given that we need only LCSMatrix(i+1, j) and LCSMatrix(i, j) at a given point we can manage with two one dimensional arrays one for (i)'th row and another for (i+1)'th row, altering the code to that given below. By the way, if you don't understand the algorithm don't worry, there is a much better explanation with good illustration graphics, available from http://www.ics.uci.edu/~eppstein/161/960229.html.

Collapse
bool CCmpMngr::compare_hashed_files_LCS(hashed_filemap &bHm,
      hashed_filemap& cHm,match& dHm)
{    
    int i,j,k,m,n;    
    m = bHm.size(); n= cHm.size(); // length of two sequences to be compared
    LCSBitMatrix.resizeTo(m+2,n+2); // fix the size of bit matrix.
    std::vector
           
            ci,ci1;

    ci.resize(n+2,0);ci1.resize(n+2,0); // resize for ample space
    for (i=0;i<=n;i++) {ci[i]=0;ci1[i]=0;} // initialize arrays

    // Prepare LCS matrix
    for (i = m; i >= 0; i--) // For each line in the first file....
    {        
        // Make a copy for comparison, We r going to initialize
        for (k=0;k<=n;k++) {ci1[k]=ci[k];} 
        
        for (k=0;k<=n;k++) {ci[k]=0;} // initialize 
        for (j = n; j >= 0; j--) // ....Find the best match in second file
        {                
            if (bHm[i].second == cHm[j].second)
            {                    
                ci[j] = 1 + ci1[j+1];
            }
            else 
            {
                if (ci1[j] > ci[j+1]) // Equivalent to above line
                {
                    // to remember the condition result even beyond loop
                    LCSBitMatrix.put(i,j,true); 

                    // to continue looping according to condition result 
                    ci[j] = ci1[j]; 
                }
                else
                {
                    // to remember the condition result even beyond loop
                    LCSBitMatrix.put(i,j,false); 

                    // to continue looping according to condition result
                    ci[j] = ci[j+1]; 
                }
            }                                                
            /* Same above done with huuuuge 2D array named LCSMatrix.
            if (bHm[i].second == cHm[j].second)
            {
                LCSMatrix(i,j) = 1 + LCSMatrix(i+1, j+1);
            }
            else 
            {
                LCSMatrix(i,j) = max(LCSMatrix(i+1, j), LCSMatrix(i, j+1));
            }
            */
        }
    }
}    

Once the matrix is populated with LCS lengths at each point, we can produce the longest common sub sequence by walking through it as follows; start with the top left element, if the elements match, then move one step in row & one step in column, and add the elements to the LCS match list. If the elements doesn't match move one step ahead in the column or row depending on which direction has the longest LCS path available.

Collapse
    dHm.empty();
    i = 0;j = 0;
    // Following link walks through the bitmatrix we created by the loop above
    // and produces a LCS, A LCS here is a vector of pairs.  A pair has two line
    // numbers each from different file which is perfect match.
    // If the pair has <12,17>.., Then it means
    // The 12th line in the File1 has became 17th line in File2, User might have
    // simply added 5 lines in between or added 8 lines and deleted 3 lines.. Etc
    while (i < m && j < n)
    {
        if (bHm[i].second == cHm[j].second)
        {
            dHm.push_back(match_pair (i,j)); // A pair match added to LCS.
            i++; j++;
       }
       else 
        {
            // In case we were using that Huuuuge 2D array, The condition would
            // will be like below             
            // if (LCSMatrix(i+1,j) >= LCSMatrix(i,j+1)) 
            if (LCSBitMatrix.get(i,j) == true) 
                i++;
            else
                j++;
        }
    }

    print_diff_in_HTML(std::string(""));
    return true;
}

How HTML output is produced

Now that we have a array of matching pairs. We can identify the added/deleted/changed lines. Again an example is worth a thousand words so let us start with a sample array of pairs

  1. (1,1)
  2. (2,2)
  3. (3,3)
  4. (4,6)
  5. (5,7)
  6. (6,8)
  7. (9,10)
  8. (10,11)
  9. (11,12)
  10. (12,13)
  11. (15,16)

Please note that you have an indication on added lines from pairs 3 and 4 (lines 4 & 5 are newly added lines in second file), you get a indication of deleted lines from pairs 6 and 7 (lines 7 & 8 are deleted from first file) and you get a indication of changed lines from pairs 10 and 11 (lines 13 and 14 from the first file and 14 and 15 from thesecond file are changed).

This information is then encoded into HTML by the print_diff_in_HTML(), method. The HTML output is composed of 3 different frames: one frame each to show both the files being compared and one main frame. The following script which is included in two sub frames enables synchronized scrolling of both;

function myScroll()
{
    if (document.layers) {//for netscape
        x  = window.pageXOffset;
        y  = window.pageYOffset;
    }
    else if (document.all) {//for IE
        x = document.body.scrollLeft;
        y = document.body.scrollTop;
    }
    parent.left.scrollTo(x,y); 
}

Points of Interest

Besides file comparison, this program uses a rare data structure; a matrix of bits. The reason to write a new class which acts as a bit matrix is the uncertainty in the way data type bool is implemented in various platforms under various memory packing schemes.

The class CBitMatrix is built on sample code from the official C++ FAQ maintained by Marshall Cline. I had a confusion on the code (what happens when overloaded functions vary only in return type & 'const'ness') and mailed him. I was surprised by his reply and his professionalism to answer questions from a "nobody".

Let me reproduce the mail as it will be useful for you. Also it answers the question why the CBitMatrix doesn't have a simple interface to put & get members.

-----Mail from Marshall Cline -----
Subject: RE: Constructive feedback on C++ FAQ Lite[13.8] (Martix sample has a bug...?)
Date: Mon, 7 Oct 2002 13:01:46 -0500
From: "Marshall Cline"

Thanks for writing.

Unfortunately the code works *exactly* according to its intention. The non-const version is *supposed* to be called in both places you said. In particular, if you have two methods in a class X that differ in their constness, e.g.,

  class Foo {
  public:
    void f();
    void f() const;
  };

then the compiler is *required* to call the non-const version if and only if the Foo object is non-const. The return type is irrelevant, and is not normally considered during this "overloading resolution" process.

Marshall

-----Original Message-----
From: shankar pratap
Sent: Monday, October 07, 2002 9:45 AM
Subject: Constructive feedback on C++ FAQ Lite[13.8] (Martix sample has a bug...?)

Dear Mr.Marshall Cline

The piece of code mentioned in the subject line does not work according to the intention.

Functions
------------
1) int& operator() (unsigned int row, unsigned int col);
2) int operator() (unsigned int row, unsigned int col) const;

Intention
---------
Matrix m(10,10);
m(5,8) = 106.15; //supposed to invoke function 1) which returns int&
std::cout << m(5,8); //supposed to invoke function 2)

but function 1) is invoked in both situations

The compiler i tried are
1) g++
2) MSVC++ 6.0.

Best Regards
Shankar Pratap

That's all for now. Happy Coding!

History

  • Feb 11 2003
  • Feb 24 2003
    1. Easy GUI with Progress bar Introduced.
    2. White spaces are not removed from HTML output anymore.
<script src="/script/togglePre.js" type="text/javascript"></script>

About shankarp


I started programming 6 years back, On a 286 with MS-DOS, My works are mostly on DOS&WINDOWS(little bit on some microcontrollers), Though i consider myself as programming language independed, I am much comfort with C++,C,Delphi,Pascal,ASM..!

Click here to view shankarp's online profile.


Other popular C++ / MFC articles:

<script language="javascript" type="text/javascript">document.write("");</script> border="0" src="/script/ann/ServeHTML.aspx?C=False&id=2257&cb=7840955" frameborder="0" width="300" scrolling="no" height="250">
[Top]Sign in to vote for this article:     PoorExcellent  
<script language="javascript" type="text/javascript">document.write(" /"/"");</script>
  <script language="javascript" type="text/javascript">document.write("/"/"");</script>
<script language="JavaScript" type="text/javascript"> var Selected = ""; var AdTime = new Date(); // Ensures the expanded message appears reasonably close to where // it should appear: on screen, and if possible, under the mouse cursor. function SwitchMessage(e) { if ( !e ) e = window.event; var target = e.target ? e.target : e.srcElement; // is it a post? while ( target && target.id != 'DynMessLink' ) target = target.parentNode; if ( !target || target.id != 'DynMessLink' ) return; if (Selected) { var body = document.getElementById(Selected + "_h1"); if (body) body.style.display = 'none'; var head = document.getElementById(Selected + "_h0"); if (head) head.bgColor = '#FEF9E7'; } if (Selected == target.name) // just collapse Selected=""; else { Selected = target.name; var body = document.getElementById(Selected + "_h1"); if (body) { if (body.style.display=='none') body.style.display=''; else body.style.display = 'none'; } var head = document.getElementById(Selected + "_h0"); if (head) head.bgColor = '#99CCFF'; if ( body && head && body.style.display != 'none' ) { // the bit that keeps the post on-screen and under the cursor //var dif = (getRealPos(head, "Top") + head.offsetHeight/2) - (document.body.scrollTop+e.clientY); //document.body.scrollTop += dif; document.body.scrollTop = getRealPos(head, "Top") - document.body.clientHeight/10; EnsureMessageVisible(target.name, true); } } if ( e.preventDefault ) e.preventDefault(); else e.returnValue = false; return false; } // does its best to make a message visible on-screen (vs. scrolled off somewhere). function EnsureMessageVisible(msgID, bShowTop) { var msgHeader = document.getElementById(msgID + "_h0"); var msgBody = document.getElementById(msgID + "_h1"); // determine scroll position of top and bottom var scrollContainer = document.body; var top = getRealPos(msgHeader, 'Top'); var bottom = getRealPos(msgBody, 'Top') + msgBody.offsetHeight; // if not already visible, scroll to make it so if ( scrollContainer.scrollTop > top && !bShowTop) scrollContainer.scrollTop = top - document.body.clientHeight/10; if ( scrollContainer.scrollTop+scrollContainer.clientHeight < bottom ) scrollContainer.scrollTop = bottom-scrollContainer.clientHeight; if ( scrollContainer.scrollTop > top && bShowTop) scrollContainer.scrollTop = top - document.body.clientHeight/10; } // utility function getRealPos(i,which) { iPos = 0 while (i!=null) { iPos += i["offset" + which]; i = i.offsetParent; } return iPos } </script>
Note: You must Sign in to post to this message board.
FAQ Message score threshold    Search comments  
 View   Per page  
 Msgs 1 to 25 of 36 (Total: 36) (Refresh)First Prev Next     
Subject Author Date 
 Can I use your code ? Itai501 5hrs 51mins ago 
 Ask for a help Mary 18:31 11 Oct '06 
 Crash when compiling with VS8.0 #9370 7:02 21 Aug '06 
 Doubt about Hashing Cheng Mo 1:22 15 Apr '05 
 Available for Enhancements dshah 23:12 27 Sep '04 
 Great tool fvcs 0:03 21 Sep '04 
 Re: Great tool Egipko Nikolay 15:24 6 Feb '05 
 Broken link to LCS material UltraJoe 8:01 18 May '04 
 Bug MalaVijay 16:22 22 Mar '04 
 How do I know something changed? Otherdave 16:48 2 Oct '03 
 Re: How do I know something changed?Unconfirmed/Anonymous posting nwsedlak@iptimaging.com 19:59 6 Nov '03 
 Bug fixes attached nwsedlak 16:05 7 Nov '03 
 Bug Jean-Michel LE FOL 5:19 1 Oct '03 
 Bug 2 Jean-Michel LE FOL 12:36 2 Oct '03 
 Re: BugUnconfirmed/Anonymous posting tibouch 5:38 26 May '04 
 Whoops! John R. Shaw 12:50 6 May '03 
 Can we pick your brains? LeeDaviesVBSource 14:56 4 Apr '03 
 Re: Can we pick your brains?Unconfirmed/Anonymous posting Anonymous 13:40 7 Apr '03 
 V Diff in vb clyde2k 1:04 5 Mar '03 
 Great! A little improvment... kfir cohen 17:41 27 Feb '03 
 Re: Great! A little improvment... shankarp 23:12 27 Feb '03 
 Re: Great! A little improvment... rguion 20:14 4 Jun '03 
 Some minor flaws... pli66 4:42 27 Feb '03 
 Re: Some minor flaws...Unconfirmed/Anonymous posting Anonymous 23:00 27 Feb '03 
 Almost perfect ! Jean-Michel LE FOL 1:23 23 Feb '03 
Last Visit: 21:46 Wednesday 10th January, 2007First Prev Next     

General comment    News / Info    Question    Answer    Joke / Game    Admin message


Updated: 6 Mar 2003 Article content copyright shankarp, 2003
everything else Copyright © CodeProject, 1999-2006.
Web07 | Advertise on The Code Project | Privacy
<script src="http://codeproject.us.intellitxt.com/intellitxt/front.asp?ipid=5102" type="text/javascript"></script> <script language="javascript" src="http://codeproject.us.intellitxt.com/v3/door.jsp?ts=1168484629593&ipid=5102&refurl=http://www.codeproject.com/cpp/vdiff.asp" type="text/javascript"></script>
The Ultimate ToolboxASP AllianceDeveloper FusionDevelopersdexDevGuruProgrammers HeavenPlanet Source CodeTek-Tips Forums
<script src="http://codeproject.us.intellitxt.com/v3/func_033.js?v=200612011034" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=0&tx=%20zxz%20This%20program%20compares%20two%20text%20files%20and%20produces%20the%20a%20difference%20analysis%20in%20various%20colours%20in%20plain%20HTML%20format%20zxz%20Comparing%20two%20files%20%20or%20rather%20two%20versions%20of%20same%20file%20%20is%20a%20problem%20programmers%20come%20across%20too%20often%20%20Remember%20the%20way%20ClearCase%20and%20other%20versioning%20systems%20show%20the%20modifications%20you%20made%20to%20your%20code%20%20how%20nice%20it%20would%20be%20if%20your%20application%20can%20provide%20such%20functionality%20to%20the%20user%20%20There%20are%20famous%20tools%20under%20every%20platform%20which%20solves%20this%20problem%20%20WinDiff%20%20on" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=1&tx=%20Windows%20%20diff%20%20on%20UNIX%20platforms%20zxz%20The%20source%20code%20for%20these%20programs%20are%20freely%20available%20too%20%20But%20they%20are%20zxz%20Not%20simple%20%20since%20they%20have%20passed%20through%20intensive%20optimization%20cycles%20zxz%20Not%20well%20documented%20%20as%20there%20were%20no%20good%20reason%20to%20zxz%20Hard%20to%20understand%20%20they%20never%20explain%20the%20underlying%20algorithms%20zxz%20They%20are%20not%20designed%20to%20be%20integrated%20into%20your%20application%20zxz%20VDiff%20is%20simple%20%20easy%20to%20understand%20and%20it%20is%20written%20in%20pure%20C++%20%20So%20it%20compiles%20literally%20under%20any%20platform%20%20test" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=2&tx=ed%20using%20VC++%206%200%20%20g++%202%2095%20%20The%20output%20of%20this%20program%20works%20fine%20with%20IE%20and%20Netscape%20%20with%20minor%20compromise%20on%20scrolling%20functionality%20%20and%20is%20easy%20to%20integrate%20into%20your%20own%20application%20%20On%20the%20other%20hand%20%20it%20is%20not%20as%20fast%20as%20the%20other%20famous%20tools%20%20ut%20I%20am%20sure%20future%20versions%20will%20be%20comparable%20to%20those%20in%20terms%20of%20speed%20zxz%20VDiff%20uses%20the%20Longest%20Common%20Sequence%20%20LCS%20%20as%20a%20algorithm%20to%20differenciate%20two%20files%20%20LCS%20is%20a%20widely%20used%20algorithm%20in%20various%20fields%20%20for%20instance%20in%20genetic%20engi" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=3&tx=neering%20to%20compare%20DNA%20Sequences%20%20Given%20two%20sequential%20array%20of%20entities%20%20the%20algorithm%20will%20find%20the%20longest%20sequence%20of%20entities%20which%20is%20found%20in%20both%20arrays%20zxz%20In%20our%20problem%20%20an%20entity%20is%20a%20line%20of%20code%20%20The%20two%20files%20are%20arrays%20of%20entities%20%20The%20LCSequence%20produced%20by%20the%20algorithm%20in%20this%20case%20is%20a%20sequence%20of%20lines%20which%20are%20unchanged%20%20keeping%20that%20as%20reference%20we%20can%20produce%20a%20picture%20of%20added/deleted/changed%20lines%20zxz%20I%20strongly%20suggest%20you%20look%20at%20zxz%20before%20going%20to%20code%20zxz%20Dan%20Hirs" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=4&tx=berg%20is%20one%20of%20the%20main%20contributors%20to%20LCS%20%20Find%20his%20work%20zxz%20CCmpMngr%20zxz%20is%20the%20interface%20class%20which%20provides%20access%20to%20the%20whole%20functionality%20%20An%20example%20is%20worth%20a%20thousand%20words%20so%20please%20have%20a%20look%20at%20the%20code%20snippet%20below%20%20This%20is%20the%20simple%20way%20of%20invoking%20it%20into%20your%20code%20zxz%20Collapse%20zxz%20main%20zxz%20argCount%20zxz%20argArray%20zxz%20argCount%20zxz%20cout%20zxz%20Usage%20%20cmp%20file1%20file2%20%20output%20dir%20zxz%20/n%20zxz%20CCmpMngr%20cMgr%20%20std%20%20string%20file1%20file2%20oDir%20%20cMgr%20baseFile%20%20std%20%20string%20argArray%20zxz%20cMgr%20co" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=5&tx=mpFile%20%20std%20%20string%20argArray%20zxz%20cMgr%20compare%20zxz%20argCount%20zxz%20oDir%20%20std%20%20string%20argArray%20zxz%20%20%20oDir%20oDir%20length%20%20-%20zxz%20//%20%20oDir%20append%20std%20%20string%20zxz%20%20//%20%20zxz%20cMgr%20print%20diff%20in%20HTML%20oDir%20%20cout%20zxz%20Added%20Lines%20zxz%20cMgr%20nAddedLines%20zxz%20/n%20zxz%20cout%20zxz%20Deleted%20Lines%20zxz%20cMgr%20nDeletedLines%20zxz%20/n%20zxz%20cout%20zxz%20Changed%20Lines%20zxz%20cMgr%20nChangedLines%20zxz%20/n%20zxz%20In%20the%20code%20above%20%20the%20files%20to%20be%20compared%20are%20taken%20from%20command%20line%20arguments%20%20Please%20notice%20the%20class%20zxz%20CCmpMngr%20zxz%20which%20has%20two%20memb" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=6&tx=ers%20zxz%20baseFile%20zxz%20compfile%20zxz%20they%20should%20be%20assigned%20with%20a%20valid%20filename%20including%20full%20path%20%20Once%20that%20is%20done%20call%20the%20zxz%20Compare%20zxz%20method%20which%20will%20do%20the%20real%20comparison%20%20After%20the%20comparison%20the%20statistics%20of%20difference%20is%20available%20through%20members%20zxz%20nAddedLines%20zxz%20nDeletedLines%20zxz%20and%20zxz%20nChangedLines%20zxz%20Now%20the%20most%20interesting%20part%20%20the%20visual%20presentation%20of%20the%20differences%20in%20various%20colours%20%20That%20is%20produced%20by%20the%20method%20zxz%20print%20diff%20in%20HTML%20oDir%20zxz%20The%20variable%20p" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=7&tx=assed%20is%20a%20preferred%20path%20name%20where%20you%20want%20the%20three%20HTML%20files%20%20explained%20later%20%20to%20be%20produced%20zxz%20The%20LCS%20algorithm%20is%20fairly%20simple%20to%20understand%20%20Let%20us%20say%20that%20we%20are%20given%20with%20two%20text%20files%20%20The%20two%20files%20are%20first%20read%20in%20as%20lines%20%20Since%20text%20lines%20are%20time%20consuming%20to%20compare%20%20they%20are%20converted%20to%20a%20integer%20value%20through%20very%20simple%20hashing%20%20It%20is%20done%20by%20zxz%20hash%20filemap%20%20f%20%20hashed%20filemap%20%20hf%20zxz%20Now%20we%20are%20left%20with%202%20arrays%20zxz%20bHm%20zxz%20and%20zxz%20cHm%20zxz%20bHm%20zxz%20base%20Hashed%20Map" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=8&tx=%20zxz%20cHm%20zxz%20comp%20Hashed%20Map%20%20For%20each%20member%20of%20zxz%20bHm%20zxz%20we%20are%20supposed%20to%20find%20a%20%20best%20%20match%20from%20zxz%20cHm%20zxz%20Or%20you%20can%20declare%20there%20is%20no%20match%20%20Now%20imagine%20comparing%20two%20%20CPP%20%20files%20%20You%20are%20at%20line%203%20and%20it%20is%20a%20single%20character%20line%20with%20%20You%20will%20get%20at%20least%20a%20hundred%20matches%20from%20the%20second%20file%20%20The%20criteria%20to%20choose%20a%20best%20match%20from%20possible%20matches%20is%20%20hmmmm%20%20Well%20it%20is%20a%20decision%20you%20make%20%20If%20you%20take%20a%20decision%20at%20that%20point%20which%20leads%20to%20finding%20a%20long%20common%20sequence%20%20t" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=9&tx=hen%20it%20is%20a%20good%20decision%20%20however%20if%20it%20leads%20to%20the%20LONGEST%20common%20sequence%20%20then%20it%20becomes%20BEST%20decision%20%20thus%20the%20BEST%20match%20zxz%20Since%20computers%20are%20stupid%20and%20have%20no%20common%20sense%20%20the%20only%20way%20to%20choose%20the%20best%20decision%20is%20to%20take%20all%20the%20decisions%20%20compare%20outcomes%20and%20decide%20best%20%20In%20order%20to%20find%20the%20best%20match%20%20decision%20%20for%20a%20member%20in%20zxz%20bHm%20zxz%20we%20have%20to%20iterate%20through%20each%20element%20%20decision%20%20in%20zxz%20cHm%20zxz%20i%20zxz%20%20%20i%20%20m%20%20i++%20%20%20zxz%20j%20zxz%20%20%20j%20%20n%20%20j++%20%20%20zxz%20Now%20imagine%20somehow%20you" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=10&tx=%20have%20done%20it%20for%20all%20the%20elements%20and%20are%20now%20at%20the%20last%20element%20%20The%20decision%20making%20is%20fairly%20simple%20because%20all%20the%20elements%20except%20the%20last%20few%20in%20zxz%20cHm%20zxz%20would%20have%20been%20declared%20as%20best%20matches%20for%20some%20element%20in%20zxz%20bHm%20zxz%20and%20you%20are%20left%20with%20one%20or%20two%20unmatched%20elements%20%20and%20most%20probably%20there%20will%20be%20no%20question%20of%20the%20best%20match%20because%20only%20one%20will%20be%20matching%20%20Even%20if%20you%20are%20left%20with%203%20lines%20and%20all%20the%20three%20matches%20perfectly%20%20you%20can%20blindly%20choose%20any%20because%20this%20d" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=11&tx=ecision%20will%20not%20effect%20the%20matching%20of%20elements%20remaining%20%20zero%20%20in%20zxz%20bHm%20zxz%20Please%20note%20here%20the%20last%20statement%20%20The%20decision%20you%20make%20at%20point%20%20x%20%20impacts%20matching%20of%20following%20elements%20%20on%20the%20other%20hand%20%20you%20need%20the%20data%20of%20matching%20for%20remaining%20elements%20in%20order%20to%20decide%20the%20best%20match%20%20To%20avoid%20this%20mutual%20dependency%20%20we%20can%20start%20from%20last%20element%20that%20had%20no%20elements%20following%20%20thus%20no%20data%20is%20required%20zxz%20i%20%20m%20%20i%20zxz%20%20%20i--%20%20%20zxz%20j%20%20n%20%20j%20zxz%20%20%20j--%20%20%20zxz%20Inside%20the%20loop%20we%20prepare%20" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=12&tx=a%20matrix%20where%20row%20and%20column%20represent%20the%20elements%20in%20first%20and%20second%20sequence%20%20The%20matrix%20is%20composed%20of%20lengths%20of%20the%20longest%20common%20subsequence%20for%20each%20match%20%20Please%20note%20that%20for%20each%20match%20the%20length%20of%20best%20available%20LCS%20is%20increased%20by%20one%20%20otherwise%20the%20the%20best%20LCS%20remains%20the%20same%20zxz%20bHm%20i%20%20second%20%20cHm%20j%20%20second%20zxz%20LCSMatrix%20i%20j%20zxz%20%20+%20LCSMatrix%20i+%20zxz%20%20%20j+%20zxz%20%20LCSMatrix%20i%20j%20%20max%20LCSMatrix%20i+%20zxz%20%20%20j%20%20LCSMatrix%20i%20%20j+%20zxz%20Please%20note%20the%20matrix%20zxz%20LCSMatrix%20zxz%20is%20very%20memory%20c" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=13&tx=onsuming%20if%20you%20are%20comparing%20big%20files%20%20i%20e%20%20if%20you%20are%20comparing%20files%20with%2030000%20lines%20each%20then%20you%20need%203%203GB%20of%20memory%20%20Given%20that%20we%20need%20only%20zxz%20LCSMatrix%20i+%20zxz%20j%20zxz%20and%20zxz%20LCSMatrix%20i%20%20j%20zxz%20at%20a%20given%20point%20we%20can%20manage%20with%20two%20one%20dimensional%20arrays%20one%20for%20%20i%20%20th%20row%20and%20another%20for%20%20i+1%20%20th%20row%20%20altering%20the%20code%20to%20that%20given%20below%20%20By%20the%20way%20%20if%20you%20don%20t%20understand%20the%20algorithm%20don%20t%20worry%20%20there%20is%20a%20much%20better%20explanation%20with%20good%20illustration%20graphics%20%20available%20from" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=14&tx=%20zxz%20Collapse%20zxz%20CCmpMngr%20%20compare%20hashed%20files%20LCS%20hashed%20filemap%20%20bHm%20%20hashed%20filemap%20%20cHm%20match%20%20dHm%20zxz%20i%20j%20k%20m%20n%20%20m%20%20bHm%20size%20%20n%20%20cHm%20size%20zxz%20%20LCSBitMatrix%20resizeTo%20m+%20zxz%20%20n+%20zxz%20std%20%20vector%20zxz%20%20ci%20ci1%20%20ci%20resize%20n+%20zxz%20%20%20ci1%20resize%20n+%20zxz%20i%20zxz%20i%20%20n%20i++%20%20ci%20i%20zxz%20ci1%20i%20zxz%20i%20%20m%20%20i%20zxz%20%20%20i--%20%20%20zxz%20k%20zxz%20k%20%20n%20k++%20%20ci1%20k%20%20ci%20k%20zxz%20k%20zxz%20k%20%20n%20k++%20%20ci%20k%20zxz%20j%20%20n%20%20j%20zxz%20%20%20j--%20%20%20zxz%20bHm%20i%20%20second%20%20cHm%20j%20%20second%20%20ci%20j%20zxz%20%20+%20ci1%20j+%20zxz%20%20%20ci1%20j%20%20ci%20j+%20zxz%20LCSBitMatrix%20put%20i%20j%20zxz%20ci%20j%20%20ci1%20j%20zx" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=15&tx=z%20LCSBitMatrix%20put%20i%20j%20zxz%20%20ci%20j%20%20ci%20j+%20zxz%20Once%20the%20matrix%20is%20populated%20with%20LCS%20lengths%20at%20each%20point%20%20we%20can%20produce%20the%20longest%20common%20sub%20sequence%20by%20walking%20through%20it%20as%20follows%20%20start%20with%20the%20top%20left%20element%20%20if%20the%20elements%20match%20%20then%20move%20one%20step%20in%20row%20%20one%20step%20in%20column%20%20and%20add%20the%20elements%20to%20the%20LCS%20match%20list%20%20If%20the%20elements%20doesn%20t%20match%20move%20one%20step%20ahead%20in%20the%20column%20or%20row%20depending%20on%20which%20direction%20has%20the%20longest%20LCS%20path%20available%20zxz%20Collapse%20zxz%20dHm%20empty%20%20i%20zx" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=16&tx=z%20j%20zxz%20i%20%20m%20%20j%20%20n%20zxz%20bHm%20i%20%20second%20%20cHm%20j%20%20second%20%20dHm%20push%20back%20match%20pair%20%20i%20j%20zxz%20%20i++%20%20j++%20%20%20zxz%20LCSBitMatrix%20get%20i%20j%20zxz%20%20%20i++%20%20%20zxz%20j++%20%20print%20diff%20in%20HTML%20std%20%20string%20zxz%20Now%20that%20we%20have%20a%20array%20of%20matching%20pairs%20%20We%20can%20identify%20the%20added/deleted/changed%20lines%20%20Again%20an%20example%20is%20worth%20a%20thousand%20words%20so%20let%20us%20start%20with%20a%20sample%20array%20of%20pairs%20zxz%201%201%20zxz%202%202%20zxz%203%203%20zxz%204%206%20zxz%205%207%20zxz%206%208%20zxz%209%2010%20zxz%2010%2011%20zxz%2011%2012%20zxz%2012%2013%20zxz%2015%2016%20zxz%20Please%20note%20that%20you%20have%20an%20indicatio" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=17&tx=n%20on%20added%20lines%20from%20pairs%203%20and%204%20%20lines%204%20%205%20are%20newly%20added%20lines%20in%20second%20file%20%20you%20get%20a%20indication%20of%20deleted%20lines%20from%20pairs%206%20and%207%20%20lines%207%20%208%20are%20deleted%20from%20first%20file%20%20and%20you%20get%20a%20indication%20of%20changed%20lines%20from%20pairs%2010%20and%2011%20%20lines%2013%20and%2014%20from%20the%20first%20file%20and%2014%20and%2015%20from%20thesecond%20file%20are%20changed%20zxz%20This%20information%20is%20then%20encoded%20into%20HTML%20by%20the%20zxz%20print%20diff%20in%20HTML%20zxz%20method%20%20The%20HTML%20output%20is%20composed%20of%203%20different%20frames%20%20one%20frame%20each%20to%20show%20both%20th" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=18&tx=e%20files%20being%20compared%20and%20one%20main%20frame%20%20The%20following%20script%20which%20is%20included%20in%20two%20sub%20frames%20enables%20synchronized%20scrolling%20of%20both%20zxz%20myScroll%20zxz%20document%20layers%20zxz%20x%20%20window%20pageXOffset%20%20y%20%20window%20pageYOffset%20zxz%20document%20all%20zxz%20x%20%20document%20body%20scrollLeft%20%20y%20%20document%20body%20scrollTop%20%20parent%20left%20scrollTo%20x%20y%20zxz%20Besides%20file%20comparison%20%20this%20program%20uses%20a%20rare%20data%20structure%20%20a%20matrix%20of%20bits%20%20The%20reason%20to%20write%20a%20new%20class%20which%20acts%20as%20a%20bit%20matrix%20is%20the%20uncertainty%20in%20the%20way" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=19&tx=%20data%20type%20bool%20is%20implemented%20in%20various%20platforms%20under%20various%20memory%20packing%20schemes%20zxz%20The%20class%20zxz%20CBitMatrix%20zxz%20is%20built%20on%20sample%20code%20from%20the%20official%20C++%20FAQ%20maintained%20by%20Marshall%20Cline%20%20I%20had%20a%20confusion%20on%20the%20code%20%20what%20happens%20when%20overloaded%20functions%20vary%20only%20in%20return%20type%20%20const%20ness%20%20and%20mailed%20him%20%20I%20was%20surprised%20by%20his%20reply%20and%20his%20professionalism%20to%20answer%20questions%20from%20a%20%20nobody%20zxz%20Let%20me%20reproduce%20the%20mail%20as%20it%20will%20be%20useful%20for%20you%20%20Also%20it%20answers%20the%20questi" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=20&tx=on%20why%20the%20zxz%20CBitMatrix%20zxz%20doesn%20t%20have%20a%20simple%20interface%20to%20put%20%20get%20members%20zxz%20-----Mail%20from%20Marshall%20Cline%20-----%20zxz%20Subject%20%20RE%20%20Constructive%20feedback%20on%20C++%20FAQ%20Lite%2013%208%20%20Martix%20sample%20has%20a%20bug%20zxz%20Date%20%20Mon%20%207%20Oct%202002%2013%2001%2046%20-0500%20zxz%20From%20%20Marshall%20Cline%20zxz%20Thanks%20for%20writing%20zxz%20Unfortunately%20the%20code%20works%20%20exactly%20%20according%20to%20its%20intention%20%20The%20non-const%20version%20is%20%20supposed%20%20to%20be%20called%20in%20both%20places%20you%20said%20%20In%20particular%20%20if%20you%20have%20two%20methods%20in%20a%20class%20X%20that%20di" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=21&tx=ffer%20in%20their%20constness%20%20e%20g%20zxz%20Foo%20zxz%20f%20zxz%20f%20zxz%20then%20the%20compiler%20is%20%20required%20%20to%20call%20the%20non-const%20version%20if%20and%20only%20if%20the%20Foo%20object%20is%20non-const%20%20The%20return%20type%20is%20irrelevant%20%20and%20is%20not%20normally%20considered%20during%20this%20%20overloading%20resolution%20%20process%20zxz%20Marshall%20zxz%20-----Original%20Message-----%20zxz%20From%20%20shankar%20pratap%20zxz%20Sent%20%20Monday%20%20October%2007%20%202002%209%2045%20AM%20zxz%20Subject%20%20Constructive%20feedback%20on%20C++%20FAQ%20Lite%2013%208%20%20Martix%20sample%20has%20a%20bug%20zxz%20Dear%20Mr%20Marshall%20Cline%20zxz%20The%20piece%20" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&ts=1168484635218&enc=&cn=22&tx=of%20code%20mentioned%20in%20the%20subject%20line%20does%20not%20work%20according%20to%20the%20intention%20zxz%20Functions%20zxz%20------------%20zxz%201%20%20int%20%20operator%20%20unsigned%20int%20row%20%20unsigned%20int%20col%20zxz%202%20%20int%20operator%20%20unsigned%20int%20row%20%20unsigned%20int%20col%20%20const%20zxz%20Intention%20zxz%20---------%20zxz%20Matrix%20m%2010%2010%20zxz%20m%205%208%20%20106%2015%20%20//supposed%20to%20invoke%20function%201%20%20which%20returns%20int%20zxz%20std%20%20cout%20%20m%205%208%20%20//supposed%20to%20invoke%20function%202%20zxz%20but%20function%201%20%20is%20invoked%20in%20both%20situations%20zxz%20The%20compiler%20i%20tried%20are%20zxz%201%20%20g++%20zxz%202%20%20MS" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/v3/chunks.jsp?ipid=5102&sid=6d10cd9401c9cef92d0e02fabd057155&nbc=0&ts=1168484635218&enc=&cn=23&tx=VC++%206%200%20zxz%20Best%20Regards%20zxz%20Shankar%20Pratap%20zxz%20That%20s%20all%20for%20now%20%20Happy%20Coding%20zxz%20Feb%2011%202003%20zxz%20Feb%2024%202003%20zxz%20Easy%20GUI%20with%20Progress%20bar%20Introduced%20zxz%20White%20spaces%20are%20not%20removed%20from%20HTML%20output%20anymore%20zxz%20" type="text/javascript"></script>
Help!
Articles
Message Boards
StoreFront
Lounge
style="Z-INDEX: 100; FILTER: Alpha(Opacity=0); LEFT: 865px; VISIBILITY: visible; WIDTH: 381px; POSITION: absolute; TOP: 123px; HEIGHT: 22px" src="http://www.codeproject.com/script/HVMenu/blank.html">
What is 'The Code Project'?
General FAQ
Post a Question
Site Directory
About Us
style="Z-INDEX: 101; FILTER: Alpha(Opacity=0); LEFT: 0px; VISIBILITY: hidden; WIDTH: 194px; POSITION: absolute; TOP: 0px; HEIGHT: 98px" src="http://www.codeproject.com/script/HVMenu/blank.html">
Latest
Most Popular
Search
Site Directory
Submit an Article
Update an Article
Article Competition
style="Z-INDEX: 101; FILTER: Alpha(Opacity=0); LEFT: 0px; VISIBILITY: hidden; WIDTH: 154px; POSITION: absolute; TOP: 0px; HEIGHT: 136px" src="http://www.codeproject.com/script/HVMenu/blank.html">
Windows Vista
Visual C++
ATL / WTL / STL
COM
C++/CLI
C#
ASP.NET
VB.NET
Web Development
.NET Framework
Mobile Development
SQL / ADO / ADO.NET
XML / XSL
OS / SysAdmin
Work Issues
Article Requests
Collaboration
General Discussions
Hardware
Algorithms / Math
Design and Architecture
Subtle Bugs
Suggestions
The Soapbox
style="Z-INDEX: 101; FILTER: Alpha(Opacity=0); LEFT: 0px; VISIBILITY: hidden; WIDTH: 174px; POSITION: absolute; TOP: 0px; HEIGHT: 459px" src="http://www.codeproject.com/script/HVMenu/blank.html"> <script src="http://codeproject.us.intellitxt.com/v3/spit.jsp?ipid=5102&ts=1168484635218&pagecl=0&rsoo=false&cc=us&rcc=cn&reg=--&dma=0&cn=23&cf=3&mk=3&kwpn=1&sid=6d10cd9401c9cef92d0e02fabd057155&si=1&rdtm=100000000&rrm=100000&rcpcm=10000&ripsm=1000&rorm=10000&wpsm=75&wpim=50&dfc=0&rp=0&so=0&nbc=0&adi=0&ac=0&dat=6,11,12,17,18,22,25&irb=1&enc=&ims=2&iek=0&iel=5&ieak=0&iedm=0&iebc=cyan&ttxt=V%20Diff%20-%20A%20File%20Comparer%20with%20visual%20output%20-%20The%20Code%20Project%20-%20C++%20/%20MFC&auat=0&ru=http%3A//www.codeproject.com/cpp/vdiff.asp" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/al.asp?ipid=5102&ts=20070111030452&mt=13&mv=1&cf=3&so=0" type="text/javascript"></script> <script src="http://codeproject.us.intellitxt.com/al.asp?ipid=5102&di=&syid=&adid=&cc=us&rcc=cn&hk=1&ts=20070111030452&so=0&mh=6d10cd9401c9cef92d0e02fabd057155" type="text/javascript"></script>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值