我可以从signed char *或unsigned char *中获取char *吗?

时间:2015-11-03 19:57:29

标签: c++ string char unsigned

我必须处理可能未签名的char数组(因为它们来自SCSI数据块)。我想用这个函数来处理它们:

template <typename CharT, size_t Len>
std::string strFromArray(CharT (&src) [Len])
{     
    return std::string((typename boost::make_signed<CharT>::type *) src, Len);
}

错误发生在std::string构造函数调用中,它不能signed char / unsigned char,但只会char

我当然可以用(char *) src替换转换,但如果我传入非char类型,我将丢失所有编译器错误。

我怎么写这个,以便它构建所有的字符串&#34; charry&#34;类型?

3 个答案:

答案 0 :(得分:2)

假设转换为string表示字节数组带有以空字符结尾的C字符串(例如字符串文字):

#include <string>
#include <stddef.h>

namespace my {
    using std::string;
    using Size = ptrdiff_t;

    namespace detail {
        auto is_char_type( char const* ) -> bool;
        auto is_char_type( signed char const* ) -> bool;
        auto is_char_type( unsigned char const* ) -> bool;
    }  // namespace detail

    template< class Char, Size n >
    auto string_from( Char (&src) [n] )
        -> string
    {     
        (void) sizeof( detail::is_char_type( src ) );
        return string( src, src + n - 1 );
    }
}  // namespace my

auto main() -> int
{
    unsigned char const data[] = "Blah";
    auto const s = my::string_from( data );

#ifdef TEST_WCHAR
    wchar_t const wdata[] = L"Blah";
    auto const ungood_s = my::string_from( wdata );      // Doesn't compile.
#endif
}

如果不是字符串,而是关于任意二进制数据,那么只使用src + n代替src + n - 1

但是,在二进制数据的情况下,您可能需要一个单独的长度,即不使用原始数组本身的长度。

答案 1 :(得分:2)

我会尽量保持简单,并使用:

#include <iostream>
#include <string>

namespace conv {
    template <size_t len>
    std::string strFromArray(const char(&arr)[len])
    {
        static_assert(len > 0, "don't use zero-sized arrays");
        return std::string(arr, len - 1);
    }

    template <size_t len>
    std::string strFromArray(const unsigned char(&arr)[len])
    {
        static_assert(len > 0, "don't use zero-sized arrays");
        return std::string((const char *)arr, len - 1);
    }
}

int main()
{
    const char charstr[] = "abcd";
    std::string str = conv::strFromArray(charstr);
    std::cout << str << std::endl;

    const unsigned char ucharstr[] = "efg";
    str = conv::strFromArray(ucharstr);
    std::cout << str << std::endl;

/*not possible:
    const wchar_t wcharstr[] = L"hijk";
    str = conv::strFromArray(wcharstr);
*/

}

Test it live

答案 2 :(得分:2)

只需在您的函数中放置一个静态断言并稍微修改它:

#include <string>

template <typename CharT, std::size_t Len>
std::string strFromArray(CharT (&src) [Len])
{
    // Anythig which looks like a char is considered a char.
    static_assert(sizeof(CharT) == sizeof(char), "Invalid Character Type");
    std::size_t n = Len;
    // Do not use a terminating zero (might be wrong if the source is no char 
    // literal, but an array of binary data.
    if( ! src[n-1])
        --n;
    return std::string(src, src + n);
}

int main()
{
    char c[3] = {};
    signed char sc[3] = {};
    unsigned char uc[3] = {};
    wchar_t wc[3] = {};
    strFromArray(c);
    strFromArray(sc);
    strFromArray(uc);
    // error: static assertion failed: Invalid Character Type
    // strFromArray(wc);
}