一、前言
代碼行數統計主要用來統計項目中的所有檔案的代碼行數,其中包括空行、注釋行、代碼行,可以指定過濾拓展名,比如隻想統計.cpp的檔案,也可以指定檔案或者指定目錄進行統計。寫完這個工具第一件事情就是統計了一下自己寫過的最大的項目大概多少行代碼,看下是不是傳說中的一行代碼一塊錢,這個最大的項目從2010年開始的,到現在差不多快10年了,是自己在現在公司寫過的最大的項目,一直在更新更新完善,途中重構過兩次,大的結構改動,統計了下好像有15W行左右的代碼,純代碼大概在10W,其餘是空行和注釋行,着實把自己吓了一跳,還算是中型項目了,然後又統計了下自定義控件的所有代碼,我勒個去,總代碼23W行,純代碼17W行呢,哎呀我去!
主要功能:
- 可分别統計代碼行/空行/注釋行
- 支援指定過濾拓展名
- 支援指定檔案或者指定目錄進行統計
- 分步顯示統計結果,不卡主界面
- 分别展示每個統計過的檔案的大小/總行數/代碼行數等
二、代碼思路
void frmCountCode::countCode(const QString &filePath)
{
QDir dir(filePath);
foreach (QFileInfo fileInfo , dir.entryInfoList()) {
if (fileInfo.isFile()) {
QString strFileName = fileInfo.fileName();
if (checkFile(strFileName)) {
listFile << fileInfo.filePath();
}
} else {
if(fileInfo.fileName() == "." || fileInfo.fileName() == "..") {
continue;
}
//遞歸找出檔案
countCode(fileInfo.absoluteFilePath());
}
}
}
void frmCountCode::countCode(const QStringList &files)
{
int lineCode;
int lineBlank;
int lineNotes;
int count = files.count();
on_btnClear_clicked();
ui->tableWidget->setRowCount(count);
quint32 totalLines = 0;
quint32 totalBytes = 0;
quint32 totalCodes = 0;
quint32 totalNotes = 0;
quint32 totalBlanks = 0;
for (int i = 0; i < count; i++) {
QFileInfo fileInfo(files.at(i));
countCode(fileInfo.filePath(), lineCode, lineBlank, lineNotes);
int lineAll = lineCode + lineBlank + lineNotes;
QTableWidgetItem *itemName = new QTableWidgetItem;
itemName->setText(fileInfo.fileName());
QTableWidgetItem *itemSuffix = new QTableWidgetItem;
itemSuffix->setText(fileInfo.suffix());
QTableWidgetItem *itemSize = new QTableWidgetItem;
itemSize->setText(QString::number(fileInfo.size()));
QTableWidgetItem *itemLine = new QTableWidgetItem;
itemLine->setText(QString::number(lineAll));
QTableWidgetItem *itemCode = new QTableWidgetItem;
itemCode->setText(QString::number(lineCode));
QTableWidgetItem *itemNote = new QTableWidgetItem;
itemNote->setText(QString::number(lineNotes));
QTableWidgetItem *itemBlank = new QTableWidgetItem;
itemBlank->setText(QString::number(lineBlank));
QTableWidgetItem *itemPath = new QTableWidgetItem;
itemPath->setText(fileInfo.filePath());
itemSuffix->setTextAlignment(Qt::AlignCenter);
itemSize->setTextAlignment(Qt::AlignCenter);
itemLine->setTextAlignment(Qt::AlignCenter);
itemCode->setTextAlignment(Qt::AlignCenter);
itemNote->setTextAlignment(Qt::AlignCenter);
itemBlank->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 0, itemName);
ui->tableWidget->setItem(i, 1, itemSuffix);
ui->tableWidget->setItem(i, 2, itemSize);
ui->tableWidget->setItem(i, 3, itemLine);
ui->tableWidget->setItem(i, 4, itemCode);
ui->tableWidget->setItem(i, 5, itemNote);
ui->tableWidget->setItem(i, 6, itemBlank);
ui->tableWidget->setItem(i, 7, itemPath);
totalBytes += fileInfo.size();
totalLines += lineAll;
totalCodes += lineCode;
totalNotes += lineNotes;
totalBlanks += lineBlank;
if (i % 100 == 0) {
qApp->processEvents();
}
}
//顯示統計結果
listFile.clear();
ui->txtCount->setText(QString::number(count));
ui->txtSize->setText(QString::number(totalBytes));
ui->txtRow->setText(QString::number(totalLines));
ui->txtCode->setText(QString::number(totalCodes));
ui->txtNote->setText(QString::number(totalNotes));
ui->txtBlank->setText(QString::number(totalBlanks));
//計算百分比
double percent = 0.0;
//代碼行所占百分比
percent = ((double)totalCodes / totalLines) * 100;
ui->labPercentCode->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
//注釋行所占百分比
percent = ((double)totalNotes / totalLines) * 100;
ui->labPercentNote->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
//空行所占百分比
percent = ((double)totalBlanks / totalLines) * 100;
ui->labPercentBlank->setText(QString("%1%").arg(percent, 5, 'f', 2, QChar(' ')));
}
void frmCountCode::countCode(const QString &fileName, int &lineCode, int &lineBlank, int &lineNotes)
{
lineCode = lineBlank = lineNotes = 0;
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QTextStream out(&file);
QString line;
bool isNote = false;
while (!out.atEnd()) {
line = out.readLine();
//移除前面的空行
if (line.startsWith(" ")) {
line.remove(" ");
}
//判斷目前行是否是注釋
if (line.startsWith("/*")) {
isNote = true;
}
//注釋部分
if (isNote) {
lineNotes++;
} else {
if (line.startsWith("//")) { //注釋行
lineNotes++;
} else if (line.isEmpty()) { //空白行
lineBlank++;
} else { //代碼行
lineCode++;
}
}
//注釋結束
if (line.endsWith("*/")) {
isNote = false;
}
}
}
}
三、效果圖

四、開源首頁
以上作品完整源碼下載下傳都在開源首頁,會持續不斷更新作品數量和品質,歡迎各位關注。