1. 程式人生 > >淺析C語言auto關鍵字和C++ 中的auto關鍵字

淺析C語言auto關鍵字和C++ 中的auto關鍵字

      最近在讀《C++ Prime》,不禁想感嘆一句:C++真是一種美麗的語言!!!!!!!

      C++提供了相比於 C語言更加豐富的庫函式,功也更加強大。舉個例子吧。

      題目:編寫一段程式,讀入一段包含標點符號的字串,將標點符號去除後輸出字串剩餘的部分。

原始碼:

//編寫一個程式,讀入一個包含標點符號的字串,將標點符號去除後輸出字串剩餘的部分

#include <iostream>
#include <string>

using namespace std;

int main()
{
	/*src為源字串即要操作的字串,dest為目標字串,存放操作結果*/
	string src, dest;             
	getline(cin, src);            /*從輸入中讀取一行賦值給str1*/
	for (auto c : src)            /*對str中的每個字元*/
	{
		if (!ispunct(c))           /*如果該字元不是標點符號*/
		{
			dest.push_back(c);     /*把該字元尾插到dest中*/
		}
	}
	cout << dest << endl;          /*輸出dest中的內容*/
	system("pause");
	return 0;
}

執行示例:


      這段程式碼的功能是,從鍵盤輸入一個字串,去除字串中的標點符號後輸出。看到這個題目,如果使用C語言,我們可能首先會想到寫一個簡單的演算法實現這一功能。或者有時會再多想一點點,既然是字串,可能有時會很自然的想到資料結構中的串 的相關知識,將字元存在字元陣列中,然後使用下標確定標點符號的位置和個數,然後移動後面的元素,覆蓋掉字串中的標點符號,但這樣有時需要移動大量元素,相對比較繁瑣,如果使用鏈式串,則可以從前往後遍歷,當遇到字元為標點符號時,使用指標指向的改變刪除標點符號,然後釋放其空間。使用C語言演算法還好,但如果使用資料結構,就有點太複雜了。如果使用C++語言,我們使用編譯器提供的庫函式,可以很方便的完成上面的題目要求。

      在上面的程式碼中用到的函式ispunct() 在C語言中也有這個庫函式,通過MSDN可以檢視這個函式,函式需要包含的標頭檔案為<ctype.h>,C語言中的標頭檔案形式:nane.h,C++則將這些檔案命名為cname。也就是去掉了.h字尾,而在檔名name之前添加了c,這裡的c表示這是一個屬於C語言標準庫的標頭檔案。所以C++中包含<ctype.h>的格式為<cctype>。上面的程式碼中還用到了一種C語言中沒有見到過的語句形式for (auto c : src) 這是C++11新標準提供的一種語句範圍for語句,在下面會詳細解釋。

      當然C++的美麗之處遠遠不止這些,更多的是面對物件的程式設計思想,使其更加適合與大型專案,以及模板和泛型程式設計等等,同時C++也是在不斷髮展的。這些美麗之處,需要我們在不斷的深入學習中慢慢去體會。

      好啦,不知不覺寫了這麼多。下面切入正題,C語言auto關鍵字和C++ 中的auto關鍵字的介紹。 最近在讀《C++ Prime》的過程中發現auto關鍵字在C++中的使用和C語言中有很大的不同,自己以前也總結過C語言中的auto關鍵字。覺得很有必要將C語言和C++相比較來理解auto關鍵字。

Ⅰ )C語言中的auto關鍵字

      C語言和C++中auto關鍵字的使用有很大區別。在C語言中使用auto關鍵字宣告一個變數為自動變數,是C語言中應用最廣泛的一種型別,在函式內定義變數時,如果沒有被宣告為其他型別的變數都是自動變數,也就是說,省去型別說明符auto的都是自動變數。這裡的其他型別指的是變數的儲存型別即:靜態型別變數(static )、暫存器型別變數(register)和外部型別變數(extern)。例如:

void Test()
{
	auto int x = 10;           //定義自動變數x,auto可以省略
	int y;                     //y和z都為自動變數,如果省略了auto 關鍵字則隱含表示為auto型別
	double z;
	...
}

      在C語言中使用auto定義的變數可以不予初始化,但在C++中必須初始化。自動變數,在函式呼叫時分配儲存空間,當完成呼叫是釋放儲存空間。當然也存在下面這種形式:

auto val;    //當省略資料型別,只使用auto修飾變數,在C語言中預設變數為int型

   為了說明當省略資料型別,只使用auto修飾變數,在C語言中預設變數為int型,可以看下面的程式碼:

#include <stdio.h>
#include <Windows.h>
int main()
{
	double value1 = 3.2, value2 = 3.5;  
	/*使用auto 定義一個變數,在C語言中可以不初始化,編譯器會使用一個隨機值
	值初始化變數val,但建議在寫程式碼時進行初始化,為了說明與C++中的不同,這裡
	不予初始化*/
	auto val;                             
	val = value1 + value2;               
	printf("%d\n", val);
	system("pause");
	return 0;
}

通過除錯監視視窗,觀察變數的值的變化,來進行驗證。


      可以看到,進入程式,當執行過double value1 = 3.2, value2 = 3.5;語句後value1和value2被初始化為3.2和3.5,在除錯過過程中編譯器把auto value;當宣告處理,跳過了該語句,可以通過型別觀察到val的資料型別一直為int 執行完求和語句val = value + value2;後,其結果為整形資料6。所以,C語言中,當省略了資料型別,則使用auto關鍵字修飾的變數預設為int 型資料。

Ⅱ)C++中的auto關鍵字

       C++中的auto關鍵字是一個型別說明符,通過變數的初始值或者表示式中參與運算的資料型別來推斷變數的型別。程式設計時通常需要把表示式值式賦給變數,這就要求在宣告變數時清楚的知道表示式的型別,C++11新標準引入了auto 型別說明符,讓編譯器去分析表示式的型別。由於,需要編譯器推斷變數或表示式的型別,所以,auto定義的變數必須初始化。例如:

auto val = 5.2f;         //編譯器會根據初始化的值來推斷val的資料型別為flaot,但要注意如果去掉f則編譯器會認為val為double型變數
	auto x = y + z;          //x初始化為y和z相加的結果,由y和z的資料型別推斷x的資料型別
	auto num;                //但如果在C++中出現這樣的語句,會編譯報錯,提示“型別包含“auto符號”必須具有初始值設定項”

      使用auto也能在一條語句中宣告多個變數。因為一條語句宣告時只能有一種基本資料型別,所以該語句中的所有變數初始基本資料型別必須一樣,例如:

auto i = 0, *p = &i;        //正確:i是整數、p是整形指標
auto sz = 0, pi = 3, 14;    //錯誤:sz和pi的型別不一致

      auto和decltype 的作用有點相似,都可以推斷某個表示式的具體型別,當我們希望從表示式的值推斷出要定義的變數的型別,但不想用該表示式的值初始化變數時,可以使用decltype,作用是選擇並返回運算元的資料型別,但並不計算表示式的值。如果decltype 使用的表示式不是一個變數,則decltype返回表示式結果對用的型別,如果我們僅僅是想根據初始值確定一個變數合適的資料型別,那麼auto是最佳人選。而只有當我們需要推斷某個表示式的資料型別,並將其作為一種新的資料型別重複使用(比如,定義多個相同型別變數)或者單獨使用(比如,作為函式的返回值型別)時,我們才真正需要用到decltype“。

      在範圍for語句中,經常會使用到auto關鍵字,正如文章開篇舉得那個例子,範圍for語句遍歷給定序列中的每個元素並對序列中的每個值執行某種操作。其語法形式為:

/*
	*declaration 部分定義一個變數,該變數用於訪問序列中的基礎元素,expression部分是一個物件,用於表示
	*一個序列。每次迭代,declaration部分的變數會初始化為expression部分的下一個元素值,statment是對字
	*符的操作語句
	*/
	
	for (declaration : expression)
	{
		statement
    }

       下面看一個例子,將上面介紹到的關鍵字和範圍for語句梳理一下:

//編寫一段程式,使用範圍for語句將字串內的所有字元用‘X’代替


#include <iostream>
#include <string>

using namespace std;

int main()
{
	string str;
	getline(cin, str);     //從輸入中讀取一行賦值給str1

	//auto 是一個型別說明符,通過變數的初始值來判斷變數的型別

    for (auto &c : str)                //對於字串str中的每一個c
	{
		//decltype 型別指示符,選擇並返回運算元的資料型別,如果decltype使用
	    //的表示式不是一個變數,則decltype返回表示式結果對應的型別
		for (decltype(str.size()) index = 0; index < str.size(); ++index)
		{
			str[index] = 'X';
		}
	}
	cout << str << endl;               //列印替換後的字串
	system("pause");
	return 0;
}

       簡單分析:上面的程式碼完成的功能是,把字串中的所有字元‘X’用代替。先 從鍵盤讀取一行字串,然後使用範圍for語句對其進行處理,在範圍for語句中使用auto關鍵字推斷變數c的資料型別,因為要改變字串中的字元,所以將迴圈變數C定義為引用型別,然後使用for迴圈依次處理字串str中的字元,將其修改為字元‘X’,在使用下標處理字串中的字元是,我們需要知道字串的長度,c++中的size()函式用於返回字串的長度,即:字串中字元的個數,類似於C語言中的strlen,字串的下標從0開始,所以下標的取值大於等於0並且小於字串的size()值,迴圈控制條件為:index < str.size(); 所以index為decltype(str.size())型的變數,這裡使用decltype返回函式size()返回值型別,並且將其作為資料型別定義index作為字串中字元的下標,(實際上size()返回的是一個size_t型別的值,個人認為,可以把 size_t 理解為unsigned int型),然後,在迴圈體內實現字元的替換,上面的程式碼中用到了本文中講到的auto型別說明符,decltype型別指示符以及範圍for語句,可以幫助我們簡單的理解其簡單應用。

 【參考目錄】

《C++ Prime》第五版