Reputation: 153
I am reading a textbook and trying to solve the question given to readers.
The fallowing code is function definition from my source file of my answer.
I want to copy content of character strings to another ones.
I chose functions strncpy_s().
But it does not work.
Microsoft Visual Studio says Debug Assertion Failed!
I have no idea how to fix it.
cow.h
// class declarations
#include <iostream>
#ifndef COW_H_
#define COW_H_
class Cow {
char name[20];
char * hobby;
double weight;
public:
Cow();
Cow(const char * nm, const char * ho, double wt);
Cow(const Cow & c);
~Cow();
Cow & operator=(const Cow & c);
void ShowCow() const; // display all cow data
};
#endif
cow.cpp
// class methods
Cow::Cow(const char * nm, const char * ho, double wt)
{
int len = std::strlen(nm);
strncpy_s(name, len, nm, len);
name[19] = '\0';
len = std::strlen(ho);
hobby = new char[len + 1];
strncpy_s(hobby, len, ho, len);
hobby[len] = '\0';
weight = wt;
}
Cow::Cow()
{
strncpy_s(name, 19, "no name", 19);
name[19] = '\0';
int len = std::strlen("no hobby");
hobby = new char[len + 1];
strncpy_s(hobby, len, "no hobby", len);
hobby[len] = '\0';
weight = 0.0;
}
Cow::Cow(const Cow & c)
{
int len = std::strlen(c.name);
strncpy_s(name, len, c.name, len);
name[19] = '\0';
len = std::strlen(c.hobby);
hobby = new char[len + 1];
strncpy_s(hobby, len, c.hobby, len);
hobby[len] = '\0';
weight = c.weight;
}
Cow::~Cow()
{
delete [] hobby;
}
Cow & Cow::operator=(const Cow & c)
{
if (this == &c)
return * this;
delete [] hobby;
int len = std::strlen(c.name);
strncpy_s(name, len, c.name, len);
name[19] = '\0';
len = std::strlen(c.hobby);
hobby = new char[len + 1];
strncpy_s(hobby, len, c.hobby, len);
hobby[len] = '\0';
weight = c.weight;
return * this;
}
void Cow::ShowCow() const
{
cout << name << ", " << hobby << ", " << weight << endl;
}
usecow.cpp
#include <iostream>
#include "cow.h"
int main()
{
Cow Japan;
Japan.ShowCow();
Cow America("Aspen", "Swim", 307.45);
America.ShowCow();
return 0;
}
Upvotes: 2
Views: 15746
Reputation: 76305
int len = std::strlen(nm);
strncpy_s(name, len, nm, len);
First, the second line should use len + 1
instead of len
. And second, it should use strcpy
instead of strncpy_s
.
Calculating the length of the source (strlen(nm)
) doesn't provide any information about the size of the target buffer (name
). And since there is no information about the size of the target buffer, restricting the number of characters to copy is meaningless. So don't do all that wheel-spinning. Just copy the string:
strcpy(name, nm);
Upvotes: 1
Reputation: 5920
From strncpy_s
documentation:
These functions try to copy the first D characters of strSource to strDest, where D is the lesser of count and the length of strSource. If those D characters will fit within strDest (whose size is given as numberOfElements) and still leave room for a null terminator, then those characters are copied and a terminating null is appended; otherwise, strDest[0] is set to the null character and the invalid parameter handler is invoked, as described in Parameter Validation.
Lets consider your code:
int len = std::strlen("no hobby");
hobby = new char[len + 1];
strncpy_s(hobby, len, "no hobby", len);
Second argument of strcpy_s
is a size of buffer in characters. Fourth - number of characters copied. Since you are passing the same len
variable, strcpy_s
detects, that buffer has insufficient size (because there should be a space for the trailing \0) and invokes invalid parameters handler. This works correctly:
int len = std::strlen("no hobby");
hobby = new char[len + 1];
strncpy_s(hobby, len+1, "no hobby", len);
Check other places where you are using strncpy_s
for this error.
Also it is a good idea to actually read text in the debug assertion windows. In this case error source is pretty straightforward:
Upvotes: 6