第二章 變量和基本類型

2.1 基本內置類型

建議:如何選擇類型

  • 明確知曉該數不能爲負數時,選用無符號類型
  • 使用int 執行整數運算。 實際中,short 太小,long和int 差不多,。如果超過int 表示的範圍,選用long long。
  • 在算術表達式中,不用char 和bool。
  • 執行浮點數運算時,選用double類型。因爲float 精度不夠,且double 運算速度更快。

2.1.2 類型轉化:

unsigned char c = -1;  // 假設char佔8bit, c值爲255
signed char c2 = 256;  // 假設char佔8bit, c2值是未定義的
  • 當賦值給無符號類型,超過它的表示範圍值時,結果是初始值對無符號類型表示數值總數取模後的餘數。 即-1對256取模後的數值255
  • 當賦值給 帶符號類型,超出它的表示範圍值時,結果是未定義。

2.1.3 字面值常量

  • 一個型如42的值被稱爲字面值常量
20        /* 十進制*/   
024      /* 八進制*/
0x       /* 十六進制*/
  • 字符串太長時,可以分開書寫
cout<<" a really, really long string literal " 
      " that spans two lines" <<endl;

2.2.2 變量聲明和定義的關係

  • c++ 採用分離式編譯機制,該機制允許將程序分割爲幾個文件,每個文件可以被獨立編譯。
  • 聲明 使得名字爲程序所知,一個文件如果想使用別處定義的名字,則必須包含那個名字的聲明,規定了變量的類型和名字; 定義 負責創建於名字關聯的實體,申請存儲空間,可能會賦值。
  • 如果只是想聲明,而不是定義,就在變量前面添加extern:
 extern int i;  // 聲明 i, 而不是定義i
 int j;        // 聲明並定義j
  • 變量只能被定義一次,但可以被多次聲明。
  • C++ 是靜態類型語言,即在編譯階段檢查類型。

2.3.1 引用

  • 引用即別名。因爲引用本身不是一個對象,所以不能定義引用的引用。
  • 引用必須初始化。因爲引用是別名,必須先有對象,初始化即對象。
  • 引用類型的初始值必須是一個對象。
  • 定義引用時,要將引用和它的初值綁定在一起,而不是將初始值拷貝給引用。

2.3.2 指針

  • 指針本身是一個對象,允許對指針賦值和拷貝;指針無須再定義時賦初值。
  • 指針存放某個對象的地址,使用取地址符
 int ival =42;
 int *p = &ival ;    //p存放變量ival 的地址,p指向變量val的指針。
 cout << *p <<endl; //輸出42    
  • 空指針不指向任何對象。
int *p1 = nullptr;   // 等價於 int *p1 = 0;
int *p2 = 0;         // 直接將p2 初始化爲字面常量0
int *p3 = NULL;      // 等價於 int *p1 = 0; 包含頭文件 #inclde cstdlib

2.3.3 複合類型說明

  • 指向指針的指針
    int ival = 1024;
    int *ip =&ival;       //   
    int **ppi = &ip;    //
    int * &r = ip;     //r 是 一個ip的別名

說明:ppi–>ip–>ival

2.4 const 限定符

  • const是一種變量。這種變量值不能被改變。 例如設置緩存區的大小,可以防止該值不小心被改變掉。
const int bufSize = 512;
  • const 對象一旦創建就不能再改變其值,所以const 對象必須初始化。
  • 編譯器在編譯時,把代碼中所有用到bufSize的地方,全部替換成對應的值。
  • const對象僅在文件內有效,當多個文件中出現了同名的const 變量時,其實等同於在不同的文件中分別定義了獨立的變量。
  • 實現文件共享,可以只在一個文件中定義const, 而在其他多個文件中聲明並使用它
// file_1.cpp 定義並初始化了一個常量,該常量能夠被其他文件訪問
extern const int bufsieze = fcn();
// file_1.h 頭文件
extern const int bufsize ;   //與file_1.cpp 定義的是同一個
  • file_1.h 中的extern 說明bufsieze 並非本文件所獨有,可以在其他文件中定義並且使用它。

2.4.1 const 的引用

2.5 處理類型

2.5.1 類型別名

typedef double wages;    // wages 是double 的同義詞
typedef wages base, *p;  //base是double的同義詞,p是double *的同義詞

2.6 自定義數據結構

2.6.1 定義Sales_data 類型

struct Sales_data{
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}, accum;     //一定要加上分號

2.6.2 使用 Sales_data 類

2.6.3 編寫自己的頭文件

  • 類通常定義在頭文件中,並且類名與所在的文件名一致。例如 庫類型string 在名爲string的頭文件中。
  • 頭文件中也常用到其他頭文件的功能。例如 編寫的Sales_data.h文件中用到了string.h頭文件。
  • 當多次包含同一個頭文件時,要使用 #pragma once。 例如本程序中,在主程序Sales_data.cpp中,包含了頭文件 string; 而在Sales_data.h 中又再次隱含了頭文件string。
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include "Version_test.h"

#include <string>

struct Sales_data {
    std::string bookNo;
#ifdef IN_CLASS_INITS
    unsigned units_sold = 0;
    double revenue = 0.0;
#else
    unsigned units_sold;  
    double revenue;
#endif
};
#endif
  • 說明:當第一次包含Sales_data.h 時,#ifndef 的檢查結果爲真,預處理器順序執行後面的操作,知道遇到程序最後面的語句 #endif。
  • 此時,預處理變量 SALES_DATA_H 的值將變爲已定義,而且 Sales_data.h 也會被拷貝到程序中。
  • 後面再次包含 Sales_data.h ,則 #ifndef 的檢查結果爲假,編譯器將忽略#ifndef… endif 之間的部分。
  • 同樣,在庫中的頭文件string也已經使用了這種預處理功能,所以不會出現重複聲明和定義的問題。
  • #pragma once 其實與#ifndef 的功能相同,只是這裏是爲了解決文件中的提示問題,可以參考文件 http://blog.sina.com.cn/s/blog_65b4bf590101hewq.html
  • 預處理變量大寫的原因是 爲了避免與程序中的其他對象實體發生衝突。
# include <iostream>
using namespace std;
# include <string>
#include "Sales_data.h"

// 自己實現輸入,輸出,相加功能
int main()
{

    Sales_data data1, data2;
// 讀入 data1 和data2 的代碼
    double price = 0.0 ;    //書的單價,用於計算銷售的收入
    // 讀入第 1 筆交易 : ISBN, 銷售數量、單價
    cin >> data1.bookNo >> data1.units_sold >> price;
    // 計算銷售收入
    data1.revenue = data1.units_sold * price;
    // 讀入第 2 筆交易 : ISBN, 銷售數量、單價
    cin >> data2.bookNo >> data2.units_sold >> price;
    // 計算銷售收入
    data2.revenue = data2.units_sold * price;
    // 檢查 data1 和data2 的ISBN 是否相同
    if (data1.bookNo == data2.bookNo)
    {
        unsigned totalCnt = data1.units_sold + data2.units_sold;
        double totalRevenue = data1.revenue + data2.revenue;
        // 如果相同,求data1 和data2 的總和
        cout << data1.bookNo << " " << totalCnt
                << " " << totalRevenue << " " ;

        if(totalCnt != 0)
            cout << totalRevenue/totalCnt <<endl;
        else 
            cout << " No sales" <<endl;
        return 0;
    }
    else 
    {   //ISBN 不相同
        cerr << " Data must refer to the same ISBN" <<endl;
        return -1;
    }

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