文章目录
0 编译运行本章例程
0.1 指针
//指针
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main(int argc, char** argv){
int x = 5;
int* p = &x;//指向x地址的指针
cout << "x = " << x << endl;
*p = 6;
cout << "x = " << x <<endl;
return 0;
}
0.2 函数指针
//函数指针
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int next(int n){
return n + 1;
}
int main(int argc, char** argv){
int (*fp)(int);
fp = &next;//将fp指向next函数
//fp = next;
int i = (*fp)(6);
// int i = fp(6);
cout << i <<endl;
return 0;
}
0.3 调用指向函数的指针
//返回指向函数的指针
#include <iostream>
#include <ostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
int test1(int a){
return a + 1;
}
int test2(int b){
return b + 3;
}
void write(ostream& out, int test(int ), int a){
out << test(a) << endl;
}
void write2(ostream& out, int (*test)(int ), int a){
out << test(a) << endl;
}
int main(int argc, char** argv){
int x = 10;
write(cout, test1, x);
write(cout, test2, x);
write2(cout, test1, x);
write2(cout, test2, x);
return 0;
}
0.4 返回指向函数的指针
//返回指向函数的指针
#include <iostream>
#include <ostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
int test1(int& a){
a++;
return a;
}
//声明
typedef int (*test_fp)(int& );
test_fp test3(int&);
//定义
test_fp test3(int& x){
int (*fp)(int& ) = &test1;
(*fp)(x);//x的值变为11
return fp;
}
//声明
int (*test4(int& ))(int& );
//定义
int (*test4(int& x))(int& ){
int (*fp)(int& ) = &test1;
(*fp)(x);//x的值变为11
return fp;
}
void write2(ostream& out, int test(int& ), int a){
out << test(a) << endl;
}
int main(int argc, char** argv){
int x = 10 ;
//test传递的时引用会导致x变化,write传递的没哟引用,计算出值后会被丢弃
//在10的基础上加2
//第一调用test时加1,由于是引用,x会实际变为11,第二次调用write时加1,虽然结果是12,但是x值还是11
write2(cout, test3(x), x);
write2(cout, test4(x), x);//在11的基础上加2
return 0;
}
0.5 初始化字符串指针数组
//初始化字符串指针数组
#include <iostream>
#include <cstddef>
using std::cout;
using std::cin;
using std::endl;
using std::string;
string letter_grade(double grade){
static const double numbers[] = {
97, 94, 90, 87, 84, 80, 77, 74, 70, 60, 0
};
static const char* const letters[] = {
"A+", "A", "B+", "B", "C+", "C", "C-", "D", "F"
};
static const size_t ngrades = sizeof(numbers)/ sizeof(*numbers);//计算该元素的个数
for (size_t i = 0; i < ngrades; ++i) {
if(grade >= numbers[i]){
return letters[i];
}
}
return "? \? \?";//C++不允许存在连续两个或多个问号
}
int main(int argc, char** argv){
const char hello[] = {'H', 'e','l','l','o','\0'};
static char hello3[] = {'H', 'e','l','l','o'};//初始化化时,自动末尾加'\0'
string hello2 = "Hello";
//测试一
// if(hello3 == hello2){
// cout <<"Yes";
// }else{
// cout <<"No";
// }
//测试二
// cout << strlen(hello) << endl;//不包括末尾的'\0'
//测试三
// string s(hello, hello + strlen(hello));
// cout << s <<endl;
//测试四
cout << letter_grade(88) << endl;
return 0;
}
0.6 main函数的参数
//mian函数的参数
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main(int argc, char** argv){
if(argc > 1){
cout << argv[1];
for (int i = 2; i != argc; ++i) {
cout <<" " << argv[i];
}
}
cout << endl;
cout << argc <<endl;
return 0;
}
0.7 处理单个文件读写
//处理文件的读写
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
int main(int argc, char** argv){
string file = "/Users/macbookpro/CLionProjects/ACM/infile.txt";
ifstream infile(file.c_str());
// ifstream infile("/Users/macbookpro/CLionProjects/ACM/infile.txt");//等价于上面的两行
ofstream outfile("/Users/macbookpro/CLionProjects/ACM/outfile.txt");
string s;
while(getline(infile, s)){
outfile << s <<endl;
}
return 0;
}
0.8 处理多个文件的读写
//多个文件读入
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::string;
using std::cerr;
int main(int argc, char** argv){
int fail_count = 0;
for (int i = 1; i < argc; ++i) {
ifstream in(argv[i]);
if(in){
string s;
while(getline(in, s)){
cout << s << endl;
}
}else{
cerr << "cannot open file" << argv[i] <<endl;
fail_count++;
}
return fail_count;
}
return 0;
}
/*
/Users/macbookpro/CLionProjects/ACM/infile2.txt /Users/macbookpro/CLionProjects/ACM/infile.txt
*/
0.9 自动管理内存
//自动管理内存
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
//故意产生一个无效指针
int* invalid_pointer(){//c++并不会发现错误
int x;
return &x;//紧急灾难
}
int* pointer_to_static(){
static int x;
return &x;
}
int main(int argc, char** argv){
cout << invalid_pointer() << endl;
cout << pointer_to_static();
return 0;
}
0.10 为对象分配释放内存
//为对象分配释放内存
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main(int argc, char** argv){
int* p = new int(42);
++ *p;
delete p;
cout << *p;//指针p依然存在,且指向的地址不变。
return 0;
}
0.11 为数组分配和释放空指针
//为数组分配和释放指针
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
int main(int argc, char** argv){
int n = 0;
int* p = new int[n];//会返回一个有效但无意义的off-the-end指针
//可以想象成一个指向(如果存在的话)首元素的指针
vector<int> v(p, p + n);
delete [] p;
return 0;
}
0.12 为数组分配释放内存
//为数组分配释放内存
#include <iostream>
#include <cstddef>
#include <string>
using std::cout;
using std::cin;
using std::endl;
size_t strlen(const char* p){
size_t size = 0;
while(*p++ != '\0'){
++size;
}
return size;
}
template<class In, class Out>
Out copy(In begin, In end, Out dest){
while (begin != end){
*dest++ = *begin++;
}
return dest;
}
char* duplicate(const char* p){
size_t length = strlen(p) + 1;//为空字符预留空间'\0'
char* result = new char[length];
copy(p, p + length, result);
return result;
}
int main(int argc, char** argv){
char str[] = {'i', 'l', 'o', 'v', 'e'};
std::string s = duplicate(str);
cout << s;
return 0;
}
1 重写学生成绩程序,要求生成字母成绩
头文件
//
// grade.h
//
#ifndef ACM_GRADE_H
#define ACM_GRADE_H
#include<vector>
#include"Student_info.h"
double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
//double grade(const Student_info&);
#endif
//
// tudent_info.h
//
#ifndef ACM_Student_info
#define ACM_Student_info
#include <iostream>
#include <string>
#include <vector>
//struct student_info{
// std::string name;
// double midterm, final;
// std::vector<double> homework;
//
// std::istream& read(std::istream&);
// double garde() const;
//};
class Student_info{
public:
Student_info();//构造一个空的Student_info对象
Student_info(std::istream&);//读一个流从而构造一个对象
bool vaild() const{ return ! homework.empty();}//检查对象是否为空
double grade() const;
std::istream& read(std::istream& );
std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
//std::istream& read(std::istream&, Student_info&);
#endif
#include <iostream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <iomanip>
#include <ios>
#include "Student_info.h"
#include "grade.h"
using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::vector;
using std::string;
using std::max;
using std::sort;
using std::domain_error;
using std::setprecision;
using std::streamsize;
//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }
bool compare(const Student_info& x, const Student_info& y){
return x.name() < y.name();
}
istream& Student_info::read(istream& in){
in >> n >> midterm >> final;
read_hw(in, homework);
return in;
}
istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}
double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(vec.begin(), vec.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}
double Student_info::grade() const {
//::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
return ::grade(midterm, final, homework);
}
double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2
double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}
string letter_grade(double grade){//新增
//分数成绩的界限
static const double numbers[] = {
97, 94, 90, 87, 84, 80, 77, 74, 70, 60, 0
};
//字母成绩表示
static const char* const letter[] = {
"A+","A","A-","B+","B","B-","C+","C","C-","D","F"
};
//根据数组的大小计算成绩的个数
//和单个元素的大小
static const size_t ngrades = sizeof(numbers)/sizeof(*numbers);
for (size_t i = 0; i < ngrades; ++i) {
if(grade >= numbers[i]){
return letter[i];
}
}
return "? \? \?";
}
int main(int argc, char const *argv[]){
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while(record.read(cin)){//
maxlen = max(maxlen, record.name().size());//
students.push_back(record);
}
sort(students.begin(), students.end(), compare);
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()//
<<string(maxlen + 1 - students[i].name().size(), ' ');
// try{
// double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
if(students[i].vaild() == true){
double final_grade = students[i].grade();
// streamsize prec = cout.precision();
// cout << setprecision(3) << final_grade
// << setprecision(prec) << endl;
cout << letter_grade(final_grade) <<endl;//新增
}else{
cout << "homework is empty!"<< endl;
}
}
return 0;
}
2 重写median函数,使之可以通过向量或C++自带的数组以调用该函数。该函数要求可以调用容纳任何算数类型的容器。
//求中位数
#include <iostream>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cstddef>
using std::cin; using std::cout;
using std::endl;
using std::vector;
using std::domain_error;
using std::sort;
using std::ostream;
template<class In>
In median(In begin, In end){
size_t size = std::distance(begin, end);
if(size == 0){
throw domain_error("median of an empty vector");
}
sort(begin, end);
size_t mid = size /2;
In ans = begin + mid;//偶数个
if(size % 2 == 0){//奇数个
*ans = (*(begin + mid) + *(begin + mid - 1)) / 2;
// *ans = (begin[mid] + begin[mid -1])/2;//与上面等价
}
return ans;
}
int main(int argc, char const *argv[])
{
vector<double> v= { 85, 74, 75, 45, 49 , 67};
cout << *median(v.begin(), v.end()) << endl;
return 0;
}
3 要求写一个不会改变容器内元素顺序的mdian函数
//求中位数
#include <iostream>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cstddef>
using std::cin; using std::cout;
using std::endl;
using std::vector;
using std::domain_error;
using std::sort;
using std::ostream;
template<class In, class T>
T median(In begin, In end){
size_t size = std::distance(begin, end);
if(size == 0){
throw domain_error("median of an empty vector");
}
//把容器内的元素复制到向量中,进行排序计算,以免影响原序列
std::vector<T> v;
while(begin != end){
v.push_back(*begin++);
}
std::sort(v.begin(), v.end());
size_t mid = size /2;
return size % 2 == 0 ? (v[mid] + v[mid -1]) /2: v[mid] ;
}
int main(int argc, char const *argv[])
{
vector<double> v= { 85, 74, 75, 45, 49 , 67};
double v2[] = {85, 74, 75, 45, 49 , 67};
cout << median<vector<double >::iterator,double>(v.begin(), v.end()) << endl;
for (vector<double >::const_iterator it = v.begin(); it != v.end(); ++it) {
cout << *it <<" ";
}
cout << endl;
cout << median<double*, double>(v2, v2 + (sizeof(v2)/ sizeof(*v2))) << endl;
for (int i = 0; i < (sizeof(v2)/ sizeof(*v2)); ++i) {
cout << v2[i] << " ";
}
return 0;
}
4 写一个类可以存储strings的链表(也就是写一个vector<string>)
头文件
#ifndef TEST_H
#define TEST_H
#include <string>
class String_list{
public:
typedef std::string* iterator;
typedef const std::string* const_iterator;
//构造函数
String_list():l(new std::string[1]),size(0),max(1){
f = l + max;
}
//复制构造函数
String_list(const String_list& s){ create(s.begin(), s.end());}
//赋值运算符函数
String_list& operator=(const String_list& rhs){
if(&rhs != this){
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
//析构函数
~String_list(){ uncreate();};
void push_back(std::string);
std::string* begin(){ return l;}
const std::string* begin() const{ return l;}
std::string* end(){ return f; }
const std::string* end() const { return f;}
private:
std::string* l;//指针指向第一个元素
std::string::size_type size;//拥有有效数值的最大长度
std::string::size_type max;//分配空间的最大长度
std::string* f;//指针指向存储元素的最后一个后面的指针
void grow();
void create(const std::string*, const std::string*);
void uncreate(){
delete[](l);
l = f = 0;
size = max = 0;
}
};
#endif
主函数
#include <iostream>
using std::cin; using std::cout;
using std::endl;
#include <string>
using std::string;
#include "test.h"
#include <algorithm>
using std::find_if;
void String_list::create(const_iterator begin, const_iterator end){
size = max = end - begin;
l = new string[size];
iterator temp = l;
while(begin != end){
*temp++ = *begin++;
}
f = l + size;
}
//push_back函数的成员函数
void String_list::grow() {
//扩展对象大小时,为对象分配实际使用的两倍大小的内存空间
max *= 2;
iterator new_l = new string[max];
//分配新的内存空间并将已存在的对象元素内容复制搭配新内存中
for (string::size_type i = 0; i != size; ++i) {
new_l[i] = l[i];
}
//删除原来的内存空间
delete[](l);
//重置指针,使其指向新分配的内存空间
l = new_l;
f = new_l + max;
}
void String_list::push_back(std::string str) {
if(size == max){
grow();
}
l[size++] = str;
}
bool not_space(char c){
return !isspace(c);
}
bool space(char c){
return isspace(c);
}
String_list split(const string& str){
typedef string::const_iterator iter;
String_list ret;
iter i = str.begin();
while(i != str.end()){
i = find_if(i, str.end(), not_space);
iter j = find_if(i, str.end(), space);
if(i != str.end()){
ret.push_back(string(i, j));
}
i = j;
}
return ret;
}
int main(int argc, char ** argv){
String_list s;
//复制构造函数
s.push_back("I");
s.push_back("love");
s.push_back("you");
s.push_back("!");
//复制构造函数
String_list s2 = s;
String_list::iterator iter = s2.begin();
while (iter != s2.end())
cout << *iter++ << endl;
//测双向迭代器
while(iter != s2.begin()){
cout << *(--iter) <<endl;
}
//测赋值运算符
// String_list s3;
// s3.push_back("I");
// s3.push_back("hate");
// s3.push_back("U");
// s2 = s3;
// for (String_list::iterator it = s2.begin(); it != s2.end(); ++it) {
// cout << *it << " ";
// }
//测split函数
// string s;
// while(cin >> s){
// String_list res = split(s);
// for (string* it = res.begin(); it != res.end(); ++it) {
// cout << *it << endl;
// }
// }
return 0;
}
5 为上面的String_list类写一个双向迭代器(不用尾指针)
#ifndef TEST_H
#define TEST_H
#include <string>
class String_list{
public:
typedef std::string* iterator;
typedef const std::string* const_iterator;
//构造函数
String_list():l(new std::string[1]),size(0),max(1){}
//复制构造函数
String_list(const String_list& s){ create(s.begin(), s.end());}
//赋值运算符函数
String_list& operator=(const String_list& rhs){
if(&rhs != this){
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
//析构函数
~String_list(){ uncreate();};
void push_back(std::string);
std::string* begin(){ return l;}
const std::string* begin() const{ return l;}
std::string* end(){ return l + size; }
const std::string* end() const { return l + size;}
private:
std::string* l;//指针指向第一个元素
std::string::size_type size;//有有效数值的最大长度
std::string::size_type max;//分配空间的最大长度
void grow();
void create(const std::string*, const std::string*);
void uncreate(){
delete[](l);
l = 0;
size = max = 0;
}
};
#endif
#include <iostream>
using std::cin; using std::cout;
using std::endl;
#include <string>
using std::string;
#include "test.h"
#include <algorithm>
using std::find_if;
void String_list::create(const_iterator begin, const_iterator end){
size = max = end - begin;
l = new string[size];
iterator temp = l;
while(begin != end){
*temp++ = *begin++;
}
}
//push_back函数的成员函数
void String_list::grow() {
//扩展对象大小时,为对象分配实际使用的两倍大小的内存空间
max *= 2;
iterator new_l = new string[max];
//分配新的内存空间并将已存在的对象元素内容复制搭配新内存中
for (string::size_type i = 0; i != size; ++i) {
new_l[i] = l[i];
}
//删除原来的内存空间
delete[](l);
//重置指针,使其指向新分配的内存空间
l = new_l;
}
void String_list::push_back(std::string str) {
if(size == max){
grow();
}
l[size++] = str;
}
bool not_space(char c){
return !isspace(c);
}
bool space(char c){
return isspace(c);
}
String_list split(const string& str){
typedef string::const_iterator iter;
String_list ret;
iter i = str.begin();
while(i != str.end()){
i = find_if(i, str.end(), not_space);
iter j = find_if(i, str.end(), space);
if(i != str.end()){
ret.push_back(string(i, j));
}
i = j;
}
return ret;
}
int main(int argc, char ** argv){
String_list s;
//复制构造函数
s.push_back("I");
s.push_back("love");
s.push_back("you");
s.push_back("!");
//
//复制构造函数
String_list s2 = s;
String_list::iterator iter = s2.begin();
while (iter != s2.end())
cout << *iter++ << endl;
//测双向迭代器
while(iter != s2.begin()){
cout << *(--iter) <<endl;
}
//
//
// //测赋值运算符
// String_list s3;
// s3.push_back("I");
// s3.push_back("hate");
// s3.push_back("U");
//
// s2 = s3;
// for (String_list::iterator it = s2.begin(); it != s2.end(); ++it) {
// cout << *it << " ";
// }
//测split函数
// string s;
// while(cin >> s){
// String_list res = split(s);
// for (string* it = res.begin(); it != res.end(); ++it) {
// cout << *it << endl;
// }
// }
return 0;
}
6 重写split函数将结果输出到String_list类中。
#ifndef TEST_H
#define TEST_H
#include <string>
class String_list{
public:
typedef std::string* iterator;
typedef const std::string* const_iterator;
//构造函数
String_list():l(new std::string[1]),size(0),max(1){}
//复制构造函数
String_list(const String_list& s){ create(s.begin(), s.end());}
//赋值运算符函数
String_list& operator=(const String_list& rhs){
if(&rhs != this){
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
//析构函数
~String_list(){ uncreate();};
void push_back(std::string);
std::string* begin(){ return l;}
const std::string* begin() const{ return l;}
std::string* end(){ return l + size; }
const std::string* end() const { return l + size;}
private:
std::string* l;//指针指向第一个元素
std::string::size_type size;//有有效数值的最大长度
std::string::size_type max;//分配空间的最大长度
void grow();
void create(const std::string*, const std::string*);
void uncreate(){
delete[](l);
l = 0;
size = max = 0;
}
};
#endif
#include <iostream>
using std::cin; using std::cout;
using std::endl;
#include <string>
using std::string;
#include "test.h"
#include <algorithm>
using std::find_if;
void String_list::create(const_iterator begin, const_iterator end){
size = max = end - begin;
l = new string[size];
iterator temp = l;
while(begin != end){
*temp++ = *begin++;
}
}
//push_back函数的成员函数
void String_list::grow() {
//扩展对象大小时,为对象分配实际使用的两倍大小的内存空间
max *= 2;
iterator new_l = new string[max];
//分配新的内存空间并将已存在的对象元素内容复制搭配新内存中
for (string::size_type i = 0; i != size; ++i) {
new_l[i] = l[i];
}
//删除原来的内存空间
delete[](l);
//重置指针,使其指向新分配的内存空间
l = new_l;
}
void String_list::push_back(std::string str) {
if(size == max){
grow();
}
l[size++] = str;
}
bool not_space(char c){
return !isspace(c);
}
bool space(char c){
return isspace(c);
}
String_list split(const string& str){
typedef string::const_iterator iter;
String_list ret;
iter i = str.begin();
while(i != str.end()){
i = find_if(i, str.end(), not_space);
iter j = find_if(i, str.end(), space);
if(i != str.end()){
ret.push_back(string(i, j));
}
i = j;
}
return ret;
}
int main(int argc, char ** argv){
// String_list s;
// //复制构造函数
// s.push_back("I");
// s.push_back("love");
// s.push_back("you");
// s.push_back("!");
// //复制构造函数
// String_list s2 = s;
//
// String_list::iterator iter = s2.begin();
// while (iter != s2.end())
// cout << *iter++ << endl;
// //测双向迭代器
// while(iter != s2.begin()){
// cout << *(--iter) <<endl;
// }
// //测赋值运算符
// String_list s3;
// s3.push_back("I");
// s3.push_back("hate");
// s3.push_back("U");
//
// s2 = s3;
// for (String_list::iterator it = s2.begin(); it != s2.end(); ++it) {
// cout << *it << " ";
// }
// 测split函数
string s;
while(cin >> s){
String_list res = split(s);
for (string* it = res.begin(); it != res.end(); ++it) {
cout << *it << endl;
}
}
return 0;
}