【问题标题】:Concatenating large string in C to write to file在C中连接大字符串以写入文件
【发布时间】:2017-09-21 20:44:07
【问题描述】:

我是 C 的新手,所以我很难弄清楚这一点。我一次读取文件 500 个字节,计算文件中的行数,然后一旦达到 500 行,我将其写入另一个文件。该文件根本没有正确输出,我认为这与我在将其写入文件之前尝试连接一个长字符串有关。这是我现在拥有的代码的主循环:

   while (lineCount != 500)
   {
    if (lineCount == 500)
      break;
    readbytes = read(infd, buf, 500);
    for (str = buf; *str; ++str)
    {
      lineCount += *str == '\n';
      char *newPtr = realloc(forkBuf, (strlen(forkBuf) + strlen(str) + 2));
      forkBuf = newPtr;
      char* newFork = realloc(forkBuf, (strlen(forkBuf) + strlen(str) + 2));
      sprintf(forkBuf, "%s%s", newFork, str);
      if (lineCount == 500)
        break;
    }
    if (lineCount < 500)
    {
      if(readbytes < 500){
        write(outfd, forkBuf, (strlen(forkBuf) + 2));
        break;
      }
      continue;
    }
    write(outfd, forkBuf, (strlen(forkBuf) + 2));
  }

【问题讨论】:

  • 你为什么要写lineCount += *str == '\n';这样的代码?这会让事情变得有点难以阅读吗?
  • 考虑到上面的while 声明,if (lineCount == 500) 的真实性如何
  • 我知道那部分肯定更具可读性。而 if 语句之所以存在,是因为我经历了许多不同的变化,试图找出这个问题。工作后需要进行一些清理
  • 我只能想到 StackOverflow 上已经有大约 5,287 个字符串连接示例。只要不耗尽系统内存,长度无关紧要。
  • 注意read()没有得到字符串;它得到一个字节数组,不一定是空终止的。实际上,它通常不是空终止的。您应该跟踪字节缓冲区的实际长度,并使用内存函数(memmove()memcpy() 等)而不是字符串函数。

标签: c string concatenation


【解决方案1】:

你有两行代码:

char* newFork = realloc(forkBuf, (strlen(forkBuf) + strlen(str) + 2));
sprintf(forkBuf, "%s%s", newFork, str);

这会导致未定义的行为;如果realloc 重新分配到一个新地址,forkBuf 将指向已释放的内存;即使realloc 工作到位,according to the standard

原始指针 ptr [forkBuf 在此示例中] 已失效,对其的任何访问都是未定义的行为(即使重新分配已就地进行)。

我还要补充一点,如果(可能会发生)forkBuf 等于 newFork,则使用 sprintf 将字符串复制到自身也是未定义的行为。

此外,这里有一个for 循环,str 基本上被视为单个字符。我会重写整个循环,但快速破解可能是:

// One byte extra for the `\0`, and one for the new character
char *newPtr = realloc(forkBuf, (strlen(forkBuf) + 2));
if (newPtr == NULL)
    panic(); // Or whatever error handling you might want
forkBuf = newPtr;
size_t len = strlen(forkBuf);
forkBuf[len] = *str;
forkBuf[len + 1] = '\0';

请注意,循环中只需要一个realloc(),或者更好的是,循环外需要一个realloc(forkBuf, (strlen(forkBuf) + strlen(str) + 2));

【讨论】:

  • 谢谢!它适用于超过 500 行的文件!我无法让它与少于 500 行的文件一起使用,我不确定,但它在末尾添加了多行。非常感谢您的帮助!
猜你喜欢
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多