C++程序设计教程 (钱能)第三章 练习3
1.打印-1234567的二进制位码。
【分析】暂未搞懂,后续更新。
【代码】(我是占位的)
2.分别输出各类型的字长和位长。
【方法1】
bool a = 0;
char b = 'A';
int c = 2;
long int d = 1;
float e = 3;
double f = 4;
long double g = 5;
cout << setw(15)<<"bool:" << sizeof(a) << " byte " << 8 * sizeof(a) << " bits" << endl;
cout << setw(15) << "char:" << sizeof(b) << " byte " << 8 * sizeof(b) << " bits" << endl;
cout << setw(15) << "int:" << sizeof(c) << " byte " << 8 * sizeof(c) << " bits" << endl;
cout << setw(15) << "long int:" << sizeof(d) << " byte " << 8 * sizeof(d) << " bits" << endl;
cout << setw(15) << "float:" << sizeof(e) << " byte " << 8 * sizeof(e) << " bits" << endl;
cout << setw(15) << "double:" << sizeof(f) << " byte " << 8 * sizeof(f) << " bits" << endl;
cout << setw(15) << "long double:" << sizeof(g) << " byte " << 8 * sizeof(g) << " bits" << endl;
/*
运行结果:
bool:1 byte 8 bits
char:1 byte 8 bits
int:4 byte 32 bits
long int:4 byte 32 bits
float:4 byte 32 bits
double:8 byte 64 bits
long double:8 byte 64 bits
*/
【方法2】
void print(char * tName, int tLen) {
cout << setw(15) << tName << ":" << tLen << "bye " << tLen * 8 << "bits\n";
}
int main(){
print("bool", sizeof(bool));
print("char", sizeof(char));
print("int", sizeof(int));
print("long int", sizeof(long int));
print("float", sizeof(float));
print("double", sizeof(double));
print("long double", sizeof(long double));
}
//运行结果同上
3.创建向量,用数组初值初始化,求该向量标准差。
【方法1】
int a[] = { 6,3,7,1,4,8,2,9,11,5 };
vector<int> va(a, a + 10);
double sum = 0, sum1 = 0;
for (int i = 0; i < va.size(); i++) {
sum += va[i];
}
double mean = sum / 10;
for (int i = 0; i < va.size(); i++) {
sum1 += pow((va[i] - mean),2);
}
double s = sqrt(sum1 / 10);
cout << "标准差为:" << s << endl;
//标准差为:3.03974
【方法2】
int a[] = { 6,3,7,1,4,8,2,9,11,5 };
int n = sizeof(a) / sizeof(a[0]);
vector<int> va(a, a + n);
double sigma = 0,pSigma = 0;
for (int i = 0; i < va.size(); i++) {
int v = va[i];
sigma += v;
pSigma += v*v;
}
sigma /= n;
cout << "标准差:" << sqrt(pSigma / n - sigma*sigma);
//将方差化简可得到这个公式
//标准差为:3.03974
4.汇总每个月25号的天数,若是加班日,该天*2。
abc.txt
Oct. 25 2003
Oct. 26 2003
Sep. 12 2003*
Juy. 25 2002*
App. 25 2004
【方法1】依次读入月份、日期和年份。
ifstream in("abc.txt");
int count = 0, day;
for (string month,year; in >> month>>day>>year; ) {
if (day == 25)
count += year.length() - 3; //没*加1,有*加2
}
cout << "每个月25号的天数:" << count << endl;
//每个月25号的天数:4
【方法2】字符串查找
ifstream in("abc.txt");
int sum = 0;
string s;
while (getline(in,s)) {
if (s.find("25") != string::npos)
if (s.find("*") != string::npos)
sum += 2;
else
sum++;
}
cout << "每个月25号的天数:" << sum << endl;
//每个月25号的天数:4
string::find()函数:是一个字符或字符串查找函数,该函数有唯一的返回类型,即string::size_type,即一个无符号整型类型,可能是整数也可能是长整数。
如果查找成功,返回按照查找规则找到的第一个字符或者子串的位置;如果查找失败,返回string::npos,即-1。
static const size_type npos = -1;
5.加密与解密字符串。
将输入的一行字符以加密形式输出,然后将其解密,解密字符序列与输入的正文进行比较,吻合时输出解密的正文,否则输出失败。
【方法1】
//ASCII中的0~31为控制字符;32~126为打印字符;127为Delete(删除)命令。
const char key[] = "4962873";
string encode(string & str) {
string result(str);
for (int i = 0; i < result.length(); i++) {
result[i] += key[i % 7] - '0';
if (result[i] > 'z') {
result[i] -= 91;
//若加上数字后,超过122,则减去91,
//保证最终落在32(' ')到122('z')区间内。
//如123 - 91 = 32 ,减完91之后能保证落在32-122的区间内
}
}
return result;
}
//解码函数做编码函数的反操作
string decode(string & str) {
string result(str);
for (int i = 0; i < result.length(); i++) {
result[i] -= key[i % 7] - '0';
if (result[i] < ' ') {
result += 91;
}
}
return result;
}
int main() {
string s;
getline(cin, s);
string t = encode(s);
cout << t << "\n";
cout << (s == decode(t) ? s + "\n" : string("decode failed!\n"));
}
/*
运行结果:
the result of 3 and 2 is not 8
xqk"zlvyuz"wm#7)gpl'5$ry"vvw$A
the result of 3 and 2 is not 8
*/
【方法2】这个方法有问题,暂未解决。
str = new char[];
问题:C3078 必须在新的表达式中指定数组大小
const int key[] = { 4,9,6,2,8,7,3 };
char *str, *str1, *str2;
str = new char[30];
//输入的字符长度为30,故给定30,不指定长度或指定大于30的长度会出错
cout << "明文:" ;
cin.getline(str, 100);
const int n = strlen(str);//strlen(str)计算给定字符串的长度
str1 = new char[n];//本没有指定长度,这样会出错
str2 = new char[n];//本没有指定长度,这样会出错
for (int i = 0; i < n; i++) {
*(str1 + i) = *(str + i) + key[i % 7];
if ((int)str1[i] > 122)
*(str1 + i) = *(str1 + i) % 90 + 32;
}
cout << "密文:" << str1 << endl;//C-串可直接用数组名输出内容
for (int j = 0; j < n; j++) {
*(str2 + j) = *(str1 + j) - key[j % 7];
if ((int)str2[j] < ' ')
*(str2 + j) = *(str2 + j) - 32 + 90;
}
if (*str2 == *str)
cout << "解密后的正文:" << str2 << endl;
else
cout << "解密失败!" << endl;
/*
明文:the result of 3 and 2 is not 8
密文:xqk"zlvyuz"wm#7)gpl'5$ry"vvw$A
解密后的正文:the result of 3 and 2 is not 8
*/
6.遍历数组的5种方法。
int sum[5] = { 0 };//存放每种方法的结果
int iArray[] = { 1,4,2,7,13,32,21,48,16,30 };
int size = sizeof(iArray) / sizeof(*iArray);//计算数组长度
int * iPtr = iArray;
for (int i = 0; i < size; i++)
{
sum[3] += iPtr[i];
}
for (int i = 0; i < size; i++)
{
sum[2] += *(iPtr + i);
}
for (int i = 0; i < size; i++)
{// 1)* 与 ++ 是同优先级。
// 2)两者结合性都是从右向左。
// 3)故 iPtr++ 先做,因为是后增,故先取值再自增,所以iPtr与*结合的同时,也自增。
sum[1] += *iPtr++;
}
for (int i = 0; i < size; i++)
{
sum[0] += iArray[i];
}
for (int i = 0; i < size; i++)
{
sum[4] += *(iArray + i);
}
for (int i = 0; i < 5; i++) {
cout << "sum["<<i<<"]:"<<sum[i] << " " << endl;
}
/*
运行结果:
sum[0]:174
sum[1]:174
sum[2]:174
sum[3]:174
sum[4]:174
*/
注:int a[] = { 1,2,3 };
cout << sizeof(a) << endl;//a数组的字节数是12
cout << *a << endl;//第一个元素的值为1
7.将程序中的指针改为引用,实现交换。
void mySwap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 16, b = 48;
cout << "a = " << a << " ,b = " << b << endl;
mySwap(&a, &b);//指针
cout << "After Being Swapped:" << endl;
cout << "a = " << a << " ,b = " << b << endl;
}
/*
运行结果:
a = 16 ,b = 48
After Being Swapped:
a = 48 ,b = 16
*/
void mySwap1(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 16, b = 48;
cout << "a = " << a << " ,b = " << b << endl;
mySwap1(a, b);//引用
cout << "After Being Swapped:" << endl;
cout << "a = " << a << " ,b = " << b << endl;
}
/*
运行结果:
a = 16 ,b = 48
After Being Swapped:
a = 48 ,b = 16
*/
void mySwap2(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 16, b = 48;
cout << "a = " << a << " ,b = " << b << endl;
mySwap2(a, b);//不会交换a和b的值
cout << "After Being Swapped:" << endl;
cout << "a = " << a << " ,b = " << b << endl;
}
/*
运行结果:
a = 16 ,b = 48
After Being Swapped:
a = 16 ,b = 48
*/
分析:
因为mySwap2(int a, int b)被调用时,实参进行副本初始化,函数并没有访问调用传递的实参本身,因而也不会修改实参的值。也就是说函数被调用时传入的是x,y的值,而不是它们的地址。
只有传入地址才能在函数调用时通过地址真正改变两个数的值。否则就只是改变了函数栈帧里创建的形参,这样当函数完成调用时,栈帧里面创建的形参就会随之消失,无法完成交换。