c++ - 如何在 C++ 中传递字符串数组

标签 c++ arrays

我正在尝试为学校项目编写命令行界面。我有一个 driver.cpp 来运行命令行,它将命令解析为 commandInterpreter 的字符串数组。当我尝试调试时,当我调用 interpreter->interpret(rowData, length); 时,看起来只有第一个字符串被传递 如果我在命令行中键入“import p filename”,它看起来like args 只包含字符串“import”。我期待它通过 {"import", "p", "filename"}。我是否错误地传递或访问了字符串数组?

驱动.cpp

#include "CommandInterpreter.h"
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main() 
{
   CommandInterpreter * interpreter = new CommandInterpreter();

   while ( !interpreter->terminate() )
   {
      string cmd;
      getline(cin, cmd);

      //Parse command args to lowercase
      int i = 0;
      while(cmd[i])
      {
         char c = cmd[i];
         putchar(tolower(c));
         i++;
      }
      //Parse command line into command and parameters.
      //Space delimited.
      stringstream ss(cmd);
      string item;
      string * rowData = new string[100];
      int length = 0;
      while (getline(ss, item, ' ')) {
         rowData[length] = item;
         length++;
      }

      //Interpret command
      interpreter->interpret(rowData, length);
      //Print feedback
      cout << interpreter->feedback() << '\n';
   }

   delete interpreter;
   return 0;
}

CommandInterpreter.h

#ifndef __COMMANDINTERPRETER_H
#define __COMMANDINTERPRETER_H

#include <string>
#include "ProjectController.h"
#include "LocationController.h"
#include "VolunteerController.h"
#include "ScheduleGenerator.h"
#include "VolunteerScheduler.h"

class ProjectController;
class LocationController;
class VolunteerController;
class ScheduleGenerator;
class VolunteerScheduler;

using namespace std;

class CommandInterpreter
{
public:
   CommandInterpreter(void);
   ~CommandInterpreter(void);

   //---------------------------------------------------------------------
   // Tells the driver when to teminate the program.
   //---------------------------------------------------------------------
   bool terminate(void);

   //---------------------------------------------------------------------
   // Interprets the given array of commands.
   //---------------------------------------------------------------------
   bool interpret(string * commands, int length);

   //---------------------------------------------------------------------
   // Provides feedback for the last command run.
   //---------------------------------------------------------------------
   string feedback(void);

private:
   bool exitFlag;
   string handback;

   ProjectController * PC;
   LocationController * LC;
   VolunteerController * VC;
   ScheduleGenerator * SG;
   VolunteerScheduler * VS;

public:
   //---------------------------------------------------------------------
   // Interprets a save command.
   //---------------------------------------------------------------------
   bool save(char arg0);

   //---------------------------------------------------------------------
   // Interprets an import command
   //---------------------------------------------------------------------
   bool import(char arg0, string filename);

   //---------------------------------------------------------------------
   // Interprets a print command.
   //---------------------------------------------------------------------
   bool print(char arg0, char arg1);

   //---------------------------------------------------------------------
   // Interprets a schedule command.
   //---------------------------------------------------------------------
   bool schedule(char arg0);

   //---------------------------------------------------------------------
   // Interprets a help command. Provides a list of commands in feedback.
   //---------------------------------------------------------------------
   bool help(void);
};

#endif

CommandInterpreter.cpp

#include "CommandInterpreter.h"

CommandInterpreter::CommandInterpreter(void)
{
   exitFlag = false;
   handback = "";
   PC = new ProjectController();
   LC = new LocationController();
   VC = new VolunteerController();
   SG = new ScheduleGenerator();
   VS = new VolunteerScheduler();
}


CommandInterpreter::~CommandInterpreter(void)
{
   delete PC;
   delete LC;
   delete VC;
   delete SG;
   delete VS;
}


bool CommandInterpreter::terminate(void)
{
   return this->exitFlag;
}


bool CommandInterpreter::interpret(string * args, int length)
{
   //args should be an array of strings like {"import","p","filename"}
   //Debug only shows "import"

   string cmd = args[0];
   handback = "";

   if(cmd == "exit")
   {
      exitFlag = true;
   }
   else if(cmd == "save")
   {
      this->save(args[1][0]);
   }
   else if(cmd == "import")
   {
      this->import(args[1][0], args[2]);
   }
   else if(cmd == "print")
   {
      if(length == 2)
         this->print(args[1][0], '0');
      else
         this->print(args[1][0], args[2][0]);
   }
   else if(cmd == "schedule")
   {
      this->schedule(args[1][0]);
   }
   else if(cmd == "help")
   {
      this->help();
   }
   else
   {
      this->handback = "Invalid Command. Type help to see commands.";
      return false;
   }

   return true;
}


string CommandInterpreter::feedback(void)
{
   return this->handback;
}


bool CommandInterpreter::save(char arg0)
{
   bool success = true;

   switch (arg0)
   {
   case 'p':
      // PC->save();
      handback = "Saved project schedule.";
      break;
   case 'v':
      // VC->save();
      handback = "Saved volunteer schedule.";
      break;
   default:
      // Uh-oh
      handback = "Invalid argument for save: " + arg0;
      success = false;
      break;
   }
   return success;
}

bool CommandInterpreter::import(char arg0, string filename)
{
   bool success = true;
   switch (arg0)
   {
   case 'p':
      PC->importCSV(filename);
      handback = "Imported projects file: " + filename;
      break;
   case 'l':
      LC->importCSV(filename);
      handback = "Imported locations file: " + filename;
      break;
   case 'v':
      VC->importCSV(filename);
      handback = "Imported volunteers file: " + filename;
      break;
   default:
      success = false;
      handback = "Invalid argument for import command: " + arg0;
      break;
   }
   return success;
}


bool CommandInterpreter::print(char arg0, char arg1)
{
   bool success = true;
   switch (arg0)
   {
   case 'p':
      // PC->print()
      // or project schedule print
      // depending on arg1
      if(arg1 == '0')
         handback = PC->getProjectStrings();
      else
         ;   //Print project schedule here.
      break;
   case 'l':
      // LC->print()
      break;
   case 'v':
      // VC->print()
      // or volunteer schedule print
      // depending on arg1
      break;
   default:
      success = false;
      handback = "Invalid argument for print command: " + arg0;
      break;
   }
   return success;
}


bool CommandInterpreter::schedule(char arg0)
{
   bool success = true;
   switch (arg0)
   {
   case 'p':
      // SG->generate()
      handback = "Project schedule generated.";
      break;
   case 'v':
      // VS->generate()
      handback = "Volunteer schedule generated.";
      break;
   default:
      success = false;
      handback = "Invalid argument for schedule command: " + arg0;
      break;
   }
   return success;
}


bool CommandInterpreter::help(void)
{
   return false;
}

最佳答案

哇,这么多问题,这么少的时间......

不必要的动态内存分配
CommandInterpreter * interpreter = new CommandInterpreter(); 您使用 std::string 而不进行动态分配,那么为什么这里有这个? 此外,如果必须动态分配,您应该使用具有指针和内存管理处理的 unique_ptrboost::scoped_ptr

如果对象对于局部变量而言太大,则将其声明为static

对 std::string 终止使用 '\0'
'\0' 是 C 风格的字符串终止符。当您使用 getline 时,它会用文本填充 std::string 对象。 std::string 不使用 nul 字符作为字符串终止。更改您的 while 循环以使用迭代器或使其成为长度为 for 的循环:

for (unsigned int i = 0; i < cmd.length(); ++i)
{
  cmd[i] = std::tolower(cmd[i]);
}

但是,当您可以使用 std::transform 转换所有字符时,为什么还要使用循环。在网络或 StackOverflow 上搜索“c++ transform tolower”。

传递 std::vector 而不是数组
正如您所发现的,将数组传递给函数很困难,尤其是语法。 vector 要容易得多:

std::vector<std::string> commands;  // Look Ma, no *new* operator.
CommandInterpreter(commands);

传递数组
请记住,数组名称可以衰减到第一个槽的地址。此外,您需要传递容量以及数组中的元素数量:

void CommandInterpreter(string * array, unsigned int items_in_array, unsigned int array_capacity);

或者

void CommandInterpreter(std::vector<std::string>& array); // Much simpler using vector.

文件命名约定
您对 C++ header 使用不同的扩展名。 “.h”后缀历来用于 C 语言头文件。例如,以下在 C 语言“.h”文件中有效:

typedef struct class
{
  unsigned int cout;
  double       private;
} class_t;

当为 C 语言编译时,您的头文件会做一些奇怪的事情。

一些约定使用“.hh”或“.hpp”来表示头文件是用于 C++ 的。

使用变量名提高可读性
两个字母变量不可读。选择更长的变量名。如果你选择了两个字母的缩写,因为它太长而无法打字,那就去上键盘课吧。

使用初始化列表
您可以在初始化列表中使用 new 运算符,这让我想起了......

检查内存分配是否有错误
每个动态内存分配都需要检查是否成功。这可以通过检查指针是否为 NULL 或捕获异常来执行。还要验证您的实现设置是否 new 抛出异常。一些编译器允许您关闭异常抛出。

不是每个函数都需要在一个对象中
一些面向对象的语言强制执行函数必须在类中的规则。 C++ 语言不同,您可以在类之外拥有称为“独立函数”的函数。尝试一下!

现在够了......

关于c++ - 如何在 C++ 中传递字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23255680/

相关文章:

c++ - 有没有办法在 C++ 泛型类中透明地包装可比较的 C 结构?

c++ - 输出结果是什么?

c# - 如何在类数组中设置类值

c++ - QT6: "qt.qpa.plugin: Could not load the Qt platform plugin "xcb"in ""即使它被发现了。"

php - 如何检查年度日期条件

php - 如何将字符串/数据库变成变量

c - 在对指针到指针数组调用 realloc 以缩小其大小之前是否有必要释放子指针?

c++ - 头文件中的类 - 无法编译?

c++ - 如何捕获 C++ 异常?

C++ STL : Why is there no upper_bound equivalent that retrieves the greatest element smaller then a specific key?