error in mystrcat

C

ceo

Hi,

This program throws a run time error as there is not enough space in
str1 to concat whole of str2. Is there way by which I can detect the
error in function mystrcat by doing some extra checking but without
passing any extra arguments to mystrcat?

Thanks,
Ceo

// A customized version of strcat().
#include <iostream>
#include <cstring>
using namespace std;

void mystrcat(char *s1, char *s2, int len = -1);

int main()
{
char str1[20] = "This is a test";
char str2[20] = "0123456789";

mystrcat(str1, str2, 5); // concatenate 5 chars
cout << str1 << '\n';

strcpy(str1, "This is a test"); // reset str1

mystrcat(str1, str2); // concatenate entire string
cout << str1 << '\n';

return 0;
}

// A custom version of strcat().
void mystrcat(char *s1, char *s2, int len)
{
// find end of s1
while(*s1) s1++;

if(len == -1) len = strlen(s2);

while(*s2 && len) {
*s1 = *s2; // copy chars
s1++;
s2++;
len--;
}
*s1 = '\0'; // null terminate s1
}
 
R

Rolf Magnus

ceo said:
Hi,

This program throws a run time error as there is not enough space in
str1 to concat whole of str2. Is there way by which I can detect the
error in function mystrcat by doing some extra checking but without
passing any extra arguments to mystrcat?

No. There is no way to detect the length of an array if you only have a
pointer to one of its elements.
// A customized version of strcat().
#include <iostream>
#include <cstring>
using namespace std;

void mystrcat(char *s1, char *s2, int len = -1);

int main()
{
char str1[20] = "This is a test";
char str2[20] = "0123456789";

mystrcat(str1, str2, 5); // concatenate 5 chars
cout << str1 << '\n';

strcpy(str1, "This is a test"); // reset str1

mystrcat(str1, str2); // concatenate entire string
cout << str1 << '\n';

return 0;
}

// A custom version of strcat().
void mystrcat(char *s1, char *s2, int len)
{
// find end of s1
while(*s1) s1++;

if(len == -1) len = strlen(s2);

while(*s2 && len) {
*s1 = *s2; // copy chars
s1++;
s2++;
len--;
}
*s1 = '\0'; // null terminate s1
}
 
H

Howard

ceo said:
Hi,

This program throws a run time error as there is not enough space in
str1 to concat whole of str2. Is there way by which I can detect the
error in function mystrcat by doing some extra checking but without
passing any extra arguments to mystrcat?

Simple answer? No. There is no way to know the size of the array whose
address gets passed in. That's one of many reasons why I use std::string
instead of C-style (null-terminated char) arrays.

Is this just for practice, or do you think there's something *better* about
your version than strncat?
Thanks,
Ceo

// A customized version of strcat().
#include <iostream>
#include <cstring>
using namespace std;

void mystrcat(char *s1, char *s2, int len = -1);

int main()
{
char str1[20] = "This is a test";
char str2[20] = "0123456789";

mystrcat(str1, str2, 5); // concatenate 5 chars
cout << str1 << '\n';

strcpy(str1, "This is a test"); // reset str1

mystrcat(str1, str2); // concatenate entire string
cout << str1 << '\n';

return 0;
}

// A custom version of strcat().
void mystrcat(char *s1, char *s2, int len)
{
// find end of s1
while(*s1) s1++;
It's possible that this might run right off the end of the array, before you
even get to the code below.
if(len == -1) len = strlen(s2);

What if len < -1?
while(*s2 && len) {
Here's where it's likely running off the end of the arrray:
*s1 = *s2; // copy chars
s1++;
s2++;

This could be written *s1++ = *s2++;
At least I think so...I always get screwed up trying to remember operator
precedence. :)
len--;
}
*s1 = '\0'; // null terminate s1
}

You have several options. You could pass the length of the arrays, but
that's a pain, and the caller might not pass the correct length, anyway.
Or, you could just document it and say "the destination string MUST be able
to fit its current content plus the content of the other array, plus the
null terminator, or else undefined behavior will result". Or, you could do
away with this kind of stuff altogether and use std::string, which is in my
opinion a much better plan! :)

-Howard
 
D

DHOLLINGSWORTH2

Howard said:
Simple answer? No. There is no way to know the size of the array whose
address gets passed in. That's one of many reasons why I use std::string
instead of C-style (null-terminated char) arrays.

Is this just for practice, or do you think there's something *better*
about your version than strncat?

Consider what happens when you type in "guest" at :

char lname[3];
scanf( "%s", lname);

if your familiar with scanf, you actually write to data space beyond the
array lname; The results are unpredictable.

I'm sure that if what you wanted to do could be done, someone would have
done it by now.

Alternate String types:
some languages, ADA I think, if I remember correctly, instead of a '\0'
terminating a string the first element is the actual length of the string.
You could adapt this a little :
struct string {
short containerSize;
short StringLength;
char * mData;
};
or using a null terminated string
struct String {
short ContainerSize;
char * mData;
};

in the second example you can still use String operations on the mData
member, while adding a level of protective information.

Dan
 
C

ceo

Simple answer? No. There is no way to know the size of the array
whose address gets passed in.

Thanks for the clarification.
That's one of many reasons why I use std::string instead of C-style
(null-terminated char) arrays.
Is this just for practice, or do you think there's something
*better* about your version than strncat?

I'm just practicing. I'm yet to learn how to use the std::string class.
 
R

Rolf Magnus

ceo said:
I'm just practicing. I'm yet to learn how to use the std::string class.

It's what you should learn first, before fiddling around with char arrays.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top