C++学习-01

//【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>
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值