还是编程入门的事,和朋友交流时很多还是推荐python,但他们都忽视了数据结构和算法,当然数据结构和编程语言是彼此独立的,不是说学数据结构必须懂C ,但是学数据结构之前必须要掌握一种语言,C 可能是较好的选择,虽然纯粹看不如C更注重算法和数据结构。
拿2017版高中信息技术课标看,不管是必修还是选修都会涉及程序语言,因为学习真正的算法之前必须学一门编程语言,VB、Pascal都是很好的语言,但基本已经走下坡了了,虽然小编还是沉醉在Delphi的世界里,但不得不承认业界用的越来越少了。从衔接看,一般大学会开设《C语言》、《C 语言》等主流编程语言的课程,不会管你是不是编程方向的,所以你有C基础可能更好接受。如果你从小就接触一些基础的C语言,到高中你会看老师的表演。你可以更快的去了解计算机的存储和组织数据的方式,去学习《数据结构》和算法了,因为高中只学习了一种数据结构,也玩不了太高级的算法,数组可能到这时候可能已经满足不了你的需求了。这时候你回头看看,会发现Python之所以让人感觉强大是因为神一样的库存在,会明白学C 的更大意义在于:有助于让你探索到编程的本质、智能的本质,让你从现实中去理解为什么需要面向过程编程思想,为什么需要面向对象编程思想。数据结构是什么,算法是什么,编译原理是什么,操作系统是什么等等更深层的东西。再说就算你以后要从事开发工作,只凭一门语言也不会打遍天下的。初学者其实也不需要纠结应该学哪一门语言,因为一门语言学明白了再迁移到另一门语言是很容易的。
01
学习任何一种编程语句最简单的方法就是多实践,拿出时间手敲代码。下面我们来练习一个实例,模拟用户登录过程,验证用户名、密码,如果全部正确提示用户登录成功,否则,提示用户相关输入错误。我们来设想下需求,程序中需要存储正确的用户名和密码,这个用户名和密码可能是数字或字符,然后cin输入的用户名和密码,利用if语句进行判断,然后cout登陆成功或输入错误提示。根据我们前面所学知识,我想你一定会先想到char来存储用户名和密码和输入的用户名和密码,但char只有一个字节,好像不能满足我们的要求。
02
这里我们要先学习一下Cpp中的字符串,在C 提供了以下两种类型的字符串表示形式:C风格字符串C 引入的string类类型
C风格的字符串起源于C语言,并在C 中继续得到支持。字符串实际上是使用null字符’\0’终止的一维字符数组。因此,一个以null结尾的字符串,包含了组成字符串的字符,为了后面更好的学习,这里做简单介绍。
下面的声明和初始化创建了一个”Hello”字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词”Hello”的字符数多一个。
char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};
依据数组初始化规则,可以把上面的语句写成以下语句:
char greeting[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};
以下是C/C 中定义的字符串的内存表示:
其实,不需要把null字符放在字符串常量的末尾。C 编译器会在初始化数组时,自动把’\0’放在字符串的末尾,如下面的例子:
#include <iostream> using namespace std; int main(){ char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’}; cout << “greeting: ” << greeting << endl; return 0; }
另外,C 标准库提供了string类类型,支持上述所有的操作,另外还增加了其他更多的功能,标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件,作为标准库的一部分string定义在标准库std中。
见下面的实例:
#include<string>//注意这里 string s1 = “abandon”; string s2 = “banana”; string s3; // 复制s1到s3 s3 = s1; cout << “s3:” << s3 << endl; // 连接s1和s2 s3 = s1 s2; cout << “s1 s2:” << s3 << endl; // 连接后的s3总长度 int len1, result1; len1 = s3.size(); cout << “s3.size():” << len1 << endl; // 比较s1和s2 result1 = s1 > s2; cout << “s1 > s2:” << result1 << endl;
另外string类提供了一系列针对字符串的操作,比如:
append() — 在字符串的末尾添加字符find() — 在字符串中查找字符串insert() — 插入字符length() — 返回字符串的长度replace() — 替换字符串substr()–返回某个子字符串
C 中输入的方式很多,可以直接用下面方式,但注意的是这里以空格分隔,如果想读取整行数据,就需要用getline()了,或者使用cin.getline()。但要注意cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数。
strings;cin >> s;利用getline()#include<iostream>#include<string> using namespace std; int main () { string str; getline(cin,str); cout<<str<<endl; }
cin.getline()是在输入一段字符完成后开始读取数据(注意,是输入完成后,以Enter为结束标志),尝试下面的实验。实验中接受5个字符到m中,其中最后一个为’\0’,所以你只看到4个字符输出;
#include <iostream> using namespace std; int main () { char m[20]; cin.getline(m,5); cout<<m<<endl; }
#include<iostream>#include<string>using namespace std;intmain(){ char str1[] = “hello world”; char str2[] = “hello world”; if(str1 == str2) cout << “str1与str2相同\n”; elsecout<<“str1与str2不同\n”;stringstr3=”helloworld”;stringstr4=”helloworld”;if(str3 == str4) cout << “str3与str4相同\n”; else cout << “str3与str4不同\n”; return 0;}所以我们重点看一下string,首先是定义和初始化string,如何初始化类由类本身决定,一个类可以定义多种初始化对象的方式。string s1;//默认初始化string s2(s1);//s2是s1的副本string s2 = s1;//等价于s2(s1),s2是s1的副本string s3(“value”);//s3是字面值”value”的副本,除了字面值最后的那个空字符外string s3 = “value”;//等价于s3(“value”),s3是字面值”value”的副本string s4(n,’c’);//把s4初始化为由连续n个字符’c’组成的串string对象上的操作,一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。下面是string对象的大多数操作。os << s //将s写到输出流os当中,返回osis >> s //从输入流is中读取字符串赋给s,字符串以空白分割,返回isgetline(is,s) //从is中读取一行赋给s,返回iss.empty() //s为空返回true否则返回falses.size() //返回s中字符的个数s[n] //返回s中第n个字符的引用,位置n从0开始s1 s2 //返回字符串s1和s2连接后的结果s1=s2 //用s2的副本代替s1中原来的字符s1==s2 //如果字符串s1和字符串s2中的字符完全一样,则返回true,否则为falses1!=s2 //如果字符串s1和字符串s2中的字符不一样,则返回true,否则返回false<,<=,>,>=//利用字符在字典中的顺序进行比较,且对字母的大小写敏感
03
大体搞定上面的知识,可以完成上面的练习了,模拟用户登录过程,验证用户名、密码,如果全部正确提示用户登录成功,否则,提示用户相关输入错误。直接上实例。
#include <iostream>#include <string>using namespace std;int main(){ string username; string password; cout <<“请输入用户名:”; getline(cin,username,’\n’); cout <<“请输入密码:”; getline(cin,password,’\n’); if(username==”abc” && password==”pass”) cout <<“登录成功” << endl; else cout <<“输入错误”<< endl;return 0;}
程序到这里可能告一段落了,但还是有很多问题?
比如,是否给用户重试的机会?重试几次?是否输入密码时显示星号*来保护密码?重试可以利用前面学习的循环结构来解决,但如何保护密码呢?
还有现在程序是固定的密码,任何的反编译和动态调试都可以找到准确的用户名和密码,该如何保护呢?
莫急,后面我们慢慢来实现~