0

我有一个小型库,其中包含一些应该在运行时可用的文档,但是 MS Visual Studio C++ 编译器只允许长度不超过2,048 字节的字符串文字,有没有一种简单的方法来解决这个限制?我能找到的唯一解决方案是创建一个字符串数组,然后分配一个新缓冲区并将字符串复制到其中。

char *doc_arr[] = {
    "Documentation for my program\n",
    "\n",
    "This is a seccond line\n",
    // and so on ....
}
int doc_arr_length = 203; // number lines in doc_arr
char doc[3502];           // number of bytes in dockumentation

strcpy(doc, doc_arr[0]);
for(int i = 1; i < doc_arr_length; i++){
    strcat(doc, doc_arr[i]);
}

更新:看起来需要一些上下文。

我有一个 ruby​​ 程序,它需要很多选项并收集大量数据并生成一个 .c 文件。.c 文件被编译为 .dll 女巫,然后在其他程序中用于快速计算。这意味着您很快就会获得大量不同的 .c 和 .dll 并且很难管理版本。我认为在源文件和编译的 dll 中包含有关提供给 ruby​​ 脚本的选项的综合文档可能是一个好主意。

4

4 回答 4

7

用更好的(IMO)替代方案回答您的问题:

在单独的文件中分发文档。在运行时,打开文件并从中读取您需要的任何内容。

外部文档在代码中没有位置。

于 2012-06-07T07:45:20.543 回答
2

如果您在 Windows 下构建应用程序,则字符串文字的位置在资源文件中 - 更易于管理并支持翻译。

直接嵌入字符串不是一个好主意。

于 2012-06-07T07:50:37.237 回答
0

这不是您问题的答案;其他人已经回答了。但是,注释不利于发布代码。

您的代码应固定为类似以下代码(未编译或测试):

const char *doc_arr[] = {
    "Documentation for my program\n",
    "\n",
    "This is a seccond line\n",
    // and so on ....
};
int doc_arr_length = 203; // number lines in doc_arr
char doc[3502];           // number of bytes in dockumentation

const char* doc_ptr = doc;

for(int i = 0; i < doc_arr_length; i++){
    int length = strlen(doc_arr[i]);
    memcpy(doc_ptr, 
           doc_arr[i], 
           sizeof(char)*length + 1);
    doc_ptr += length;
}

已修复的问题:

  • 每当处理字符串文字时,总是使用 const 指针。有意或无意地通过指针修改字符串文字会调用未定义的行为。
  • 您的循环条件不正确,循环很奇怪。

优化:

  • 在这样的循环中重复调用 strcat 将非常低效。对于每个循环迭代, strcat() 必须遍历稳定增长的字符串以寻找空终止。通过指针跟踪最后位置,您的程序不需要在循环中的每一圈都执行这种缓慢的查找。
  • 在介绍上面提到的指针时,我们需要知道要复制的字符串的字符串长度。由于我们现在已经通过调用 strlen() 提供了这些信息,因此我们不需要调用像 strcat() 和 strcpy() 这样的“慢”函数来搜索空终止。我们可以使用 strncpy() 或 memcpy() 代替。我选择 memcpy() 是因为 strncpy() 中的额外功能(附加额外的空终止符)在这种情况下是无用的。
于 2012-06-07T08:39:40.357 回答
0

正如其他人所建议的那样,使用单独的文件可能更容易,尽管这在部署时确实会增加复杂性。或者,我经常做的是使用一个字符串表,每一行都在一个单独的条目中:

char const* doc[] =
{
    "first line",
    "next line",
    //  ...
    "last line",
};

并输出,例如:

std::copy( begin(doc), end(doc),
           std::ostream_iterator<std::string>( std::cout, "\n" ) );

这似乎运作良好,并允许视觉格式化。或其他:在 vim 中,我将标记块并执行:s/ *"\(.*\)",/\1/(只是对标记的块进行标准搜索和替换),然后使用任何合适的工具进行格式化,或者使用编辑器的内部命令(相当简单),或者通过管道到一些外部命令(可以像你喜欢的那样复杂),最后,:s/.*/ "&",/恢复 C++ 标点符号。

于 2012-06-07T08:03:56.673 回答