Advice needed :How to avoid duplicate code?

Hi all,

I am trying to avoid writing code for the same thing twice. For example consider:

   Serial.print ("Free RAM: ");Serial.print (freeRam());
   Serial.print ("IP Address : ");PrintIPAddress(IP);
   Serial.print ("Subnet Mask : ");PrintIPAddress(subnet);
   Serial.print ("Gateway ");PrintIPAddress(gateway);
   Serial.print ("Dns : ");PrintIPAddress(DNS);

and :

   client.print ("Free RAM: ");client.print (freeRam());
   client.print ("IP Address : ");PrintIPAddress(IP);
   client.print ("Subnet Mask : ");PrintIPAddress(subnet);
   client.print ("Gateway ");PrintIPAddress(gateway);
   client.print ("Dns : ");PrintIPAddress(DNS);

Is there a way of avoiding writing two separate functions for the above? In other words is it possible to re-direct the output from Serial to client without adding more code for the same functionality?

Thanks for your help..

First of all...how does PrintIPAddress know to print through serial or client?

just make 2 functions for each of those and call the functions instead...

First of all...how does PrintIPAddress know to print through serial or client?

For now PrintIPAddress only prints through Serial. I am looking at ways to make it also print through client without writing an entirely separate function. The same applies for other functions as well. The above is only an example.

The only way I can think of doing that would be to make a function with a type of parameter, but the object types would need to be the same, but they are not...so you would need a new class, but from here it gets completely pointless...so I got nothing...

I was also thinking that maybe I could pass a parameter to a function which would somehow determine where the output goes. But then couldn't figure out how to actually do it from there.

Thanks for your help anyhow :slight_smile:

In C++, you would do this using a polymorphic class:

class PrintThing {
  public:
    virtual void prints(char *);
    virtual void printi(int);

    void info() {
      prints ("Free RAM: ");
      printi(1);
      prints ("IP Address : ");
      printi(2);
      prints ("Subnet Mask : ");
      printi(3);
      prints ("Gateway ");
      printi(4);
      prints ("Dns : ");
      printi(5);
    }

};

class PrintToSerial : public PrintThing {
    void prints(char *s) {
      Serial.print(s);
    }
    void printi(int i) {
      Serial.print(i);
    }
} printToSerial;

class PrintToClient : public PrintThing {
    void prints(char *s) {
      /* implementation of client.prints */
    }
    void printi(int i) {
      /* implementation of client,printi */
    }
} printToClient;

void someFunction() {
  printToSerial.info();
  // or
  printToClient.info();

  // or choose a printer based on a boolean value

  PrintThing *thePrinter;
  if (1 > 2) {
    thePrinter = &printToSerial;
  }
  else {
    thePrinter = &printToClient;
  }

  thePrinter->info();
  thePrinter->prints("\n ==== END OF PRINTING ===\n");

}

Your client printer probably needs to take a "client" pointer in its constructor, and to save that value in a class variable.

Maybe something like this

const Stream * streams[] = { &Serial, &client };

...
template <typename T> void printToStreams( T val );
template <typename T> void printToStreams( T val )
{
  Stream * stream;
    
  for ( uint8_t i = 0; i < sizeof( streams ) / sizeof( Stream * ); i++)
  {
    stream = (Stream *) streams[i];
    stream->println( val );
  }
}

...

printToStreams( "Free RAM: " );
printToStreams( freeRam() );
...

Thank you all for your input.

You guys are over-complicating this. Both HardwareSerial and EthernetClient extend the Print class, which has the print and println methods. Just make your functions take a reference to an instance of the Print class.

Could you give an example christop?

I'm on my phone so I can't test this example, but it should look something like this:

void printIt(Print& p)
{
    p.println("whatever");
}

Edit to add:

Then call it like this:

printIt(Serial);
printIt(client);

I will sure give it a try! Thanks

Success! Works perfect christop. Simple and easy.!

Thanks a lot!