0

I have to generate a string command to configure a device using a microcontroller, hence the need for C-style strings instead of regular std::string.

Each step requires an enter press or a Y/N + enter answer and I need a line of code for each one. Code example:

#define YES "Y\n"
#define NO "N\n"
#define ENTER "\n"
#define DEFAULT_COMMAND_SIZE 30
    
static char command[DEFAULT_COMMAND_SIZE];

if (getChangePassword()) { // just a function that returns true if password has to be changed
    if (getTelnetPassword() != nullptr) {
        std::strcat(command, YES);
        std::strcat(command, getTelnetPassword()); // password is a char*, same as command
        std::strcat(command, ENTER);
    }
} else {
    std::strcat(command, NO);
}

Can I somehow reduce the number of repeating LOC?

Andrei
  • 59
  • 5
  • 2
    If `command` is global, you can write a wrapper function `catCommand` to at least avoid repeating the argument three times. Also if the user provides a long password, you have a buffer overflow there. – Thomas Oct 22 '20 at 08:30
  • Why not https://stackoverflow.com/questions/51162346/how-do-i-perform-string-formatting-to-a-static-buffer-in-c ? – KamilCuk Oct 22 '20 at 08:30
  • 5
    Why don't you generate a `std::string` and then use [`c_str()`](http://www.cplusplus.com/reference/string/string/c_str/)? – Jabberwocky Oct 22 '20 at 08:33
  • 3
    Well you can write `std::strcat(std::strcat(std::strcat(command, YES), getTelnetPassword()), ENTER);`. It's only one line, but I wouldn't call it an improvement. Trying to minimise the number of lines of code is a bit artificial. Just try to make the code as clear as possible, however few or many lines that takes. – john Oct 22 '20 at 08:33
  • 3
    That an API call takes a `const car *` as an argument does not mean that you cannot use `std::string` to generate and hold the string data. It just means that you need to find a way (e.g. `c_str`) to pass it to the API. – t.niese Oct 22 '20 at 08:41
  • 3
    Note that minimizing LOC doesn't mean reducing assembly code – Ranoiaetep Oct 22 '20 at 08:43
  • don't concatenate C-strings like that. You'll have the same [Shlemiel the painter’s issue](https://www.joelonsoftware.com/2001/12/11/back-to-basics/) – phuclv Oct 22 '20 at 09:05

1 Answers1

0

Use a std::string and once done, copy it into command:

Demonstration:

#include <iostream>
#include <string>
#include <string.h>

#define YES "Y\n"
#define NO "N\n"
#define ENTER "\n"
#define DEFAULT_COMMAND_SIZE 30

static char command[DEFAULT_COMMAND_SIZE];

bool getChangePassword()
{
  return true;
}

char *getTelnetPassword()
{
  return (char*)"testpassword";
}

int main()
{
  std::string scommand;
  if (getChangePassword()) { // just a function that returns true if password has to be changed
    if (getTelnetPassword() != nullptr) {
      scommand += YES;
      scommand += getTelnetPassword();
      scommand += ENTER;
    }
  }
  else {
    scommand = NO;
  }

  std::strcpy(command, scommand.c_str());

  std::cout << command;
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 1
    Including `` and using `std::string` even briefly will not still burden the microcontroller? This module is just a small part of a significantly larger software that will be used. – Andrei Oct 22 '20 at 08:49
  • 1
    @AndreiVicol if you're on an MCU then please tag it in the question – phuclv Oct 22 '20 at 09:06