HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinorCanonical

Pointer version of strcat()

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
versionpointerstrcat

Problem

Seems to work fine, I guess it won't work if the destination array's size is not defined by a macro, but a variable or something else, I thought about adding a third argument which is the size and let the user enter it, but that might be worse.

#include 
#include 
#include 
#define MAX_SIZE 100

char *ptr_str_cat(char *dest, const char* src){
    char *original;
    original = dest;
    if((strlen(dest) + strlen(src)) > MAX_SIZE){
        puts("The source string is too big for the destination");
        exit(EXIT_FAILURE);
    }
    dest = strchr(dest, '\0');
    *dest = '0';
    while((*dest++ = *src++) != '\0'){
        ; /*do nothing*/
    }
    return original;
}

int main(void){
    char dest [MAX_SIZE];
    char source [MAX_SIZE];
    puts("Enter the destination string");
    fgets(dest, sizeof(dest), stdin);
    dest[strlen(dest) -1 ] = '\0'; /*Remove trailing newline*/
    puts("Enter the source string");
    fgets(source, sizeof(source), stdin);

    printf("%s", ptr_str_cat(dest, source));

    return 0;
}

Solution

ptr_str_cat function:

-
The ISO C90 strcat requires the string dest to have sufficient space to hold the result of the concatenation. On the other hand strncat takes another argument size_t n and won't copy more then n characters to dest (+ the null terminator). You should definitely consider to implement one of these approaches, since the macro seems rather randomly chosen (you don't know whether dest is big enough to hold src).

Edit: See @JS1's answer to take a look at the approach of strncat. He also has a good catch with the Off-by-one-error.

-
If you want to completely leave out library function calls, you could even replace the strchr call with a simple loop.

while(*dest != '\0')
  dest++;


-
There is no need to explicitly overwrite the null terminator in dest. It will get overwritten by the contents of src and in the case of an empty src the null terminator is actually wanted.

-
The while-loop doesn't require extra curly braces. The NULL statement is sufficient.

while((*dest++ = *src++) != '\0')
    ; /* Intentionally left blank */


-
This is what you would come up with:

char *ptr_str_cat(char *dest, const char* src){
  char *original = dest

  while(*dest != '\0')
    dest++;

  while((*dest++ = *src++) != '\0')
    ;  /* Intentionally left blank */

  return original;
}


You don't even need to include ` using this implementation (since you don't use exit anymore).

main function:

  • Minor: dest[strlen(dest) - 1] = '\0'; will overwrite valid input (not the '\n'), when the first input line is longer than MAX_SIZE.



EDIT:

Good question regarding how to handle large input. I think this somehow depends on the target. I'd say our goal here is to create a piece of software, which is able to read in two strings (of any unknown size, separated by
'\n') and later on have a pointer to the concatenation of these two strings.

One approach would be to allocate
MAX_SIZE bytes of memory using malloc. Using fgets we fill the allocated memory and each time the string does not end on '\n' we reallocate MAX_SIZE` more bytes and read in more characters. This will work until you run out of memory.

Code Snippets

while(*dest != '\0')
  dest++;
while((*dest++ = *src++) != '\0')
    ; /* Intentionally left blank */
char *ptr_str_cat(char *dest, const char* src){
  char *original = dest

  while(*dest != '\0')
    dest++;

  while((*dest++ = *src++) != '\0')
    ;  /* Intentionally left blank */

  return original;
}

Context

StackExchange Code Review Q#159735, answer score: 4

Revisions (0)

No revisions yet.