コード最適化の自動修正

9079 ワード

一、コード最適化のテキスト編集ツール
コード最適化を行う場合、コードの検索や置換、手動「ctrl+c」や「ctrl+v」などの操作によく遭遇します.ブロガーは主にVS 2013をコード編集ツールとして使用しており、まずいくつかのVS 2013の一般的なショートカット操作を紹介します.(参考:VS 2013ショートカットキー)
1,VS 2013でサポートされている操作
「ctrl+f」はファイル内で検索したり、置換を実行したりすることができます(f--find)
「ctrl+shift+f」ソリューション全体を検索(選択可能ダイアログボックス)
"ctrl+Tab"ページング(ローテーション)
"ctrl+k+c"コメント(c--comment line);"ctrl+k+u「注釈を解く;
「alt+shift+上下矢印」virtualキーワードの統一追加や削除など、列モードを有効にします.
2,notepad++
1)notepad++の「ctrl+f」の機能はもっと強い.
2)その「編集」メニューバーは「空白」(行末空白、行頭空白)の処理を提供している.
3)その「編集」メニューバーは「スペース」と「Tab」の変換を提供する.
4)その「編集」メニューバーには「大文字と小文字の変換」機能があります.
5)列モードをサポートする;
6)フォーマット変換「UTF-8」と「ANSI」を提供し、「UTF-8 BOMなしフォーマット」を推奨し、参考:UTF-8とUTF-8 BOMなし
3,SVNとBC
SVNのコード比較ツールをBCに設定することを推奨します
二、ケース導入
多くの場合、私たちが直面している多くのコード最適化の問題は、「ctrl+f」と列モードで簡単に解決できません.例えば、前のブログ(コード最適化mapアプリケーション)では、if/else if文ブロックをmapの初期化リストに直接変換することはできません.
ソース:
<span style="font-size:14px;">//           
void classA::ParseMeasurementFlag(const QString &itemName)  
{  
    if (itemName.isEmpty())  
    {  
        qCritical() << "itemName.isEmpty()";  
        return;  
    }  
  
    long lMeasurementFlag = 0;  
    long lCurrTestItemFlag = 0;  
  
    if (!QString::compare(itemName, QString1, Qt::CaseInsensitive))  
    {  
        lMeasurementFlag = bit1 | bit2 | bit3;  
        lCurrTestItemFlag = enum1;  
    }  
    else if (!QString::compare(itemName, QString2, Qt::CaseInsensitive))  
    {  
        lMeasurementFlag = bit3 | bit5 | bit7;  
        lCurrTestItemFlag = enum2;  
    }  
    ...  
    else  
    {  
        lMeasurementFlag = 0;  
        lCurrTestItemFlag = 0;  
    }  
} </span>

ターゲットコード:
<span style="font-size:14px;">void classA::InitTestCaseMap()  
{  
#define INSERT_MAP(expression1, expression2, expression3) \  
    m_mapTestCase.insert(QString(expression1).trimmed().toLower(), { expression2, expression3 })  
  
    INSERT_MAP(QString1,  bit1 | bit2 | bit3, enum1);  
    INSERT_MAP(QString2,  bit3 | bit5 | bit7, enum2);  
    INSERT_MAP(QString3,  bit2 | bit5 | bit8, enum4);  
    ...  
#undef INSERT_MAP(expression1, expression2, expression3)  
}  </span>

この問題は、1回以上の検索と置換に関連し、集計行にも設計されています.
ツールができない以上、自分で小さなプログラムを作ってこの機能を実現したほうが、その核心は文字列処理です.
PS:notepad++のマクロ録画機能を試みたところ、効果が理想的ではなく、コントロールできず、問題がどこにあるかをチェックすることもできませんでした.
三、「文字検索、置換、連結行」プログラム設計
1、設計構想
このプログラムの目的は、「source.cpp」ファイルから文字行を読み出し、ターゲット関数を見つけることです.ターゲット関数ブロック(1対のスプラインを境界とする)の文字行を読み込み、「QString::compare(itemName)」を検索し、行を見つけ、string 1などの中間文字列を提示し、「lMeasurementFlag」を検索して等号の後の値を抽出します.次に、「lCurrTestItemFlag」を検索し、等号の後の値を抽出します.最後に、抽出した3つの値をターゲットファイルのフォーマットで1行構成し、「target.cpp」ファイルに出力します.上記の「読み込み、検索、抽出、組み立て、出力」の操作を関数の最後まで繰り返します.
2、注意点:
1)全体の処理はすでに関数ブロックが上下の境界であり、簡単な方法は処理する内容を1つの空白ファイルにコピーし、境界を関数ブロックから全体のファイルに変えることである.複雑な方法は、カウンタを設計することです.関数名の後に「{」があり、関数の最後には対応する「}」があり、関数体では、スプラインもペアで表示されます.これにより、変数「int count=0」を定義します.「ループ終了判定条件として、1つの」{「則」++count;";1つの"}"則"--count;“.
2)循環体では,毎回1行の文字のみを処理し,vectorのようなコンテナを設計し,複数回反復した処理結果をキャッシュする.最初は、「QString::compare(itemName)」を見つけて1行を読み出して破棄し、さらに1行を読み出し、「lMeasurementFlag」に対応する値を抽出し、1行を読み、「lCurrTestItemFlag」に対応する値を抽出し、最後に1行を読み出して破棄するように設計しました.しかし、コードブロックに注釈行が数行増えたため、この設計の予想を狂わせました.
3)文字行の処理にはQStringを推奨する.最初はstd::stringを使っていましたが、サブ文字の抽出が不便であることに気づきました.
上のコード:
<span style="font-size:14px;">#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QString>
#include <QStringList>
#include <iostream>

void MergeLines(QTextStream & in, QTextStream & out);

int main(int argc, char *argv[])
{
    //QCoreApplication a(argc, argv);

    QString fileName = {"source.txt"};
    QFile inFile(fileName);
    if (inFile.exists())
        inFile.open(QIODevice::ReadOnly);
    else
        qDebug("The input file does not exist !");
    QTextStream in(&inFile);

    QFile outFile(QString("_") + fileName);
    outFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
    QTextStream out(&outFile);

    MergeLines(in, out);

    outFile.flush();
	outFile.close();
	inFile.close();

    return EXIT_SUCCESS;    //return a.exec();
}

void MergeLines(QTextStream & in, QTextStream & out)
{
    int countLine = 0;
    int count = 0;
    QString line;
    QStringList list;
    while (!in.atEnd())
    {
        line = in.readLine();
        std::cout << ++countLine << "\t";
        
        if (line.indexOf("Qt::CaseInsensitive") != -1)
        {
            QStringList list1 = line.split(", ");
            list.append(list1[1].trimmed());
        }
        else if (line.indexOf("lMeasurementFlag") != -1 || line.indexOf("lCurrTestItemFlag") != -1)
        {
            QStringList list2 = line.split(" = ");
            list2[1].chop(1);
            list.append(list2[1].trimmed());
        }

        if (list.size() == 3)
        {
            std::cout << "
" << ++count << "
"; QString align1; if (list[0].size() < 15) align1 = { "\t\t" }; else align1 = { "\t" }; //out << "m_mapTestCase.insert(QString(" << list[0] << ").trimmed().toLower()," << align1 << "{ " // << list[1] << ",\t" << list[2] << " });" << "
"; out << "INSERT_MAP1(" << list[0] << "," << align1 << list[1] << ",\t" << list[2] << " );" << "
"; list.clear(); } } }</span>

注意:
1,Qt consoleプログラムを新規作成する;
2,source.txtには、コピーされた処理対象コードブロック(簡略化処理)が保存される.
四、「プログラム設計の検索と置換」
上記のケースに続いて、「QString 1,QString 2,QString 3,...「constant.h」ファイルに定義されます.フォーマットは次のとおりです.
<span style="font-size:14px;">#ifndef CONSTANTS
#define CONSTANTS

const QString QString1          = "dog";
const QString QString2          = "cat";
const QString QString3          = "mouse";
const QString QString4          = "marmot";
...

#endif</span>

コンパクトコードが必要です.mapの「QString 1,QString 2,QString 3,...「元の文字列に置き換え、constant.h」ファイルを削除します.これにより、プログラムが設計されました.
からsource.txt"で行を読み出し、"QString 1,QString 2,QString 3,...「constant.h」ファイルに対応する文字列を見つけて置き換え、最後に新しい文字列を出力します.
上のコード:
<span style="font-size:14px;">...

void SearchAndReplace(QTextStream & in, QTextStream & in2, QTextStream & out);
int main(int argc, char *argv[])
{
    //QCoreApplication a(argc, argv);

    QString fileName = {"_source.txt"};
    QFile inFile(fileName);
    if (inFile.exists())
        inFile.open(QIODevice::ReadOnly);
    else
        qDebug("The input file does not exist !");
    QTextStream in(&inFile);

    QFile inFile2("constants.h");
    if (inFile2.exists())
        inFile2.open(QIODevice::ReadOnly);
    else
        qDebug("The input file does not exist !");
    QTextStream in2(&inFile2);

    QFile outFile(QString("_") + fileName);
    outFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
    QTextStream out(&outFile);

    //MergeLines(in, out);
    SearchAndReplace(in, in2, out);

    outFile.flush();
    inFile.close();
    inFile2.close();
    outFile.close();

    return EXIT_SUCCESS;    //return a.exec();
}

void SearchAndReplace(QTextStream & in, QTextStream & in2, QTextStream & out)
{
    while (!in.atEnd())
    {
        QString line1;
        QString source;
        line1 = in.readLine();
        if (!line1.isEmpty())
        {
            QStringList list1 = line1.split(",");
            source = list1[0].trimmed();
            source.remove(0, 12);
        }

        QString target{};
        while (!in2.atEnd())
        {
            QString line2;
            line2 = in2.readLine();
            if (line1.isEmpty())
                continue;
            QStringList list2 = line2.split("=");
            if (list2.size() == 2)
            {
                list2[0] = list2[0].trimmed();
                list2[0].remove(0, 14);
                if (source == list2[0])
                {
                    target = list2[1].trimmed();
                    target.chop(1);
                    break;
                }
            }
        }

        if (!target.isEmpty())
            line1.replace(source, target);
        out << line1 << "
"; } }</span>

五、まとめ
主に問題を簡略化し、細分化することです.簡略化:処理対象コードを個別のファイルとして保存する.≪ドリルダウン|Tessellation|oem_src≫:集計行と置換をそれぞれ1つの関数またはプログラム処理で設計します.