【问题标题】:C Concatenate string in while loopC在while循环中连接字符串
【发布时间】:2017-01-20 15:28:00
【问题描述】:

我正在尝试将结构的一部分与十六进制值连接起来。我遍历循环中的每个字节并转换为十六进制,然后我想将所有十六进制连接成一个长字符串。

但是,我在循环结束时只得到一个值。由于某种原因,字符串没有正确连接。知道我做错了什么吗?

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);

};

【问题讨论】:

  • strcpy() 将源字符串复制到目标字符串,覆盖其先前的内容。你可能想要strcat(),而不是。
  • int index=0; index += sprintf(&amp;buffer[index], "%02X", (ch &amp; 0x00FF));
  • 请注意,您没有使缓冲区足够大。每个输入字符在缓冲区中需要两个十六进制数字,但您只为一个字符留出足够的空间。
  • 您好 John Bollinger,感谢您确认这一点,我认为这是一个问题。我仍然想知道我是否也必须将空终止符计数加倍。
  • 嗨 LP,如果它是 int,我如何以十六进制打印?整数索引=0; index += sprintf(&buffer[index], "%02X", (ch & 0x00FF));

标签: c string loops while-loop printf


【解决方案1】:

使用strcat 代替strcpy。这应该可以解决您的问题。

为了提高效率,请考虑使用char *p = buffer 之类的写指针,并使用p += sprintf(p, "%02X", (ch &amp; 0x00FF)) 之类的东西推进写位置

您的if(loop == sz2) break 支票也是while(loop &lt; sz2) 支票的无用副本。如果loop 等于或大于sz2,则不会执行while 循环。

还想知道为什么你只需要一个字符时使用freadfgetcgetc 似乎是更好的选择。

另外,无论您使用fread 还是getc,您都需要检查文件结尾。如果文件中 not 包含 sz2 字节怎么办?因为所有现代系统都是多进程和多用户的,所以有人可能会在调用 ftell 后缩短文件。你永远不应该假设事情,因为即使你只是检查它,它也可以改变。做出这种假设是导致 TOCTTOU(检查时间到使用时间)错误的原因。

【讨论】:

  • 嗨,赞,除了指针部分,全部都明白了。我如何将它包含在我的代码中?创建缓冲区时,我是否在顶部声明 char *p?
  • @Ke。它必须在创建缓冲区之后出现,所以它有一些指向。而且它不能在循环内,否则它会在每个循环上重置为缓冲区。
  • 好的我想我现在得到了指针的东西,以及 sprintf 的工作原理,所以谢谢你,现在我正在尝试向数组添加一些额外的字符 "\n\t\t\t \t" 并且它似乎没有工作,知道为什么吗?
  • @Ke。在我看来,您好像需要学习使用调试器。您应该拥有所有可用的工具来完成这项工作。
  • @Ke。你问这个问题的方式我也无法回答。您遗漏了所有重要的细节。
【解决方案2】:

do_file() 中,您正在为while 循环中的单个字节复制十六进制值。因此,您应该在 while 循环的每次迭代中转到字符数组 buffer 的下一个字节,即 buffer++strcpy(buffer[loop], msg);

【讨论】:

    猜你喜欢
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 2014-09-25
    • 2011-06-18
    相关资源
    最近更新 更多