文章目录
这篇文章主要用于总结一些错误
问题1:未知重写说明符
#include <iostream>
#include <Windows.h>
#include <string>
#include <array>
#include <vector>
struct yu {
string x;//品种
float y;//重量
float j;//长度
};
using namespace std;
int main(void) {
struct yu* s1 = new struct yu;
s1->x = { "草鱼" };
s1->y = 5.6;
s1->j = 15.4;
cout << s1->x <<" " << s1->y << "KG " << s1->j << "CM" << endl;
delete s1;
system("pause");
return 0;
}
这是报错的源代码,编译器没有任何报错,但是一编译就出问题,我看了半天才发现原来是struct中的string 前面没有加std::以为我在mani函数前加了using namespace std;
但是我定义struct的时候定义在了using namespace std;前面,所以导致了“未知重写说明符”
改进方法
1.要么在struct结构体中的string前面加上std::
2.把using namespace std;放在struct结构体前面
改进后的代码
#include <iostream>
#include <Windows.h>
#include <string>
#include <array>
#include <vector>
using namespace std;
struct yu {
string x;//品种
float y;//重量
float j;//长度
};
int main(void) {
struct yu* s1 = new struct yu;
s1->x = { "草鱼" };
s1->y = 5.6;
s1->j = 15.4;
cout << s1->x <<" " << s1->y << "KG " << s1->j << "CM" << endl;
delete s1;
system("pause");
return 0;
}
问题2 : 没有与参数列表匹配的构造函数
今天敲代码遇到一个很费解的问题,明明写了构造函数,也对的上,但是编译器报错
问题代码
//构造函数
Father(string &name,int age);
//这是构造函数的实现
Father::Father(string &name,int age) {
this->name = name;
this->age = age;
}
//这是对象创建
Father zyy(“智羊羊”, 42);
问题所在
TMD居然说不匹配,后面经过一系类研究,终于发现问题所在了
问题就在Father(string &name,int age);中的string &name中
加了引用,而输入的字符串是const char*类型,定义的字符串是string
类型肯定不匹配
问题原因
因为加上引用,就相当于是直接修改类中name的值,而且不会产生形参副本,
就是不会构建另外一个string
但是去掉引用就没事了,这是因为不加引用会创建一个形参副本,会调用string
的拷贝函数,然后就是拷贝函数内部自动拷贝,自动转类型
意思就是不加引用会产生两个string类型,一个在类的内部,这是两块不同的内存
,内部自己会调用拷贝构造函数
进行拷贝等操作,内部可以操作,但是加引用就相当于是直接操作内部的值C++的机制是不允许的
解决方法
1.最简单的是去掉引用
2.重构构造函数,使用const char*类型
3.传入一个string 类型
string zyy1(“智羊羊”);
Father zyy(zyy1, 42);
小笔记
// 子类对象调用方法时, 先在自己定义的方法中去寻找, 如果有, 就调用自己定义的方法
// 如果找不到, 就到父类的方法中去找, 如果有, 就调用父类的这个同名方法
// 如果还是找不到, 就是发生错误!
问题3:文件结束符eof()函数
今天写代码带的时候,发现,我文件里面数据只有三行,但是while()循环却循环了四次,一次读一行,应该读三次就结束的,多读了一次,导致错误
原因
原因是eof函数,是在文件最后面,就比如说我文件里面有三行数据,读三次就没了,当读完第三行的时候,文件内部有一个文件位置指针,读完第三行后,文件指针已经指向eof了,也就是指向文件结束符了,但仅仅是指向了eof文件结束符,并没有读取到eof文件结束符,最后一行读完后,文件位置指针,指向eof后,会在多读一次,然后就遇到eof了,就结束了,文件位置指针指向了eof并不代表读到了eof结束符,eof结束符需要遇到了才会结束,并不是文件位置指针指向了结束,可以简单理解为,一行数据,需要读两次才会结束
解决方法
解决方法就是先读了在判断是否遇到eof结束符,我在代码中是这样写的
while(file.eof()) 这样写,虽然方便,但是就存在着上面的问题,这样写是先
判断是否遇到eof结束符,在读取的,读都没读取,肯定遇不到eof结束符
应该这样写
while(true){
读文件
if(file.eof()){
break;
}
}
先读文件在判断就不会出现上面的问题
错误代码
while (!file.eof()){
string line;
string name1;
char name[64];
int age;
int salary;
getline(file,line);
int ret=sscanf_s(line.c_str(),"性别:男 姓名:%s 年龄:%d 薪资:%d",name,sizeof(name),&age,&salary);
if (ret <= 0) {
cout << "男嘉宾数据库信息匹配失败!" << endl;
exit(1);
}
boys.push_back(Boy(name1,age,salary));
file.close();
}
改进后代码
while (true){
string line;
string name1;
char name[64];
int age;
int salary;
getline(file,line);
if (file.eof()) {
break;
}
int ret=sscanf_s(line.c_str(),"性别:男 姓名:%s 年龄:%d 薪资:%d",name,sizeof(name),&age,&salary);
if (ret <= 0) {
cout << "男嘉宾数据库信息匹配失败!" << endl;
exit(1);
}
boys.push_back(Boy(name1,age,salary));
file.close();
}
问题:4:c语言中的sscanf按指定格式读取数据
sscanf函数中,只要是有字符串,就必须用char类型字符串,不能用string类型字符串,即使,使用了也不会报错,所以要特别注意
int ret=sscanf_s(line.c_str(),"性别:男 姓名:%s 年龄:%d 薪资:%d",name,sizeof(name),&age,&salary);
可以使用一个变量来接收返回值,如上代码中有三个变量,如果全部没问题就会返回3,如果返回值小于或等于0就是读取失败了
错误代码
while (true){
string line;
string name1;
//char name[64];
int age;
int salary;
getline(file,line);
if (file.eof()) {
break;
}
int ret=sscanf_s(line.c_str(),"性别:男 姓名:%s 年龄:%d 薪资:%d",name1,&age,&salary);
if (ret <= 0) {
cout << "男嘉宾数据库信息匹配失败!" << endl;
exit(1);
}
boys.push_back(Boy(name1,age,salary));
改正后代码
while (true){
string line;
//string name1;
char name[64];
int age;
int salary;
getline(file,line);
if (file.eof()) {
break;
}
int ret=sscanf_s(line.c_str(),"性别:男 姓名:%s 年龄:%d 薪资:%d",name,sizeof(name),&age,&salary);
if (ret <= 0) {
cout << "男嘉宾数据库信息匹配失败!" << endl;
exit(1);
}
小笔记
sscanf中的所有字符串也就是%s都必须加sizeof()函数计算大小,不然编译器不知道读多少数据,不加sizeof编译器也不会报错,切记
其他类型成员也要加&取地址符
笔记 .h头文件不能相互包含头文件,因为会相互拷贝.cpp文件可以相互包含头文件
笔记 假如有一个boy类,里面有拷贝构造函数和=赋值构造函数
boy f1(数据);
boy f2=(f1); //调用拷贝构造函数,拷贝构造函数不能连续赋值
笔记 注意这里是调用的拷贝构造函数而不是=赋值构造函数
boy f1(数据);
boy f2;
f2=f1;
笔记 这里才是调用=赋值构造函数
笔记 =赋值构造函数和拷贝构造函数的区别,是=赋值构造函数可以连续赋值而拷贝构造函数只能赋一个值
boy f1(数据);
boy f2;
boy f3;
f3=f2=f1; //调用=赋值构造函数,=赋值构造函数可以连续赋值
问题5:出现cout 或者各种不明确的时候解决方法
解决方法就是先把using namespace std;先注释掉,在取消注释
问题6:双向链表错误总结
在双向链表中插入数据的时候一点要注意,修改指针域顺序的先后
如图,我这里,先把p->prev指向了s
执行p->prev->next = s;的时候,p->prev不就是指向了自己嘛,这里原本是要把前一个节点的指针域指向自己,这样写,就是把自己的后置指针域,指向自己了,就会导致插入出现问题
正确的写法:
先使用了,在去修改
问题7:不能将 “LinkNode *” 类型的值分配到 “_LinNode *” 类型的实体
这里是因为我没有提前定义_LinNode
改进前
改进后
使用前需要提前声明
问题8: 不存在从某某数据类型转换某某类的适当构造函数
问题描述
当在一个类中,包含了另外一个类作为自己的数据成员,而且这个类的数据类型是定义成数组的,那么就需要使用初始化列表
问题源代码
#pragma once
#include <string>
#include <sstream>
#include "Engine.h"
#include "Tyre.h"
using namespace std;
class Automobile{
public:
Automobile();
Automobile(const string brand,string model,
unsigned int price, unsigned int actual,
string GetBrand,float GetSize,float GatAir, //轮胎参数
string Getbrand,string Getmodel); //发动机参数
~Automobile();
string getBrand() const;
string getModel() const;
unsigned int getPrice() const;
unsigned int getActual() const;
string description() const;
private:
Tyre tyre[4]; //轮胎
Engine engine; //发动机
string brand; //品牌
string model; //型号
unsigned int price;
unsigned int actual; //行驶里程
};
这个问题就是初始化Tyre tyre[4];
这是初始化构造函数
Automobile::Automobile(const string brand, string model, unsigned int price, unsigned int actual,
string GetBrand, float GetSize, float GatAir, //轮胎
string Getbrand, string Getmodel) : //发动机
engine(Getbrand, Getmodel),
tyre{(GetBrand,GetSize,GatAir),(GetBrand,GetSize,GatAir),
(GetBrand,GetSize,GatAir),(GetBrand,GetSize,GatAir), }
{
this->brand = brand;
this->model = model;
this->price = price;
this->actual = actual;
}
解决问题
解决问题很简单,只需要使用正确的语法就可以了,语法如下
Automobile::Automobile(const string brand, string model, unsigned int price, unsigned int actual,
string GetBrand, float GetSize, float GatAir, //轮胎
string Getbrand, string Getmodel) : //发动机
engine(Getbrand, Getmodel),
tyre{Tyre(GetBrand,GetSize,GatAir),Tyre(GetBrand,GetSize,GatAir),
Tyre(GetBrand,GetSize,GatAir),Tyre(GetBrand,GetSize,GatAir), }
{
this->brand = brand;
this->model = model;
this->price = price;
this->actual = actual;
}
using namespace std;笔记
using namespace std;
是一个常见的C++语句,它的作用是将命名空间 std
中的标识符引入当前的作用域,使得可以直接使用 std
命名空间中的标识符,而无需在每个标识符前添加 std::
前缀。
在C++标准库中,许多标准库的类、函数和对象都定义在 std
命名空间中。例如,std::cout
、std::cin
、std::string
等都是在 std
命名空间中定义的。
使用 using namespace std;
可以简化代码,使得在使用标准库中的标识符时不需要添加 std::
前缀,提高了代码的可读性和编写效率。例如,通过使用 using namespace std;
,可以直接写 cout << "Hello, world!" << endl;
而不需要写成 std::cout << "Hello, world!" << std::endl;
。
需要注意的是,using namespace std;
是在全局作用域或函数内部使用的,不推荐在头文件中使用,以避免引入命名冲突或命名污染的问题。在大型项目中,更好的做法是在需要使用的特定作用域内使用 using
语句,或者使用具体的 std
命名空间的成员。例如,可以使用 using std::cout;
来引入 std::cout
,而不是一次性引入整个 std
命名空间。
总之,using namespace std;
可以简化代码,但在使用时需要注意命名冲突和代码可读性的问题。