954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

String ADT

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* );
Castiel1631
Newbie Poster
9 posts since Sep 2010
Reputation Points: 10
Solved Threads: 0
 

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

gerard4143
Nearly a Posting Maven
2,272 posts since Jan 2008
Reputation Points: 512
Solved Threads: 387
 

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. ;)

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

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?

Castiel1631
Newbie Poster
9 posts since Sep 2010
Reputation Points: 10
Solved Threads: 0
 

>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.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

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.

Castiel1631
Newbie Poster
9 posts since Sep 2010
Reputation Points: 10
Solved Threads: 0
 

>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.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

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

Castiel1631
Newbie Poster
9 posts since Sep 2010
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: