c - 使用指向 char 的指针时如何使用 snprintf

标签 c

现在我正在使用 sprintf,但想更改为 snprintf

我的问题是,当我使用指针执行以下代码之类的操作时,确保不发生缓冲区溢出的最佳方法是什么:

这是代码的快速示例,在我的代码中,string_pos += get_line_to_buffer(&string[string_pos]); 被多次调用。所以我要向缓冲区添加大量数据,因此我想确保我不会写入太多数据。

int main(void){
    char string[50];
    size_t string_pos = 0;

    string_pos += get_line_to_buffer(&string[string_pos]);
}

static size_t get_line_to_buffer(char *buffer){
    char* p = buffer;

    p += sprintf(p, "%d,%s,%s,%lu", version, fileName, Id, timestamp);
    p += sprintf(p, ",%d,%d,%f", noOfObs, frequency, sum);
    p += sprintf(p, ",%f,%f", latitude, longitude);
    p += sprintf(p, ",%f,%d", speed, errorCode);
    p += sprintf(p, "\r\n");

    return p - buffer;
}

最佳答案

仔细阅读documentation of snprintf (和/或 Linux 的 snprintf(3) )。请注意,它可能会因返回负值而失败。您可能会对它的 %n 感兴趣。

您需要知道缓冲区的大小。一个好方法是将其作为第二个参数传递给 get_line_to_buffer 函数:

ssize_t get_line_to_buffer(char *buffer, size_t siz) {
  char* p = buffer;
  char* start = buffer;
  char* end = buffer + siz;
  int n = 0;
  if (p < end)
     n = snprintf(p, siz, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
  else
     n = snprintf(NULL, 0, "%d, %s, %s, %lu", version, fileName, Id, timestamp);
  if (n<0) return -1;
  p += n, siz -= n;
  if (siz<0) return -1;
  if (p < end)
     n = snprintf(p, siz, ",%d,%d,%f", noOfObs, frequency, sum);
  else
      n = snprintf(NULL, 0, ",%d,%d,%f", noOfObs, frequency, sum);
  if (n<0) return -1;
  p += n; siz -= n;
  return p - start;
}

其实,你可以考虑使用 asprintf(3)如果您的系统有的话。

您也可以使用 fmemopen(3) 打开内存中的流。或open_memstream(3)并对其使用fprintf

顺便说一句,您可以简单地执行一个 snprintf 但将其格式控制字符串拆分为多个物理行:

int n = snprintf(p, siz,  
                 "%d, %s, %s, %lu"
                 ",%d,%d,%f",
                 version, fileName, Id, timestamp,
                 noOfObs, frequency, sum);

关于c - 使用指向 char 的指针时如何使用 snprintf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52039290/

相关文章:

c - C中输出单个字符

使用 Visual Studio 2005 的 C 编译错误

c - 带有说明符 "%g"的 printf 的精度

c++ - while( scanf ("%d", &n) ) { ... } 在 Linux 上按 Ctrl+D 时不退出

c - 文件作为 Win32 应用程序的参数

C 中的计算天数函数

c++ - 使用 openssl 检查 PKCS#7 中的根证书是否被撤销

c - 多线程、gtk3 和 cairo : drawing in a cairo surface

c - 警告 : format ‘%s’ expects type ‘char *’ , 但参数 2 的类型为 ‘int’

java - 在没有 gcj 的情况下组合 Java 和 C——将 C 迁移到 Java 还是将 Java 迁移到 C?