如何在 C 中打开 4 个字符的字符串?

发布于 2024-12-15 00:42:53 字数 586 浏览 1 评论 0原文

我需要根据 4 个字符的字符串进行切换。我将字符串放入联合中,这样我至少可以将其称为 32 位整数。

union
{
    int32u  integer;
    char    string[4];
}software_version;

但现在我不知道在案例陈述中该写什么。我需要某种宏来将 4 个字符的字符串文字转换为整数。 EG

#define STRING_TO_INTEGER(s)    ?? What goes here ??
#define VERSION_2_3_7           STRING_TO_INTEGER("0237")
#define VERSION_2_4_1           STRING_TO_INTEGER("0241")

switch (array[i].software_version.integer)
{
    case VERSION_2_3_7:
        break;

    case VERSION_2_4_1:
        break;
}

有没有办法制作 STRING_TO_INTEGER() 宏。或者有更好的方法来处理切换吗?

I need to switch based on a 4-character string. I put the string in a union so I can at least refer to it as a 32-bit integer.

union
{
    int32u  integer;
    char    string[4];
}software_version;

But now I don't know what to write in the case statements. I need some kind of macro to convert a 4-character string literal into the integer. E.G.

#define STRING_TO_INTEGER(s)    ?? What goes here ??
#define VERSION_2_3_7           STRING_TO_INTEGER("0237")
#define VERSION_2_4_1           STRING_TO_INTEGER("0241")

switch (array[i].software_version.integer)
{
    case VERSION_2_3_7:
        break;

    case VERSION_2_4_1:
        break;
}

Is there a way to make the STRING_TO_INTEGER() macro. Or is there a better way to handle the switch?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ぃ双果 2024-12-22 00:42:53

可移植示例代码:

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#define CHARS_TO_U32(c1, c2, c3, c4) (((uint32_t)(uint8_t)(c1) | \
    (uint32_t)(uint8_t)(c2) << 8 | (uint32_t)(uint8_t)(c3) << 16 | \
    (uint32_t)(uint8_t)(c4) << 24))

static inline uint32_t string_to_u32(const char *string)
{
    assert(strlen(string) >= 4);
    return CHARS_TO_U32(string[0], string[1], string[2], string[3]);
}

#define VERSION_2_3_7 CHARS_TO_U32('0', '2', '3', '7')
#define VERSION_2_4_1 CHARS_TO_U32('0', '2', '4', '1')

int main(int argc, char *argv[])
{
    assert(argc == 2);
    switch(string_to_u32(argv[1]))
    {
        case VERSION_2_3_7:
        case VERSION_2_4_1:
        puts("supported version");
        return 0;

        default:
        puts("unsupported version");
        return 1;
    }
}

该代码仅假设存在整数类型 uint8_tuint32_t,并且与 char 类型的宽度和符号无关作为字节序。只要字符编码仅使用 uint8_t 范围内的值,就不会发生冲突。

Portable example code:

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>

#define CHARS_TO_U32(c1, c2, c3, c4) (((uint32_t)(uint8_t)(c1) | \
    (uint32_t)(uint8_t)(c2) << 8 | (uint32_t)(uint8_t)(c3) << 16 | \
    (uint32_t)(uint8_t)(c4) << 24))

static inline uint32_t string_to_u32(const char *string)
{
    assert(strlen(string) >= 4);
    return CHARS_TO_U32(string[0], string[1], string[2], string[3]);
}

#define VERSION_2_3_7 CHARS_TO_U32('0', '2', '3', '7')
#define VERSION_2_4_1 CHARS_TO_U32('0', '2', '4', '1')

int main(int argc, char *argv[])
{
    assert(argc == 2);
    switch(string_to_u32(argv[1]))
    {
        case VERSION_2_3_7:
        case VERSION_2_4_1:
        puts("supported version");
        return 0;

        default:
        puts("unsupported version");
        return 1;
    }
}

The code only assumes the existence of the integer types uint8_t and uint32_t and is agnostic to width and signedness of type char as well as endianness. It is free of collisions as long as the character encoding only uses values in range of uint8_t.

北方。的韩爷 2024-12-22 00:42:53

您可以像这样打开四字符代码,

switch (fourcc) {
case 'FROB':
}

请注意区别:"XXXX" 是字符串,'XXXX' 是字符/整数文字。

但是,我建议您使用单独的版本号,例如:

struct Version {
    int major, minor, patch;
};

bool smaller (Version lhs, Version rhs) {
    if (lhs.major < rhs.major) return true;
    if (lhs.major > rhs.major) return false;
    if (lhs.minor < rhs.minor) return true;
    if (lhs.minor > rhs.minor) return false;
    if (lhs.patch < rhs.patch) return true;
    if (lhs.patch > rhs.patch) return false; // redundant, for readabiltiy

    return false; // equal
}

You switch on four-character-codes like this

switch (fourcc) {
case 'FROB':
}

Note the difference: "XXXX" is a string, 'XXXX' is a character/integer literal.

However, I would propose you use seperate version numbers instead, e.g.:

struct Version {
    int major, minor, patch;
};

bool smaller (Version lhs, Version rhs) {
    if (lhs.major < rhs.major) return true;
    if (lhs.major > rhs.major) return false;
    if (lhs.minor < rhs.minor) return true;
    if (lhs.minor > rhs.minor) return false;
    if (lhs.patch < rhs.patch) return true;
    if (lhs.patch > rhs.patch) return false; // redundant, for readabiltiy

    return false; // equal
}
荆棘i 2024-12-22 00:42:53

更新:

#define VERSION_2_3_7 '0237'

Updated:

#define VERSION_2_3_7 '0237'
半葬歌 2024-12-22 00:42:53
int versionstring_to_int(char * str)
{
char temp [ 1+ sizeof software_version.string ]; /* typically 1+4 */

if (!str || ! *str) return -1;
memcpy (temp, str, sizeof temp -1);
temp [sizeof temp -1] = 0;

return atoi (temp );
}

编辑:

#define STRING_TO_INTEGER(s)    versionstring_to_int(s)
#define VERSION_2_3_7           237
#define VERSION_2_4_1           241

switch ( STRING_TO_INTEGER( array[i].software_version.string) )
{
case VERSION_2_3_7:
    break;

case VERSION_2_4_1:
    break;
}
int versionstring_to_int(char * str)
{
char temp [ 1+ sizeof software_version.string ]; /* typically 1+4 */

if (!str || ! *str) return -1;
memcpy (temp, str, sizeof temp -1);
temp [sizeof temp -1] = 0;

return atoi (temp );
}

EDIT:

#define STRING_TO_INTEGER(s)    versionstring_to_int(s)
#define VERSION_2_3_7           237
#define VERSION_2_4_1           241

switch ( STRING_TO_INTEGER( array[i].software_version.string) )
{
case VERSION_2_3_7:
    break;

case VERSION_2_4_1:
    break;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文