9

所以,我开始使用 C++,具有半充足的 python 背景。在 python 中,你创建一个这样的列表/数组:

x = [1, 2, 3, 4, 5, 6, 7, 8, 9]

然后,要打印包含方括号的列表,您要做的就是:

print x

这将显示:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

我将如何在 C++ 中做同样的事情,以优雅/干净的方式打印括号和元素?注意我不想要数组的元素,我想要整个数组,像这样:

{1, 2, 3, 4, 5, 6, 7, 8, 9}

当我使用此代码尝试打印数组时,会发生这种情况:

输入:

#include <iostream>
using namespace std;


int main()
{
    int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    cout << anArray << endl;

}

输出是数组存储在内存中的位置(我认为是这样,如果我错了,请纠正我):

0x28fedc

作为旁注,我不知道如何创建具有许多不同数据类型的数组,例如整数、字符串等,所以如果有人能启发我,那就太好了!感谢您回答我辛辛苦苦的明显/愚蠢的问题!

4

6 回答 6

14

您可以编写一个简单的辅助函数来允许您将数组流式传输到输出流(包括但不限于std::cout):

#include <iostream>
// print an array to an output stream
// prints to std::cout by default
template <typename T, std::size_t N>
void print_array(const T(&a)[N], std::ostream& o = std::cout)
{
  o << "{";
  for (std::size_t i = 0; i < N-1; ++i)
  {
    o << a[i] << ", ";
  }
  o << a[N-1] << "}\n";
}

其中函数模板用于在编译时推断数组的类型和大小。你可以像这样使用它:

#include <fstream>
int main()
{
  int a[] = {1,2,3,4,5};
  print_array(a); // prints {1, 2, 3, 4, 5} to stdout

  std::string sa[] = {"hello", "world"};
  print_array(sa, std::cerr); // prints {hello, world} to stderr

  std::ofstream output("array.txt");
  print_array(a, output); // prints {1, 2, 3, 4, 5} to file array.txt
}

这个解决方案可以简单地推广到处理范围和标准库容器。有关更通用的方法,请参见此处

至于旁注,你不能在 C++ 中做到这一点。数组只能保存一种类型的对象。

于 2013-06-22T07:38:00.103 回答
7

受到 juanchopanza 和 Raxman 答案的启发,我决定做一个真正的 IO 操纵器,它的语法如下:

const char* arr[] = { "hello", "bye" };
std::cout 
    << "Woot, I can has " << print(arr)
    << " and even " << print(std::vector<int> { 1,2,3,42 }, ":") << "!\n";

印刷

Woot, I can has { hello, bye } and even { 1:2:3:42 }!

笔记

  • operator<<它与往常一样使用链式输出流无缝工作
  • 它是完全通用的(支持任何可流式类型的容器)
  • 它甚至允许传递分隔符(例如)
  • 使用更多模板参数,它可以变得如此通用,以便与 ostream、wostream 等一起使用。
  • 有趣:由于分隔符也可以是任何可流式传输的“事物”,您甚至可以...使用数组作为分隔符:

    std::cout << "or bizarrely: " << print(arr, print(arr)) << "\n";
    

    导致相当奇怪的样本输出:

    or bizarrely: { hello{ hello, bye }bye }
    

    如果你问我,仍然展示了无缝连接到 IO 流的强大功能。

我相信在 C++ 中它不会比这更无缝。当然还有一些实现要做,但是正如您所看到的,您可以利用完整的通用性,因此您可以立即完成任何可流式类型的容器:

#include <iostream>
#include <vector>

namespace manips
{
    template <typename Cont, typename Delim=const char*>
    struct PrintManip { 
        PrintManip(Cont const& v, Delim d = ", ") : _v(v), _d(std::move(d)) { }

        Cont const& _v;
        Delim _d;

        friend std::ostream& operator<<(std::ostream& os, PrintManip const& manip) {
            using namespace std;
            auto f = begin(manip._v), l(end(manip._v)); 

            os << "{ ";
            while (f != l)
                if ((os << *f) && (++f != l))
                    os << manip._d;
            return os << " }";
        }
    };

    template <typename T, typename Delim=const char*> 
    manips::PrintManip<T, Delim> print(T const& deduce, Delim delim = ", ") { 
        return { deduce, std::move(delim) }; 
    }
}

using manips::print;

int main()
{
    const char* arr[] = { "hello", "bye" };
    std::cout 
        << "Woot, I can has " << print(arr)
        << " and even: " << print(std::vector<int> { 1,2,3,42 }, ':') << "!\n"
        << "or bizarrely: " << print(arr, print(arr)) << "\n";
}

在http://ideone.com/E4G9Fp现场观看

于 2013-06-24T21:54:33.747 回答
2
for(int i=0;i<9;i++)
cout << anArray[i] << endl;

啊,用括号可以这样(只是数组的数组打印逻辑,你以后可以让它更通用)

  cout<<'{';
    for(int i=0;i<8;i++)
           cout << anArray[i] <<','; 
    cout<<anArray[8]<<'}';

对于 python 用户和c++ 爱好者,有 std::vector 。

这里如何打印矢量的逻辑 // 使用 [] 运算符的解决方案

if(anVector.size()>=1){
     std::cout<<"{";
      for(int i=0;i<anVector.size()-1;i++){
            std::cout<<anVector[i]<<',' ; 

      }
    std::cout<<anVector[anVector.size()-1]<<'}' ; 
}

//用迭代器解决

  std::vector<int>::iterator it =anVector.begin();
       if(it!=anVector.end()){ 
            std::cout << '{'<<*it;
            ++it;
            for (; it != anVector.end(); ++it){
               std::cout<<','<< *it ; 
            }
            std::cout << '}';
        }

还要检查 C++ 11 std::vector 。在新的标准初始化和其他更优雅的事情中

于 2013-06-22T07:36:52.593 回答
1

如果您不太关心逗号作为分隔符,您也可以使用输出迭代器

#include <iostream>
#include <iterator>
#include <algorithm>

...

int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

std::cout << "{ ";
std::copy(anArray, anArray + 9, std::ostream_iterator<int>(std::cout, " "));
std::cout << "}" << std::endl;
于 2013-06-24T22:20:45.593 回答
1

可能最简单的方法可以很好地打印一个数组(假设它的长度大于零)是这样的:

std::cout << "{" << anArray[0];
for (int i = 1; i < sizeof (anArray) / sizeof (*anArray); i++)
    std::cout << ", " << array[i];
std::cout << "}";

如果您希望能够打印少于完整数组的内容,则需要一种指定长度的方法(可能为零,因此您应该处理这种情况:

if (length == 0)
    std::cout << "{}";
else {
    std::cout << "{" << anArray[0];
    for (int i = 1; i < length; i++)
        std::cout << ", " << array[i];
    std::cout << "}";
}

可能还有其他变体,例如在给定的起点打印而不是元素零,但我不会在这里讨论。可以说,这只是对循环和if条件的一个小修改。

当然,如果你想用简单的方式来做std::cout << myvariable;,你可以考虑将整个事情包装在一个类中并operator<<为它提供你自己的——这将是一种更加面向对象的做事方式。

于 2013-06-22T07:48:58.823 回答
0

实现这一点的另一个想法是定义一个宏来将 c 数组转换为 std::vector 和一个模板函数来输出 std::vector,如下所示:

#include <vector>
#include <iostream>

// convert an array (e.g. int32_t x[20]) into an std::vector
#define ARRAY_TO_STD_VECTOR(VAR, TYPE) std::vector<TYPE>(VAR, VAR + sizeof(VAR)/sizeof(TYPE))

// output of std::vector<T>
namespace std {
  template<typename T>
  std::ostream& operator<<(std::ostream& p, const std::vector<T>& v)
  {
    p << "{";
    for (size_t i = 0; i < v.size(); ++i)
    {
      p << v[i];
      if (i < (v.size() - 1)) p << ", ";
    }
    p << "}";
    return p;
  }
}

有了这个,你可以像这样输出你的数组:

int main()
{
    int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    cout << ARRAY_TO_STD_VECTOR(anArray, int) << endl;

}
于 2020-12-15T12:17:26.820 回答