代码之家  ›  专栏  ›  技术社区  ›  pythonic metaphor

C++ STD::String和NULL const char

  •  8
  • pythonic metaphor  · 技术社区  · 16 年前

    我在C++中使用了两个大的代码,一个是用“C风格”,一个是“C++风格”。

    C型代码具有返回conchchar的功能,C++代码在很多地方都有类似的功能。

    const char* somecstylefunction();
    ...
    std::string imacppstring = somecstylefunction();
    

    从C样式代码返回的常量char*构造字符串。

    这种方法一直有效,直到C样式的代码发生变化,并且有时开始返回空指针。这当然会导致SEG故障。

    周围有很多代码,所以我想以最节俭的方式解决这个问题。在这种情况下,预期的行为是imacppstring将是空字符串。有没有一个好的,巧妙的解决方案?

    更新

    这些函数返回的常量char*始终是指向静态字符串的指针。它们主要用于传递有关函数中任何意外行为的信息性消息(最有可能用于日志记录)。决定在“无需报告”上使用这些返回空值是很好的,因为这样您就可以将返回值用作条件,即。

    if (somecstylefunction()) do_something;
    

    而在函数返回静态字符串“”之前;

    不管这是否是个好主意,我都不会去碰这个代码,不管怎样这也不是我的事。

    我想要避免的是跟踪每个字符串初始化以添加包装函数。

    7 回复  |  直到 10 年前
        1
  •  13
  •   Michael Burr    16 年前

    最好的做法可能是将C库函数修复为其中断前的更改行为。但也许你不能控制那个图书馆。

    要考虑的第二件事是更改所有依赖于返回空字符串的C lib函数的实例,以使用将“修复”空指针的包装函数:

    const char* nullToEmpty( char const* s)
    {
        return (s ? s : "");
    }
    

    所以现在

    std::string imacppstring = somecstylefunction();
    

    可能看起来像:

    std::string imacppstring( nullToEmpty( somecstylefunction());
    

    如果这是不可接受的(这可能是一个繁忙的工作,但它应该是一次性的机械更改),您可以实现一个与当前使用的C lib同名的“并行”库,这些函数只需调用原始的C lib函数并适当地修复空指针。你需要玩一些棘手的游戏,用标题、链接器和/或C++命名空间来让它工作,这有很大的可能导致混乱的道路,所以我在下一条路之前会认真思考。

    但是像下面这样的事情可能会让你开始:

    // .h file for a C++ wrapper for the C Lib
    namespace clib_fixer {
        const char* somecstylefunction();
    }
    
    
    // .cpp file for a C++ wrapper for the C Lib
    namespace clib_fixer {
        const char* somecstylefunction() {
            const char* p = ::somecstylefunction();
    
            return (p ? p : "");
        }
    }
    

    现在,您只需将该头添加到当前调用C lib函数的.cpp文件中(并且可能删除C lib的头),然后添加

    using namespace clib_fixer;
    

    使用这些函数到.cpp文件。

    那可能不是 坏的。也许吧。

        2
  •  6
  •   AnT stands with Russia    16 年前

    没有改变C++的每个地方 std::string 直接从C函数调用初始化(添加空指针检查),唯一的解决方案是禁止C函数返回空指针。

    在gcc编译器中,可以使用编译器扩展名“省略操作数的条件”为C函数创建包装宏。

    #define somecstylefunction() (somecstylefunction() ? : "")
    

    但在一般情况下,我建议不要这样做。

        3
  •  3
  •   Charles Salvia    16 年前

    我想您可以添加一个包装函数来测试空值,并返回一个空的std::string。但更重要的是,为什么C函数现在返回空值?空指针表示什么?如果它指示一个严重的错误,您可能希望包装函数抛出一个异常。

    或者为了安全起见,您可以检查空值,处理空值大小写,然后构造一个std::string。

    const char* s = somecstylefunction();
    if (!s) explode();
    std::string str(s);
    
        4
  •  2
  •   peterchen    12 年前

    对于便携式解决方案:

    (A)定义您自己的字符串类型。最大的部分是整个项目的搜索和替换——如果总是std::string,或者一次性的大麻烦,那么这很简单。(我唯一要求的是,它是std::string的liskov可替换字符串,但也从一个空字符*构造一个空字符串。

    最简单的实现是从std::string公开继承。即使这是不允许的(出于可以理解的原因),在这种情况下也可以,并且有助于第三方图书馆期望 std::string 以及调试工具。或者,阿格盖特和前锋-尤克。

    (B)将std::string定义为您自己的字符串类型。危险,不推荐。我不会这么做,除非我很清楚代码库的关系,并且为您节省了大量的工作(我还添加了一些免责声明来保护我的声誉)。

    (c)我通过将冒犯性类型重新定义为某个实用程序类来解决一些这样的情况,仅仅是为了包括(因此定义的范围更为有限)。但是,我不知道该怎么做 char * .

    (d)写一个导入包装。如果C库头有一个比较规则的布局,和/或你知道有人分析C++代码的一些经验,你可以生成一个“包装头”。

    (e)要求库所有者至少在编译时配置“空字符串”值。(切换到0后的一个可接受请求可能会破坏兼容性,在其他情况下也是如此)如果这对您来说不太管用,您甚至可以自己提交更改!

        5
  •  2
  •   underscore_d    10 年前

    您可以将对c-stlye函数的所有调用包装成这样的函数…

    std::string makeCppString(const char* cStr)
    {
        return cStr ? std::string(cStr) : std::string("");
    }
    

    那么无论你在哪里:

    std::string imacppstring = somecstylefunction(); 
    

    替换为:

    std::string imacppstring = makeCppString( somecystylefunction() );
    

    当然,这假设在函数返回空值时构造空字符串是可以接受的行为。

        6
  •  1
  •   Mark Ransom    16 年前

    我一般不提倡对标准容器进行子类化,但在这种情况下,它可能会起作用。

    class mystring : public std::string
    {
        // ... appropriate constructors are an exercise left to the reader
        mystring & operator=(const char * right)
        {
            if (right == NULL)
            {
                clear();
            }
            else
            {
                std::string::operator=(right);  // I think this works, didn't check it...
            }
            return *this;
        }
    };
    
        7
  •  0
  •   Carl Norum    16 年前

    这样可以解决你的问题。

    const char *cString;
    std::string imacppstring;
    
    cString = somecstylefunction();
    if (cString == NULL) {
      imacppstring = "";
    } else {
      imacppstring = cString;
    }
    

    如果您愿意,可以将错误检查逻辑插入到它自己的函数中。那么,您必须将这个代码块放在更少的地方。