【问题标题】:Searching text file for name and ID pairs, try/catch exceptions在文本文件中搜索名称和 ID 对,尝试/捕获异常
【发布时间】:2021-11-24 09:43:39
【问题描述】:

我没有看到这个问题已经发布,或者任何有用的类似内容。

我正在上第二学期的 C++ 课程,并且只通过了 10 个测试点中的 5 个。我可以看出我的 try/catch 设置有问题。在网上搜索之后,我可能对我遇到的错误更加困惑:

main.cpp: In function ‘std::string FindID(std::string, std::ifstream&)’:
main.cpp:24:1: warning: control reaches end of non-void function [-Wreturn-type]
   24 | }
      | ^
main.cpp: In function ‘std::string FindName(std::string, std::ifstream&)’:
main.cpp:49:1: warning: control reaches end of non-void function [-Wreturn-type]
   49 | }
      | ^

问题和我的代码如下:


6.9 LAB:找不到学生信息

给定一个在文本文件中搜索学生 ID 或姓名的程序,完成 FindID()FindName() 函数。然后,在main()中插入一条try/catch语句,捕获FindID()FindName()抛出的任何异常,并输出异常信息。文本文件中的每一行都包含由空格分隔的名称和 ID。

函数FindID() 有两个参数:学生姓名(字符串)和文本文件内容(ifstream)。如果学生姓名在文件中,函数FindID() 返回与学生姓名相关联的 ID,否则,该函数会抛出带有消息“Student ID not found for studentName”的runtime_error,其中 studentName 是学生的姓名.

函数FindName() 有两个参数:学生的ID(字符串)和文本文件的内容(ifstream)。如果 ID 在文件中,函数 FindName() 将返回与学生 ID 关联的名称,否则,该函数将引发 runtime_error 并显示消息“Student name not found for studentID”,其中 studentID 是学生的 ID。

主程序接受用户的三个输入:文本文件的名称(字符串)、用于查找学生 ID 或姓名的搜索选项(int)以及学生的 ID 或姓名(字符串) .如果搜索选项为 0,则使用学生姓名作为参数调用 FindID()。如果搜索选项为 1,则使用学生 ID 作为参数调用 FindName()。主程序输出搜索结果或捕获到的异常信息。

例如:如果程序的输入是:

roster.txt 0 Reagan

而 roster.txt 的内容是:

Reagan rebradshaw835
Ryley rbarber894
Peyton pstott885
Tyrese tmayo945
Caius ccharlton329

程序的输出是:

rebradshaw835

例如:如果程序的输入是:

roster.txt 0 Mcauley

程序输出异常信息:

Student ID not found for Mcauley

例如:如果程序的输入是:

roster.txt 1 rebradshaw835

程序的输出是:

Reagan

例如:如果程序的输入是:

roster.txt 1 mpreston272

程序输出异常信息:

Student name not found for mpreston272

我的 main.cpp 代码:

#include <string>
#include <iostream>
#include <stdexcept>
#include <fstream>
using namespace std;

string FindID(string name, ifstream &infoFS) {
   bool foundID = false;
   string input;
   infoFS >> input;
   while (infoFS) 
   {
      if (input == name)
      {
         infoFS >> input;
         return input;
      }
      else { infoFS >> input; }
   }
   if (foundID == false)  
   {
      throw name;
   }   
}

string FindName(string ID, ifstream &infoFS) {
   bool foundName = false;
   string previous;
   string input;
   infoFS >> previous;
   infoFS >> input;
   while (infoFS) 
   {
      if (input == ID)
      {
         foundName = true;
         return previous;         
      }
      else 
      { 
         previous = input;
         infoFS >> input; 
      }
   }
   if (foundName == false) 
   {
      throw ID;
   }   
}

int main() {
   int userChoice;
   string studentName;
   string studentID;
   string studentInfoFileName;
   ifstream studentInfoFS;
   
   // Read the text file name from user
   cin >> studentInfoFileName;
   
   // Open the text file
   studentInfoFS.open(studentInfoFileName);
   
   // Read search option from user. 0: FindID(), 1: FindName()
   cin >> userChoice;

   try 
   {
      if (userChoice == 0) {
         cin >> studentName;
         studentID = FindID(studentName, studentInfoFS);
         cout << studentID << endl;
      }
      else {
         cin >> studentID;
         studentName = FindName(studentID, studentInfoFS);
         cout << studentName << endl;
      }
   }
   catch (string name)
   {
      if (userChoice == 0) {
         cout << "Student ID not found for " << name << endl;
      }
   }  
   catch (char ID)
   {
      cout << "Student name not found for " << ID << endl;
   }
    
   studentInfoFS.close();
   return 0;
}

我提交时的编译器警告:

main.cpp: In function ‘std::string FindID(std::string, std::ifstream&)’:
main.cpp:24:1: warning: control reaches end of non-void function [-Wreturn-type]
   24 | }
      | ^
main.cpp: In function ‘std::string FindName(std::string, std::ifstream&)’:
main.cpp:49:1: warning: control reaches end of non-void function [-Wreturn-type]
   49 | }
      | ^

通过测试:

1: Compare output

    Input
    roster.txt 0 Reagan
    Your output
    rebradshaw835

2: Compare output

    Input
    roster.txt 0 Mcauley
    Your output
    Student ID not found for Mcauley

3: Compare output

    Input
    roster.txt 1 rebradshaw835
    Your output
    Reagan
7: Unit test

    Test FindName("mpreston272", infoFS) with roster1.txt, should return Mcauley
    Your output
    FindName("mpreston272", infoFS) correctly returned Mcauley

8: Unit test

    Test FindID("Mcauley", infoFS) with roster1.txt, should return mpreston272
    Your output
    FindID("Mcauley", infoFS) correctly returned mpreston272

测试失败:

4: Compare output

    Input
    roster.txt 1 mpreston272
    Your output
    Your program produced no output
    Expected output
    Student name not found for mpreston272

5: Unit test

    Test FindID("John", infoFS) with roster1.txt, should throw an exception
    Returned unexpected error code (-6)

6: Unit test

    Test FindName("jsmith474", infoFS) with roster1.txt, should throw an exception
    Returned unexpected error code (-6)

【问题讨论】:

  • 函数期望你返回一个字符串,你什么都没有返回。
  • 你用的是什么C++标准版?
  • foundIDfoundNametrue 时,你应该返回什么?
  • 您收到警告是因为您的if (foundID == false)。删除条件,因为无论如何它都没用。
  • 另外,不要用throwstd::stringthrowstd::runtime_error 代替。然后,将您的 exception 处理程序更改为:catch ( const std::exception&amp; error )

标签: c++ exception try-catch ifstream


【解决方案1】:

我终于让它工作并通过了所有 10 项测试。感谢@Wbuck 的评论让我仔细研究了 try/catch 语法:“不要抛出 std::string、throw 和 std::runtime_error。然后,将您的异常处理程序更改为:catch ( const std: :异常和错误) – Wbuck"

我发现这篇文章很有帮助:How to throw a C++ exception

以及cpp参考站:https://en.cppreference.com/w/cpp/language/function-try-block

我试图传递通用错误字符串,然后在 catch 语句中添加变量名称/ID 输入,但除非变量被传递,否则这不起作用。所以我必须使用默认消息 + 输入变量创建一个新字符串,然后将其作为一个字符串传递给抛出的 runtime_error。

编译器内置在 ZyBooks 的网站中,它没有说明它使用什么版本的 C++。

这是通过所有测试的代码,以防其他人遇到类似问题。

#include <string>
#include <iostream>
#include <stdexcept>
#include <fstream>
using namespace std;

string FindID(string name, ifstream &infoFS) {
   bool foundID = false;
   string input;
   infoFS >> input;
   while (infoFS) 
   {
      if (input == name)
      {
         foundID = true;
         infoFS >> input;
         return input;
         break;
      }
      else { infoFS >> input; }
   }
   if (foundID == false)  
   {
      string NoNameMsg = "Student ID not found for " + name;
      throw runtime_error(NoNameMsg);
   }   
   return "";
}

string FindName(string ID, ifstream &infoFS) {
   bool foundName = false;
   string previous;
   string input;
   infoFS >> previous;
   infoFS >> input;
   while (infoFS) 
   {
      if (input == ID)
      {
         foundName = true;
         return previous;
         break;
      }
      else 
      { 
         previous = input;
         infoFS >> input; 
      }
   }
   if (foundName == false) 
   {
      string NoIDMsg = "Student name not found for " + ID;
      throw std::runtime_error(NoIDMsg);
   }  
   return "";
}

int main() {
   int userChoice;
   string studentName;
   string studentID;
   string studentInfoFileName;
   ifstream studentInfoFS;
   
   // Read the text file name from user
   cin >> studentInfoFileName;
   
   // Open the text file
   studentInfoFS.open(studentInfoFileName);
   
   // Read search option from user. 0: FindID(), 1: FindName()
   cin >> userChoice;

   try 
   {
      if (userChoice == 0) {
         cin >> studentName;
         studentID = FindID(studentName, studentInfoFS);
         cout << studentID << endl;
      }
      else {
         cin >> studentID;
         studentName = FindName(studentID, studentInfoFS);
         cout << studentName << endl;
      }
   }
   catch ( const std::runtime_error& e )
   {
      cout << e.what() << endl;
   } 
         
   studentInfoFS.close();
   return 0;
}

【讨论】:

  • 虽然这在技术上是可行的,但看到您尝试在程序中使用throw/catch onn 字符串有点令人惊讶。通常,throw / catch 用于处理异常,这对于处理意外错误很有用。在你的情况下,你想为你的错误定义一个新的异常类型,所以你可以定义你自己的异常类,用一个描述错误的字符串初始化
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2021-12-13
  • 2011-12-05
  • 2014-05-11
  • 2019-01-06
相关资源
最近更新 更多