面试官居然让我手撕大一课设代码?那offer还不是手到擒来?

简介: 该篇文章涉及知识点:结构体的定义、vector的使用、迭代器的使用、野迭代器的避免、排序的方法。如果你需要做一个学生管理系统这样的课程设计,那么这篇文章将是非常重要的基础,在此基础之上,可以帮你很简单的完成学生管理系统的设计。

文章中涉及到的是某互联网知名大厂的面试最后一题,文中有详细的函数实现以及注释,文末有整个工程的完整可运行代码,如果觉得不错,麻烦给博主来个一键三连+评论区互动,谢谢各位


题目要求:

定义一个Student的结构体,包含name和age两个成员,用vector对Student对象进行管理。

1、实现init函数,向vector中放入三个student元素(“Siri”, 17), (“Xiaoai”, 20), (“Xiaoyi”, 19);

2、实现sort_student函数,对vector中所有student对象按照年龄从小到大排序

3、实现add_student函数,可以让外部调用往vector中增加一个student,增加一个(“Siri”, 18)

4、实现delete函数,可以让外部调用删除指定名字的所有student,删除所有名字叫Siri的student


开始解答:

定义结构体:

typedef struct _STUDENT_
{
  string name;//姓名
  int age;//年龄
}STUDENT, *PSTUDENT;

我们来定义一个结构体,默认其中包括两个成员,一个是姓名,一个是年龄,姓名是string类型,年龄是int类型。

完成第一个要求,实现init函数,在其中完成三个成员的初始化工作:

/*
函数是用来初始化三个成员,并且将成员存放到vector数组中去
参数:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
*/
void Init(vector<STUDENT>& Parameter)
{
  STUDENT student_1[3];//用来存放三个学生的信息
  student_1[0].name = "Siri";
  student_1[0].age = 17;
  student_1[1].name = "Xiaoai";
  student_1[1].age = 20;
  student_1[2].name = "Xiaoyi";
  student_1[2].age = 19;
  for (int i = 0; i < 3; i++)
  {
  Parameter.push_back(student_1[i]);//向vector数组中压入参数
  }
}

我们用以上函数完成对vector数组的初始化工作。注意参数是引用类型,也就意味着形参的改变会直接影响到实参的值。


接着我们实现sort_student的的,把vector数组中的成员按照age大小,从小到大排序:

/*
函数用来对vector数组进行排序
参数:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
*/
void sort_student(vector<STUDENT>& Parameter)
{
  //sort函数是algorithm库下的一个函数,用来实现比较排序的功能
  sort(Parameter.begin(), Parameter.end(), compare);//注意该函数的第三参数是函数指针
}
/*
函数用来对比较年龄大小,并且返回比较结果
参数1:const STUDENT& a 是一个常量引用
参数2:const STUDENT& a 是一个常量引用
返回值:bool类型,是true或者false
*/
bool compare(const STUDENT& a, const STUDENT& b)
{
  return a.age < b.age;
}

我们使用algorithm中的sort函数,来进行年龄大小的比较并排序,在这个函数执行之后,所有的成员按照年龄由小到大排序。


实现add_student的要求,对vector中添加新的学生成员(“Siri”, 18),代码如下:

/*
函数实现对外部变量的添加功能,通过传入的参数,将新成员增加到vector数组中
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来传输外部新增成员的名字
参数3:int age 年龄,外部输入新增成员的年龄
*/
void add_student(vector<STUDENT>& Parameter, const char* name,int age)
{
  STUDENT Student;
  Student.name = name;
  Student.age = age;
  Parameter.push_back(Student);
  sort_student(Parameter);//加入完学生的信息,再次进行排序
}

我们通过传参来把需要新增的学生信息传递进来之后,在里面声明局部结构体变量用来存放这些信息,最后压入vector数组中之后,将学生进行再次排序。


实现delete函数,让外部调用删除所有名字叫Siri的student:

/*
函数实现了对指定学生的删除,通过姓名来搜索匹配,最终进行删除
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来存放需要删除的学生姓名
返回值:bool类型,是为了告诉调用者是否删除成功
*/
bool delete_student(vector<STUDENT>& Parameter, const char* name)
{
  bool IsOk = false;
  //for循环中涉及到了vector的迭代器的使用,也就是vector<STUDENT>::iterator v1
  //一定要小心“野”迭代器的发生,所以for循环的++操作,被我放在了ifelse语句中
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  //比较名字是否和我们要删除的一致
  if (strcmp((*v1).name.c_str(), name) == 0)
  {
    IsOk = true;
    //返回的就是删除之后的一个元素
    v1 = Parameter.erase(v1);//进行数据擦除
    //被erase之后变成了一个“野迭代器”,对其进行++操作会发生奔溃
  }
  else
  {
    v1++;
  }
  }
  return IsOk;
}

其实delete的实现,是最需要主义的一个地方,因为其中涉及到野迭代器的问题,就是使用vector::erase之后,会把当前数组的下一个迭代器作为返回值返回,而当前迭代器因为erase操作已经变得失效了,是一个野迭代器,直接进行++操作会导致程序崩溃。


对于面试题的基本要求其实已经完成了,然后我又写了个改和查的功能,毕竟既然写了增和删,就顺便写个改和查吧,其实改和查相比起删除来说,还是有点像的,话不多说,先看一个修改信息的代码:

bool change_student(vector<STUDENT>& Parameter, 
  const char* old_name,
  const char* new_name = "default",
  int new_age = 0);
/*
change_student函数是想修改之前已经存放好的信息,如果学生的姓名出错,可以修改,年龄出错也可以修改
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* old_name 需要信息的学生姓名
参数3:const char* new_name 需要改成的新的名字,默认值为default
参数4:int new_age 需要修改成的新年龄,默认值为0
返回值:bool类型,是为了告诉调用者是否删除成功
*/
bool change_student(vector<STUDENT>& Parameter,
  const char* old_name, 
  const char* new_name,
  int new_age)
{
  bool IsOk = false;
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  if (strcmp((*v1).name.c_str(), old_name) == 0)
  {
    IsOk = true;
    if (strcmp(new_name, "default") != 0)
    {
    //看名字是否是需要修改,如果不为default 则需要修改
    (*v1).name = new_name;
    }
    if (new_age != 0)
    {
    //看年龄是否是需要修改,如果不为0 则需要修改
    (*v1).age = new_age;
    }
    v1++;//迭代器后移
  }
  else
  {
    v1++;
  }
  }
  return IsOk;
}

以上代码我列出了函数的声明和定义,声明时候出现了参数默认值,参数默认赋值的意思,就是说这些参数如果不传的话,是可以将默认值传入进去的。


最后再来一个根据学生姓名查找学生信息的函数,来完成我们这次代码的简单工作:

/*
函数实现了学生信息的查找,通过姓名来搜索匹配,最终输出结果
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来存放需要查找的学生姓名
*/
void find_student(vector<STUDENT>& Parameter, const char* name)
{
  bool IsOk = false;
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  //比较名字是否和我们要查找的一致
  if (strcmp((*v1).name.c_str(), name) == 0)
  {
    cout << "Student Name is " << name << endl;
    cout << "Student age is " << (*v1).age << endl;
    v1++;//迭代器后移
  }
  else
  {
    v1++;
  }
  }
}

就是很简单的从外部传入学生的姓名,然后使用迭代器对vector数组进行遍历,判断匹配之后,输出学生的信息。

完整可运行代码如下:

//头文件 main.h
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef struct _STUDENT_
{
  string name;
  int age;
}STUDENT, *PSTUDENT;
void Init(vector<STUDENT>& Parameter);
void add_student(vector<STUDENT>& Parameter, const char* name, int age);
bool delete_student(vector<STUDENT>& Parameter, const char* name);
void sort_student(vector<STUDENT>& Parameter);
bool compare(const STUDENT& a, const STUDENT& b);
bool change_student(vector<STUDENT>& Parameter, 
  const char* old_name,
  const char* new_name = "default",
  int new_age = 0);
void find_student(vector<STUDENT>& Parameter, const char* name);


//cpp main.cpp
#include"main.h"
/*
函数是用来初始化三个成员,并且将成员存放到vector数组中去
参数:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
*/
void Init(vector<STUDENT>& Parameter)
{
  STUDENT student_1[3];//用来存放三个学生的信息
  student_1[0].name = "Siri";
  student_1[0].age = 17;
  student_1[1].name = "Xiaoai";
  student_1[1].age = 20;
  student_1[2].name = "Xiaoyi";
  student_1[2].age = 19;
  for (int i = 0; i < 3; i++)
  {
  Parameter.push_back(student_1[i]);//向vector数组中压入参数
  }
}
/*
函数用来对vector数组进行排序
参数:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
*/
void sort_student(vector<STUDENT>& Parameter)
{
  //sort函数是algorithm库下的一个函数,用来实现比较排序的功能
  sort(Parameter.begin(), Parameter.end(), compare);//注意该函数的第三参数是函数指针
}
/*
函数用来对比较年龄大小,并且返回比较结果
参数1:const STUDENT& a 是一个常量引用
参数2:const STUDENT& a 是一个常量引用
返回值:bool类型,是true或者false
*/
bool compare(const STUDENT& a, const STUDENT& b)
{
  return a.age < b.age;
}
/*
函数实现对外部变量的添加功能,通过传入的参数,将新成员增加到vector数组中
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来传输外部新增成员的名字
参数3:int age 年龄,外部输入新增成员的年龄
*/
void add_student(vector<STUDENT>& Parameter, const char* name,int age)
{
  STUDENT Student;
  Student.name = name;
  Student.age = age;
  Parameter.push_back(Student);
  sort_student(Parameter);//加入完学生的信息,再次进行排序
}
/*
函数实现了对指定学生的删除,通过姓名来搜索匹配,最终进行删除
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来存放需要删除的学生姓名
返回值:bool类型,是为了告诉调用者是否删除成功
*/
bool delete_student(vector<STUDENT>& Parameter, const char* name)
{
  bool IsOk = false;
  //for循环中涉及到了vector的迭代器的使用,也就是vector<STUDENT>::iterator v1
  //一定要小心“野”迭代器的发生,所以for循环的++操作,被我放在了ifelse语句中
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  //比较名字是否和我们要删除的一致
  if (strcmp((*v1).name.c_str(), name) == 0)
  {
    IsOk = true;
    //返回的就是删除之后的一个元素
    v1 = Parameter.erase(v1);//进行数据擦除
    //被erase之后变成了一个“野迭代器”,对其进行++操作会发生奔溃
  }
  else
  {
    v1++;
  }
  }
  return IsOk;
}
/*
change_student函数是想修改之前已经存放好的信息,如果学生的姓名出错,可以修改,年龄出错也可以修改
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* old_name 需要信息的学生姓名
参数3:const char* new_name 需要改成的新的名字,默认值为default
参数4:int new_age 需要修改成的新年龄,默认值为0
返回值:bool类型,是为了告诉调用者是否删除成功
*/
bool change_student(vector<STUDENT>& Parameter,
  const char* old_name, 
  const char* new_name,
  int new_age)
{
  bool IsOk = false;
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  if (strcmp((*v1).name.c_str(), old_name) == 0)
  {
    IsOk = true;
    if (strcmp(new_name, "default") != 0)
    {
    //看名字是否是需要修改,如果不为default 则需要修改
    (*v1).name = new_name;
    }
    if (new_age != 0)
    {
    //看年龄是否是需要修改,如果不为0 则需要修改
    (*v1).age = new_age;
    }
    v1++;//迭代器后移
  }
  else
  {
    v1++;
  }
  }
  return IsOk;
}
/*
函数实现了学生信息的查找,通过姓名来搜索匹配,最终输出结果
参数1:vector<STUDENT>& Parameter  是外部传参的引用,改变这个参数,
也就是改变外部的那个实参
参数2:const char* name 常量字符指针,用来存放需要查找的学生姓名
*/
void find_student(vector<STUDENT>& Parameter, const char* name)
{
  bool IsOk = false;
  for (vector<STUDENT>::iterator v1 = Parameter.begin();
  v1 != Parameter.end();)
  {
  //比较名字是否和我们要查找的一致
  if (strcmp((*v1).name.c_str(), name) == 0)
  {
    cout << "Student Name is " << name << endl;
    cout << "Student age is " << (*v1).age << endl;
    v1++;//迭代器后移
  }
  else
  {
    v1++;
  }
  }
}
int main()
{
  vector<STUDENT> Student;
  Init(Student);//初始化三个学生的信息
  sort_student(Student);
  add_student(Student, "Siri",18);
  delete_student(Student, "Siri");
  change_student(Student, "Xiaoai","Xiaobu");
  find_student(Student, "Xiaoyi");
  return 0;
}

还是那句话:如果喜欢博主的文章,关注之后,我们慢慢处。


今日励志句子 “You made a choice. Don’t look back.”


目录
相关文章
|
3月前
|
Java 编译器 C++
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
这篇文章解释了Java能够实现“一次编写,到处运行”的原因,主要归功于Java虚拟机(JVM),它能够在不同平台上将Java源代码编译成的字节码转换成对应平台的机器码,实现跨平台运行。
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
|
11天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
44 1
|
2月前
|
Web App开发 前端开发 Linux
「offer来了」浅谈前端面试中开发环境常考知识点
该文章归纳了前端开发环境中常见的面试知识点,特别是围绕Git的使用进行了详细介绍,包括Git的基本概念、常用命令以及在团队协作中的最佳实践,同时还涉及了Chrome调试工具和Linux命令行的基础操作。
「offer来了」浅谈前端面试中开发环境常考知识点
|
2月前
|
存储 移动开发 前端开发
「offer来了」面试中必考的15个html知识点
该文章汇总了前端面试中常见的15个HTML知识点,涵盖了从HTML文档的规范书写、doctype声明的作用到新兴的HTML5标签应用及移动端viewport设置等内容,旨在帮助求职者更好地准备相关技术面试。
「offer来了」面试中必考的15个html知识点
|
3月前
|
存储 缓存 Java
面试问Spring循环依赖?今天通过代码调试让你记住
该文章讨论了Spring框架中循环依赖的概念,并通过代码示例帮助读者理解这一概念。
面试问Spring循环依赖?今天通过代码调试让你记住
|
2月前
|
Web App开发 前端开发 JavaScript
「offer来了」1张思维导图,6大知识板块,带你梳理面试中CSS的知识点!
该文章通过一张思维导图和六大知识板块系统梳理了前端面试中涉及的CSS核心知识点,包括CSS框架、基础样式问题、布局技巧、动画处理、浏览器兼容性及性能优化等方面的内容。
|
3月前
|
JavaScript 前端开发 程序员
JS小白请看!一招让你的面试成功率大大提高——规范代码
JS小白请看!一招让你的面试成功率大大提高——规范代码
|
6月前
|
Android开发 API
顺利通过阿里Android岗面试,已拿offer
顺利通过阿里Android岗面试,已拿offer
顺利通过阿里Android岗面试,已拿offer
|
5月前
|
存储 算法 Java
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
|
6月前
|
缓存 监控 算法
Python性能优化面试:代码级、架构级与系统级优化
【4月更文挑战第19天】本文探讨了Python性能优化面试的重点,包括代码级、架构级和系统级优化。代码级优化涉及时间复杂度、空间复杂度分析,使用内置数据结构和性能分析工具。易错点包括过度优化和滥用全局变量。架构级优化关注异步编程、缓存策略和分布式系统,强调合理利用异步和缓存。系统级优化则涵盖操作系统原理、Python虚拟机优化和服务器调优,需注意监控系统资源和使用编译器加速。面试者应全面理解这些层面,以提高程序性能和面试竞争力。
79 1
Python性能优化面试:代码级、架构级与系统级优化