怎樣提高自己代碼可讀性?

是一個努力成為程序員的學生,想知道怎樣形成好一點的編程風格.

比如有什麼好的編程習慣,

通常的變數命名法和函數命名法,

或著一些通常的編程規範.

這是自己寫的一點 c 代碼,請各路大神提出寶貴的建議,謝謝啦!


直接回答具體內容太無聊,我給你個思路。

題主要明白代碼可讀性不是看起來好看那麼簡單。代碼追求可讀性的目的是降低他人閱讀你的代碼的難度,所以你的代碼要在以下三個層次上易讀:

1)文本清晰可讀

2)信息充分富集

3)邏輯容易理解

從1到3,越來越抽象,也越來越重要。

所以以你的代碼為基礎我們從這三個層次來看一下有哪些地方可以改進。

文本清晰可讀:

1)代碼色彩很好,但是這沒什麼卵用。因為別人不見得用你的色彩方案。

2)段落間沒有空白。合適的空行可以起到突出段落的作用,可以讓你的代碼結構看起來更直觀。

3)符號旁沒有空白。同樣的道理,符號旁空白起到一個將對象和操作隔離的作用。當然具體操作上有懶散有極端的,有人只空二元操作符,有人任何操作符都空格。請自行選擇,或者參考一些代碼標準。

4)注釋與被注釋內容的位置關係。插在簽名與主體之間是一個方法,我個人不喜歡。不過也許有人覺得這樣容易讀。

信息充分富集

1)有注釋。

2)對象名、函數名信息充分。只是有拼寫錯誤,Create不是creat。

3)臨時變數名或可少許增加信息量,例如p改為ptr。不過並不重要。

總的來說這個層面上題主做的不錯。

邏輯容易理解

老實說,C的邏輯關係意義不大,不過想必題主將來不會止於C。

這段代碼中所暴露出來的少許邏輯結構都不錯。

以下給一些參考的代碼風格。

Recommended C Style and Coding Standards

https://gcc.gnu.org/codingconventions.html

Coding Style Conventions (Windows)

我個人不覺得其中哪個明顯好於另一個,所以請題主自行參考。

注1:我知道是C代碼,用了「對象」這樣的說法只是習慣「對象」與「實體」互用。


1. 宏定義、類型定義、函數之間,都加上空行,如:

#include&
#include&

#define MAX 20

typedef struct Student {
//Todo
} Student;

Student* readStudentInfo() {
//Todo
}

註:如果是C++的話不需要用typedef,直接struct Student就能正常用Student了。

2. 除了一元運算符,運算符、變數之間加上空格,如:

scanf("%d", p-&>StudentID); //逗號之後加空格,之前不加空格

headPointer-&>next = readStudentInfo(); //二元運算符(. -&> 除外)兩邊加空格

for(int i = 0; i &< length; i++); //分號後面加,前面不加;一元運算符不加 char gender = (id[16] == "1"? "m": "f"); //三元運算符也是加在後,最好加括弧

3. 一個類型不要有兩個名稱,如:

typedef struct Student {
...
} Student; //就夠了,注意Student前一樣有空格

註:盡量不要對基本類型(如int)指定別名,作用應在變數名中體現而非類型名。

4. 命名不要太過冗餘,如:

typedef struct Student {
int id;
char name[MAX];
float grade;
struct Student *next;
} Student; //類型名不要重複在成員變數裡面

註:如果是C++的話,命名空間和類名的處理也是一樣。

5. *號應跟在變數名而不是類型名,如:

Student *headPointer = (Student*)malloc(sizeof(Student)); //看下面連續2個變數的時候是用對了的

6. 指針名不要用p、ptr、pointer這樣空泛的名稱,是什麼就叫什麼,如:

Student *student = doSomeThing();

printf("...");
scanf("%d", student-&>id); //-&>兩邊層次清晰

7. 判斷的時候變數名寫左邊,常量寫右邊,如:

Student *student = doSomeThing();
if(student == NULL) {
//Todo
}

8. 注釋寫在函數簽名上面,如:

//學生信息定義
typedef struct Student {
//Todo
}

//從標準輸入讀取學生信息,返回學生指針
Student* readStudentInfo() {
//Todo
}

註:參數為空的時候直接空著,不要寫void

9. 任何情況下if、while、for代碼塊都加上花括弧,如:

Student *student;
doSomeThing();
while(student-&>next != NULL) {
student = student-&>next;
}

註:不要利用C語言弱類型特性在if或while條件裡面直接判斷整型變數,永遠判斷比較結果

10. 類型名用大寫,變數名用小寫,如:

//基本符合,注意下Student的成員名,HeadPointer變數名

11. 重複代碼提取成獨立函數,如:

void CheckNotNull(Student *student) {
if(student == NULL) {
printf("Error!
");
exit(1);
}
}

someType someFunction(someType someArgument) {
Student *student = doSomeThing();
CheckNotNull(student);
//Todo
}

12. 先睡覺啦。。o=(&>.&<)=o


我感覺你這個代碼寫的算挺容易看懂的,加點空格會更好吧


說下注釋吧,po主的注釋寫的太教科書味道了。函數介面的注釋應該寫清楚函數的功能、參數說明、返回值含義、注意事項等內容。

另外注釋一般是寫在要注釋的內容(函數介面、變數定義、語句等)的上部而不是寫在下面。

函數介面注釋的格式也應該規範統一,可以參考下注釋文檔抽取工具Doxygen的注釋規定來寫。

具體的格式寫法可以根據環境(語言、IDE等)選擇最合適的,這裡給一個註解函數聲明的簡單例子。

/**
* Do subtraction of two integers.
* @param[in] a The minuend.
* @param[in] b The subtrahend.
* @return Result of a-b.
* @note The function is not overflow safe.
*/
int Sub(int a, int b);


建議1:不要對結構體使用 typedef,除非你明確的希望隱藏其內部細節。如果你有這種需求,比較好的做法也是先在 .c 中定義結構體,再在 .h 中進行 typedef 。

建議2:不要對 malloc 的返回值進行強制類型轉換,除非你需要針對 C++ 做兼容。不過即使你有這種需求,比較好的做法是使用 extern "C" { } 把使用 C 規範的代碼包起來。

建議3:在使用 exit 退出前最好顯式的將之前 malloc 的內存 free 掉。

建議4:不要使用 sizeof(Student),改用 sizeof(*p) 。


送上一本谷歌的CPP編碼規範...

祝你學有所成...

E文原版

Google C++ Style Guide

中文

Google C++ 編碼規範(中文版)


首先你得寫正確的程序, 其次才是以正確的方式寫程序。

(1) typedef struct Student {...} Student, *StudentPointer; // 指針類型重命名 r u ok ?

(2) scanf("%d", p-&>StudentID); scanf("%f", p-&>StudentGrade); // 取地址; StudentGrade 拷代碼考錯!

(3) createStudentList(StudentPointer *phead) 參數類型不應該是 Student* head,因為你實際上修改的是 頭指針的值,所以應該是指針的指針!

其次,以正確的方式寫程序, 這個問題貌似更多, 真的不是三五處的事:

(1) Student 結構中還需要 StudentID 這樣寫, 蛋疼不? 直接 id,name, grade 搞起!

(2) MAX 用 NAME_MAX

(3) 不要交替用 Student* 和 StudentPointer, 雖然它們是同一個類型;而且貌似一個 StudentPointer 不能涵蓋語義,應該再來一個 *StudentList;

(4) createStudentList 裡面怎麼會有一條 readStudentInfo() ; 放的位置不對;

(5) if(p) 或是 if(p != NULL) , if(!p) 或是 if(p == NULL) 請保持一種姿勢,不要一會這種 if(p == NULL),一會那種 if(p) !

(6) 空格、換行, {} ,注釋的問題;

(7) 此處省略一千字... ... (洗洗碎覺)


注釋太空泛了...

函數名已經代表注釋信息了...

注釋應該是容易產生誤解的地方,比如返回值的具體含義,比如一些特殊情況的處理...


同意樓上某個答案所說的,不僅要對函數名的功能注釋,更應該對那些變數啊,還有關鍵的邏輯進行注釋~像現在做這種C語言的作業變數少,放到函數裡面還能看懂,等到寫更大的程序動輒十好幾個變數就蒙圈啦~所以不僅要注釋函數的功能哦~


你這代碼根本沒法編譯吧?

typedef struct Student {...} StudentPointer*;

完全看不懂這是什麼。

總要先把代碼寫對才能談得上風格吧


可以讀一下林銳的《高質量C/C++編程指南》。


記得重構的書上說,讓代碼寫到不需要注釋就能看懂,就是不錯的代碼


如果可以的話,我建議你好好閱讀一下代碼規範,只靠別人口口相傳不是辦法。關於代碼規範的資料書籍有很多,我現在公司的Coding Rules是我比較推崇的,只是公司版權問題,不能與你分享


Atitit. 提升可讀性推薦標準規範解決方案 關於編程語言的v5 docx

1. 提升可讀性的意義 1

2. 提升可讀性大原則: 2

2.1. 分解 分類 層次結構 2

2.2. 命名規範推薦標準 2

2.3. 關注點分離原則 2

2.4. 面向人類編程,優先於面向機器,可讀性優先於性能原則 2

3. 具體措施 2

3.1. (推薦)Dsl **重要 2

3.2. **(推薦)使用漢字命名,獲取更大的可讀性,適合於絕大多數項目利大於弊(推薦) 2

3.3. (推薦)使用命名空間,不支持命名空間的事業類似前綴 3

3.4. (推薦)有時候異常處理也會提升可讀性 3

3.5. (推薦)限制使用spring等框架範圍,防止濫用 3

3.6. (推薦)提高抽象級別,what與how相分離,優先指明what 3

3.7. (推薦)減少架構層次,雙層比三層四層架構更加簡單易讀 3

3.8. (推薦)注意學院派與工程派完全不同 3

3.9. 命名規範 參考知名api 3

3.10. (推薦)Sql style api 4

3.11. 適當分層、DI和AOP是繼OO之後的分解方法 4

3.12. 函數式樣 流程式控制制全部函數化 4

3.13. 遞歸代替循環 4

3.14. 中綴表達式 優先於 前後綴表達式 5

3.15. 防止出現大量介面,,介面過多過濫 5

3.16. 減少 嵌套級別 5

3.17. (推薦)使用模板法,關注點分離。。字元串拼接太難讀怎麼辦?? 5

3.18. 減少「語法噪音」 5

3.19. 參考 5

4. Refactor 5

4.1. 方法鏈 5

5. 參考資料 5

1. 提升可讀性的意義

不管對項目還是產品模式,提升可讀性都意義重大。

· 優化可讀性可以讓代碼易於閱讀和調試,從而縮短開發周期,降低開發成本;

優化可讀性——讓代碼更容易閱讀、跟蹤和理解。

在優化時難以兼顧各個方面。 例如,當致力於性能優化時,你很可能讓應用程序內存消耗增加,同時代碼可讀性也變差。

2. 提升可讀性大原則:

2.1. 分解 分類 層次結構

2.2. 命名規範推薦標準

2.3. 關注點分離原則

2.4. 面向人類編程,優先於面向機器,可讀性優先於性能原則

大部分情況下,默認的性能即可滿足要求。。

3. 具體措施

3.1. (推薦)Dsl **重要

常見的DSL就是h5 sql script腳本。。界面用h5,業務邏輯儘可能用優先使用腳本和sql sp,數據存儲用sql

通用語言GPL儘可能用來縮小使用範圍,用來寫庫是個不錯的使用場景。。。

3.2. **(推薦)使用漢字命名,獲取更大的可讀性,適合於絕大多數項目利大於弊(推薦)

當然喪失了跨國人員合作特性。不過對於大多數都是國內項目來說,就很合適了,根本就沒有外籍人員參與。。

如果發現少部分工具對漢字支持不佳,使用拼音即可。拼音也是拼音文字中文

3.3. (推薦)使用命名空間,不支持命名空間的事業類似前綴

缺點就是命名長度變長了,單是可讀性優先,會提升可讀性,名字長度有ide自動補全緩解。。

3.4. (推薦)有時候異常處理也會提升可讀性

異常處理

3.5. (推薦)限制使用spring等框架範圍,防止濫用

一般他們都會提升複雜度,降低可讀性,應當儘可能的限制其模塊使用範圍

3.6. (推薦)提高抽象級別,what與how相分離,優先指明what

3.7. (推薦)減少架構層次,雙層比三層四層架構更加簡單易讀

當然一些複雜模塊可以使用更多的層數來分解。。

Iso規定有7層網路,實際的tcp只有4層,就是為了降低複雜度。。

3.8. (推薦)注意學院派與工程派完全不同

3.9. 命名規範 參考知名api

參考知名api 參考知名sdk 遊戲cocos2d、等..

這樣可以大大減少資料文檔的編撰。。互聯網上已經有了

3.10. (推薦)Sql style api

Sql是個可讀性很好的dsl,對於一些操作以及統計方法,使用sql分格的命名很好理解

private void process(BufferedImage img, int grayLevDeep, int radis) {

new GrayLayerCater().groupByGrayRang(grayLevDeep);

//對模板選框內內的像素顏色對灰度分組聚合分類,分別放在不同的灰度層次裡面

GrayLayerCater1.insertTo_Layers_select_Colors_From(Matrix1).Groupby_GrayRang();

//選擇最多顏色點的那個層次

Layer ColorsNumsTop1Layer = GrayLayerCater1.get_top1_from_Layers_Orderby_ColorsNum_desc();

//計算顏色均值,分別對各個rgb分量計算,與合成

Color avgColor = ColorsNumsTop1Layer.avgColor_retClr();

}

3.11. 適當分層、DI和AOP是繼OO之後的分解方法

3.12. 函數式樣 流程式控制制全部函數化

特殊字(如while、class和for)

3.13. 遞歸代替循環

3.14. 中綴表達式 優先於 前後綴表達式

3.15. 防止出現大量介面,,介面過多過濫

3.16. 減少 嵌套級別

3.17. (推薦)使用模板法,關注點分離。。字元串拼接太難讀怎麼辦??

var sql=" insert `常用洗衣網點`(工號,網點名稱)value("@uid@","@add@")";

sql=sql.replace("@uid@","123");

sql=sql.replace("@add@","實際地址");

alert(sql);

3.18. 減少「語法噪音」

3.19. 參考

4. Refactor

4.1. 方法鏈

5. 參考資料

Atitit.提升語言可讀性原理與實踐

Atitit usrQBF2312 命名空間pkg 以及 api命名 spec規範

如何提高代碼可讀性 - GC2013 - 博客園.html

如何提高代碼可讀性、可維護性 - zm1_1zm - 博客頻道 - CSDN.NET.html

作者:: 綽號:老哇的爪子claw of Eagle 偶像破壞者Iconoclast image-smasher

捕鳥王"Bird Catcher 王中之王King of Kings 虔誠者Pious 宗教信仰捍衛者 Defender of the Faith. 卡拉卡拉紅斗篷 Caracalla red cloak

簡稱:: Emir Attilax Akbar 埃米爾 阿提拉克斯 阿克巴

全名::Emir Attilax Akbar bin Mahmud bin attila bin Solomon Al Rapanui

埃米爾 阿提拉克斯 阿克巴 本 馬哈茂德 本 阿提拉 本 所羅門 阿爾 拉帕努伊

常用名:艾提拉(艾龍), EMAIL:1466519819@qq.com

轉載請註明來源:attilax的專欄 http://blog.csdn.net/attilax

--Atiend

[?1P[?1??


推薦閱讀:

大學裡教的C語言,與知乎上說的入門編程要學的C語言是同一個東西嗎?
sizeof(list) 如何區分list是變數還是類型?
學c語言應該買什麼樣的電腦?
c語言編程軟體哪個好用?
x86上為什麼C語言調用一個函數要先把參數壓棧,之後才是返回地址?

TAG:編程 | 計算機 | 代碼 | C編程語言 | 代碼質量 |