1

I originally programmed an assignment using Microsoft/visual c++ compilers, but my course requires me to run and compile on unix using G++

However, strncpy_s does not compile using g++, any workaround for my specific program?

This is code snippet that uses it:

void PhoneNumber::setName(const char name[])
{
    strncpy_s(_name, name, MAX_NAME_LENGTH);
}
sepp2k
  • 363,768
  • 54
  • 674
  • 675
andirewftw
  • 13
  • 4

2 Answers2

7

The *_s functions are Microsoft's attempt at being clever and "securing" the C runtime library's string functions. The functions even made it into C99's Appendix K. They are not implemented in Linux' glibc at the time of this writing. If you absolutely must (and I advise against it), just use the normal C library functions correctly (this means no magic numbers and proper buffer sizes everywhere), and yes, this is a pain in the bum.

This might or might not be usable within the context of your assignment, but it is really the only correct answer:

class PhoneNumber
{
private:
  std::string name;
  // ...
public:
  void setName(std::string name);
  //...
};

void PhoneNumber::setName(std::string name)
{
  this->name = std::move(name); // 'this->' is optional, but clarifies without resorting to some clever renaming of the variables
}

Alternatively, drop the setter altogether:

struct PhoneNumber
{
  std::string name;
  // ...
};

and assign the member directly. But this style of coding, although perfectly sane, might get you yelled at by your teacher.

Don't use C char arrays in C++. You'll shoot yourself in the foot for no good reason. It also gets rid of the magic number in your code, which is always a plus.


Tiny C++11 and later template wankery. The ideal solution of implementing the setter is using templates, so that a potential costly double-move can be prevented if the setter is called like setName(std::move(some_string)):

template<typename T>
void setName(T&& name) { this->name = std::forward<T>(name); }

This will allow anything that is assignable/moveable to a std::string to be accepted, which is actually quite nice all in all. As an added benefit, you get the best possible code path selected for you automagically. Of course for your assignment this will be huge overkill, but if you take the time to learn about these concepts you might just teach the teacher something. Again, prefer a public member to this template ... wankery, because that is what this is.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • 2
    It is better to use references to avoid object copy operation on method call + use const – iwlagn Feb 06 '15 at 15:31
  • @iwlagn Not quite that simple in c++11 (I did miss a `std::move` though), see e.g. http://stackoverflow.com/a/7592741/256138 – rubenvb Feb 06 '15 at 15:38
-2

You should not be using strncpy or its _s version, it may be quite surprising in its behaviour.

Use strlcpy instead, see strlcpy and strlcat - consistent, safe, string copy and concatenation.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 1
    `strlcpy` is not available with glibc. It's not certain that the OP is using glibc, but it is very likely. –  Feb 06 '15 at 15:21
  • @hvd _The source code for strlcpy() and strlcat() is available free of charge and under a BSD-style license as part of the OpenBSD operating system. You may also download the code and its associated manual pages via anonymous ftp from ftp.openbsd.org in the directory /pub/OpenBSD/src/lib/libc/string. The source code for strlcpy() and strlcat() is in strlcpy.c and strlcat.c. The documentation (which uses the tmac.doc troff macros) may be found in strlcpy.3._ – Maxim Egorushkin Feb 06 '15 at 15:24