4.1
(a) 数组大小用变量定义,非法
(b) 数组大小用函数返回值定义,非法
(c) 数组大小用整型表达式定义,合法
(d) 用字符串字面值初始化字符数组,数组大小不够。字符串字面值还有末尾的'\0'。
4.2
函数外定义,sa都是空字符串,ia都是0。
函数内定义,sa2都是空字符串,ia2都是未定义值。
4.3
(a) 是对的。
(b) 是错误的,vector不能用初始化列表来初始化,也不能用普通数组来初始化。
(c) 是错的。不能用一个数组直接初始化另一个数组(用一个数组整体赋值给另一个数组)
(d) 是错误的,不能用一个vector去初始化一个数组。
4.4
int a[10] = {1,2,3}; // 初始化一部分元素
int a[] = {1,2,3}; // 初始化全部元素
4.5
使用数组的缺点:
- 更容易溢出,也就是下标越界。
- 缺少一些方便的函数,比如size, empty等
- 不能动态添加数组元素
4.6
当ix=10的时候,下标越界,下标从0开始,到size-1.
size_t ix=1,这个错误,应该是 ix=0;
ix<=array_size,这个错误,应该是 ix<array_size
4.7
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
int main() {
int a[] = {1, 2, 3};
size_t size = sizeof(a) / sizeof(a[0]);
int b[size];
for(size_t i=0; i<size; i++)
b[i] = a[i];
for (size_t i=0; i<size; i++)
printf("%d\t", b[i]);
printf("\n");
vector<int> c;
for(size_t i=0; i<size; i++)
c.push_back(a[i]);
vector<int> d(c);
for(vector<int>::const_iterator iter=d.begin(); iter!=d.end(); iter++)
cout << *iter << endl;
return 0;
}
4.8
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
bool isEqual(int a[], int asz, int b[], int bsz) {
if(asz!=bsz)
return false;
for(size_t i=0; i<asz; i++)
if(a[i] != b[i])
return false;
return true;
}
bool isEqual2(vector<int> &a, vector<int>& b) {
if(a.size()!=b.size())
return false;
for(vector<int>::size_type i=0; i<a.size(); i++)
if(a[i] != b[i])
return false;
return true;
}
int main() {
int a[] = {1,2,3};
int b[] = {2,3,4};
int c[] = {1,2,3};
printf("%s\n", isEqual(a, 3, b, 3)?"is equal": "not equal");
printf("%s\n", isEqual(a, 3, c, 3)?"is equal": "not equal");
printf("%s\n", isEqual(b, 3, c, 3)?"is equal": "not equal");
vector<int> aa, bb, cc;
aa.push_back(1);
aa.push_back(2);
aa.push_back(3);
bb.push_back(2);
bb.push_back(3);
bb.push_back(4);
cc.push_back(1);
cc.push_back(2);
cc.push_back(3);
printf("%s\n", isEqual2(aa, bb)?"is equal": "not equal");
printf("%s\n", isEqual2(aa, cc)?"is equal": "not equal");
printf("%s\n", isEqual2(bb, cc)?"is equal": "not equal");
return 0;
}
4.9
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
int main() {
int a[10];
for(size_t i=0; i<10; i++)
a[i] = i;
return 0;
}
4.10
将*号和标识符连在一起,适合于一次定义多个指针。看到标识符前面有个*号,就可以认为是指针,指向的元素类型就是*号前面的类型。
*号和类型连在一起,容易认为是一种数据类型,会在定义多个变量的时候,造成混乱。
4.11
(a) 合法的,定义了一个指针,但是没有初始化,是个野指针。
(b) 合法
(c) 非法,指针类型和初始化使用的变量类型不一致
(d) 合法,又是野指针
(e) 合法,标准的定义空指针
(f) 合法,同上
4.12
不能检查是否指向了一个有效的对象。指针只是对象的地址,也就是一片内存的地址,至于这片内存上的对象是不是存活,什么状态,都不清楚。
4.13
void*指针,可以指向任何类型的地址,他表示,只是指向了一片内存,不清楚内存上有什么类型。
第二个指针初始化不合法的原因在于,类型不一致。
4.14
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
int main() {
// 修改指针所指向对象的值
int a;
int *p = &a;
cin >> a;
cout << *p << endl;
*p += 1;
cout << *p << endl;
// 修改指针的值
int b;
cin >> b;
p = &b;
cout << *p << endl;
return 0;
}
4.15
指针和引用的区别:
- 指针是所指对象的地址,引用是所关联对象的别名。
- 指针可以修改,引用不能重新关联。
- 指针可以判空,引用定义的时候必须初始化,没有空的引用。
- 有指针的指针,没有引用的引用。
4.16
将j变成42*1024,将i变成42*42.
4.17
作用是将p1指向p2,先计算p2与p1的距离,p1加上这个距离就是p2所指向的地址。当p1是const类型是,该操作非法。
4.18
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
int main() {
int a[] = {1,2,3};
size_t sz = sizeof(a) / sizeof(a[0]);
for(int *pbegin=a, *pend=a+sz; pbegin!=pend; pbegin++)
*pbegin = 0;
return 0;
}
4.19
(a) 定义一个int
(b) 定义一个常量int,定义的时候没有初始化,非法
(c) 定义一个指针,指向的类型是const int
(d) 定义一个const指针,指向的类型是int,定义的时候必须初始化,之后不能指向其他的地址,该项明显非法。
(e) 定义一个const指针,指向的类型也是const int,非法,定义的时候没有初始化,其初始化的对象可以是const也可以是非const,但是都不能修改该指针指向别的地址,也不能修改该指针指向的值。
4.20
(d) 是非法的,ic是一个const int,但是cpi是一个const指针,指向的是个非const int,通过cpi是可以修改所指向的值的。其余都正确。
(a) 是普通int
(b) 是const int;
(c) 是非const指针,指向const int
(e) 是const指针,指向const int
4.21
(a) 合法,用const变量赋值非const变量
(b) 合法,pic是个指针,指向const int类型的变量,ic就是 const int,取ic的地址给给pic,使其指向ic
(c) 非法, cpi是个const指针,指向int,初始化之后不能再被赋值
(d) 合法,虽然pic和cpic的类型不一致,但是pic指向的是一个const int,cpic也是指向的一个const int
(e) 非法,cpic是一个const指针,初始化之后不能被赋值
(f) 非法,ic是一个const int,初始化之后不能被赋值
4.22
第一个循环是死循环,cp是指针,会一直++;
第二个循环是正常的循环,*cp等于'\0'时,条件判断失败
4.23
想遍历输出字符串,但是循环不会停止,直到*cp=='\0'为止。因为C风格字符串没有'\0'结尾。
4.24
区别是,strncpy需要指定拷贝的字节数,也就是拷贝字符串的前几个字符。优点是有效的降低的数组溢出的可能性。安全性更高。
strcpy不需要指定拷贝的字节数。使用更便利。
两者都假设C风格的字符串以'\0'结尾,切被拷贝字符数组有足够的空间。
4.25
#include <iostream>
using namespace std;
int compare_string(const string &s1, const string &s2) {
if(s1 == s2)
return 0;
else if(s1 > s2)
return 1;
else
return -1;
}
int compare_c_style_string(const char* s1, size_t s1_sz, const char *s2, size_t s2_sz) {
if(s1_sz > s2_sz)
return 1;
else if (s1_sz < s2_sz)
return -1;
else {
for(size_t i=0; i<s1_sz; i++)
if (s1[i] > s2[i])
return 1;
else if (s1[i] < s2[i])
return -1;
return 0;
}
}
int main() {
string s1("zhaosp"), s2("zhaa");
cout << compare_string(s1, s2) << endl;
cout << compare_c_style_string(s1.c_str(), s1.size(), s2.c_str(), s2.size()) << endl;
s1 = "zhaosp";
s2 = "zhaosp";
cout << compare_string(s1, s2) << endl;
cout << compare_c_style_string(s1.c_str(), s1.size(), s2.c_str(), s2.size()) << endl;
s2 = "zhaosz";
cout << compare_string(s1, s2) << endl;
cout << compare_c_style_string(s1.c_str(), s1.size(), s2.c_str(), s2.size()) << endl;
return 0;
}
4.26
#include <iostream>
#define INIT_SIZE 10
#define INCREMENTAL_SIZE 10
using namespace std;
int main() {
/*
* 从标准输入读取一个C风格字符串,fixme: run出一个随机性的crash
*
* */
char ch;
char *p = (char*)malloc(sizeof(char) * INIT_SIZE);
size_t count(0), size(INIT_SIZE);
while (true) {
scanf("%c", &ch);
if(count == size) {
printf("realloc memory\n");
p = (char*)realloc(p, sizeof(char) * (size + INCREMENTAL_SIZE));
}
p[count++] = ch;
if(ch == '\n') {
p[count] = '\0';
break;
}
}
printf("\nc style string: %s", p);
free(p);
return 0;
}
4.27
delete [] pa;
4.28
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int main() {
vector<int> a;
int b;
while (cin >> b)
a.push_back(b);
int *p = new int[a.size()];
for(size_t i=0; i<a.size(); i++)
p[i] = a[i];
for(size_t i=0; i<a.size(); i++)
cout << p[i] << endl;
delete [] p;
return 0;
}
4.29
(a) 哪两个?
(b) 预计一样。还不知道具体什么原因。
4.30
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int main() {
char str1[10] = "fule";
const char *str2 = "sbhwt";
strcat(str1, str2);
printf("%s\n", str1);
string s1("fule"), s2(str2);
cout << s1 + s2 << endl;
return 0;
}
4.31
纯C风格的处理方式,回车换行,结束一个字符串的处理,quit退出程序。
#include <iostream>
#include <cstring>
#define INIT_SIZE 10
#define INCREMENTAL_SIZE 5
using namespace std;
int main() {
char test[5];
scanf("%s", test); // 不会考虑到字符数组的长度是否合适,是否溢出,通常溢出会crash
printf("%s", test);
// 脱了裤子放屁的方式
string s;
cin >> s;
char tmp[s.size()+1];
for(size_t i=0; i<s.size(); i++)
tmp[i] = s[i];
tmp[s.size()] = '\0';
printf("%s", tmp);
while (true) {
char ch;
char *p = (char*)malloc(sizeof(char) * INIT_SIZE);
size_t count(0), size(INIT_SIZE);
while (true) {
scanf("%c", &ch);
if(ch == '\n')
break;
if(count == size-1) {
p = (char*)realloc(p, sizeof(char) * size + INCREMENTAL_SIZE);
size += INCREMENTAL_SIZE;
}
p[count++] = ch;
}
p[count] = '\0';
printf("%s", p);
int flag = strcmp("quit", p);
free(p);
if(flag==0)
break;
}
return 0;
}
4.32
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a[] = {0,1,2,3};
vector<int> b(a, a + sizeof(a)/sizeof(a[0]));
for(vector<int>::const_iterator iter=b.begin(); iter!=b.end(); iter++)
cout << *iter << endl;
return 0;
}
4.33
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> a(3, 1);
int b[a.size()];
for(vector<int>::size_type i=0; i<a.size(); i++)
b[i] = a[i];
for(size_t i=0; i<a.size(); i++)
cout << b[i] << endl;
return 0;
}
4.34
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int main() {
vector<string> vs;
string tmp;
while (cin >> tmp) {
if (tmp == "quit")
break;
vs.push_back(tmp);
}
for(vector<string>::const_iterator iter=vs.begin(); iter!=vs.end(); iter++)
printf("%s\t", iter->c_str());
printf("\n");
char* arr[vs.size()];
for(vector<string>::size_type i=0; i<vs.size(); i++) {
size_t sz = vs[i].size();
arr[i] = new char[sz +1];
strcpy(arr[i], vs[i].c_str());
arr[i][sz] = '\0';
}
for(size_t i=0; i<vs.size(); i++) {
printf("%s\t", arr[i]);
delete [] arr[i];
}
return 0;
}
4.35
见4.34
4.36
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef int int_array[4];
int main() {
int a[3][4] = {1,2,3,4,5,6};
int b[3][4] = {{1}, {2,3}, {4, 0, 0, 1}};
// 题目要求的输出
int_array *ip = a;
for(size_t i=0; i<3; i++) {
for(int *q = a[i]; q!= a[i] +4; ++q)
printf("%d\t", *q);
printf("\n");
}
// 数组方式的输出
for(size_t i=0; i<3; i++) {
for(size_t j=0; j<4; j++)
printf("%d\t", a[i][j]);
printf("\n");
}
printf("\n");
// 数组方式的输出
for(size_t i=0; i<3; i++) {
for(size_t j=0; j<4; j++)
printf("%d\t", b[i][j]);
printf("\n");
}
printf("\n");
int (*p)[4] = b;
for(size_t i=0; i<3; i++)
cout << **(p+i) << endl; // p指向第一行,p+i指向第i行,*p是第一行数组的地址,**p是第一行数组的首元素的地址,*(*(p+i)+j)就是a[i][j]
return 0;
}