【问题标题】:Use sprintf with fixed width, left-justified field and concatenation使用具有固定宽度、左对齐字段和连接的 sprintf
【发布时间】:2015-07-27 15:37:33
【问题描述】:

我正在使用sprintf 来制作漂亮的列输出(通过printffprintf),但是在组合两个字符串时遇到了可变字符串长度的问题。

在大多数情况下,我使用它并且它有效:

sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum,
        measurementname, setvalue, measuredvalue);

在每个测量函数中运行时,输出如下:

1    MeasurementNameA            75    77 8
2    MeasNameB                   50    52 2

但是,有时我想添加到字符串但保持正确调整。没有固定宽度,代码如下:

sprintf(strtmp, "%i\t%s_setup%i\t% 2.2f\t% 2.2f", measnum,
        measurementname, counter, setvalue, measuredvalue);

1    MeasureNameA    75    77 8  
2    MeasNameB_setup1    50    52 2
3    MeasNameB_setup2    50    51 6

如何在不使用多个步骤的情况下将这些组合起来,这样我的输出是:

1    MeasureNameA                75    77 8
2    MeasNameB_x1                50    52 2
3    MeasNameB_x2                51    53 6

我不能使用 boost。

可能需要额外的信息。
我的伪代码是这样的:

(measurementA)
   -Setup measurement A -
   -Take measurement A -
   -sprintf
   -printf, fprintf

(measB)
   -Setup measurement B
   for(x=1; x<10; x++)
       -Set x
       -Take measurement B
          -sprintf
          -printf, fprintf
          -end for loop

【问题讨论】:

  • 为什么只显示伪代码?
  • 1 MeasurementNameA 75 77 8 中的MeasurementNameA 后面有 3 个数字。 8 来自哪里?
  • Cleb - 因为我简化了一大组代码以排除我无法共享的内容并仅包含相关信息,即格式化字符串。
    Alk - 在我的格式化字符串中或stackoverflow 输入
    Chux - 它应该是十进制 77 点 8。

标签: c++ c printf


【解决方案1】:

有一些方法可以做到这一点,你可以使用临时缓冲区来生成名称,然后打印出来:

char buf[64];
snprintf(buf, 64, "%s_setup%i", measurementname, counter);
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum, buf, setvalue, measuredvalue);

或者你可以探索可变填充的奇妙之处:

sprintf(strtmp, "%i\t%s_setup%*i\t% 2.2f\t% 2.2f", measnum,
    measurementname, strlen(measurementname) - 14, counter, setvalue, measuredvalue);

【讨论】:

    【解决方案2】:

    您可以拆分您的sprintf(同时,为了安全起见,请改用snprintf),并使用前一个的返回值来准确了解打印了多少字符。

    类似的东西:

    // Will split in columns = 10, 50, 60
    void formatMyString(int num, char *name, int counter, float setval, float mes)
    {
        char buf[256] = {0};
        int cnt = 0;
        cnt = snprintf(buf, 256-cnt, "%i ", num);
        if (cnt < 10) {
            memset(&buf[cnt], ' ', 10-cnt);
            cnt = 10;
        }
        cnt += snprintf(&buf[cnt], 256-cnt, "%s_setup%i ", name, counter);
        if (cnt < 50) {
            memset(&buf[cnt], ' ', 50-cnt);
            cnt = 50;
        }
        cnt += snprintf(&buf[cnt], 256-cnt, "%2.2f ", setval);
        if (cnt < 60) {
            memset(&buf[cnt], ' ', 60-cnt);
            cnt = 60;
        }
        snprintf(&buf[cnt], 256-cnt, "%2.2f", mes);
        printf("%s\n", buf);
    }
    

    这应该可行。您可以通过更改常量来更改拆分列,并调整为 thour 格式。 如果输入长于预期大小,则不进行填充。

    【讨论】:

      【解决方案3】:

      您可以在格式化为它将容纳的文本的最大长度时指定第二列的宽度。如有必要,提高该值。

      printf("%-40s", "Some text");
      

      - 将您在该字段中的文本左对齐,长度为 40 个字符,否则它将是正确的。没有其他好的方法可以做到这一点。 同样适用于sprintffprintf

      如果总是输出到文件,可以转储sprintf,直接用fprintf替换。

      【讨论】:

      【解决方案4】:

      如何在不使用多个步骤的情况下组合这些 [...]

      你不能。但是您可以编写一个辅助函数并使用它:

      const char *combineFixedWidth(char *buf, size_t width, const char *str, const char *suff)
      {
          size_t len, slen;
      
          memset(buf, ' ', width);
          buf[width] = 0;
          len = strlen(str);
          slen = strlen(suff);
          if (len > width)
          {
              memcpy(buf, str, width);
              return buf;
          }
          memcpy(buf, str, len);
          width -= len;
          if (slen < width) width = slen;
          memcpy(buf+len, suff, width);
          return buf;
      }
      

      然后提供char buf[21] 并像这样使用它:

      sprintf(strtmp, "%i\t%s%i\t% 2.2f\t% 2.2f", measnum,
              combineFixedWidth(buf, 20, measurementname, "_setup"),
              counter, setvalue, measuredvalue);
      

      免责声明:此处输入的代码未经测试,可能包含错误。

      【讨论】:

        【解决方案5】:

        仅通过格式说明符没有简单的方法可以做到这一点。您可以在字符串格式中使用 * 说明符来指定动态字符串宽度,但这仍然需要您计算名称字符串长度,以及添加的字符串 + 数字长度。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-08
          • 1970-01-01
          • 1970-01-01
          • 2012-02-20
          相关资源
          最近更新 更多