1

Ive been asked to write a function that merges two sorted (ascii sorted) strings without duplicates. For example, for string1 = aabcd, and string2 = abbcdg, the end result string should be abcdg. For some reason, the end result string doesnt allocate well, or so I think.. its not working anyway and its giving me weird characters instead of what its supposed to give. The value of stringToReturn is always 0xfffffffe "Error reading characters of string", and inside it says "Unable to read memory"

main.c:

#include <stdio.h>
#include <stdlib.h>
#include "bohan.h"

int main() {
char* string1;
char* string2;
char* mergedString;
string1 = (char*)malloc(MAX_TEXT + 1);
if (string1 == NULL)
    return;
string2 = (char*)malloc(MAX_TEXT + 1);
if (string2 == NULL)
    return;
printf("Please enter string no. 1: ");
scanf("%s", string1);
printf("Please enter string no. 2: ");
scanf("%s", string2);
mergedString = merge_strings(string1, string2);
printf("%s \n", mergedString);

free(string1);
free(string2);
free(mergedString);
}

bohan.c:

#include <stdio.h>
#include <stdlib.h>
#include "bohan.h"

int checkNumberOfChars(char* text) {
int sum = 0;
if (text == NULL)
    return 0;
while (*text != '\0')
{
    sum++;
    text++;
}
return sum;
}

char* merge_strings(char* text1, char* text2) {
int i;
int hasChanged;
char* stringToReturn;
if (text1 == NULL && text2 == NULL)
    return NULL;
stringToReturn = (char *)malloc(checkNumberOfChars(text1) + checkNumberOfChars(text2) + 1);
if (stringToReturn == NULL)
    return NULL;
for (i = 1; i <= MAX_ASCII; i++) {
    hasChanged = FALSE;
    if (*text1 != '\0' || *text2 != '\0') {
        if (*text1 != '\0') {
            if (i == *text1) {
                *stringToReturn = i;
                stringToReturn++;
                hasChanged = TRUE;
                while (*text1 == i)
                    text1++;
            }
        }
        if (*text2 != '\0') {
            if (i == *text2) {
                if (!hasChanged) {
                *stringToReturn = i;
                stringToReturn++;
                }
                while (*text2 == i)
                    text2++;
            }
        }
    }
    else
        break;
}
return stringToReturn;
}

bohan.h:

#ifndef DEF
#define TRUE 1
#define FALSE 0
#define MAX_TEXT 100
#define MAX_ASCII 255

int checkNumberOfChars(char *text);
char *merge_strings(char *text1, char *text2);

#endif DEF
Django Freeman
  • 81
  • 1
  • 2
  • 9
  • 2
    There are several rather odd things about your code, some of them surely flaws, but likely the one that is causing the trouble you asked about is your failure to ensure that the merged string has a terminator (for which you must also ensure space is allocated). – John Bollinger Dec 02 '15 at 15:09
  • Why do you re-implement `strlen()`? That's just insane. if you have `malloc()`, you surely have `strlen()`. Aargh. Also, [please don't cast the return value of `malloc()` in C](http://stackoverflow.com/a/605858/28169). – unwind Dec 02 '15 at 16:04
  • I'm kinda new to C, and I get to know new methods and stuff every day.. I'm not sure my lecturer told me about strlen().. but he saw my code and he didnt tell me anything about it.. in fact he wrote a similar function.. John, could you please tell me what else is bad in the code? I like to improve :) – Django Freeman Dec 02 '15 at 18:29

1 Answers1

2

In the merge_strings method you must define a pointer (beginOfStringToReturn) to hold the address of the beginning of the merged string. The merge_strings method should return this pointer at the end. Also add '\0' after the merged string has been built.

char* merge_strings(char* text1, char* text2) {
int i;
int hasChanged;
char* stringToReturn;
if (text1 == NULL && text2 == NULL)
    return NULL;
stringToReturn = (char *)malloc(checkNumberOfChars(text1) + checkNumberOfChars(text2) + 1);
char* beginOfStringToReturn = stringToReturn;
if (stringToReturn == NULL)
    return NULL;
for (i = 1; i <= MAX_ASCII; i++) {
    hasChanged = FALSE;
if (*text1 != '\0' || *text2 != '\0') {
    if (*text1 != '\0') {
        if (i == *text1) {
            *stringToReturn = i;
            stringToReturn++;
            hasChanged = TRUE;
            while (*text1 == i)
                text1++;
        }
    }
    if (*text2 != '\0') {
        if (i == *text2) {
            if (!hasChanged) {
            *stringToReturn = i;
            stringToReturn++;
            }
            while (*text2 == i)
                text2++;
        }
    }
}
else
    break;
}
*stringToReturn = '\0';
return beginOfStringToReturn;
}

In bohan.h include the guard like this:

#ifndef BOHAN_H
#define BOHAN_H
#define TRUE 1
#define FALSE 0
#define MAX_TEXT 100
#define MAX_ASCII 255

int checkNumberOfChars(char *text);
char *merge_strings(char *text1, char *text2);

#endif
Peter
  • 213
  • 2
  • 5
  • 14
  • Your method checkNumberOfChars works fine but, like @unwind suggested, you could use the C library function size_t strlen(const char *str) like this `stringToReturn = (char *)malloc(strlen(text1) + strlen(text2) + 1);` Just make sure to include the library `#include ` in bohan.c. – Peter Dec 02 '15 at 16:17
  • Thanks for the answer. What does stringToReturn = '\0' do? dont I need to add it somehow like this: *stringToReturn = '\0' ? – Django Freeman Dec 02 '15 at 18:33
  • It now works, but adds garbage at the end of the string.. when I added a * before the stringToReturn = '\0' it worked and printed it just right – Django Freeman Dec 02 '15 at 18:58
  • 1
    yes, it should be `*stringToReturn='\0'`. It adds the null terminator at the end of the string. It basically marks where the string ends. The string begins at the address specified by beginOfStringToReturn and ends where the null terminator '\0' is encountered. That is why `printf("%s \n", mergedString);` is able to print the string. You provide it the start address mergedString and it will print the content until the null terminator '\0' is encountered. – Peter Dec 03 '15 at 14:20