//【Essential C++课后练习】纯代码(更新中)
//第一章 C++编程基础
//练习 1.4
/*********************************************************************
说明:试着扩充这个程序的内容:
(1)要求用户同时输入名字(first name)和姓氏(last name),
(2)修改输出结果,同时打印出姓氏和名字。
*********************************************************************/
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string firstName;
string lastName;
cout << "please enter your first name and last name:\n";
cin >> firstName;
cin >> lastName;
// cout << "hello, " firstName lastName;
cout << "hello, " << firstName << lastName;
cout << '\n';
cout << "hello, " << firstName << ' ' << lastName;
cout << '\n';
return 0;
}
/*
代码编译不过:
g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:14:19: error: expected ‘;’ before ‘firstName’
14 | cout << "hello, " firstName lastName;
正确写法如下:
cout << "hello, " << firstName << lastName;
执行结果:
/a.out
please enter your first name and last name:
zhang liang
hello, zhangliang
hello, zhang liang
【注意:空格对于 cin输入的内容,空格作为数据输入的分隔符】
思考:怎么在 第一个名字 和 第二个名字之间增加空格呢?
cout << "hello, " << firstName << ' ' << lastName;
*/
//练习 1.5
/*********************************************************************
说明:编写一个程序,能够询问用户的姓名,并读取用户所输入的内容。请确保用户输入的名称长度大
于两个字符。如果用户的确输入了有效名称,就响应一些信息。
请以两种方式实现:
第一种使用C-style字符串,
第二种使用string对象。
*********************************************************************/
// 第一种使用C-style字符串
// 第一种使用C-style字符串
#include <iostream>
#include <cstring>
using namespace std;
#define NAME_LEN_MAX 32
int main(void)
{
char name1[NAME_LEN_MAX];
/// err: cout << "what's your name? please enter:\n"
cout << "what's your name? please enter:\n";
cin >> name1;
int name1Len = strlen(name1);
int nameMinSize = 2;
if (name1Len <= nameMinSize) {
cout << "the name size is too short\n";
} else {
/// err: cout << "you enter name: ", << name, << " is correct\n";
cout << "you enter name: " << name1 << " is correct\n";
}
return 0;
}
/*
编译错误:
test.cpp: In function ‘int main()’:
test.cpp:15:18: warning: NULL used in arithmetic [-Wpointer-arith]
15 | if (name1[3] == NULL) {
| ^~~~
test.cpp:18:31: error: expected primary-expression before ‘<<’ token
18 | cout << "you enter name: ", << name, << " is correct\n";
| ^~
test.cpp:18:34: error: ‘name’ was not declared in this scope; did you mean ‘name1’?
18 | cout << "you enter name: ", << name, << " is correct\n";
| ^~~~
| name1
test.cpp:18:40: error: expected primary-expression before ‘<<’ token
18 | cout << "you enter name: ", << name, << " is correct\n";
执行结果:
/a.out
what's your name? please enter:
tudou
you enter name: tudou is correct
./a.out
what's your name? please enter:
t
the name size is too short
【注意】
在C++中,C-style字符串的长度可以通过标准库函数strlen来获取,该函数位于头文件<cstring>中。
*/
// 第二种使用string对象
#include <iostream>
#include <string>
using namespace std;
#define NAME_LEN_MAX 64
int main(void)
{
string name;
cout << "what's your name? please enter:\n";
cin >> name;
if (name.size() <= 2) {
cout << "the name size is too short\n";
} else {
// cout << "you enter name: ", << name, << " is correct\n";
cout << "you enter name: " << name << " is correct\n";
}
return 0;
}
/*
编译错误:
g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:13:11: error: request for member ‘size’ in ‘name’, which is of non-class type ‘char [64]’
13 | if (name.size <= 2) {
g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:14:11: error: invalid use of member function ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]’ (did you forget the ‘()’ ?)
14 | if (name.size <= 2) {
执行结果:
./a.out
what's your name? please enter:
woniu
you enter name: woniu is correct
【注意】
C++中求string类型的字符串长度:
1.length()成员函数 length()函数是string的内置成员,用于返回string类型字符串的实际长度。
cout << s.length() << endl;
2.size()成员函数 size()函数与length()一样,没有本质区别。string类刚开始只有length()函数,延续了C语言的风格。引入STL之后,为了兼容又加入了size,这样就可以方便的使用于STL的算法。
cout << s.size() << endl;
3.借助strlen()函数 strlen函数:计算字符串str的长度,从字符的首地址开始遍历,以 ‘\0’ 为结束标志,然后将计算的长度返回,计算的长度并不包含’\0’。
因为 strlen() 函数是用于 C 风格字符串的,因此要使用 c_str() 成员函数来获取 string 对象的 C 风格字符串表示,然后将它传递给 strlen() 函数。
cout << strlen(s.c_str()) << endl;
(1)length()方法和size()方法是不受结束标志‘\0’ ,返回的是字符串的实际长度,而strlen() 函数遇到结束标志‘\0’就停止,返回的是遇到的第一个结束标志前的字符串长度。
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char buf[10] = { 0 };
buf[0] = 'a';
buf[2] = 'v';
buf[3] = 'h';
buf[4] = '\0';
string s(buf, 6);
cout << "s:" << s << endl;
cout << "length方法:" << s.length() << endl;
cout << "size方法:" << s.size() << endl;
cout << "strlen方法:"<< strlen(s.c_str()) << endl;
return 0;
}
执行结果是:
6
6
1
注意:char buf[10] = { 0 }是只给buf数组的第一个元素赋结束标志’\0‘,剩余的9个元素没进行赋值操作,也都为结束标志’\0’。
从结果中可以看到,length()和size()方法返回的是字符串的实际长度,而strlen方法则是受到’\0‘的影响进行截断了。
(2)此外这里还有一个坑需要注意:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string s= "hello\0 world!";
cout << "length方法:" << s.length() << endl;
cout << "size方法:" << s.size() << endl;
cout << "strlen方法:"<< strlen(s.c_str()) << endl;
return 0;
}
执行结果是:
5
5
5
这是为何呢?
实际上,string是C++的一个类,在string s= “hello\0 world!”;这行代码中,它的构造函数是借助了strlen函数实现的
因此,实际上s字符串只取到了’\n‘前面的字符串,后面的都被截断了,我们可以输出看一下:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string s= "hello\0 world!";
cout << s << endl;
return 0;
}
因此,采用string直接定义的字符串利用length()方法和size()方法时,实际的长度和strlen()方法一样,但是其中的原理是不同的。
在弄清原理后,就很好区分这三种方法了。
*/
/// 名字没有 cin获取,直接初始化, .size() 测试OK
#include <iostream>
#include <string>
using namespace std;
#define NAME_LEN_MAX 64
int main(void)
{
// char name[NAME_LEN_MAX];
string name = "zhangliangliang";
cout << "what's your name? please enter:\n";
//cin >> name;
if (name.size() <= 2) {
cout << "the name size is too short\n";
} else {
cout << "you enter name: " << name << " is correct\n";
}
return 0;
}
//练习 1.6
/*********************************************************************
说明:编写一个程序,从标准输入设备读取一串整数,并将读入的整数依次放到array及
vector,然后遍历这两种容器,求取数值总和。将总和及平均值输出至标准输出设备
*********************************************************************/
// 方案1:使用 array
// 方案1:使用 array
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string numStr;
cout << "please input one number string:\n";
cin >> numStr;
int array[128]; /// 注意:数组必须指定其大小,也可以使用 new的方式分配内存
int index;
/// err: for (int index = 0; index < numStr.size; index++) {
for (index = 0; index < numStr.size(); index++) {
// array[index] = numStr[index] - 0x32;
array[index] = numStr[index] - '0';
cout << array[index] << endl;
}
int sum = 0;
/// err: for (index = 0; index < numStr.size; index++) {
for (index = 0; index < numStr.size(); index++) {
sum += array[index];
}
/// err: cout << "sum: " << sum, "average: " << sum/numStr.size();
cout << "sum: " << sum << ", average: " << sum/numStr.size();
cout << '\n';
return 0;
}
/*
执行结果:
/a.out
please input one number string:
123456
1
2
3
4
5
6
sum: 21 average: 3
【注意】
使用 array时,是否支持直接输入到数组呢?
cin 输入的数字是字符串,字符串的数值 如何转换成数字呢?
1、字符型数字数值型数字
以‘1‘转换成1为例,字符型数字在计算机中以ASCII码值存放(二进制表示的49)来存储,数字型数字在计算机中是以二进制的1来存储,所以将字符型数字转换成数字型数字,需要减去48,即减去字符’0‘(ASCII码值为48),即’1‘-’0‘转换成了数字1。
相反也是同样的道理,数字1加上48就变成了字符型数字,即1+’0‘转换成了字符型数字’1‘。
原文链接:https://blog.youkuaiyun.com/shentu7/article/details/105998066
2、字母大小写转换
前文中提到大写字母比小写字母的ASCII码小32,所以将大写字母转换成小写字母时,只要加上32即可。
#include<iostream>
using namespace std;
int main() {
string str="12345";//定义字符串
int num = 0;
for(int i=0;i<5;i++){
num = num * 10 + (str[i] - '0');//str[i] - '0'字符转换成数字
}
cout << num<<endl;
system("PAUSE");
return 0;
}
*/
// 方案2:使用vector
#include <iostream>
#include <string>
#include <vector> /// vector 的头文件
using namespace std;
int main(void)
{
vector<int> vecNumber;
cout << "please input one number string:\n";
/// err: cin >> vecNumber;
int index;
/// int value; C++ 对于输入的数据存储的类型:char 类型1 和 int 类型1是不一样的。
char inputData;
for (index = 0; cin >> inputData;) {
int value = inputData - '0'; /// add
vecNumber.push_back(value);
if (value == 9) {
///if (cin.get() == '\n') {
break;
}
}
int sum = 0;
for (index = 0; index < vecNumber.size(); index++) {
/// sum += vecNumber[index];
sum += vecNumber[index];
}
cout << "sum: " << sum << " average: " << sum/vecNumber.size();
cout << '\n';
return 0;
}
/*
执行结果:
/a.out
please input one number string:
1
2
3
4
5
6
9
sum: 30 average: 4
【注意】
vector 存储int 类型的数据,如何通过cin接受赋值呢? 如果存储 struct类型的数据,如何通过 cin接受存储呢?
在这个例子中,我们定义了一个std::vector<int>,然后通过一个循环从标准输入读取整数,并使用push_back方法将它们添加到向量中。最后,我们遍历向量并打印所有元素。
如果你想要输入一种特定的类型数据,比如自定义的结构体,你可以定义一个std::vector<自定义类型>,然后按照上面的方式进行操作。例如,如果有一个struct定义如下:
/// int value; C++ 对于输入的数据存储的类型:char 类型1 和 int 类型1是不一样的。
char inputData;
*/
//练习 1.7
/*********************************************************************
说明:使用你最趁手的编辑工具,输入两行(或更多)文字并存盘。然后编写一个程序,打开该文本文
件,将其中每个字都读取到一个vector<string>对象中。遍历该vector,将内容显示到cout。
然后利用泛型算法sort(),对所有文字排序:
#include <algorithm>
sort( container.beginer(), container.end() );
再将排序后的结果输出到另一个文件。
*********************************************************************/
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm> // sort() 函数的头文件
using namespace std;
int main(void)
{
/// 1)向文件中写数据
/// iostream outfile("file_1-7_test.txt");
/// fstream iofile("file_1_7_src.txt", ios_base::app);
fstream iofile("file_1_7_src.txt");
/// err: if (iofile == NULL) {
if (!iofile) {
cout << "iofile error" << endl;
return -1;
}
cout << "iofile open success" << endl;
iofile << "hello everyone" << endl;
iofile << "today is too cold" << endl;
iofile.close();
/// 2)从文件中读取数据,并保存在 vector
errno = 0;
ifstream infile("file_1_7_src.txt");
if (!infile) {
cout << "infile errno: " << errno << endl;
return -1;
}
string readFileData;
vector<string> vecFileWords;
while (infile >> readFileData) {
/// 从文件中读取数据,打印到终端,然后再保存到 vector类型的变量中
cout << readFileData << endl;
vecFileWords.push_back(readFileData);
}
infile.close();
/// 3)读取到的数据排序
sort(vecFileWords.begin(), vecFileWords.end());
/// 4)排序后的数据重新写入文件
fstream outfile("file_1_7_after_sore.txt", ios_base::app);
if (!outfile) {
cout << "outfile error" << endl;
return -1;
}
for (int i = 0; i < vecFileWords.size(); i++) {
outfile << vecFileWords[i] << " ";
}
outfile << endl;
outfile.close();
return 0;
}
/*
运行结果:
因文件名写错,导致“以读取模式打开文件失败”
/a.out
iofile open success
infile errno: 2
【注意】
0、C++ 不支持 NULL关键字;/// 文件流校验错误用法: if (iofile == NULL) {
1、如何关闭文件
打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。
2、C++ 中 *fstream 操作包含哪些?
建立文件
为了通过流对文件进行操作,应先建立文件流对象,如下所示:
ifstream iFile;
ofstream oFile;
fstream ioFile;
这里定义了iFile,oFile,ioFile三个文件流对象。iFile是输入文件流对象;oFile是输出文件流对象;ioFile是输入输出文件流对象。
3、从文件中读取的数据,如何存储到 vector里面呢?
从文件中读取的数据,可以先用一个变量接收,然后再通过 vector 的内部函数 **.push_back(); 将读取的数据保存到vector中。
*/
//练习 1.8
/*********************************************************************
说明:switch语句让我们得以根据用户答错的次数提供不同的安慰语句。请以array储存四种
不同的字符串信息,并以用户答错次数作为array的索引值,以此方式来显示安慰语句。
*********************************************************************/
/*********************************************************************
说明:switch语句让我们得以根据用户答错的次数提供不同的安慰语句。请以array储存四种
不同的字符串信息,并以用户答错次数作为array的索引值,以此方式来显示安慰语句。
*********************************************************************/
#include <iostream>
using namespace std;
const char *msg_to_usr(int num_tries)
{
/// const int rsp_cnt = 5; // 二维数组的行数定义,也可以不定义,直接计算
/// static const char *usr_msgs[rsp_cnt] = {
static const char *usr_msgs[] = {
"Go on, make a guess. ",
"Oops! Nice guess but not quite it.",
"Hmm, Sorry. Wrong a second time.",
"Ah, this is harder than it looks, no?",
"It must be getting pretty frustrating by now!"
};
int count = sizeof(usr_msgs) / sizeof(usr_msgs[0]);
cout << "usr_msgs size: " << count << endl;
if (num_tries < 0) {
num_tries = 0;
/// } else if (num_tries >= rsp_cnt) {
} else if (num_tries >= count) {
/// num_tries = rsp_cnt - 1;
num_tries = count - 1;
}
return usr_msgs[num_tries];
}
int main()
{
cout << msg_to_usr(3) << endl;
int tryTimes;
while (1) {
cin >> tryTimes;
cout << msg_to_usr(tryTimes) << endl;
}
return 0;
}
/*
// 执行结果:
/a.out
usr_msgs size: 5
Ah, this is harder than it looks, no?
0
usr_msgs size: 5
Go on, make a guess.
1
usr_msgs size: 5
Oops! Nice guess but not quite it.
2
usr_msgs size: 5
Hmm, Sorry. Wrong a second time.
3
usr_msgs size: 5
Ah, this is harder than it looks, no?
4
usr_msgs size: 5
It must be getting pretty frustrating by now!
5
usr_msgs size: 5
It must be getting pretty frustrating by now!
6
usr_msgs size: 5
It must be getting pretty frustrating by now!
【注意】
1、如何获取二维数组的行数?
C++获取二维数组行列数
//方法一:
//对于type array[A][B];形式的二维数组,可以通过计算sizeof获取行列数。
sizeof(array[0][0]) 为一个元素占用的空间;
sizeof(array[0]) 为一行元素占用的空间;
sizeof(array) 为整个数组占用的空间
sizeof (array) / sizeof(array[0]) 计算二维数组的行数
行数 = sizeof(array)/sizeof(array[0]);
列数 = sizeof(array[0]/sizeof(array[0][0]);
//方法二:(利用vector类来定义一个二维数组array)
vector<vector<int> > array;
行数 = array.size();
列数 = array[0].size();</int>
*/
C++学习-01
于 2024-09-22 10:58:27 首次发布