3

Is there a way to do the following, but passing only bounds to printf?

double *bounds = getBounds();
printf("%f-%f, %f-%f, %f-%f",
    bounds[0], bounds[1],
    bounds[2], bounds[3],
    bounds[4], bounds[5] );

// what I'd like to write instead:
xxxprintf("%f-%f, %f-%f, %f-%f", bounds);
5
  • While there's no portable Standard way, some printf implementations allow new conversion formats that give you options - e.g. gnu.org/software/libc/manual/html_node/Customizing-Printf.html Commented May 9, 2014 at 12:48
  • Is it that you want a general way of printing arrays/vectors or the question is whether you can achieve such behaviour specifically with printf? Commented May 9, 2014 at 13:01
  • @40two The former. I think it's ugly to pass the six arguments and want to solve this in some other way (without a loop). Commented May 9, 2014 at 13:06
  • @Anna you are restricted in using only printf can you use std::cout? Commented May 9, 2014 at 13:08
  • @40two I am not restricted to printf. I think I could use std::cout. Commented May 9, 2014 at 13:11

4 Answers 4

4

You can write your own xxxprintf()

#include <stdio.h>

int arrayprintf_dbl(const char *fmt, const double *data) {
  int n = 0;
  const char *p = fmt;
  const double *x = data;
  while (*p) {
    if (*p == '%') {
      // complicate as needed ...
      p++;
      if (*p != 'f') return -1; // error
      n += printf("%f", *x++);
    } else {
      putchar(*p);
      n++;
    }
    p++;
  }
  return n;
}

int main(void) {
  double bonus[6] = {1, 2, 3, 4, 5, 6};
  arrayprintf_dbl("%f-%f, %f-%f, %f-%f\n", bonus);
  return 0;
}

I wrote this in C, I think it can be converted to C++ easily (I don't know C++).

Sign up to request clarification or add additional context in comments.

Comments

1

I assume the reason why you want to optimize this is that you need to print a lot of bounds in your program and it is tiresome to write like this, it is error prone etc.


In C, you could use a macro like this:

#define BOUNDS_FORMAT "%f-%f, %f-%f, %f-%f"
#define BOUNDS_ARG(b) b[0], b[1], b[2], b[3], b[4], b[5]

Then write it just like so:

printf(BOUNDS_FORMAT, BOUNDS_ARG(bounds));
// ... some other code, then another call, with more text around this time:
printf("Output of pass #%d: " BOUNDS_FORMAT "\n", passNumber, BOUNDS_ARG(bounds));

In C++, you are more expected to use std::cout or similar stream. Then you could write a custom object to do this for you:

class PrintBounds {
  protected:
    const double* m_bounds;

  public:
    PrintBounds(const double* bounds)
      : m_bounds(bounds)
    {
    }

    friend std::ostream& operator<<(std::ostream& os, const PrintBounds& self)
    {
        os << self.m_bounds[0] << "-" << self.m_bounds[1] << ", "
           << self.m_bounds[2] << "-" << self.m_bounds[3] << ", "
           << self.m_bounds[3] << "-" << self.m_bounds[5];
        return os;
    }
};

Then you would use it like this:

std::cout << "Some other text: " << PrintBounds(bounds) << " ...\n";

Comments

1
  • I'm posting a C++11 version of a one line printing algorithm. I coded a functor (i.e., PairPrintFunctor) that in association with for_each can print containers with even number of elements. If the container contains odd number of elements the last is ignored. You can also set your own delimiters.

  • Note However, that you can't avoid the iteration. In the background there's an iterative procedure due to for_each.


#include <iostream>
#include <algorithm> 
#include <iterator>
#include <utility>
#include <memory>
#include <string>
#include <vector>

template<typename T>
class PairPrintFunctor
{
  std::size_t         _n;
  std::ostream       &_out;
  std::string         _delim;
  std::string         _sep;
  std::shared_ptr<T>   state;
public:
    explicit PairPrintFunctor(std::ostream &out, std::string delim = " ", std::string sep = " - ") : _n(0), _out(out), _delim(delim), _sep(sep) { }
    void operator()(T const &elem) 
    { 
        if(state == nullptr) {
          state.reset(new T(elem));
        } else {
          if (_n > 0) _out << _delim;
          _out << *state << _sep << elem;
          state.reset();
          state = nullptr;
          ++_n;
        }
    }
};

int main()
{
    int a[] {1, 2, 3, 4, 5, 6, 7, 8};
    std::for_each(std::begin(a), std::end(a), PairPrintFunctor<int>(std::cout, ", ", " --- "));
    std::cout << std::endl;
    std::vector<int> v{ 10, 20, 30, 40, 50, 60, 70, 80};
    std::for_each(std::begin(v), std::end(v), PairPrintFunctor<int>(std::cout, ", ", " --- "));
    std::cout << std::endl;
    return 0;
}

HTH

Comments

0

Its not possible. See:

http://en.cppreference.com/w/c/io/fprintf

Alternatively, break out the code into its own function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.