第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日 -------------------------