大一c++大题笔记

题目整理自网络,版权归原作者所有。

1.程序改错(有一处错误)

#include <iostream>
using namespace std;
class Square
{
	
private:
	int n;
public:
   Square();
   Square(int nn);
   int square();
};

Square::Square(){
	n=0;
}

Square::Square(int nn){
	n=nn;
}

Square::double square(){
	return double(n*n);
}

int main()
{
    Square s(10);
    cout<<s.square()<<endl;
    return 0;
}

错误在于 Square::double square() 函数的返回类型和声明不一致。由于只让改一处,将11行int square();改为double square();

2.程序改错(有一处错误)

#include <iostream>
using namespace std;
class A
{
	
protected:
	int a1,a2;
public:
   A(){
   	a1=0;a2=0;
   }
   A(int aa1,int aa2)
   {
   	a1=aa1;a2=aa2;
   }
   int add()
   {
   	return a1+a2;
   }
};



int main()
{
    A a;
    cout<<"input first number:";cin>>a.a1;
    cout<<"input second number:";cin>>a.a2;
    cout<<"sum="<<a.add()<<endl;
    return 0;
}

问题在于尝试在 main 函数中直接访问 A 类的保护成员 a1 和 a2。在 C++ 中,保护成员只能在类的成员函数、友元函数或派生类中访问,而不能在类的外部直接访问。故将类A中的protected改为public。

3.程序改错(有一处错误)

#include <iostream>
#include<string>
#include<ctime>
#include<cstdlib>
using namespace std;
class A
{
	
protected:
	int x;
public:
   A(){
   	x=0;
   }
   A(int xx)
   {
   	x=xx;
   }
   void display()
   {
   	cout<<x<<endl;
   }
};

class B:A{
	protected:
	int y;
public:
   B(){
   	y=0;
   }
   B(int xx,int yy):
   {
   	y=yy;
   }
   void display()
   {
   	cout<<x<<endl;
   	cout<<y<<endl;
   }
};

int main()
{
    B b(1,2);
    b.display();
    return 0;
}

class B 继承自 class A,但是在 B 的构造函数定义中存在错误,没有正确地初始化基类 A 的成员 x。在 C++ 中,当一个派生类构造函数被调用时,它需要负责初始化自己的成员以及基类的成员。为了初始化基类的成员,派生类构造函数使用初始化列表来调用基类的构造函数。这是因为在派生类构造函数开始执行之前,基类的构造函数必须先被调用。

故将32行修改为B(int xx,int yy):A(xx)

4.程序填空

//重载“-”运算符,从对象的数据(s串)中删除所有指定的子串(s1串)
//重载“<<”运算符,输出对象中的数据(s串)
#include <iostream>
#include<string>
#include<ctime>
#include<cstdlib>
using namespace std;

class A
{
private:
	string s;
public:
   A(string ss=""){
   	s=ss;
   }
   void input(){
   	cout<<"input string:";
   	cin>>s;
   }
   void output(){
   	cout<<"the string is:"<<s<<endl;
   }
   A operator-(A a){
   	A temp;
   	string s1=a.s;
   	string::size_type n=0;
   	while(true)
   	{
   		if(s.find(s1,n)!=string::npos)
   		{
   			//------------------------------------------
   			          //填空
   			//------------------------------------------
   			s.erase(n,s1.size())
		   }
		   else
		   break;
	   }
	temp.s=s;
	return temp;
   }
};

ostream& operator<<(ostream& os,A a)
{
	//-------------------------------------
	                //填空
	//-------------------------------------
	return os;
}

int main()
{
   A s1("this is a book!");
   A s2("is");
   cout<<s1;
   cout<<s2;
   cout<<s1-s2;
    return 0;
}

首先明确几个相关概念

  • find 方法: find 方法是 std::string 类的一个成员函数,用于在字符串中查找子串。它接受两个参数:要查找的子串和开始查找的位置。如果找到了子串,它返回子串在字符串中第一次出现的位置;如果没有找到,它返回 std::string::npos
  • erase 方法: erase 方法也是 std::string 类的一个成员函数,用于从字符串中删除字符。它接受两个参数:开始删除的位置和要删除的字符数。这个方法会从指定的位置开始删除指定数量的字符。
  • string::size_type n = 0;: 这行代码声明了一个变量 n,其类型为 string::size_typestring::size_type 是一个无符号整数类型,通常用于表示字符串的大小或索引。在这里,n 被初始化为 0,表示从字符串的开始位置开始查找子串。
  • ostream& operator<<(ostream& os, A a): 这是一个重载的输出运算符函数。它接受一个 ostream 引用(如 cout)和一个 A 类的对象 a。这个函数的作用是将 A 对象中的字符串输出到 ostream 对象 os 中。函数的返回类型是 ostream&,这意味着它返回对 os 的引用,允许链式输出操作,例如 cout << a << b;

故第一个空处填n=s.find(s1,n);第二个空处填a.output();

5.编程综合题 从键盘输入一个整数,求它的平方。要求做容错处理,判断输入的是否为数字。

//one possible version
#include <iostream>
#include<string>
#include<sstream>

using namespace std;

class Square
{
private:
	int n;
	string s;
public:
   Square(){//构造函数
   }
   int str2num(string s){//串转数
   int temp;
   stringstream ss;
   //stringstream 是 C++ 标准库中的一个类,它允许你在字符串和基本数据类型之间进行转换。
   //通过创建一个 stringstream 对象,你可以将字符串插入到流中,或者从流中提取数据并转换为其他数据类型。
   //在这里,ss 是一个 stringstream 对象,用于字符串和整数之间的转换。
   ss<<s;
   //这行代码使用插入运算符 << 将字符串 s 插入到 stringstream 对象 ss 中。
   //这相当于将字符串 s 的内容“放入”流 ss 中,以便后续可以从这个流中提取数据。
   ss>>temp;
   //这行代码使用提取运算符 >> 从 stringstream 对象 ss 中提取数据,并将其存储在整数变量 temp 中。
   //这个操作将流中的字符串转换为整数。
   //如果流中的字符串格式正确(即它表示一个有效的整数),temp 将包含转换后的整数值。
   return temp;
   }
   
   bool input(){//输入并判断是否是数字
   		bool flag=true;
		cout<<"input a number:";
   		cin>>s;
   		for(int i=0;i<s.size(),++i){
                //s.size()是 std::string 类的一个成员函数,用于返回字符串 s 的长度(即字符串中字符的数量)。
                //在这个上下文中,s.size() 返回字符串 s 中的字符数,用于控制循环或确定字符串的长度。
   			if(s[i]>='0'&&s[i]<='9')
   				continue;
   			else{
   				cout<<"输入的不是数字,请重新输入!"<<endl;
   				flag=false;
   				break;
			   }
   			
		   }
		return flag;
   }
   
   void cal()
   {//计算平方
   while(true)
   {
   	if(input()==true)
   		{
   			n=str2num(s);
   			cout<<"square:"<<n*n<<endl;
   			break;
		   }
   	
   }
   		
   }
   
};


int main()
{
   Square s;
   s.cal();
    return 0;
}

6.程序填空

现有程序预期的输入输出如下:

输入:abc def

输出:

abc,abc,abc

def,def,def

#include <iostream>
using namespace std;

#include <string>
#include <cstring>

class StringPlus
{
    char *p;

public:
    StringPlus(const char *s)
    {
        if (s)
        {
            p = new char[strlen(s) + 1]
            strcpy(p, s);
        }
        else
            p = NULL;
    }
    StringPlus(const StringPlus &s)
    {
        if (s.p != NULL)
        {
            p = new char[strlen(s.p) + 1];
            strcpy(p, s.p);
        }
        
        else
            p = NULL;
    }
    
    ~StringPlus()
    {
        if (p)
            delete[] p;

    }
//类的定义不完整,请补充
};
int main()
{
    char w1[200] , w2[100];

    while (cin>>w1>>w2)
    {
        StringPlus s1(w1), s2 = s1;
        StringPlus s3(NULL);
        s3.Copy(w1);
        cout << s1 << "," << s2 << "," << s3 << endl;
        s2 = w2;
        s3 = s2;
        s1 = s3;
        cout << s1 << "," << s2 << "," << s3 << endl;
    }
}

答案如下 

    void Copy(char *s)
    {
        //这个函数用于将一个字符串 s 复制到 StringPlus 对象的内部字符数组 p 中。
        //如果 s 不是 NULL,它会先删除原有的 p(如果有的话),然后分配新的内存并复制 s 的内容。
        //如果 s 是 NULL,并且 p 不是 NULL,它会删除 p 并将其设置为 NULL。
        if (s != NULL)
        {
            if (p != NULL)
            {
                delete[] p;
            }
            p = new char[strlen(s) + 1];
            strcpy(p, s);
        }
        else if (p != NULL)
        {
            delete[] p;
            p = NULL;
        }
    }
    StringPlus &operator=(const StringPlus &s)
    {
        //这个函数重载了赋值运算符,使得 StringPlus 对象可以被赋值。
        //如果源对象 s 的 p 不是 NULL,它会先删除当前对象的 p(如果有的话),然后分配新的内存并复制 s.p 的内容。
        //如果 s.p 是 NULL,并且当前对象的 p 不是 NULL,它会删除 p 并将其设置为 NULL。
        ///函数返回当前对象的引用,以便支持链式赋值。
        if (s.p != NULL)
        {
            if (p != NULL)
                delete[] p;
            p = new char[strlen(s.p) + 1];
            strcpy(p, s.p);
        }
        else if (p != NULL)
        {
            delete[] p;
            p = NULL;
        }
        return *this;
    }
    friend ostream &operator<<(ostream &out, StringPlus &s)
    {
        //这个函数重载了输出运算符,使得 StringPlus 对象可以直接通过 cout 输出。
        //它接受一个 ostream 引用和一个 StringPlus 引用,将 StringPlus 对象的内部字符数组 p 的内容输出到流 out 中,
        //并返回该流,以便支持链式输出。
        out << s.p;
        //这是输出运算符重载的一部分,用于将 StringPlus 对象的内容输出到输出流 out 中。
        //在这个上下文中,out 是一个 ostream 对象(例如 cout),s 是一个 StringPlus 对象。
        //s.p 是 StringPlus 对象内部的字符数组,存储了实际的字符串内容。
        //通过 out << s.p;,字符串内容被插入到输出流中,从而可以被打印到控制台或其他输出设备。
        //这个操作是输出运算符重载的核心,它允许用户直接使用 cout 来输出 StringPlus 对象,就像输出普通字符串一样。
        return out;
    }
/*整个程序的逻辑是:
在 main 函数中,创建了两个字符数组 w1 和 w2。
进入一个无限循环,创建 StringPlus 对象 s1 和 s2,并复制 s1 到 s2。
创建 s3 并使用 Copy 函数从 w1 复制内容到 s3。
输出 s1、s2 和 s3 的内容。
然后进行一系列的赋值操作,改变 s1、s2 和 s3 的内容,并再次输出。
最后通过 break 退出循环。*/

7.编程综合题 允许输入三次密码,输入密码时显示为“*”。(提示:用getch()函数无回显输入单个字符)

//one possible version
#include <iostream>
#include<string>
#include<conio.h>

using namespace std;

class Password
{
private:
	int times;
	string password;
public:
   Password(string ss,int nn)
   {
   	password=ss;
   	times=nn;
   }
   string Input1()
   {
   	string temp;
   char c;
   cout<<"input password:";
   while(true)
   {
   	c=getch();
   	if(c!=13)
   	{//在 ASCII 码中,13 对应的是回车键(Enter 键)。
         //这个条件判断的目的是检查用户是否按下了回车键。如果不是回车键,则执行花括号内的代码块。
   		temp=temp+c;
   		cout<<'*';
	}
	else break;
   }
   cout<<endl;
   return temp;
   }
   void input2()
   {
   	string temp;
   	while(true)
   	{
   		temp=input1();
   		if(temp==password){
   			cout<<"密码正确!"<<endl;
   			break;
		   }
		else{
			cout<<"密码不正确!"<<endl;
			--times;
			if(times<=0){
				cout<<"输入错误,系统已退出!";
				break;
			}
		}
	   }
   }
   
   
};


int main()
{
   Password p("123456",3);
   p.input2();
    return 0;
}

8.编写程序,从文件text.dat中读取数据并打印。已有类申明及部分主函数如下:

#include <iostream>
#include<fstream>

using namespace std;
#define MAX 10

class Student
{
	
public:
  char name[25];
  int Ex1,Ex2;
};


int main()
{
    Student st[MAX];
    int count = 0;
    ifstream in("test.dat",ios::in);
    if(!in)
    {
    	cout<<"Cannot open test.dat.\n";
    	return 1;
	}
	in>>st[count].name>>st[count].Ex1>>st[count].Ex2;
	//请补充程序---------//
	
	
	//-------------------//
	in.close();
	return 0;
}

答案如下

//one possible version
while(!in.eof())
	{
		cout<<st[count].name<<""<<st[count].Ex1<<""<<st[count].Ex2<<"\n";
		count++;
		if(cout>=10)
		{
			cout<<"Exceed MAX:"<<MAX<<endl;
			in.close();
			return (-1);
		}
		in>>st[count].name>>st[count].Ex1>>st[count].Ex2;
	}

9.写出下列代码的运行结果,并简述运行过程

#include <iostream>
#include<string>

using namespace std;


class Oyster{
	public:
		Oyster(string genusString)
		{
			genus=genusString;
		}
		string getPhylum() const{//phylum 门类
			return "Mollusca";
		}
		virtual string getName() const{
			return "Oyster class";
		}
		string getGenus() const{//genus 属类
			return genus;
		}
		virtual void print() const=0;
	private:
		string genus;
};

class VirginiaOyster:public Oyster{
	public:
		VirginiaOyster():Oyster("Crassostrea"){//太平洋
		}
		virtual string getName() const{
			return"VirginiaOyster class";
		}
		virtual void print() const{
			cout<<"Phylum:"<<getPhylum().c_str()<<"\tGenus:"<<getGenus().c_str()<<"\tName:"<<getName().c_str();
		}
               //.c_str()是一个字符串处理函数,它用于将C++中的std::string类型转换为C语言风格的字符串,即以null结尾的字符数组
};

int main()
{
    VirginiaOyster oyster;
    Oyster *baseClassPtr;
    baseClassPtr=&oyster;
    baseClassPtr->print();
    cout<<endl;
    return 0;
}

运行过程如下:

  • 创建了一个VirginiaOyster对象oyster
  • 定义了一个指向Oyster类的指针baseClassPtr,并将其指向oyster对象。
  • 调用baseClassPtr->print()
  • VirginiaOyster类中,实现了print()函数,先调用getPhylum()函数返回字符串"Mollusca",再调用getGenus()函数返回字符串"Crassostrea",最后调用getName()函数返回字符串"VirginiaOyster class",将这些信息打印出来。
  • 输出结果为"Phylum: Mollusca Genus: Crassostrea Name: VirginiaOyster class"。

10.知识点整理——try和throw关键字

当我们编写代码时,可能会遇到潜在的错误或异常情况。为了处理这些异常,我们可以使用trythrow关键字。

try语句块用于包围可能会抛出异常的代码块,它的作用是捕获并处理异常。try语句块的基本语法如下:

try {
    // 可能会抛出异常的代码块
} catch (ExceptionType1 e1) {
    // 捕获并处理异常类型1的代码块
} catch (ExceptionType2 e2) {
    // 捕获并处理异常类型2的代码块
} catch (...) {
    // 捕获并处理其他异常的代码块
}

try语句块中的代码可能会抛出异常,当抛出异常时,程序会立即跳转到匹配的catch语句块中。

throw关键字用于在代码中主动抛出异常。我们可以使用throw关键字抛出一个异常对象,它可以是任意类型的对象,通常是派生自std::exception类或其子类的对象。throw的基本用法如下:

throw ExceptionType(); // 抛出一个异常对象

throw语句执行时,程序会立即跳转到调用栈中的最近的异常处理语句,寻找匹配的catch语句块来处理异常。

结合起来,trythrow关键字一起使用可以实现异常处理机制。我们使用try语句块包围可能会抛出异常的代码块,当在try语句块中的代码抛出异常时,程序会跳转到匹配的catch语句块中,用于捕获并处理异常。

11.问答题 已知Base类和Derive类有如下继承关系:

class Base{
	public:
		Base();
		virtual ~BaseV()
};
class Derived:public Base{
	public:
		Derived();
		~Derived();
		void PrintMessage();
};

请问:下面的函数是否有Bug,如果有,请说明并修正。

void foo(Base* b){
Derived*pd=dynamic_cast<Derived*>(b);
d->PrintMessage();
}

dynamic_cast是C++中的一个运算符,用于在类层次结构中进行安全的向下类型转换(downcast)。

在多态的情况下,当基类指针或引用指向派生类对象时,可以使用dynamic_cast将其转换为派生类指针或引用。这个转换是在运行时进行的,因此可以动态地检查是否可以进行安全的类型转换。

在使用dynamic_cast时,需要谨慎处理转换失败的情况,以避免访问无效的指针或引用。通常,可以通过检查转换结果是否为空指针来判断转换是否成功,并采取相应的错误处理措施。

在函数foo中,使用了动态类型转换dynamic_castBase*指针转换为Derived*指针,并尝试调用PrintMessage函数。

然而,如果传递给foo函数的Base*指针指向的对象不是Derived类的实例,那么dynamic_cast会返回一个空指针,而空指针是无效的,尝试通过空指针调用成员函数PrintMessage会导致未定义行为

为了修复这个问题,我们应该在调用PrintMessage函数之前,先检查dynamic_cast的返回值是否为空指针。如果为空指针,我们可以选择相应的错误处理方法,例如抛出异常、输出错误消息等。

修正为在两行间插入if(d);

12.问答题 运行下面的程序会产生何种结果,为什么?

#include <iostream>
#include<string>
#include<cstdlib>
#include<cstdio>
using namespace std;

int main()
{
   char *str=(char*)malloc(100);
   strcpy(str,"hello");
   free(str);
   if(str!=NULL)
   {
   	strcpy(str,"world");
   	printf(str);
   }
    return 0;
}

free(str); 释放了分配给 str 的内存。在 free(str) 之后,str 指向的内存区域不再有效,因此后续对 str 的任何操作(如 strcpy 和 printf)都会导致未定义行为。如果在 free(str) 之后不再需要 str,那么释放内存是正确的。但是,如果在释放内存后仍然尝试使用 str,这会导致内存泄漏,因为 str 指向的内存区域已经被释放,无法再次安全地使用。篡改动态内存区的内容,后果难以预料,非常危险。

13.编写求数组最小值的模板函数,使得如下程序输出:10,1

int main()
{
  	int arr1[]={10,20,15,12};
  	int n1=sizeof(arr1)/sizeof(arr1[0]);
  	int arr2[]={1,2,3};
  	int n2=sizeof(arr2)/sizeof(arr2[0]);
  	cout<<arrMin<int>(arr1,n1)<<endl;
  	cout<<arrMin<char>(arr2,n1)<<endl;
	return 0;
}

答案如下

template <class T>
int arrMin(T arr[],int len)
{
	int min=arr[0];
	for(int i=0;i<len;i++){
		
		if(arr[i]<=min)
		{
			min=arr[i];
		}
	}
	return min;
}//这里存在一些问题。函数的返回类型与函数体内使用的类型不一致。
//函数 arrMin 被声明为返回 int,但在函数体内,min 变量是模板类型 T。
//这意味着如果 T 不是 int,那么返回的值将与函数的返回类型不匹配,导致编译错误。
template <class T>
T arrMin(T arr[], int len)
{
    T min = arr[0];
    for (int i = 0; i < len; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return min;
}

14.编程题 运行如下文件后,文件:example.txt中的内容是什么?

编写程序读取example.txt中的内容并显示

#include <iostream>
#include<fstream>

using namespace std;

int main()
{
  	ofstream myfile("example.txt");
  	if(myfile.is_open())
  	{
  		myfile<<"This is a line.\n";
  		myfile<<"this is another line\n";
  		myfile.close();
	  }
	else cout<<"unable to open file";
	return 0;
}

答案如下

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    ifstream myfile("example.txt");
    if (myfile.is_open())
    {
        string line;
        while (!myfile.eof())
        {
            getline(myfile,line);
            //是 C++ 标准库中的一个函数调用,用于从输入流 myfile 中读取一行文本,
            //并将读取的内容存储在字符串变量 line 中。这个函数通常用于处理文件或标准输入(如键盘输入)。
            cout << line << endl;
        }
        myfile.close();
    }
    else
    {
        cout << "Unable to open file";
    }
    return 0;
}

15.定义一个名为“computer”的类,该类包含一个名为”name“的数据成员和一个名为”print“的成员函数,”print“用来打印该”name“数据成员;定义一个从”computer“派生而来的名为”Macintosh“的类,该类包含一个名为”color“的数据成员和一个名为”print“的成员函数,该成员函数用来打印”name“和”color“。

下面是用来测试的main函数

int main()
{
  	computer *p;
  	Macintosh imac("Joe`s IMAC","Blue");
  	p=&imac;
  	p->print();
	return 0;
}

希望上面的测试程序得到如下的输出结果

name:Joe`s IMAC

color:Blue

答案如下

//one possible version
class computer
{
	public:
		string _name;
		computer(string name){
		_name= name;
		}
		virtual void print(){
			cout<<"name:"<<_name<<endl;
		}
		
	
};

class Macintosh : public computer{
	public:
		string _color;
		Macintosh(string name,string color):computer(name)
		{
			_color=color;
		}
		void print(){
			 computer::print();
			 cout<<"color:"<<_color<<endl;
		}
};

16.已知类string的原型为:

class String{
	public:
		String(const char *str=NULL);
		String(const String &other);
		~String(void);
		String & operate=(const String &other);
	private:
		char *m_data;
};

请编写String的拷贝构造函数和赋值函数。

//析构函数
String::~String(void){
	delete[] m_data;
}

//普通构造函数
String::String(const char *str)
{
	if(str==NULL)
	{
		m_data=new char[1];
		*m_data="\0";
	}
	else{
		int length=strlen(str);
		m_data=new char[length+1];
		strcpy(m_data,str);
	}
}

//拷贝构造函数
String::String(const String &other)
{
	int length=strlen(other.m_data);
	m_data=new char[length+1];
	strcpy(m_data,other.m_data);
}

//赋值函数
String &String::operate=(const String &other)
{
	//检查自赋值
	if(this==&other)
	return *this;
	//释放原有的内存资源
	delete[] m_data;
	//分配新的内存资源,并复制内容
	int length=strlen(other.m_data);
	m_data=new char[length+1];
	strcpy(m_data,other.m_data);
	//返回本对象的引用
	return *this;
}
  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霜见月九

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值