使用具有固定宽度,左对齐字段和连接的sprintf

时间:2015-07-27 15:37:34

标签: c++ c printf

我正在使用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

我无法使用提升。

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

(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

5 个答案:

答案 0 :(得分:2)

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

        class Example: UIViewController {
        var run = true
        var timer: NSTimer!
        var number = 1 
        var array: [Int]!
         @IBOutlet weak var label: UILabel!
         @IBOutlet weak var resultLabel: UILabel!
          func switchNumberOnLabel() {
           var appendthing = Int.random()
            label.text = "\(appendthing)"
           array.append(appendthing)
            number += 1
            if number == 3 {
           timer.invalidate()
           resultLabel.text = "\(addArrayElements(array))"
}
        }

         func addArrayElements(array: [Int])->Int {
         return array[0] + array[1] + array[2]
}
          @IBAction func buttonClicked(sender: UIButton) {
                if run {
                timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "switchNumberOnLabel", userInfo: nil, repeats: true)
                var randomnumber = Int.random()
                array.append(randomnumber)
                label.text = "\(randomnumber)"
                run = false
                }

        }



        }

        extension Int {
           static func random()-> Int {
            return Int(arc4random() % UInt32(9)) + 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);

答案 1 :(得分:0)

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

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

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

如果您始终输出到文件,则可以转储sprintf并直接将其替换为fprintf

答案 2 :(得分:0)

  

如何在不使用多个步骤[...]

的情况下组合这些组合

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

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);

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

答案 3 :(得分:0)

你可以拆分你的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);
}

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

答案 4 :(得分:0)

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