Essential C++学习笔记及源代码(第1章 C++编程基础)

第1章是本书的基本知识和入门重点。
本章介绍了C++的基础编程知识,其中包括:
1、一些基础数据类型:布尔型(bool)、字符型(char)、整型(int)以及浮点型(float和double)。
2、算术运算符、关系运算符以及逻辑运算符,用以操作上述基础数据类型。这些运算符包括加(+)、减(-)、乘(*)、除(/)、相等运算符(==)、小于等于运算符(<=)以及赋值运算符(=),也包含比较特殊的递增运算符(++)、条件运算符(?:)以及复合赋值运算符例如+=等。
3、条件分支以及循环控制语句,if和while循环可用来改变程序的控制流程。
4、一些复合数据类型,例如指针以及数组。指针可以让我们间接使用一个已存在的对象,数组则用来定义一组具有相同数据类型的元素。
5、一套标准的、通用的抽象化库,例如字符串(string)以及向量(vector)。
作者使用了一个小程序帮助读者们很好地掌握C++的基础知识,笔者在此处归纳总结并进行分析,再附上课后编程练习解答使得更好地掌握已学知识,注意建立工程文件后再运行小程序,若是对您有用的话请点赞或分享提供给它人。

//ch1_main.cpp

#include <iostream>
#include <string>
#include "ch1.h"
using namespace std;

int main()
{
    user_profile up; //声明一个玩家对象;

    if (greet_user(&up)) //问候玩家并选择是否开始游戏;
    {
        play_game(&up);          //游戏主菜单;
        display_statistics(&up); //显示玩家猜测次数和猜测正确率;
    }

    return 0;
}

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//ch1.cpp

#include "ch1.h"

pvec Fibonacci_gen_elems(int pos) //生成一个Fibonacci数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.empty())
    {
        _elems.push_back(1);
        _elems.push_back(1);
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size();
        int n_2 = _elems[ix - 2];
        int n_1 = _elems[ix - 1];

        for (int elem; ix < pos; ++ix)
        {
            elem = n_2 + n_1;
            _elems.push_back(elem);
            n_2 = n_1;
            n_1 = elem;
        }
    }
    return &_elems;
}

pvec Pell_gen_elems(int pos) //生成一个Pell数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.empty())
    {
        _elems.push_back(1);
        _elems.push_back(2);
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size();
        int n_2 = _elems[ix - 2];
        int n_1 = _elems[ix - 1];

        for (int elem; ix < pos; ++ix)
        {
            elem = n_2 + 2 * n_1;
            _elems.push_back(elem);
            n_2 = n_1;
            n_1 = elem;
        }
    }
    return &_elems;
}

pvec Lucas_gen_elems(int pos) //生成一个Lucas数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.empty())
    {
        _elems.push_back(1);
        _elems.push_back(3);
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size();
        int n_2 = _elems[ix - 2];
        int n_1 = _elems[ix - 1];

        for (int elem; ix < pos; ++ix)
        {
            elem = n_2 + n_1;
            _elems.push_back(elem);
            n_2 = n_1;
            n_1 = elem;
        }
    }
    return &_elems;
}

pvec Triangular_gen_elems(int pos) //生成一个Triangular数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size() ? _elems.size() + 1 : 1;
        for (; ix <= pos; ++ix)
        {
            _elems.push_back(ix * (ix + 1) / 2);
        }
    }
    return &_elems;
}

pvec Square_gen_elems(int pos) //生成一个Square数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size() ? _elems.size() + 1 : 1;
        for (; ix <= pos; ++ix)
        {
            _elems.push_back(ix * ix);
        }
    }
    return &_elems;
}

pvec Pentagonal_gen_elems(int pos) //生成一个Pentagonal数列;
{
    static vector<unsigned> _elems;

    if (!check_integrity(pos))
    {
        return 0;
    }
    if (_elems.size() < pos)
    {
        int ix = _elems.size() ? _elems.size() + 1 : 1;
        for (; ix <= pos; ++ix)
        {
            _elems.push_back(ix * (3 * ix - 1) / 2);
        }
    }
    return &_elems;
}

//使用一个函数指针数组来访问在每个函数中产生的静态数列;
pfunc gen_elems[] =
{
    0,
    Fibonacci_gen_elems,
    Pell_gen_elems,
    Lucas_gen_elems,
    Triangular_gen_elems,
    Square_gen_elems,
    Pentagonal_gen_elems
};

//生成数列的种类;
const char *name_seq[] = 
{
    "Invalid Sequence",
    "Fibonacci", "Pell", "Lucas",
    "Triangular", "Square", "Pentagonal"
};

//游戏等级;
int level_size[] = {8, 8, 32, 128, 512};

//一些反馈信息;
const char *wrong_msg[] =
{
    "Oops! Nice guess but not quite it.",
    "Hmm. Sorry. Wrong again.",
    "Ah, this is harder than it looks, isn't it?",
    "It must be getting pretty frustrating by now!"
};

//显示玩家在游戏中的猜测信息;
void display_statistics(user_profile *puser)
{
    cout << "Game Statistics for " << puser->name << "\n\t";
    cout << "# guesses: " << puser->guesses << "\n\t";
    cout << "# correct: " << puser->correct << "\n\t";
    cout << "% correct: ";
    cout << (static_cast<float>(puser->correct) / static_cast<float>(puser->guesses)) * 100 << endl;
    return;
}

//初始化玩家信息和游戏信息;
bool greet_user(user_profile *puser)
{
    cout << "Hi. What's your name? ";

    string nm;
    cin >> nm;
    if (nm.empty() || nm[0] == ' ')
    {
        cout << "ok. I guess you don't want to play. See ya!\n";
        return false;
    }
    cout << "Hi, " << nm;
    cout << " Would you like to play Guess the Sequence? (y/n) ";

    char ch;
    cin >> ch;
    if (ch != 'y' && ch != 'Y')
    {
        cout << "ok. I'm sorry you don't want to play.\n";
        return false;
    }
    cout << "\n\n";
    cout << "Hey, that's great, " << nm << ".\n";
    cout << "We'll start in just a moment.\nIt\'s simple, really!\n";
    cout << "I will print out two elements of a sequence\n";
    cout << "You just answer with the element value that comes next!\n\n";

    cout << "Oh, by the way, do you consider yourself a\n\t";
    cout << "beginner     -- enter 1\n\t";
    cout << "intermediate -- enter 2\n\t";
    cout << "advanced     -- enter 3\n\t";
    cout << "guru         -- enter 4\n\t" << endl;

    int level;
    cin >> level;
    if (level < 1 || level > 4)
    {
        level = 4;
    }
    init_user(puser, nm, level); //初始化游戏各项信息;
    return true;
}

//打印当前数列中的所有元素;
void print_seq(user_profile *puser)
{
    for (int i = 0; i < puser->cur_seq_vec->size(); ++i)
    {
        cout << (*puser->cur_seq_vec)[i] << ' ';
    }
    cout << endl;
    return;
}

void display_seq(user_profile *puser)
{
    pvec p = seq_vec(puser);
    cout << "The first two elements of the series are: ";
    cout << (*p)[puser->pos - 3] << ", " << (*p)[puser->pos - 2]; //显示倒数第3个和倒数第2个数;
    cout << "\nWhat is the next element? ";
    return;
}

void set_up_index(user_profile *puser)
{
    static string wherefrom("set_up_index");

    //在数列等级数组中随机获取一个位置;
    puser->pos = rand() % (level_size[puser->level]);

    if (puser->pos < 3) //显示数列最后3个数, 位置不对的话就加3防止出错;
    {
        puser->pos += 3;
    }
    set_seq_vec(puser, (*gen_elems[puser->cur_seq])(puser->pos));
    trace(wherefrom, "new position: ", puser->pos);
    return;
}

void reset_seq(user_profile *puser)
{
    static string wherefrom("reset_seq");

    int new_seq = gen_seq_id(puser->level); //设置游戏猜测序列的种类;
    if (new_seq == puser->cur_seq)
    {
        new_seq = new_seq < ns_cnt ? new_seq + 1 : 1;
    }
    puser->cur_seq = static_cast<num_sequence>(new_seq); //设置玩家当前猜测序列的种类;

    set_up_index(puser);

    print_seq(puser);
    trace(wherefrom, "new sequence: ", name_seq[puser->cur_seq]);
    return;
}

void init_user(user_profile *puser, const string &nm, int level)
{
    static string wherefrom("init_user");

    puser->name = nm;
    puser->guesses = 0;
    puser->correct = 0;
    puser->level = level;

    reset_seq(puser);                            //设置游戏参数;
    trace(wherefrom, nm, puser->cur_seq, level); //打印追踪信息;
    return;
}

bool correct_guess(user_profile *puser, int guess)
{
    pvec p = seq_vec(puser);
    if (guess == (*p)[puser->pos - 1])
    {
        return true;
    }
    return false;
}

void play_game(user_profile *puser)
{
    bool next_seq = true;
    bool go_for_it = true;
    bool got_it = false;
    int num_tries;

    while (next_seq == true)
    {
        num_tries = 0;
        display_seq(puser);
        while ((got_it == false) && (go_for_it == true))
        {
            unsigned int usr_guess;
            cin >> usr_guess;

            if (correct_guess(puser, usr_guess)) //玩家猜对了;
            {
                bump_correct(puser);
                got_it = true;
                cout << "Hey, most excellent! \n\t";
                cout << usr_guess << " is element # ";
                cout << puser->pos << " of the ";
                cout << name_seq[puser->cur_seq] << " sequence.\n"; //打印当前数列的部分信息;
            }
            else
            {
                bump_guess(puser);
                cout << wrong_msg[num_tries < ns_wrong_msg ? num_tries : ns_wrong_msg - 1]; //打印一条反馈信息;
                cout << " Would you like to try again? (y/n) ";

                char usr_rsp;
                cin >> usr_rsp;

                if (usr_rsp == 'N' || usr_rsp == 'n')
                {
                    go_for_it = false;
                }
                else
                {
                    ++num_tries;
                    cout << "Your next guess? ";
                }
            }
        }

        cout << "Want to try another sequence? (y/n) ";
        char try_again;
        cin >> try_again;

        if (try_again == 'N' || try_again == 'n')
        {
            next_seq = false;
        }
        else
        {
            got_it = false;
            reset_seq(puser); //再次尝试游戏则重置游戏信息;
        }
    }
    return;
}

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//ch1.h

#ifndef CH1_H_
#define CH1_H_
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;

typedef const vector<unsigned> *(*pfunc)(int); //声明一个函数指针指向返回值为const vector<unsigned> *参数列表为int的函数;
typedef const vector<unsigned> *pvec;          //声明一个指向const vector<unsigned>对象的指针;

enum num_sequence //定义一些元素序列的值;
{
    ns_unk,
    ns_fib,
    ns_pell,
    ns_lucas,
    ns_tri,
    ns_sq,
    ns_pent,
    ns_cnt = 6,
    ns_wrong_msg = 4
};

struct user_profile
{
    string name;          //玩家名字;
    int guesses;          //玩家猜测次数;
    int correct;          //玩家猜测正确次数;
    int level;            //玩家游戏等级;
    num_sequence cur_seq; //玩家猜测数列的类型;
    pvec cur_seq_vec;     //存储玩家当前猜测数列的元素;
    int pos;              //存储玩家当前猜测数列的随机一个元素位置;
};

extern pfunc gen_elems[];
extern const char *name_seq[];
extern const char *wrong_msg[];
extern int level_size[];

extern bool greet_user(user_profile *);
extern void play_game(user_profile *);
extern void display_statistics(user_profile *);

extern pvec Fibonacci_gen_elems(int);
extern pvec Pell_gen_elems(int);
extern pvec Lucas_gen_elems(int);
extern pvec Triangular_gen_elems(int);
extern pvec Square_gen_elems(int);
extern pvec Pentagonal_gen_elems(int);

extern void set_seq(user_profile *, int);
extern const char *seq_id(user_profile *);
extern void init_user(user_profile *puser, const string &nm, int level);
extern bool correct_guess(user_profile *puser, int guess);

inline void set_seq_vec(user_profile *pu, pvec p) { pu->cur_seq_vec = p; } //设置玩家当前所猜数列, 赋予一个新数列;
inline pvec seq_vec(user_profile *pu) { return pu->cur_seq_vec; }          //获取玩家当前所猜数列的地址;

inline string
user_name(user_profile *puser)
{
    return puser->name; //获取玩家名字;
}

inline num_sequence
seq(user_profile *puser)
{
    return puser->cur_seq; //获取玩家当前猜测的数列类型;
}

inline void
bump_guess(user_profile *puser)
{
    ++puser->guesses; //递增猜测次数;
}

inline void
bump_correct(user_profile *puser)
{
    bump_guess(puser);
    ++puser->correct; //递增猜测次数和猜测正确次数;
}

inline num_sequence
gen_seq_id(unsigned ui)
{
    srand(ui++);
    return static_cast<num_sequence>((rand() % ns_cnt) + 1); //随机选择一个数列进行游戏猜测;
}

/*
    重载打印追踪信息的一系列函数显示当前游戏情况;
*/
inline void trace(const string &where, const string &msg, const string &data)
{
    cerr << where << " " << msg << " " << data << endl;
}

inline void trace(const string &where, const string &msg, int val)
{
    cerr << where << " " << msg << " " << val << endl;
}

inline void trace(const string &where, const string &msg, int val, int val2)
{
    cerr << where << " " << msg << " " << val << ' ' << val2 << endl;
}

inline void trace(const string &where, int val1, int val2)
{
    cerr << where << " " << val1 << " " << val2 << endl;
}

inline bool
check_integrity(int pos) //检查元素索引是否正确;
{
    const int max_elems = 512;

    if (pos <= 0 || pos > max_elems)
    {
        cerr << "!! invalid position: " << pos;
        cerr << " Cannot honor request\n";
        return false;
    }
    return true;
}

inline num_sequence check_sequence(int id) //检查数列索引是否正确;
{
    if (id <= 0 || id > ns_cnt)
    {
        cerr << "!! invalid sequence value: " << id;
        cerr << " Choosing one at random\n";
        id = (id % ns_cnt) + 1;
    }
    return static_cast<num_sequence>(id);
}

#endif

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//Practise1.1.cpp

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string user_name;

    cout << "Please enter your first name: ";
    cin >> user_name;
    cout << "\nHello, " << user_name << " ... and goodbye!\n";

    return 0;
}

//-----------------------------------------------------------;

Practise1.2中注释掉#include <string>导致程序未找到对象string产生错误;注释掉using namespace std;后程序找不到所有包含在命名空间std中的类,产生错误。

Practise1.3中将main改为my_main后操作系统找不到程序的入口点main函数产生错误,因为一个C++程序必定要有一个main函数。

//-----------------------------------------------------------;
//Practise1.4.cpp

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string firstname, lastname;

    cout << "Please enter your first name and last name: ";
    cin >> firstname >> lastname;
    cout << "\nHello, " << firstname << " " << lastname << " ... and goodbye!\n";

    return 0;
}

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//Practise1.5.cpp

#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
using namespace std;

void solve_by_string()
{
    string user_name;

    cout << "Please enter your name: ";
    cin >> user_name;

    switch (user_name.size())
    {
    case 0:
    {
        cout << "Ah, the user with no name. ";
        cout << "Well, ok, hi, user with no name\n";
        break;
    }
    case 1:
    {
        cout << "A 1-character name? Hmm, have you read Kafka?: ";
        cout << "hello, " << user_name << endl;
        break;
    }
    default:
    {
        cout << "Hello, " << user_name;
        cout << " -- happy to make your acquaintance!\n";
        break;
    }
    }
    return;
}

void solve_by_cstyle()
{
    const int maxn = 128;
    char user_name[maxn];

    cout << "Please enter your name: ";
    cin >> setw(maxn) >> user_name; //限制输入的字符数目;

    switch (strlen(user_name))
    {
    case maxn - 1:
    {
        cout << "That is a very big name, indeed -- ";
        cout << "we may have needed to shorten it!\n";
        cout << "In any case,\n";
    }
    default:
    {
        cout << "Hello, " << user_name;
        cout << " -- happy to make your acquaintance!\n";
        break;
    }
    }
    return;
}

int main()
{
    cout << "Output contents by string" << endl;
    solve_by_string();
    cout << "Output contents by cstyle" << endl;
    solve_by_cstyle();

    return 0;
}

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//Practise1.6.cpp

#include <iostream>
#include <vector>
using namespace std;

void solve_by_vector()
{
    int i, t, n;
    int sum = 0;
    vector<int> vt;

    cout << "Please enter a number for number of elements: ";
    cin >> n;
    cout << "Enter " << n << " numbers:" << endl;
    for (i = 0; i < n; ++i)
    {
        cin >> t;
        vt.push_back(t);
    }
    for (i = 0; i < vt.size(); ++i)
    {
        sum += vt[i];
    }
    cout << "Sum of " << n << " elements: " << sum;
    cout << ". Average: " << static_cast<double>(sum) / n << "(Vector)\n";
    return;
}

void solve_by_array()
{
    const int maxn = 100;
    int sum = 0;
    int i, n, a[maxn];

    cout << "Please enter a number for number of elements(0 < n <= 100): ";
    cin >> n;
    if (n <= 0 || n > 100)
    {
        cout << "Uncorrect number! n will be assigned " << maxn << ".\n";
        n = maxn;
    }
    cout << "Enter " << n << " numbers:" << endl;
    for (i = 0; i < n; ++i)
    {
        cin >> a[i];
    }
    for (i = 0; i < n; ++i)
    {
        sum += a[i];
    }
    cout << "Sum of " << n << " elements: " << sum;
    cout << ". Average: " << static_cast<double>(sum) / n << "(Array)\n";
    return;
}

int main()
{
    solve_by_vector();
    solve_by_array();

    return 0;
}

//-----------------------------------------------------------;

//-----------------------------------------------------------;
//Practise1.7.cpp

/*
在源文件Practise1.7.cpp所在目录下创建一个文本文件text.txt
内容如下:
we were her pride of ten she named us:
Phoenix, the Prodigal, Benjamin,
and perspicacious, pacific Suzanne.
*/

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    ifstream infile("text.txt");
    if (!infile)
    {
        cout << "Don't exist words.txt!\n";
        exit(EXIT_FAILURE);
    }
    ofstream outfile("sorted_text.txt");
    if (!outfile)
    {
        cout << "Don't exist sorted_words.txt!\n";
        exit(EXIT_FAILURE);
    }
    string word;
    vector<string> text;

    while (infile >> word)
    {
        text.push_back(word);
    }
    cout << "Original text:\n";
    for (int i = 0; i < text.size(); ++i)
    {
        cout << text[i] << ' ';
    }
    sort(text.begin(), text.end());
    cout << "\nSorted text:\n";
    for (int i = 0; i < text.size(); ++i)
    {
        cout << text[i] << ' ';
        outfile << text[i] << ' ';
    }
    outfile << endl;

    return 0;
}

//-----------------------------------------------------------------

Practise1.8可以参考书上的P210和211页。

//--------------------2021年6月17日 -------------------------

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MZZDX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值