【问题标题】:Absolute positioning in printout with cout in C++?在 C++ 中使用 cout 打印输出中的绝对定位?
【发布时间】:2010-02-08 14:26:57
【问题描述】:

如何使用 cout 获得“绝对定位”的列,左对齐文本和右对齐数字?

#include <iostream>
#include <iomanip>
using namespace std;

struct Human {
    char name[20];
    char name2[20];
    char name3[20];
    double pts;
};

int main() {
    int i;
    Human myHumen[3] = {
        {"Mr", "Alan", "Turing", 12.25},
        {"Ms", "Ada", "Lovelace", 15.25},
        {"Sir",  "Edgar Allan", "Poe", 45.25}
    };
    cout << "Name1" << setw(22) << "Name2" << setw(22) << "Name3" << setw(22) << "Rating" <<endl;
    cout << "-----------------------------------------------------------------------\n";
    for(i = 0; i < 3; i++) {
        cout << myHumen[i].name << setw(22) << myHumen[i].name2 << setw(22) << myHumen[i].name3 << setw(20) << myHumen[i].pts << endl;
    }//this didn't do nice printouts, with leftalign for text and rightalign with numbers
}

【问题讨论】:

标签: c++ formatting cout


【解决方案1】:

您使用“左”和“右”操纵器:

cout << std::left  << std::setw(30) << "This is left aligned"
     << std::right << std::setw(30) << "This is right aligned";

文字+数字的例子:

typedef std::vector<std::pair<std::string, int> > Vec;
std::vector<std::pair<std::string, int> > data;
data.push_back(std::make_pair("Alan Turing", 125));
data.push_back(std::make_pair("Ada Lovelace", 2115));

for(Vec::iterator it = data.begin(), e = data.end(); it != e; ++it)
{
    cout << std::left << std::setw(20) << it->first
         << std::right << std::setw(20) << it->second << "\n";
}

哪些打印:

Alan Turing                          125
Ada Lovelace                        2115

【讨论】:

  • 我自己和罗杰一起解决了这个问题。你认为我取消了什么改变?
  • 另外,在那个所谓的重复中,我没有看到任何提到 std::right
  • 重点不在于两个问题是否与字母相同——而是它们是否处理完全相同的解决方案。提到right 并没有什么不同,IMO。当然,没必要激动。
  • @dirk - 我认为这不是一个重复,因为这里明确提到了“右对齐数字”。但我承认这两个问题非常接近。我不是故意要严厉的,如果你这么认为的话,我很抱歉。
【解决方案2】:

这会有点不受欢迎,但你可以使用 printf 来完成这种快速程序。格式化字符串更容易理解和使用(假设有人同时了解 iostreams 和 printf)。

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>

struct Human {
  char name[20];   // consider using std::string
  char name2[20];
  char name3[20];
  double pts;
};

int main() {
  using namespace std;
  Human people[3] = {
    {"Mr", "Alan", "Turing", 12.25},
    {"Ms", "Ada", "Lovelace", 15.25},
    {"Sir",  "Edgar Allan", "Poe", 45.25}
  };
  printf("%-22s%-22s%-22s%20s\n", "Name1", "Name2", "Name3", "Rating");
  cout << string(22 * 3 + 20, '-') << '\n';
  for (int i = 0; i < 3; i++) {
    Human const& h = people[i];
    printf("%-22s%-22s%-22s%20f\n", h.name, h.name2, h.name3, h.pts);
  }
  return 0;
}

混合使用 cout 和 printf 是安全的(默认情况下,请参见 std::sync_with_stdio),一个好的编译器也可以为您检查格式字符串的类型(gcc 中的 -Wall)。

【讨论】:

  • 混合 C 和 C++ 风格的 i/o 绝不是一个好主意(sync_with_stdio 之前的任何 i/o 在调用点之前都具有实现定义的语义)。如果你取出流浪的cout——这绝对是一个替代方案;-) 注意,你可以在for 循环中声明int i。此外,提及#include &lt;cstdio&gt; 会让这一切变得甜蜜。我的 0.02 美元。
  • @dirk:我把 cout 留在里面是为了表明你可以混合它们。 sync_with_stdio 存在的全部意义在于它是安全的,除非您明确提出其他要求(因此可能会获得小的性能提升),并且如果您不调用它,它是 not 实现定义的。 (实现定义是在 输出之后调用它。)
  • 我还遗漏了他程序的整个第一部分,如果您尝试编译它,这会导致错误,但您是对的,完成这项工作并没有太多工作。
猜你喜欢
  • 1970-01-01
  • 2011-01-29
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2013-12-06
相关资源
最近更新 更多