doub.h
#ifndef DOUB_H
#define DOUB_H
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
int doub(int n); //函數必須在使用前聲明,可以多次聲明,但只能定義一次
//如果這個函數永遠不會用到,可以只有聲明沒有定義
//返回類型,函數名,形參列表描述了函數的接口,也稱函數原型(function prototyp)
#endif
doub.cpp
#include "doub.h"
int doub(int n) //doub 函數名, 前面的 int 是返回類型(return type), 圓括號內是形參列表(parameter list)
{
static int cnt = 0; //局部靜態變量
int i = 3;
cout << "cnt : " << cnt << endl;
cout << "i : " << i << endl;
cout << "n : " << n << endl;
++cnt;
return 2 * n + i; //函數體,語句塊
}
find_char.h
#ifndef FIND_CHAR_H
#define FIND_CHAR_H
#include<string>
#include<iostream>
#include<initializer_list>
using std::string;
using std::cout;
using std::endl;
using std::initializer_list;
string::size_type find_char(const string &s, char c, string::size_type &occure);
void error_msg(initializer_list<string> il);
#endif //FIND_CHAR_H
find_char.cpp
#include "find_char.h"
//根據之前 const 限定類型的拷貝規則,
//我們不對 s 進行改寫操作,所以定義爲 const, 如果 s 是非const,則無法接受 const 實參,所以定義函數時儘量使用 const
//const char c 和 char c 在進行拷貝初始化時是一樣的,頂層 const 會忽略
//occure 需要改變其值,不能設爲 const
string::size_type find_char(const string &s, char c, string::size_type &occure)
{
auto ret = s.size();
for (decltype(ret) i = 0; i != s.size(); ++i)
{
if (s[i] == c)
{
if (ret == s.size())
ret = i;
++occure;
}
}
return ret;
}
/*
initializer_list 形參, 適用於實參數量未知,但全部實參的類型相同
表示某種特定類型的數組, initializer_list 類定義在 initializer_list.h
模板類,使用時必須指明所含元素的類型,不同於 vector, 其元素永遠是常量值,無法改變其元素的值
*/
void error_msg(initializer_list<string> il)
{
for (auto beg = il.begin(); beg != il.end(); ++beg)
cout << *beg << endl;
}
main.cpp
#include "doub.h"
#include "find_char.h"
#include<cstddef>
//可以通過2個可選形參將命令選項傳達給程序
//argv 是一個數組,其元素是指向 c 風格字符串的指針,尾後指針保證爲0;argc 表示 argv 中字符串的數量
int main(int argc, char **argv)
{
/*
函數調用時完成2個工作,
一是隱式定義形參並用實參初始化,
二是將控制權轉移給被調用函數(called function),主調函數(calling function)暫時中斷
當遇到 return 語句時,調用函數結束執行,同樣執行2個工作
一是返回 return 中的值
二是將控制權轉移給調用函數
形參與實參:根據位置一一對應,數量和類型都要匹配
可以定義空形參列表,如果需要兼容 c 語言,使用 void
同表達式的運算一樣,標準並未定義實參的求值順序
任何 2 個形參都不能重名,函數體最外層作用域的局部變量也不可以和形參重名
返回類型:不能是數組或函數,但可以是指向他們的指針,特殊一類類型 void 表示不返回任何值
*/
/*
局部變量(local variable):定義在塊作用域內的變量,僅在塊域中可見,會隱藏外層作用域的同名聲明
自動對象(automatic object):對於普通局部變量的對象,當函數控制路徑經過變量定義語句時創建對象,
到達所在塊域末端時,銷燬,這種存在於塊執行期間的對象稱爲自動對象
局部靜態對象(local static object):使用 static 關鍵字將自動對象定義爲局部靜態對象,
當函數控制路徑經過變量定義語句時創建對象,直到程序終止才結束
局部靜態對象如果沒有顯式的初始值,執行值初始化,內置類型初始化爲 0
*/
int i = 0;
while (i < 10)
{
int res = doub(i); //調用函數 doub,返回值用來初始化 res
cout << "res : " << res << endl;
++i;
}
/*
參數傳遞:
引用傳遞(passed by reference),形參是引用類型,調用時綁定實參,函數被傳引用調用(called by reference)
對形參的任何操作實際上是對實參的操作
值傳遞(passed by value),將實參的值拷貝給形參, 函數被傳值調用(called by value)
對形參的任何操作不會影響傳入的實參
當形參是指針時,雖然2個指針是不同的指針的,但指向的對象是同一個
當拷貝較大的類類型或容器時,效率低,而且有些類型不支持拷貝操作,建議使用引用避免拷貝
如果不需要改變引用形參的值,最好將其聲明爲常量引用
引用形參可以作爲返回結果的途徑
*/
//string s{ "fadsjflwkejrhafbnsxfhklsjadfhl" };
//char c = 'n';
string::size_type occurs = 0, pos = 0;
//通過參數將搜索信息傳入函數
//先判斷下參數個數
if (argc != 3)
{
//cout << "wrong parameter! input like this : lesson_6_1.exe abcdefgdafadljljl f" << endl;
error_msg({"wrong parameter!","input like this : lesson_6_1.exe abcdefgdafadljljl f","exit"}); //initializer_list 類需使用初始化列表傳入
return 0;
}
pos = find_char(argv[1], *argv[2], occurs);
cout << "pos : " << pos << "; occurs : " << occurs << endl;
/*
數組形參,因爲數組不可以進行拷貝,當我們使用數組名時,其實是指向數組第一個元素的指針
1>使用標記指定數組長度,多用於 c 風格字符串,有一個明顯的空字符結尾
void print(const char *cp)
{
if(cp)
while(*cp) //以空字符作爲標誌
cout << *cp++;
}
2>使用標準庫規範,首指針,尾後指針
void print(const int *begin, const int *end)
{
while(begin != end)
cout << *begin++;
}
3>顯式定義一個表示數組大小的形參
void print(const int ai[], size_t size)
{
for(size_t i = 0; i != size; ++i)
cout << ia[i];
}
4>數組引用形參,這種寫法寫死了維度
void print(const int (&ra)[10])
{
for(auto i : ra)
cout << i << endl;
}
5>多維數組形參,指明一個維度的大小
void print(const int (*pa)[3], size_t rowsize)
{
for(size_t i = 0; i < rowsize; ++i)
{
for(auto i : *pa)
cout << i << endl;
++pa;
}
}
*/
return 0;
}