我正在尝试用十六进制值连接结构的一部分。我遍历循环中的每个字节并将其转换为十六进制,然后将所有十六进制连接成一个长字符串。
但是,循环结束时我只得到一个值。由于某些原因,字符串没有正确连接。知道我做错了什么吗?

typedef struct OPTIONS_STR
{
    int max;
    int printName;
} OPTIONS;

void set_default_options(OPTIONS *options)
{
    options->max = -1;
    options->printName = 0;
}

void do_file(FILE *in, FILE *out, OPTIONS *options)
{
    char ch;
    int loop = 0;
    char buf[81];
    buf[0] = '\0';
    int sz1;
    int sz2;
    int sz3;

    int seeker = offsetof(struct myStruct, contents.datas);

    //find total length of file
    fseek(in, 0L, SEEK_END);
    sz1 = ftell(in);

    //find length from beggining to struct beginning and minus that from total length
    fseek(in, seeker, SEEK_SET);
    sz2 = sz1 - ftell(in);

    //set seek location at beginning of struct offset
    fseek(in, seeker, SEEK_SET);

    sz3 = sz2 + 1;
    char buffer[sz3];
    char msg[sz3];

    buffer[0] = '\0';

    while (loop < sz2)
    {
        if (loop == sz2)
        {
            break;
        }

        fread(&ch, 1, 1, in);
        sprintf(msg, "%02X", (ch & 0x00FF));
        strcpy(buffer, msg);

        ++loop;
    }
    printf("%s\n", buffer);
}

int main(int argc, const char * argv[]) {

    OPTIONS options;
    set_default_options(&options);

    const char *current = "/myfile.txt";
    FILE *f = fopen(current, "rb");
    do_file(f, stdout, &options);
    fclose(f);

};

最佳答案

使用strcat而不是strcpy。那应该能解决你的问题。
为了提高效率,可以使用类似于char *p = buffer的写指针,并使用类似于p += sprintf(p, "%02X", (ch & 0x00FF))的指针提升写位置
您的if(loop == sz2) break检查也是while(loop < sz2)检查的无用副本。如果loop等于或大于sz2,while循环将不会执行。
还想知道为什么只需要一个字符时使用freadfgetcgetc似乎是更好的选择。
此外,无论您使用fread还是getc,都需要检查文件的结尾。如果文件中没有sz2字节怎么办?因为所有现代系统都是多进程和多用户的,所以在调用ftell之后可能会有人缩短文件。你不应该想当然,因为即使你刚刚检查过,它也会改变。做出这种假设是导致toctou(检查时间到使用时间)错误的原因。

09-25 21:32