天天看點

cpp 學習筆記

1、C++中模仿gets是  getline(cin, string object)

cpp 學習筆記
cpp 學習筆記

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

struct CanyBar {
    string info; // 存儲匹薩的品牌
    double weight; // 披薩的重量
    double diameter;; // 披薩的直徑
    void showInfomation();
} piSa;
void CanyBar::showInfomation() {
    cout << "品牌" << " " << info << endl;
    cout << "重量" << " " << weight << endl;
    cout << "直徑" << " " << diameter << endl;
}
void work() {
    cout << "請輸入披薩的品牌 :";
//    getline()
    getline(cin, piSa.info);
//    cin >> piSa.info;
    cout << "請輸入披薩的直徑 :";
    cin >> piSa.diameter;
    cout << "請輸入披薩的重量 :";
    cin >> piSa.weight;
    piSa.showInfomation();
}

int main() {
//#ifdef local
//    freopen("data.txt", "r", stdin);
////    freopen("data.txt", "w", stdout);
//#endif
    work();
    return 0;
}      

View Code

2、C++的array好像沒什麼用啊,

cpp 學習筆記
cpp 學習筆記
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

void work() {
    array<double, 3> a;
    double sum = 0;
    cout << "請輸入三次40米跑成績" << endl;
    for (int i = 0; i < 3; ++i) {
        cin >> a[i];
        sum += a[i];
    }
    cout << sum / 3 << endl;
}

int main() {
    work();
    return 0;
}      

3、input file stream    ----> ifstream      input  output stream ---> iostream

cpp 學習筆記
cpp 學習筆記
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
void work() {
    ifstream input("data.txt");
    char ch;
    int ans = 0;
    if (input.is_open()) {
        string s;
        while (!input.eof()) {
            input.get(ch);
            ans++;
        }
        input.close();
        cout << ans - 2 << endl; //會讀取'\n',
        //回車 + 換行 兩個字元
    }
}

int main() {
//#ifdef local
//    freopen("data.txt", "r", stdin);
////    freopen("data.txt", "w", stdout);
//#endif
    work();
    return 0;
}      

4、要傳回指針,不能用局部變量

cpp 學習筆記
cpp 學習筆記
// arrfun3.cpp -- array functions and const
#include <iostream>
const int Max = 5;

// function prototypes
int* fill_array(double ar[], int *begin, int *end);
void show_array(const double ar[], int *end);  // don't change data
void revalue(double r, double ar[], int *end);

int main() { //要傳回指針,不能用局部變量
    using namespace std;
    double properties[Max];
    int begin = 0, end = 5;
    int *size = fill_array(properties, &begin, &end);
    show_array(properties, size);
    if (*size > 0) {
        cout << "Enter revaluation factor: ";
        double factor;
        while (!(cin >> factor)) {  // bad input
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; Please enter a number: ";
        }
        revalue(factor, properties, size);
        show_array(properties, size);
    }
    cout << "Done.\n";
    // cin.get();
    // cin.get();
    return 0;
}

int * fill_array(double ar[], int *begin, int *end) {
    using namespace std;
    double temp;
    static int i;
    for (i = *begin; i < *end; i++) {
        cout << "Enter value #" << (i + 1) << ": ";
        cin >> temp;
        if (!cin) {  // bad input
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; input process terminated.\n";
            break;
        } else if (temp < 0)   // signal to terminate
            break;
        ar[i] = temp;
    }
    return &i; //這個會消失,是以用不了,或者static
}

// the following function can use, but not alter,
// the array whose address is ar
void show_array(const double ar[], int *end) {
    using namespace std;
    for (int i = 0; i < (*end); i++) {
        cout << "Property #" << (i + 1) << ": $";
        cout << ar[i] << endl;
    }
}

// multiplies each element of ar[] by r
void revalue(double r, double ar[], int *end) {
//    cout << (*end) << endl;
    for (int i = 0; i < (*end); i++)
        ar[i] *= r;
}      

5、template <typename T>

 模闆不會生成函數的定義,也就是不會生成

void work() {

   printf("fff"); // 這樣的具體的函數

}

但是它卻會生成函數定義的方案

template <> void swap(int &, int &); // 顯示具體化

template <> void swap<int>(int &, int &); // 顯示具體化

template void swap(int &, int &); // 顯示執行個體化,少了一個在template後面的<>

title1:編寫一個模闆函數,接受一個類型為T的數組,和一個n表示數組長度

尋找數組中最大值。

template <class T>
T maxn(T *a, int len) {
    T mx = a[0];
    for (int i = 1; i < len; ++i) mx = max(mx, a[i]);
    return mx;
}      

需要一個執行個體化,接受一個char *str[]的數組,數組中每一個指針指向一個字元串,然後求出最長的那個字元串。

關鍵是怎麼傳參,先來探讨下二維數組要怎麼傳參

int f[12][N];
void fun(const int f[][N]) {
    f[1][0] = 1; // 編譯失敗
    printf("%d\n", f[1][0]);
}      

①、第二維的大小必須指出,因為,f[1][0]的尋址方式是,*((*(f + 1)) + 0),因為二維數組中,在記憶體裡面也是連續存放的,需要告訴系統,每次 + 1需要跳多遠,就是跳N格。

②、要知道其本質,二維數組的名字,就是一個指向長度為N的一維數組的指針。這樣是得f + 1每次跳N格就好。

是以,是這樣寫

void fun(const int (*f)[N]) {
    printf("%d\n", f[1][2]);
}      

③、如果你是用int **p = new的,則需要fun(int **p),也就是什麼樣的類型,什麼樣的形參

二維數組傳參

cpp 學習筆記
cpp 學習筆記
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

template <class T>
T maxn(T *a, int len) {
    T mx = a[0];
    for (int i = 1; i < len; ++i) mx = max(mx, a[i]);
    return mx;
}
template <> char * maxn(char *str[], int len) {
    char *id = str[0];
    int mx = strlen(str[0]);
    for (int i = 1; i < len; ++i) {
        if (mx < strlen(str[i])) {
            mx = strlen(str[i]);
            id = str[i];
        }
    }
    return id;
}
int a[22];
char *str[222];
void work() {
    for (int i = 0; i < 4; ++i) str[i] = new char[22];
    strcpy(str[0], "22");
    strcpy(str[1], "23");
    strcpy(str[2], "232");
    strcpy(str[3], "1");
    cout << maxn(str, 4) << endl;
}


int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}      

char **str,不是二維數組,他是二級指針,和char *str[]一樣

是以是這樣

char **str;

str = new char *[4]; //先配置設定

for (int i = 0; i < 4; ++i) str[i] = new char[22];

而二維數組 char str[][],對應的是char (*str)[]

int (*p)[22] = new int[33][22]; // 可以

int (*p)[c] = new int[22][c]; // 不可以。形參不可以。

const int c = 22;

int (*p)[c] = new int[22][c]; //可以

cpp 學習筆記
cpp 學習筆記
#include <bits/stdc++.h>
#include <windows.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
struct Node {
    int w, v; // w物品重量, v是物品體積
    Node(int _w, int _v) : w(_w), v(_v) {}
};
int calc_dp(const vector<Node> vc, const int c) { //c是背包容量
    int **dp = new int *[vc.size()];
    for (int i = 0; i < vc.size(); ++i) dp[i] = new int[c + 1];
//    int (*dp)[c + 1] = new int[vc.size()][c + 1];  這樣不行
    for (int i = 0; i < vc.size(); ++i) dp[i][0] = 0;
    for (int i = 0; i <= c; ++i) {
        if (i >= vc[0].w) dp[0][i] = vc[0].v;
        else dp[0][i] = 0;
    }

    bool *sel = new bool[vc.size()];
    for (int i = 0; i < vc.size(); ++i) sel[i] = false;

    for (int i = 1; i < vc.size(); ++i) {
        for (int j = 0; j <= c; ++j) {
            if (j >= vc[i].w) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - vc[i].w] + vc[i].v);
            else dp[i][j] = dp[i - 1][j];
        }
    }
    int tc = c;
    for (int i = vc.size() - 1; i >= 1; --i) {
        if (dp[i][tc] != dp[i - 1][tc]) {
            sel[i] = true;
            tc -= vc[i].w;
        }
    }
    if (tc) sel[0] = true;
    for (int i = 0; i < vc.size(); ++i) printf("%d ", sel[i]);
    printf("\n");
    return dp[vc.size() - 1][c];
}

int mxState, mxValue;

void calc_baoli(const vector<Node> vc, int c, int now, int state, int ans) { // calc_baoli(vc, c, 0)
    if (now == vc.size()) {
        if (mxValue < ans) {
            mxValue = ans;
            mxState = state;
//            printf("%d %d\n", ans, state);
        }
        return ;
    }
    calc_baoli(vc, c, now + 1, state, ans);
    if (c >= vc[now].w) {
        calc_baoli(vc, c - vc[now].w, now + 1, state | (1 << now), ans + vc[now].v);
    }
}

int calc_greedy(const vector<Node> vc, int c) { // calc_greedy(vc, c)
    vector< pair<double, int> > b;
    b.clear();
    for (int i = 0; i < vc.size(); ++i) b.push_back(make_pair(1.0 * vc[i].v / vc[i].w, i));
    sort(b.begin(), b.end(), greater< pair<double, int> >());
    bool *sel = new bool[vc.size()];
    for (int i = 0; i < vc.size(); ++i) sel[i] = false;
    int ans = 0;
    for (int i = 0; i < b.size(); ++i) {
        if (c >= vc[b[i].second].w) {
            c -= vc[b[i].second].w;
            ans += vc[b[i].second].v;
            sel[b[i].second] = true;
        }
    }
    for (int i = 0; i < vc.size(); ++i) printf("%d ", sel[i]);
    printf("\n");
    return ans;
}
void work_dp(vector<Node> vc, int c) {
    long long be = clock();
    printf("動态規劃的答案: %d  時間: ", calc_dp(vc, c));
    long long t = clock() - be;
    printf("%lld\n\n", t);
}

void work_greedy(vector<Node> vc, int c) {
    long long be = clock();
    printf("貪心的答案: %d 時間: ", calc_greedy(vc, c));
    long long t = clock() - be;
    printf("%lld\n\n", t);
}

void work_baoli(vector<Node> vc, int c) {
    long long be = clock();
    mxState = 0, mxValue = -1;
    calc_baoli(vc, c, 0, 0, 0);
    for (int i = 0; i < vc.size(); ++i) {
        if (mxState & (1 << i)) {
            printf("1 ");
        } else printf("0 ");
    }
    printf("\n");
    printf("暴力的答案: %d 時間: ", mxValue);
    long long t = clock() - be;
    printf("%lld\n\n", t);
}

void work() {
    vector<Node> vc;
    vc.clear();
    int n, c;
    srand(time(NULL));
    printf("---------請輸入背包容量-------------------\n");
    scanf("%d", &c);
    printf("---------請輸入物品個數-------------------\n");
    scanf("%d", &n);
    printf("---------請輸入%d個物品-------------------\n", n);
    for (int i = 0; i < n; ++i) {
        int w, v;
         w = rand() % 10 + 1;
         v = rand() % 20 + 1;
         printf("%d %d\n",w,v);
        vc.push_back(Node(w, v));
    }
    work_dp(vc, c);
    work_greedy(vc, c);
    work_baoli(vc, c);
}

int main() {
//#ifdef local
//    freopen("data.txt", "r", stdin);
////    freopen("data.txt", "w", stdout);
//#endif
    work();
    return 0;
}      

函數調用時候選擇的優先級

1、完全比對,但正常函數優于模闆

2、提升轉換,char和short自動去int, float自動去double

3、标準轉換,int 轉為  char, long 轉為 double

4、使用者定義的轉換

6、在函數中的形參放入const,隻是一個修飾符,表明這個形參是不可以變化的,不是定義一個不可變化的常量一樣。

是以當我們傳入參數進去的時候,不用以為const也是可變的。這裡的const和const int a = 1, //a不可變,是不同的。

和重載運算符那個一樣的。

再比如strcmp(const char * str, const char * sub) // 這個稱謂常量指針,確定這個指針不能修改那塊記憶體的東西,但是卻可以改變這個指針指向的記憶體位置。  “傳入來的指針就算變了指向,和一開始的也是沒關系的

相當于我把家裡的鑰匙複制一份給你,你把他扔了,和我無關”

還有一個就是指針常量, int * const p = &a,說明這個指針的指向不能再改變。

指針常量和常量指針

1、模闆函數、或者模闆類需要在.h檔案下給出函數的定義,因為在其他一個cpp裡面,隻include了它的.h檔案,是以如果你隻是聲明了的話,在cpp裡面就無法找到它的定義,也就是無法按照模闆生成一個具體的函數了,這樣做編譯的時候沒問題,連接配接程式的時候會失敗。

解決方案

1、include file2.cpp,這個操作很騷

2、在file2.cpp中來一個顯式執行個體化,但是這就違背了模闆的作用,難道你為每一個都顯式執行個體化嗎。也好,分為int和double兩種而已。

3、在.h中給出定義(最優), STL也是這麼用

https://zhidao.baidu.com/question/1946414924223767268.html

-------------------------2017年12月22日 21:01:30--------------------------------------------------

輸入的東西會放去緩沖區,比如輸入兩個string1, string2可以cin >> s1, cout << s1, cin >> s2,也是可以得。

就是asb  sba

這樣可以兩個串都同時得到。

用cin.sync();  可以清除緩沖區,這樣第二個字元串就輸入不了了。或者fflush(stdin)

javascript:void(0)

注意用cin.get(str, 6, 結束符),隻能最多讀取5個字元,因為有一個是回車,而且他不接受回車,讓它留在緩沖區、   

--------------------------------------2018-1-4 14:19:13-------------------------------------------------------------

如果一個函數是傳回一個引用,這個時候就要注意了,因為傳回引用的話,calc(val) = 2是可以直接指派的,這樣在if的時候可能會出錯

雖然我覺得if那裡很難寫錯,可能以後熬夜寫代碼會寫錯。

是以,應該考慮下是否要放回const的引用。

cpp 學習筆記
cpp 學習筆記
1 int & calc(int val) {
2     int ans = 0;
3     while (val / 10 > 0) {
4         ans += val % 10;
5         val /= 10;
6     }
7     ans += val;
8     return ans;
9 }      

沒傳回const,危險

重載運算符的時候,我剛才在重載 = 這個運算符,這個運算符應該是在裡面搞事。

先說說重載會怎樣。

比如重載了+号,那麼a + c就會退化成a.operator+(c),調用這樣的一個函數。

然後a = a + c,傳回一個一模一樣類型的值給a,是以a的值有改變。。。。

我剛才也一樣,重載了 = ,也是傳回一個一模一樣的類型值,以為a = c也會傳回一個一模一樣的值給a,實則不然。

這其實相當于a.operator=(c),然後就沒了,他不是a = a.operator=(c),就算是這樣,也是徒勞,遞歸一次就知道這是錯的。

是以重載 = 應該是在裡面搞事,在裡面就改了a的值了。而重載其他的 + 之類的,直接重載即可。

再一次解釋,因為它一般會這樣用,a = a + c這樣退化成a = a.operator+(c);,這樣傳回一個一模一樣的類型,指派給a,是可以得。