C語言小項目——動手打造屬於自己的C語言IDE

自己動手打造屬於自己的C語言IDE

建議:建議先觀看功能演示,然後根據功能演示想想思路,然後看博文中的思路,最後再看博文代碼,最後再看完整代碼,這樣效果會更好。

功能介紹:一款基於QT的簡易c語言編輯器,可以編輯,編譯和運行。

環境配置:編譯運行功能的前提是windows平臺上已經安裝gcc並配置到系統環境變量中,這個的配置方式可自行百度,很多帖子有講。或直接安裝QT,便於閱讀源碼。同時,安裝QT自帶會安裝gcc,將其配置到環境變量中即可

整體運行效果可觀看成品展示

UI

在創建工程的時候勾選上UI選項,會自動生成一個mainWindow,在菜單欄中點擊添加菜單功能,然後在ui文件中通過拖拽控件佈局。佈局完成後,在佈局下方找到對應控件名稱並右鍵轉到槽,工程會自動在mainwindow.cpp中生成對應的槽函數,在槽函數中即可實現各自功能。槽函數的命名爲on_action控件名_triggered

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-FHhevjxk-1587451488157)(D:…/configImages/QT_UI.png)]

主要功能實現

打開文件

思路:通過QFileDialog::getOpenFileName()函數獲取文件路徑。然後通過fopen打開路徑對應的文件,並通過一個臨時變量str存放文件中的內容,最後通過ui->textEdit->setText()函數將臨時變量中的內容展示在文本編輯控件中。最後關閉文件。

注意:通過QFileDialog::getOpenFileName()函數獲取的文件路徑是QString類型的數據,所以在給fopen使用前需要轉換爲char *類型。QT中使用UTF-8編碼,所以如果文件使用GBK編碼,需要轉換編碼方式。

API說明

  • QFileDialog::getOpenFileName() 通過可視化方式獲取路徑
  • codec->fromUnicode(path).data()改變編碼方式並轉換數據類型
  • codec->toUnicode(buf) 轉換爲UTF-8編碼
  • ui->textEdit->setText(str) 向文本編輯框放入待編輯內容

代碼實現:

void MainWindow::on_actionOPEN_triggered()
{
    // 打開文件,獲取文件路徑
    path = QFileDialog::getOpenFileName();
    cout << "path=" << path;
    if(path.isEmpty())
    {
        // 沒有選擇路徑直接退出
        return;
    }
    // 字符編碼轉換
    char *fileName = codec->fromUnicode(path).data();
    // 打開文件並讀取內容,並放進編輯區
    FILE *fp = fopen(fileName, "rb");
    if(fp == NULL)
    {
        cout << "on_actionOPEN_triggered() fopen err";
        return;
    }

    char buf[1024*5];
    QString str = "";

    // 讀取文件
    while (1) {
        memset(buf, 0, sizeof (buf));
        fgets(buf, sizeof (buf), fp);

        // 根據標誌位改變字符編碼方式
        if(flag == utf_8)
        {
            str += buf;
        }
        else if(flag == GBK)
        {
            str += codec->toUnicode(buf);
        }
        if(feof(fp))
        {
            break;
        }
    }

    // 將文件內容放進編輯區
    ui->textEdit->setText(str);

    // 關閉文件
    fclose(fp);
    fp = NULL;

}

文件另存爲

思路:通過QFileDialog::getSaveFileName()獲取文件待保存的路徑,然後通過臨時變量保存文本編輯區的內容,最後通過寫的方式打開待保存的路徑,將臨時變量內容寫入,關閉文件即可。

注意:依舊是編碼方式,還有QStringchar *類型的不同

API說明

  • QFileDialog::getSaveFileName() 通過可視化方式獲取保存路徑
  • str.toStdString().data()QString轉換爲char * 類型
  • ui->textEdit->toPlainText() 獲取文本編輯框內容

代碼實現:

void MainWindow::on_actionSAVE_AS_triggered()
{
    // 選擇另存爲的路徑,爲UTF8編碼,返回類型爲QString類型
    path = QFileDialog::getSaveFileName();
    if(path.isEmpty())
    {
        // 如果沒有選擇路徑直接退出
        return;
    }
    // 需要將路徑轉換爲GBK編碼,並且爲char * 類型
    const char *fileName = codec->fromUnicode(path).data();
    cout << fileName;

    // 打開文件並讀取內容,並放進編輯區
    FILE *fp = fopen(fileName, "wb");
    if(fp == NULL)
    {
        cout << "on_actionSAVE_AS_triggered open file err";
    }

    // 獲取編輯區的內容,返回QString
    QString str = ui->textEdit->toPlainText();

    // 將QString轉換爲char * 類型
    const char *buf = str.toStdString().data();
    fputs(buf, fp);

    // 關閉文件
    fclose(fp);
}

文件保存

思路:如果是open一個文件改動後需要保存,那麼在open的時候就已經獲取到了文件路徑,直接將編輯區的內容獲取後保存到指定文件中即可。如果打開編輯器後開始編輯內容需要保存,那麼此時沒有獲取過路徑,就需要通過QFileDialog::getSaveFileName()獲取一下保存路徑。

注意:依舊是編碼方式,還有QStringchar *類型的不同。

API說明:無特殊API用到的上面已經介紹過。

代碼實現:

void MainWindow::on_actionSAVE_triggered()
{
    // 如果剛打開編輯器開始寫東西,此時path爲空就需要通過getSaveFileName獲取一個路徑
    if(path.isEmpty())
    {
        path = QFileDialog::getSaveFileName();
    }
    const char *fileName = codec->fromUnicode(path).data();
    // 打開文件並讀取內容,並放進編輯區
    FILE *fp = fopen(fileName, "wb");
    if(fp == NULL)
    {
        cout << "on_actionSAVE_triggered open file err";
    }

    // 獲取編輯區的內容,返回QString
    QString str = ui->textEdit->toPlainText();

    // 將QString轉換爲char * 類型
    const char *buf = str.toStdString().data();
    fputs(buf, fp);

    // 關閉文件
    fclose(fp);
}

編譯運行

思路:首先判斷一下需要運行的文件是否已經存在,如保存文件中出現的第二種情況,一打開編輯器就開始編輯的文件,還沒保存到本地,那麼就需要先保存到本地。然後通過gcc filename.c -o filename生成可執行文件,再執行可執行程序即可。第一步獲取filename:通過QString的replace函數將路徑最後的.c去掉即可。第二步執行可執行程序。

注意:執行以上的兩部都需要在終端執行,直接調用system函數即可。如果編譯出錯,那麼就不能繼續執行,需終端停留在報錯頁面,使用cmd /k可實現終端停留

API說明:

  • replace() QString中的函數,替換字符串中指定字符串。
  • QString("gcc %1 -o %2").arg(arg1).arg(arg2) QString格式化
  • ui->textEdit->toPlainText() 獲取文本編輯框內容

代碼實現:

void MainWindow::on_actioncomplie_triggered()
{
    if(path.isEmpty())
    {
        // 如果沒有路徑則需要保存一下才能運行
        this->on_actionSAVE_triggered();
    }

    QString demo = path;

    // 生成的目標文件名
    demo.replace(".c", "");

    // gcc filename.c -o filename
    QString cmd = QString("gcc %1 -o %2").arg(path).arg(demo);

    // system執行成返回0
    int ret = system(codec->fromUnicode(cmd).data());
    if(ret != 0)
    {
        // cmd /k 停留在終端
        cmd = QString("cmd /k gcc %1 -o %2").arg(path).arg(demo);
        system(codec->fromUnicode(cmd).data());
        return;
    }
    QString target = QString("cmd /k %1").arg(demo);
    system(codec->fromUnicode(target).data());
    system("cmd");
}

改變字符編碼

思路:通過codec->fromUnicode(path)codec->toUnicode(buf)兩個API實現編碼轉換功能。由於字符編碼需要在好幾個槽函數中使用,所以思考定義一個全局變量,通過這個全局變量的狀態來判斷如何轉換。通過ui->label->setText在左下角實時顯示當前的編碼方式。

注意:別的槽函數使用,所以需要使用全局變量。

API說明:

  • replace() QString中的函數,替換字符串中指定字符串。
  • QString("gcc %1 -o %2").arg(arg1).arg(arg2) QString格式化
  • ui->label->setText("當前以GBK顯示,切換編碼後請重新打開文件") 將制定內容顯示在label中。

代碼實現:

// UTF_8轉換函數
void MainWindow::on_actionUTF_8_triggered()
{
    // 按下轉換按鍵,爲UTF_8
    flag = utf_8;
    ui->label->setText("當前以UTF-8顯示,切換編碼後請重新打開文件");
}

// GBK轉換函數
void MainWindow::on_actionGBK_triggered()
{
    // 按下按鍵轉換爲GBK
    flag = GBK;
    ui->label->setText("當前以GBK顯示,切換編碼後請重新打開文件");
}

退出、複製、粘貼、剪切、撤銷

思路:直接調用QT自帶的相應的功能函數。

API說明:

  • ui->textEdit->copy() 複製
  • ui->textEdit->paste() 粘貼
  • ui->textEdit->cut() 剪切
  • ui->textEdit->undo()撤銷

代碼實現:

// 複製
void MainWindow::on_actioncopy_triggered()
{
    ui->textEdit->copy();
}

// 粘貼
void MainWindow::on_actionpaste_triggered()
{
    ui->textEdit->paste();
}

// 剪切
void MainWindow::on_actioncut_triggered()
{
    ui->textEdit->cut();
}

// 撤銷
void MainWindow::on_actionundo_triggered()
{
    ui->textEdit->undo();
}

// 退出系統
void MainWindow::on_actionQUITE_triggered()
{
    exit(0);
}

完整代碼

完整的工程代碼連接:https://github.com/wtzhu13/CPPOrCProectDemo/tree/master/IDE

**彩蛋:**這個項目中還包含其他一些練手小項目,後續會慢慢更新,不斷往裏添加。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章