I am creating an abstract data type for strings implementing the string functions but not using the string library. I have my .c file and my .h file below. The problem seems to lie in addMystring I have commented out the area's that seem to have the problem. when they are not commented out I have a segmentation fault. though, it should work, so I believe that theres something wrong with my resizing functions, though I cannot figure out what. If someone could tell me what I am doing wrong I would appreciate it!

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

# define bool int
# define true 1
# define false 0

typedef struct 
{
	int length;
	int capacity;
	char* data;
	}MyString;


int stringlen(char*);
void doubleMyString(MyString*);
void halfMyString(MyString*);
//     Implementation/Process:
//     Takes in an address of a string of type MyString, and sets length to 0, capacity //to 10
//     and data pointing to 10 bytes of memory. If the character array for data isn't //null then
//     true is returned.
bool initMyString( MyString* aStr )
{
	aStr= (MyString*)malloc(sizeof(MyString));
	aStr->length= 0;
	aStr->capacity = 10;
	aStr->data = (char*)malloc(sizeof(char)*10);

	if(aStr->data==NULL)
		return false;
	else
		return true;

}
//If the character string is larger than the capaicity of the MyString then the string is //doubled
void doubleMyString(MyString* aStr)
{
	char* temp;
	int i;

		temp= (char*)malloc(sizeof(char)*aStr->capacity*2);
		
		for( i=0; i< aStr->length; i++)
		{
			temp[i]=aStr->data[i];
		}
		
		temp[i]='\0';

		aStr->capacity*=2;
		
		free( aStr->data); 
		aStr-> data =temp;
		
}

void halfMyString(MyString* aStr)
{
//if the character string is less than 25% of the capacity of the MyString string then //the memory is halved
	int i;
	char* temp;

	temp= (char*)malloc(sizeof(char)*aStr->capacity/2);

	for(i=0; i< aStr->length; i++)

	{
		temp[i]= aStr->data[i];
	}
	
	temp[i] = '\0';

	aStr->capacity/=4;

	free(aStr->data);
	aStr->data= temp;
	
}

bool copyMyString( MyString* aStr, char* cStr)
{
// Takes in a pointer to a MyString string and a pointer to a character string, the //values in the character string are copied into the MyString string.
//True is returned if the string is allocated correctly.
	int i, length;
	
	aStr->data =(char*)malloc(sizeof(char)*10);
	length= stringlen(cStr) +1;

	if (length >= (aStr->capacity-aStr->length))
		while (length <= aStr->capacity- aStr->length)
		{
			doubleMyString(aStr);
		}
	else if (length < (aStr->capacity/4)-aStr->length)
		while(length < (aStr->capacity/4) - aStr->length)
		{		
			halfMyString(aStr);
		}
	
	i= 0; 
	while(cStr[i] !='\0')
	{
		aStr->data[i] = cStr[i];
		i++;
	}
		aStr->data[i]='\0';
		
		if (aStr->data !=NULL)
		return true;
}

bool addMyString(MyString* aStr, char ch)
{
//     Takes in a pointer of a string of type MyString and adds a character to the end of //the string. If there is not enough memory allocated to hold the character then the //capacity is doubled.
	int length= aStr->length;
	printf("%d",aStr->length);
	//aStr->data[length]=ch;
	//aStr->data[length +1]='\0'; 
	aStr->length+=2;
	
	if ((aStr->length) >= (aStr->capacity))
	{
		//doubleMyString(aStr);
	}

	if (aStr->data!=NULL)
		return true;
}

bool catMyString( MyString* aStr , char* cStr)
{
//     Takes in a pointer of a string of type MyString and a pointer to a string and 
//     concatenates the string to the end of the MyString string. If MyString isn't null
//     true is returned. 
	int i;
	for(i=0 ; i< stringlen(cStr); i++)
	{	
		addMyString(aStr, cStr[i]);
	}
	
	aStr->data[i] = '\0'; 

	if ( aStr->data != NULL)
		return true;
		
}

bool readMyString( MyString* aStr, FILE* inFile, char delimit, int number)
{

//     Takes in a pointer of a string of type MyString and a pointer to a file, the //characters from a file are read into the MyString, if there is not enough space, the //string is doubled. If the string isn't null, true is returned. 
	int i=0;

	while((getc(inFile)!=EOF)|(i==number))
	{
		addMyString(aStr,getc(inFile));
		i++;
	}

	if ( aStr->data != NULL)
		return true;
}

void destroyMyString( MyString* aStr)
{
//     Takes in a pointer of a string of type MyString and frees the memory allocated for
//     the string and sets the data members to their initial states. 
	free(aStr->data);
}

int stringlen(char* Str)
{
	int i=0;

	while(Str[i] != '\0')
	{
		i++;
	}
	
	return i;
}

here is my .h file

# define bool int
# define true 1
# define false 0

typedef struct 
{
	int length;
	int capacity;
	char* data;
	}MyString;


bool initMyString( MyString* );
bool copyMyString( MyString* , char*);
bool addMyString(MyString*, char);
bool catMyString( MyString*, char*);
bool readMyString( MyString*, FILE*, char, int);
void destroyMyString( MyString* );

I quickly looked at your 'addMyString' function...Your adding the character before you check the capacity. Shouldn't it be the other way around?

Edited 5 Years Ago by gerard4143: n/a

I see quite a few issues, but the most immediate is a misunderstanding of how pointers work when passed to a function. Your initMyString will completely fail to do what you're expecting because the parameter is a copy of the argument, not a reference to it.

See this article for more details. Fix that and we can talk about further issues. ;)

I see quite a few issues, but the most immediate is a misunderstanding of how pointers work when passed to a function. Your initMyString will completely fail to do what you're expecting because the parameter is a copy of the argument, not a reference to it.

See this article for more details. Fix that and we can talk about further issues. ;)

so, I believe this should work?

bool initMyString(MyString ** aStr )
{
	*aStr= (MyString*)malloc(sizeof(MyString));
	*aStr->length= 0;
	*aStr->capacity = 10;
	*aStr->data = (char*)malloc(sizeof(char)*10);

	if(*aStr->data==NULL)
		return false;
	else
		return true;

}

though I'm still confused about copies. so when you pass in a pointer to a pointer, and you dereference it you just have a pointer, then you allocate memory to it right? what I had before was just a pointer, then allocating memory to the address? or well the page said to a copy of the pointer. but if you're passing in the address of a pointer, how is that a copy of the pointer?

>but if you're passing in the address of a pointer, how is that a copy of the pointer?
Pointers aren't magic. A pointer is just a variable, and the value of that variable is an address. You wouldn't expect the following to print 12345, would you? The idea is exactly the same:

#include <stdio.h>

void foo(int x)
{
    x = 12345;
}

int main(void)
{
    int x = 0;

    foo(x);
    printf("%d\n", x);

    return 0;
}

Adding a level of indirection seems to make people forget the most fundamental concepts of C.

yes, that is understood but, my requirement is this:

bool initMyString( MyString* aStr )

Initializes the MyString with ten capacity, zero length, and pointing to 10 bytes of memory.

if I'm required to pass in a pointer I don't see how I can pass in a pointer to a pointer unless I change the function parameters. Unfortunately I can't find any examples of how ADT's work so obviously I have no idea what I'm doing.

>if I'm required to pass in a pointer I don't see how I can pass in a pointer to a pointer
If you're being passed a pointer, simply assume that it already points to a valid object. You don't need to call malloc on aStr, but you do need to malloc aStr->data .

>Unfortunately I can't find any examples of how ADT's work so obviously I have no idea what I'm doing.
You can find several ADT examples in the libraries section here. They're serious libraries though, not student examples, so they may or may not be helpful.

okay, thank you, that was helpful.
I see I was just allocating memory where there was no need for me to be doing so.

This article has been dead for over six months. Start a new discussion instead.