我需要澄清为什么会出现这种错误?
char name[50];
clrscr();
cout<<"Please enter the name of the medicine: ";cin>>name;
pharmacy_personnel *ob2;//pharmacy_personnel is a class
ob2 = new pharmacy_personnel[total];
for(int i=0; i<total; i++){
if(strcmp(name,ob2[i].get_name_of_medicine())==0)
{
//code
}
}
错误出现在strcmp()
函数中: -
类型&#34; char&#34;的参数与#34; const char *&#34;类型的参数不兼容
有什么建议吗?
答案 0 :(得分:2)
有什么建议吗?
是的,不少。
首先,如果您遇到错误而无法自行解决并决定寻求帮助,请务必发布可重现问题的代码。如果你无法弄清楚错误的来源,你就不太可能正确地确定你的程序的哪些部分与错误相关,哪些部分不相关。我通常的做法是从一个新文件开始并添加代码,直到错误再次出现。我避免复制和粘贴有利于重新输入,因为这样可以避免复制愚蠢的错别字。通常,您将通过尝试创建这样的最小工作(或者,在这种情况下失败)示例来学习如何自己解决问题。如果它们与您的问题无关,请尽量避免示例中的非标准依赖项。在您的示例中,应删除clrscr
函数。此外,最好花两分钟时间以可读的方式格式化代码。
现在你的代码:我已经创建了一个最小的工作示例。
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <iostream>
struct pharmacy_personnel
{
pharmacy_personnel(const char *const name_of_medicine = "Tonic Water")
{
std::strncpy(this->name_of_medicine_, name_of_medicine, 50);
this->name_of_medicine_[49] = '\0';
}
const char *
get_name_of_medicine() const
{
return this->name_of_medicine_;
}
private:
char name_of_medicine_[50];
};
int
main()
{
const std::size_t total = 10;
char name[50];
//clrscr();
std::cout << "Please enter the name of the medicine: ";
std::cin >> name;
pharmacy_personnel * ob2 = new pharmacy_personnel[total];
for (std::size_t i = 0; i < total; ++i)
{
if(std::strcmp(name, ob2[i].get_name_of_medicine()) == 0)
{
std::cout << "Yes, we have that medicine.\n";
return EXIT_SUCCESS;
}
}
std::cout << "Sorry, we don't have that medicine.\n";
return EXIT_FAILURE;
}
“突然间”它编译没有错误。这表示您的原始问题缺少相关信息。我最好的选择是pharmacy_presonnel::get_name_of_medicine()
的实施在返回char
时会返回const char *
。
但是这个代码还有很多其他的东西需要修复。
第一个惊喜可能就是这个:
$ ./a.out
Please enter the name of the medicine: Tonic Water
Sorry, we don't have that medicine.
第二个可能是这个(希望你在攻击者之前发现它):
$ ./a.out
Please enter the name of the medicine: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Segmentation fault
这两个问题都源于您不使用C ++技术而是不安全的低级C风格I / O.它们肯定可以用C风格的编程来修复,但是,为什么要使用C ++呢?
在C ++中,我们通常在std::string
类中存储字符串。这个类将负责为字符串分配足够大的缓冲区(只是),并在对象超出范围时解除分配。那么,实际上,我们还应该在pharmacy_personnel
类中使用C ++字符串。
关于std::string
的另一个好处是你可以简单地使用运算符==
来比较它们。这使cstring
标头变得多余。
正常的“输入操作符”>>
在空格处停止。由于药物的名称很可能包含空白,我们最好使用std::getline
函数来读取整行输入。
应用所有这些我们得到:
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <string> // This is the C++, not the C header!
struct pharmacy_personnel
{
pharmacy_personnel(const std::string& name_of_medicine = "Tonic Water")
: name_of_medicine_(name_of_medicine)
{
}
std::string
get_name_of_medicine() const
{
return this->name_of_medicine_;
}
private:
std::string name_of_medicine_;
};
int
main()
{
const std::size_t total = 10;
std::string name;
std::cout << "Please enter the name of the medicine: ";
std::getline(std::cin, name);
pharmacy_personnel * ob2 = new pharmacy_personnel[total];
for (std::size_t i = 0; i < total; ++i)
{
if(name == ob2[i].get_name_of_medicine())
{
std::cout << "Yes, we have that medicine.\n";
return EXIT_SUCCESS;
}
}
std::cout << "Sorry, we don't have that medicine.\n";
return EXIT_FAILURE;
}
这解决了与字符串相关的问题,但还有其他问题。我不太确定将name
与total
相同字符串进行比较的目的是什么,但使用“裸”运算符new
几乎肯定是个坏主意。 (到目前为止发布的程序都有内存泄漏的原因。)我们将升级到C ++的std::vector
。
// Other headers as before.
#include <vector> // for std::vector
// No changes to struct pharmacy_personnel.
int
main()
{
const std::size_t total = 10;
std::string name;
std::cout << "Please enter the name of the medicine: ";
std::getline(std::cin, name);
std::vector<pharmacy_personnel> ob2(total);
for (std::size_t i = 0; i < ob2.size(); ++i)
{
if(name == ob2[i].get_name_of_medicine())
{
std::cout << "Yes, we have that medicine.\n";
return EXIT_SUCCESS;
}
}
std::cout << "Sorry, we don't have that medicine.\n";
return EXIT_FAILURE;
}
如果您已经在使用C ++ 11,我们可以通过使用range-for循环使代码更具表现力(并且更不容易出错)。这使我们免于明确编号向量元素的需要。 (使用迭代器,您也不需要在C ++ 98中执行此操作,但新语法更清晰。我从未发现手动使用迭代器可以获得更易读的代码。)
for (const auto& iter : ob2)
{
if(name == iter.get_name_of_medicine())
{
std::cout << "Yes, we have that medicine.\n";
return EXIT_SUCCESS;
}
}
我想提到的最后一点是你的命名和类设计可能会有所改进。名称ob2
应该告诉我什么?更重要的是:为什么班级pharmacy_personnel
(应该代表一名员工?)具有与之相关的药品名称?如果每个员工只负责一种药物,这最终会有意义,但这听起来很奇怪。理想情况下,您的类尽可能地为您的域(即现实生活)建模。旨在实现这一目标将使您的代码更好地结构化,更易于理解,从而更易于维护 - 最重要的是 - 编写代码更有趣。
答案 1 :(得分:0)
您正在将C ++流(cin,cout)与C风格的strcmp混合使用。这不是一个好主意,它会导致您比较不兼容的对象。特别是,cin>>name
并没有按照您的想法行事。您可能希望name
成为std :: string,并使用相等而不是strcmp
。
如果您了解 ranged for loops 和std::find
,您的代码也会更清晰,更强大。现在值得做,以便以后有更好的代码。