IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《c++编程思想第1卷》第4章练习题答案 -> 正文阅读

[C++知识库]《c++编程思想第1卷》第4章练习题答案

作者:recommend-item-box type_blog clearfix

4-1

在标准C库中,函数puts()能显示字符数组到控制台上(所以能写puts(“hello”))。试写一个C语言程序,这个程序使用puts(),但不包含<stdio.h>,也不声明这个函数。用C编译器编译这个程序。(有些C++编译器并不与它们的C编译器分开;在这种情况下,可能需要使用一个强制C编译的命令行标记。)然后再用C++编译器对它编译,注意它们之间的区别。
CPP文件:

int main() {
	puts("hello");
}

我用g++编译,只是出现一个警告:

4-1.c: In function 'main':
4-1.c:2:2: warning: implicit declaration of function 'puts' [-Wimplicit-function-declaration]
    2 |  puts("hello");
      |  ^~~~

按道理,应该给出错误提示才对,不知道怎么回事?按照作者的文章里的讲解,这时候应该是编译错误才对,因为使用了未声明的函数。不过这个不重要,我们知道就好了。

4-2

创建一个struct声明,它有单个成员函数,然后为这个成员函数创建定义。创建这个新数据类型的对象,再调用这个成员函数。

#include <iostream>
using namespace std;

struct MyStruct {
	void f();
};

void MyStruct::f() {
	cout << "void MyStruct::f() 被调用" << endl;
}

int main() {
	MyStruct myStruct;
	myStruct.f();
}

输出:

void MyStruct::f() 被调用

4-3

改变练习2的答案,使得struct在合适的“防护”头文件中声明,同时,它的定义在一个cpp文件中,main()在另一个文件中。
MyStruct.h

#ifndef MYSTRUCT_H
#define MYSTRUCT_H
struct MyStruct {
	void f();
};
#endif

MyStruct.cpp

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

void MyStruct::f() {
	cout << "void MyStruct::f() 被调用" << endl;
}

4-3.cpp

#include "MyStruct.h"

int main() {
	MyStruct myStruct;
	myStruct.f();
}

输出:

void MyStruct::f() 被调用

4-4

创建一个struct,它有一个int数据成员,再创建两个全局函数,每个函数都接受一个指向该struct的指针。第一个函数有第二个int参数,并设置这个struct的int为它的参数值,第二个函数显示来自这个struct的int。测试这两个函数。

#include <iostream>
using namespace std;

struct S {
	int a;
};

void setS(S *ps, int a) {
	ps->a = a;
}

void display(S *ps) {
	cout << ps->a << endl;
}

int main() {
	S s;
	setS(&s, 1);
	display(&s);
}

4-5

重写练习4,将两个函数改为这个struct的成员函数,再次测试。

#include <iostream>
using namespace std;

struct S {
	int a;
	void set(int a);
	void display();
};

void S::set(int a) {
	this->a = a;
}

void S::display() {
	cout << a << endl;
}

int main() {
	S s;
	s.set(1);
	s.display();
}

4-6

创建一个类,它使用this关键字(冗余地)执行数据成员选择和成员函数调用。(this表示当前对象的地址)。

#include <iostream>
using namespace std;

struct S {
	int a;
	void set(int a);
	void display();
};

void S::set(int a) {
	this->a = a;
	cout << "当前a为:";
	this->display();
}

void S::display() {
	cout << a << endl;
}

int main() {
	S s;
	s.set(1);
}

输出:

当前a为:1

4-7

让Stash存放double,存入25个double值,然后把它们显示到控制台上。

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

int main() {
  Stash doubleStash;
  doubleStash.initialize(sizeof(double));
  double k = 1.0;
  for(int i = 0; i < 10; i++, k+=0.1)
    doubleStash.add(&k);
  for(int j = 0; j < doubleStash.count(); j++)
    cout << "doubleStash.fetch(" << j << ") = "
         << *(double*)doubleStash.fetch(j)
         << endl;  
  doubleStash.cleanup();
}

输出:

doubleStash.fetch(0) = 1
doubleStash.fetch(1) = 1.1
doubleStash.fetch(2) = 1.2
doubleStash.fetch(3) = 1.3
doubleStash.fetch(4) = 1.4
doubleStash.fetch(5) = 1.5
doubleStash.fetch(6) = 1.6
doubleStash.fetch(7) = 1.7
doubleStash.fetch(8) = 1.8
doubleStash.fetch(9) = 1.9
freeing storage

4-8

用Stack重写练习7。

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

int main(int argc, char* argv[]) {
  Stack doubleStack;
  doubleStack.initialize();
  double d[10];
  for (int i = 0; i < 10; i++) {
	  d[i] = i + 0.1;
	  doubleStack.push(&d[i]);
  }
  // Pop the lines from the Stack and print them:
  double *pd;
  while((pd = (double*)doubleStack.pop()) != 0) {
    cout << *pd << endl; 
  }
  doubleStack.cleanup();
} 

输出:

9.1
8.1
7.1
6.1
5.1
4.1
3.1
2.1
1.1
0.1

4-9

创建一个文件,包含以int为参数的函数f(),用<stdio.h>中的printf()函数将参数int的值显示到控制台上,即写printf("%d\n", i),这里i是希望显示的int。创建另外一个单独的文件,它包含main(),在该文件中声明f()接受float参数。从main()中调用f()。尝试用c++编译器编译和连接这个程序,看看会发生什么事情。再用c编译器编译和连接这个程序,观察运行时会发生什么事情。解释这里的行为。
f.cpp

#include <cstdio>
using namespace std;

void f(int i) {
	printf("%d\n", i);
}

4-9.cpp

extern void f(float f);

int main() {
	f(1.0);
}

C++编译连接出错:

$ make -f gcc.makefile 4-9
g++  -c 4-9.cpp
g++  -c f.cpp
g++ -o4-9 4-9.o f.o
D:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 4-9.o:4-9.cpp:(.text+0x16): undefined reference to `f(float)'
collect2.exe: error: ld returned 1 exit status
make: *** [gcc.makefile:91: 4-9] Error 1

C编译器应该不会出错,因为C编译器只看函数名是否匹配,不管参数。

4-10

发现如何由你的C编译器和C++编译器产生汇编语言。用C写一个函数和用C++写一个带有一个成员函数的struct。由每一个编译器产生汇编语言,找出由你的C函数和C++成员函数产生的函数名,这样,你能看到什么样的名字修饰出现在编译器内部。
4-10.c

void f(int i) {}

使用gcc -S 选项就可以编译成汇编语言:

gcc -S 4-10.c

生成汇编4-10.s:

	.file	"4-10.c"
	.text
	.globl	f
	.def	f;	.scl	2;	.type	32;	.endef
	.seh_proc	f
f:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	.seh_endprologue
	movl	%ecx, 16(%rbp)
	nop
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (Rev5, Built by MSYS2 project) 10.3.0"

函数名就是f,如果用C++编译器呢?

	.file	"4-10.c"
	.text
	.globl	_Z1fi
	.def	_Z1fi;	.scl	2;	.type	32;	.endef
	.seh_proc	_Z1fi
_Z1fi:
.LFB0:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	.seh_endprologue
	movl	%ecx, 16(%rbp)
	nop
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (Rev5, Built by MSYS2 project) 10.3.0"

函数名是_Z1fi,里面包含了参数信息,所以C++函数是可以重载的,因为它的名字会跟参数有关,而C则没有,我们现在再来看一下struct成员函数的名字:
4-10.cpp

struct S {
	void f(int i);
};

void S::f(int i) {}

编译:

g++ -S 4-10.cpp

输出汇编:

	.file	"4-10.cpp"
	.text
	.align 2
	.globl	_ZN1S1fEi
	.def	_ZN1S1fEi;	.scl	2;	.type	32;	.endef
	.seh_proc	_ZN1S1fEi
_ZN1S1fEi:
.LFB0:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	.seh_endprologue
	movq	%rcx, 16(%rbp)
	movl	%edx, 24(%rbp)
	nop
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (Rev5, Built by MSYS2 project) 10.3.0"

函数名为_ZN1S1fEi,名字由结构体名字,函数名,以及参数组成。

4-11

写一个main()中有条件编译代码的程序,使得当预处理器的值被定义时打印一条消息,而不被定义时则打印另外一条消息。编译这一代码段在程序中有#define的试验代码,然后找出你的编译器在命令行上定义预处理器的方法,对它进行试验。
4-11.cpp

#include <iostream>
using namespace std;

int main() {
	#ifdef MYDEBUG
	cout << "定义了MYDEBUG" << endl;
	#else
	cout << "没有定义MYDEBUG" << endl;
	#endif
}

编译:

$ g++ -o 4-11 4-11.cpp && ./4-11
没有定义MYDEBUG

这次在命令行上通过 -D来定义宏:

$ g++ -o 4-11 -DMYDEBUG 4-11.cpp && ./4-11
定义了MYDEBUG

4-12

写一个程序,它带有参数总是为假(零)的assert(),当运行时看发生什么现象。现在用#define NDEBUG编译它,再次运行它,看有什么不同。
4-12.cpp

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

int main() {
	assert(0, "值为false");
	cout << "assert 没有执行" << endl;
}

执行不带NDEBUG宏定义:

$ g++ -o 4-12 4-12.cpp && ./4-12
Assertion failed: 0, file 4-12.cpp, line 6

执行带NDEBUG宏定义:

$ g++ -o 4-12 -DNDEBUG 4-12.cpp && ./4-12
assert 没有执行

4-13

创建一个抽象数据类型,它表示录像带租赁店中的录像带,试考虑在录像带租赁管理系统中为使录像带(Video)类型运行良好而必须的所有数据与运算。包含一个能显示录像带Video信息的print()成员函数。
VideoTape.h

#ifndef VIDEOTAPE_H
#define VIDEOTAPE_H
#include <string>

struct VideoTape {
	int id;// 录像带ID
	std::string name;// 录像带片名
	void setName(std::string &name);//设置名字
	void setId(int id);//设置ID
	void print();//打印信息
};

#endif

VideoTape.cpp

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

void VideoTape::setId(int id) {
	this->id = id;
}

void VideoTape::setName(string &name) {
	this->name = name;
}

void VideoTape::print() {
	cout << "ID:" << id
	     << ",名字:" << name << endl;
}

VideoTapeTest.cpp

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

int main() {
	VideoTape tape;
	tape.setId(1);
	string name = "战狼";
	tape.setName(name);
	tape.print();
}

编译输出:

$ g++ -o VideoTapeTest VideoTapeTest.cpp VideoTape.cpp && ./VideoTapeTest
ID:1,名字:战狼

4-14

创建一个Stack对象,能存放练习13中的Video对象。创建几个Video对象,把它们存放在Stack中,然后用Video::print()显示它们。
4-14.cpp

#include "Stack.h"
#include "VideoTape.h"
using namespace std;

int main(int argc, char* argv[]) {
  Stack videoStack;
  videoStack.initialize();
  string movies[] = {"战狼", "复仇者联盟", "失控玩家", "怒火重案", "峰爆"};
  for (int i = 0, len = sizeof(movies)/sizeof(string); i < len; i++) {	  
	  VideoTape *pvt = new VideoTape;
	  pvt->setId(i);
	  pvt->setName(movies[i]);
	  videoStack.push(pvt);
  }
  // Pop the lines from the Stack and print them:
  VideoTape *pvt;
  while((pvt = (VideoTape*)videoStack.pop()) != 0) {
    pvt->print();
	delete pvt;
  }
  videoStack.cleanup();
} 

编译输出:

ID:4,名字:峰爆
ID:3,名字:怒火重案
ID:2,名字:失控玩家
ID:1,名字:复仇者联盟
ID:0,名字:战狼

4-15

写一个程序,使用sizeof打印出你的编译器的所有基本数据类型的长度。
省略

4-16

修改Stash,使用vector<char>作为它的底层数据结果。
CppLib.h

#include <vector>

struct Stash {
  int size;      // Size of each space
  std::vector<unsigned char> storage;
  // Functions!
  void initialize(int size);
  void cleanup();
  int add(const void* element);
  void* fetch(int index);
  int count();
  void inflate(int increase);
};

CppLib.cpp

#include "CppLib.h"
#include <iostream>
#include <cassert>
using namespace std;

void Stash::initialize(int sz)
{
	size = sz;
}

int Stash::add(const void *element)
{
	unsigned char *e = (unsigned char *)element;
	for (int i = 0; i < size; i++)
	{
		storage.push_back(e[i]);
	}
	return storage.size()/size - 1; // Index number
}

void *Stash::fetch(int index)
{
	// Check index boundaries:
	assert(0 <= index);
	int maxIndex = count() - 1;
	if (index > maxIndex)
		return 0; // To indicate the end
	// Produce pointer to desired element:
	unsigned char *p = new unsigned char[size];
	for (int i = 0; i < size; i++) {
		p[i] = storage[i + index * size];
	}
	return p;
}

int Stash::count()
{
	return storage.size()/size; // Number of elements in CStash
}

void Stash::inflate(int increase)
{
	//vector自动增长,无须操作
}

void Stash::cleanup()
{
	// 我们没有分配任何空间,不需要delete
}

CppLibTest.cpp

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

int main() {
  Stash intStash;
  intStash.initialize(sizeof(int));
  for(int i = 0; i < 100; i++)
    intStash.add(&i);
  for(int j = 0; j < intStash.count(); j++) {
	int *element = (int*)intStash.fetch(j);
    cout << "intStash.fetch(" << j << ") = "
         << *element
         << endl;
	delete element;//需要释放空间,因为我们在fetch里分配了空间
  }
  // Holds 80-character strings:
  Stash stringStash;
  const int bufsize = 80;
  stringStash.initialize(sizeof(char) * bufsize);
  ifstream in("CppLibTest.cpp");
  string line;
  while(getline(in, line))
    stringStash.add(line.c_str());
  int k = 0;
  char* cp;
  while((cp =(char*)stringStash.fetch(k++)) != 0) {
    cout << "stringStash.fetch(" << k << ") = "
         << cp << endl;
	delete cp;//需要释放空间,因为我们在fetch里分配了空间
  }
  intStash.cleanup();
  stringStash.cleanup();
} 

编译输出:

$ g++ -o CppLibTest CppLibTest.cpp CppLib.cpp && ./CppLibTest
intStash.fetch(0) = 0
intStash.fetch(1) = 1
intStash.fetch(2) = 2
intStash.fetch(3) = 3
intStash.fetch(4) = 4
intStash.fetch(5) = 5
intStash.fetch(6) = 6
intStash.fetch(7) = 7
intStash.fetch(8) = 8
intStash.fetch(9) = 9
intStash.fetch(10) = 10
intStash.fetch(11) = 11
intStash.fetch(12) = 12
intStash.fetch(13) = 13
intStash.fetch(14) = 14
intStash.fetch(15) = 15
intStash.fetch(16) = 16
intStash.fetch(17) = 17
intStash.fetch(18) = 18
intStash.fetch(19) = 19
intStash.fetch(20) = 20
intStash.fetch(21) = 21
intStash.fetch(22) = 22
intStash.fetch(23) = 23
intStash.fetch(24) = 24
intStash.fetch(25) = 25
intStash.fetch(26) = 26
intStash.fetch(27) = 27
intStash.fetch(28) = 28
intStash.fetch(29) = 29
intStash.fetch(30) = 30
intStash.fetch(31) = 31
intStash.fetch(32) = 32
intStash.fetch(33) = 33
intStash.fetch(34) = 34
intStash.fetch(35) = 35
intStash.fetch(36) = 36
intStash.fetch(37) = 37
intStash.fetch(38) = 38
intStash.fetch(39) = 39
intStash.fetch(40) = 40
intStash.fetch(41) = 41
intStash.fetch(42) = 42
intStash.fetch(43) = 43
intStash.fetch(44) = 44
intStash.fetch(45) = 45
intStash.fetch(46) = 46
intStash.fetch(47) = 47
intStash.fetch(48) = 48
intStash.fetch(49) = 49
intStash.fetch(50) = 50
intStash.fetch(51) = 51
intStash.fetch(52) = 52
intStash.fetch(53) = 53
intStash.fetch(54) = 54
intStash.fetch(55) = 55
intStash.fetch(56) = 56
intStash.fetch(57) = 57
intStash.fetch(58) = 58
intStash.fetch(59) = 59
intStash.fetch(60) = 60
intStash.fetch(61) = 61
intStash.fetch(62) = 62
intStash.fetch(63) = 63
intStash.fetch(64) = 64
intStash.fetch(65) = 65
intStash.fetch(66) = 66
intStash.fetch(67) = 67
intStash.fetch(68) = 68
intStash.fetch(69) = 69
intStash.fetch(70) = 70
intStash.fetch(71) = 71
intStash.fetch(72) = 72
intStash.fetch(73) = 73
intStash.fetch(74) = 74
intStash.fetch(75) = 75
intStash.fetch(76) = 76
intStash.fetch(77) = 77
intStash.fetch(78) = 78
intStash.fetch(79) = 79
intStash.fetch(80) = 80
intStash.fetch(81) = 81
intStash.fetch(82) = 82
intStash.fetch(83) = 83
intStash.fetch(84) = 84
intStash.fetch(85) = 85
intStash.fetch(86) = 86
intStash.fetch(87) = 87
intStash.fetch(88) = 88
intStash.fetch(89) = 89
intStash.fetch(90) = 90
intStash.fetch(91) = 91
intStash.fetch(92) = 92
intStash.fetch(93) = 93
intStash.fetch(94) = 94
intStash.fetch(95) = 95
intStash.fetch(96) = 96
intStash.fetch(97) = 97
intStash.fetch(98) = 98
intStash.fetch(99) = 99
stringStash.fetch(1) = #include "CppLib.h"
stringStash.fetch(2) = #include <fstream>
stringStash.fetch(3) = #include <iostream>
stringStash.fetch(4) = #include <string>
stringStash.fetch(5) = using namespace std;
stringStash.fetch(6) =
stringStash.fetch(7) = int main() {
stringStash.fetch(8) =   Stash intStash;
stringStash.fetch(9) =   intStash.initialize(sizeof(int));
stringStash.fetch(10) =   for(int i = 0; i < 100; i++)
stringStash.fetch(11) =     intStash.add(&i);
stringStash.fetch(12) =   for(int j = 0; j < intStash.count(); j++) {
stringStash.fetch(13) =         int *element = (int*)intStash.fetch(j);
stringStash.fetch(14) =     cout << "intStash.fetch(" << j << ") = "
stringStash.fetch(15) =          << *element
stringStash.fetch(16) =          << endl;
stringStash.fetch(17) =         delete element;//需要释放空间,因为我们在fetch里分配了空间
stringStash.fetch(18) =   }
stringStash.fetch(19) =   // Holds 80-character strings:
stringStash.fetch(20) =   Stash stringStash;
stringStash.fetch(21) =   const int bufsize = 80;
stringStash.fetch(22) =   stringStash.initialize(sizeof(char) * bufsize);
stringStash.fetch(23) =   ifstream in("CppLibTest.cpp");
stringStash.fetch(24) =   string line;
stringStash.fetch(25) =   while(getline(in, line))
stringStash.fetch(26) =     stringStash.add(line.c_str());
stringStash.fetch(27) =   int k = 0;
stringStash.fetch(28) =   char* cp;
stringStash.fetch(29) =   while((cp =(char*)stringStash.fetch(k++)) != 0) {
stringStash.fetch(30) =     cout << "stringStash.fetch(" << k << ") = "
stringStash.fetch(31) =          << cp << endl;
stringStash.fetch(32) =         delete cp;
stringStash.fetch(33) =   }
stringStash.fetch(34) =   intStash.cleanup();
stringStash.fetch(35) =   stringStash.cleanup();
stringStash.fetch(36) = }

4-17

使用new动态创建下面类型的存储块:int、long、一个能存放100个char的数组、一个能存放100个float的数组。打印它们的地址,然后用delete释放这些存储。
4-17.cpp

#include <iostream>
using namespace std;

int main() {
	int *pi = new int;
	long *pl = new long;
	char *pstr = new char[100];
	float *pfarr = new float[100];
	cout << pi << " " << pl <<
		" " << (void*)pstr << " " << pfarr << endl;
	delete pi;
	delete pl;
	delete pstr;
	delete pfarr;
}

编译输出:

$ g++ -o 4-17 4-17.cpp && ./4-17
0x238893e6400 0x238893e6420 0x238893e6a50 0x238893e6ac0

4-18

写一个带有char*参数的函数。用new动态申请一个char数组,长度与传给这个函数的char数组同。 使用数组下标,从参数中拷贝字符到这个动态申请的数组中(不要忘记null终结符)并且返回拷贝的指针。在main()中,通过传递静态引用字符数组,测试这个函数。然后取这个结果,再传回这个函数。打印这两个字符串和这两个指针,这样我们可以看到它们是不同的存储。使用delete,清除所有的动态存储。
4-18.cpp

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

char *f(const char *p) {
	int len = strlen(p);
	char *pnew = new char[len+1];
	int i = 0;
	while (pnew[i] = p[i]) {
		i++;
	}
	return pnew;
}

int main() {
	const char *p = "Hi Bixby, 今天天气怎么样呢?";
	char *p1 = f(p);
	cout << (void*)p1 << ": " << p1 << endl;
	char *p2 = f(p1);
	cout << (void*)p2 << ": " << p2 << endl;
	delete p1;
	delete p2;
}

编译输出:

$ g++ -o 4-18 4-18.cpp && ./4-18
0x17205ea6400: Hi Bixby, 今天天气怎么样呢?
0x17205ea6a50: Hi Bixby, 今天天气怎么样呢?

4-19

显示在一个结构中声明另一个结构的例子(嵌套结构),声明这两个struct的数据成员,声明和定义这两个struct的成员函数。写一个main(),测试这两个新类型。
4-19.cpp

#include <iostream>
using namespace std;

struct OuterStruct {
	void f();
	struct NestedStruct {
		void f();
	};
};

void OuterStruct::f() {
	cout << "OuterStruct::f()被调用" << endl;
}

void OuterStruct::NestedStruct::f() {
	cout << "OuterStruct::NestedStruct::f()被调用" << endl;
}

int main() {
	OuterStruct outS;
	OuterStruct::NestedStruct nestedS;
	outS.f();
	nestedS.f();
}

编译输出:

$ g++ -o 4-19 4-19.cpp && ./4-19
OuterStruct::f()被调用
OuterStruct::NestedStruct::f()被调用

4-20

结构有多大?写一段代码,打印几个结构的长度。创建几个只有数据成员的结构和几个既有数据成员又有函数成员的结构,然后创建一个完全没有成员的结构。打印出所有这些结构的长度。解释产生完全没有成员的结构的长度结果的原因。
4-20.cpp

#include <iostream>
using namespace std;

struct S1 {
	int a;
};

struct S2 {	
};

struct S3 {
	int a;
	void f(){}
};

int main() {
	S1 s1; S2 s2; S3 s3;
	cout << &s1 << ": " << sizeof(S1) << endl;
	cout << &s2 << ": " << sizeof(S2) << endl;
	cout << &s3 << ": " << sizeof(S3) << endl;
}

编译输出:

$ g++ -o 4-20 4-20.cpp && ./4-20
0x97a01ffd1c: 4
0x97a01ffd1b: 1
0x97a01ffd14: 4

没有数据成员的结构大小为1, 因为任何结构其实都是一个自定义类型,一个类型必须有大小,否则如何创建这个类型的变量呢?所以就给了一个默认的最小值1。

4-21

C++自动创建struct的typedef的等价物,正如在本章中看到的。对于枚举和联合类型也是如此。写一个小程序来证明这一点。
4-21.cpp

enum Color {
	RED, GREEN, BLUE
};

union Data {
	int i;
	long j;
};

int main() {
	Color color = GREEN;
	Data data;
	data.j = 2;
}

编译没有错误,就说明了自动创建typedef等价物:

$ g++ -o 4-21 4-21.cpp && ./4-21

4-22

创建一个存放Stash的Stack,每个Stash存放来自输入文件的5行。使用new创建Stash,读文件进入Stack,然后从这个Stack中提取并按原来的形式打印出来。
4-22.cpp

#include "Stack.h"
#include "CppLib.h"
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

void displayStash(Stash* pStash) {
	int k = 0;
	char* cp;
	while((cp =(char*)pStash->fetch(k++)) != 0)
		cout << "stringStash.fetch(" << k << ") = "
			<< cp << endl;
}

int main() {
	Stack stashStack;	
  	stashStack.initialize();
	ifstream in("4-22.cpp");
	string line;
	int lineNo = 0;
	while (getline(in, line)) {
		Stash *pStash = 0;
		if (lineNo == 0) {
			pStash = new Stash();
			pStash->initialize(sizeof(char) * 80);
			stashStack.push(pStash);
		} else {
			pStash = (Stash*)stashStack.peek();
		}
		if (++lineNo == 5) {
			lineNo = 0;
		}
		pStash->add(line.c_str());
	}

	Stash *pStash;
	while((pStash = (Stash*)stashStack.pop()) != 0) {
		displayStash(pStash);
		pStash->cleanup();
	}
	stashStack.cleanup();
}

编译输出:

$ g++ -o 4-22 4-22.cpp CppLib.cpp Stack.cpp && ./4-22
stringStash.fetch(1) =  }
stringStash.fetch(2) =  stashStack.cleanup();
stringStash.fetch(3) = }
freeing storage
stringStash.fetch(1) =
stringStash.fetch(2) =  Stash *pStash;
stringStash.fetch(3) =  while((pStash = (Stash*)stashStack.pop()) != 0) {
stringStash.fetch(4) =          displayStash(pStash);
stringStash.fetch(5) =          pStash->cleanup();
freeing storage
stringStash.fetch(1) =          if (++lineNo == 5) {
stringStash.fetch(2) =                  lineNo = 0;
stringStash.fetch(3) =          }
stringStash.fetch(4) =          pStash->add(line.c_str());
stringStash.fetch(5) =  }
freeing storage
stringStash.fetch(1) =                  pStash->initialize(sizeof(char) * 80);
stringStash.fetch(2) =                  stashStack.push(pStash);
stringStash.fetch(3) =          } else {
stringStash.fetch(4) =                  pStash = (Stash*)stashStack.peek();
stringStash.fetch(5) =          }
freeing storage
stringStash.fetch(1) =  int lineNo = 0;
stringStash.fetch(2) =  while (getline(in, line)) {
stringStash.fetch(3) =          Stash *pStash = 0;
stringStash.fetch(4) =          if (lineNo == 0) {
stringStash.fetch(5) =                  pStash = new Stash();
freeing storage
stringStash.fetch(1) = int main() {
stringStash.fetch(2) =  Stack stashStack;
stringStash.fetch(3) =          stashStack.initialize();
stringStash.fetch(4) =  ifstream in("4-22.cpp");
stringStash.fetch(5) =  string line;
freeing storage
stringStash.fetch(1) =  while((cp =(char*)pStash->fetch(k++)) != 0)
stringStash.fetch(2) =          cout << "stringStash.fetch(" << k << ") = "
stringStash.fetch(3) =                  << cp << endl;
stringStash.fetch(4) = }
stringStash.fetch(5) =
freeing storage
stringStash.fetch(1) = using namespace std;
stringStash.fetch(2) =
stringStash.fetch(3) = void displayStash(Stash* pStash) {
stringStash.fetch(4) =  int k = 0;
stringStash.fetch(5) =  char* cp;
freeing storage
stringStash.fetch(1) = #include "Stack.h"
stringStash.fetch(2) = #include "CppLib.h"
stringStash.fetch(3) = #include <fstream>
stringStash.fetch(4) = #include <string>
stringStash.fetch(5) = #include <iostream>
freeing storage

4-23

修改练习22,使得创建一个struct,它封装几个Stash的Stack。用户只能通过成员函数添加和得到一行,在这个覆盖下,struct使用Stash的Stack。
省略

4-24

创建一个struct,它存放一个int和一个指向相同struct的另一个实例的指针。写一个函数,它能取这些struct的地址,并且能取一个表示被创建的表的长度的int。这个函数产生这些struct的一个完整链(链表),链表的头指针是这个函数的参数,struct中的指针指向下一个struct。用new产生一些新struct,将计数(对象数目)放在这个int中,对这个链表的最后一个struct的指针位置零值,表示链表结束。写第二个函数,它取这个链表的头指针,并且向后移动到最后,打印出每个struct的指针值和int值。
4-24.cpp

#include <iostream>
using namespace std;

struct Node {
	int value;
	Node *next;
};

void makeLinkedList(Node **ppNode) {
	Node *pHead = NULL;
	int count = 0;
	for (int i = 0; i < 5; i++) {
		Node *p = new Node();
		p->value = ++count;
		p->next = pHead;
		pHead = p;
	}
	*ppNode = pHead;
}

void displayLinkedList(Node *pHead) {
	Node *pNext = pHead;
	while (pNext) {
		cout << "value: " << pNext->value << endl;
		pNext = pNext->next;
	}
}

int main() {
	Node *pHead = NULL;
	makeLinkedList(&pHead);
	displayLinkedList(pHead);
}

编译输出:

$ g++ -o 4-24 4-24.cpp && ./4-24
value: 5
value: 4
value: 3
value: 2
value: 1

4-25

重复练习24, 但是将这些函数放在一个struct内部,而不是用“原始”的struct和函数。
4-25.cpp

#include <iostream>
using namespace std;

struct Node {
	int value;
	Node *next;
};

struct LinkedList {
	Node *pHead;
	void makeLinkedList();
	void displayLinkedList();
};

void LinkedList::makeLinkedList() {
	pHead = NULL;
	int count = 0;
	for (int i = 0; i < 5; i++) {
		Node *p = new Node();
		p->value = ++count;
		p->next = pHead;
		pHead = p;
	}
}

void LinkedList::displayLinkedList() {
	Node *pNext = pHead;
	while (pNext) {
		cout << "value: " << pNext->value << endl;
		pNext = pNext->next;
	}
}

int main() {
	LinkedList lst;
	lst.makeLinkedList();
	lst.displayLinkedList();
}

编译输出:

$ g++ -o 4-25 4-25.cpp && ./4-25
value: 5
value: 4
value: 3
value: 2
value: 1
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 09:54:07  更:2021-09-18 09:59:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 20:51:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码