【问题标题】:Compare multiple chars without using string compare functions比较多个字符而不使用字符串比较函数
【发布时间】:2021-05-14 06:45:34
【问题描述】:

我正在尝试使用可以在mode 参数中传递到我的文件类构造函数的参数创建一个 switch 语句。但是,由于模式最多可以包含 2 个字符('r'、'r+'、'w' 或 'w+'),我不知道如何创建一个 switch 语句来为我完成这项工作。

有没有人对如何实现这一点有任何建议?目前,我在下面的内容中遇到了 'r+' 和 'w+' 情况的错误,因为它们不是字符。

File::File(const char *name, const char *mode) {
  int fileMode = 0;    //Initializing mode to 0
  fileName = name;    //Setting the file name of this File object to the name we pass in.

  switch(*mode){
    case 'r':
      fileMode = O_RDONLY | O_CREAT;
      canWeRead = true;
      canWeWrite = false;
      break;

    // Open a text file for update (that is, for both reading and writing)
    case 'r+':            
      fileMode = O_RDWR | O_CREAT;
      canWeRead = true;
      canWeWrite = true;
      break;

    case 'w':
      fileMode = O_WRONLY | O_CREAT;
      canWeRead = false;
      canWeWrite = true;
      break;

    // Open a text file for update (reading and writing),
    // first truncating the file to zero length if it exists
    // or creating the file if it does not exist.
    case 'w+':           
      fileMode = O_RDWR | O_CREAT | O_TRUNC;
      canWeRead = true;
      canWeWrite = true;
      break;
    
    default:    //We should never reach the default case, so I assert(0)
      assert(0);
  }

  fileBuffer = (char*)malloc(bufsiz); //Create buffer with malloc
  //Free is called in the File class destructor.

  assert(fileBuffer != NULL); //If fileBuffer == NULL, we did not allocate a buffer.

  fileDescriptor = open(name, fileMode);
  /*On success, open() returns the new file descriptor (a nonnegative integer).
    On error, -1 is returned and errno is set to indicate the error.*/

  assert(fileDescriptor >= 0);  //If we dont get a positive nonnegative int, we have a problem.

}

File::~File() {
    free(fileBuffer);                      //Free the memory we have for the buffer
    int rc = close(this->fileDescriptor);  //We want to close the FileDescriptor of the current File object.
    assert(rc == 0);                        //close returns 0 on success. So if we dont get 0, we have a problem.
}

【问题讨论】:

  • 您不能使用switch/case 来比较字符串。 'r+' 不是有效的字符常量。在您的情况下,您可能能够将两个字符组合成一个值uint16_t,但这不会使您的代码易于阅读。我建议使用switch/case 来检查'r''w' 或无效字符,并在这两种情况下使用额外的if(mode[1]=='+')。顺便说一句:如果您的代码预计永远不会使用无效的输入字符串调用您的构造函数,则在 default 情况下使用 assert 可能是可以接受的,但您不应该使用 assert 来处理运行时错误,例如malloc, open ...

标签: c++ unix system-calls


【解决方案1】:

您不能使用多个值以防万一。

1 - 您可以使用多个开关:

switch(mode[0]){
    case 'r':
        switch(mode[1]){
            case '+':
                switch(mode[2]){
                    case 0:
                        fileMode = O_RDWR | O_CREAT;
                        canWeRead = true;
                        canWeWrite = true;
                        break;
                    default:
                        assert(0);
                }
            case 0:
                fileMode = O_RDONLY | O_CREAT;
                canWeRead = true;
                canWeWrite = false;
                break;
        }
        break;
    case 'w':
        switch(mode[1]){
            case '+':
                switch(mode[2]){
                    case 0:
                        fileMode = O_RDWR | O_CREAT | O_TRUNC;
                        canWeRead = true;
                        canWeWrite = true;
                        break;
                    default:
                        assert(0);
                }
            case 0:
                fileMode = O_WRONLY | O_CREAT;
                canWeRead = false;
                canWeWrite = true;
                break;
        }
        break;
    default:
        assert(0);
}

2 - 你可以让mode 的类型为 char[4] 并有丑陋的函数调用。点赞File("filename", {'r', '+'})(这种方式会受到字节序差异的影响)

switch(*(uint32_t *)mode){
    // r
    case 0x72000000:
        fileMode = O_RDONLY | O_CREAT;
        canWeRead = true;
        canWeWrite = false;
        break;
    // r+
    case 0x722b0000:
        fileMode = O_RDWR | O_CREAT;
        canWeRead = true;
        canWeWrite = true;
        break;
    // w
    case 0x77000000:
        fileMode = O_WRONLY | O_CREAT;
        canWeRead = false;
        canWeWrite = true;
        break;
    // w+
    case 0x772b0000:
        fileMode = O_RDWR | O_CREAT | O_TRUNC;
        canWeRead = true;
        canWeWrite = true;
        break;
    default:
        assert(0);
}

无论如何,这些方法对于简单的事情来说太过分了。系统调用会比字符串比较多消耗数千倍的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多