轻微错误在strcmp()函数中

时间:2014-09-06 21:16:44

标签: c++ string

我需要澄清为什么会出现这种错误?

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;类型的参数不兼容

有什么建议吗?

2 个答案:

答案 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;
}

这解决了与字符串相关的问题,但还有其他问题。我不太确定将nametotal相同字符串进行比较的目的是什么,但使用“裸”运算符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,您的代码也会更清晰,更强大。现在值得做,以便以后有更好的代码。