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

时间:2018-08-27 12:22:58

标签: 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;
}

1 个答案:

答案 0 :(得分:1)

请仔细阅读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);