program behaves strange

I have this structure:

1
2
3
4
5
struct elementtype{
	int				elementcount;
	char			*str[10];
	int				size;
};


Then I have this function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
elementtype test(char* str_contend){

	char *token, *tmp;
	int i = 0;
	elementtype element = InitializeElement(element);
	strcpy(tmp, str_contend);

	token = strtok (tmp,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;
	i++;
	token = strtok (NULL,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;
	i++;
	token = strtok (NULL,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;

	return element;
}


This function is called from main()

1
2
3
4
5
6
7
8
9
int main(int argc, char *argv[]){

	elementtype element = InitializeElement(element);
	
	element = test("a;b;c;d;e;f;g;h;i;j");
	cout << "main: " << element.str[0] << endl;
	cout << "main: " << element.str[1] << endl;
	cout << "main: " << element.str[2] << endl;
}

The resulting output for this program is:
test: a
test: b
test: c
main: a
main: b
main: c


So this code works. But this code requires me to repeat the same statement
1
2
3
4
	i++;
	token = strtok (NULL,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;

over and over again, for as much pointers are in element.str[].

But trying to work this code into a loop [neither for() nor while()] did not work. It even makes my program crash instantly when test() is called;

I can't see whats wrong with this code or where the difference between these two code is (except that repeating the same instruction programaticly instead by hand before compiling).

Can anybody give me at least a clue on why the loop version did not work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
elementtype test(char* str_contend){

	char *token, *tmp;
	int i = 0;
	elementtype element = InitializeElement(element);
	strcpy(tmp, str_contend);

	token = strtok (tmp,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;

	while(i < 3){
		i++;
		token = strtok (NULL,";");
		element.str[i] = token;
		cout << "test: " << element.str[i] << endl;
	}
//	i++;
//	token = strtok (NULL,";");
//	element.str[i] = token;
//	cout << "test: " << element.str[i] << endl;

	return element;
}


Last edited on
elementtype element = InitializeElement(element);
Ugh.

Your loop is running one time too many.
How can it be running one time to many?

The string that should get split is "a;b;c;d;e;f;g;h;i;j", so strtok (NULL,";") can be called 9 times. I did it only 2 times. even setting i=0 and
1
2
3
while(i < 1){
i++;
}

without doing anything in the loop, except incrementin i, crashes the program.

as for

elementtype element = InitializeElement(element);

I didn't like it myself, but I didn't get it to work as

void InitializeElement(element)
Last edited on
Ok, it seems that calling

elementtype element = InitializeElement(element);

is doing something very nasty.

When i start a loop (even if it's doing absolutly nothing like an empty for(i = 0; i < 1; i++){}) after calling InitializeElement() the program goes boom.

Is something dangerous or false that I'm doing here?

1
2
3
4
5
6
7
elementtype InitializeElement(elementtype el){

	el.size = 10;
	el.elementcount = 0;

	return el;
}
Last edited on
void InitializeElement(element) would work, you just have to pass the data by reference (or pass a pointer to it). Put a '&' like this:

void InitializeElement(elementtype &element/*or whatever you want to name it*/)

Btw, I would like to see the initialization function (again XP)

1
2
3
4
5
	char *token, *tmp;
	int i = 0;
	elementtype element = InitializeElement(element);
	strcpy(tmp, str_contend); //???????
I copy the chararray because i wasn't quite sure if strtok creates new char* and copy the created contend to this new memory or if it just replaces the delimiter with '\0' in memory and produces pointer with adress of memory just beyound that '\0' for next token.
Last edited on
I don't think any of the functions in the C library allocate memory (except for the memory allocation functions, of course). strtok() is no exception.
Ok, finally I got it to work.
Thanks at firedraco, that did the trick for the InitializeElement() function.
Now it's

1
2
3
4
5
6
7
8
void InitializeElement(elementtype &el){

	el.size = sizeof(el.str) / sizeof(el.str[0]);
	for(int i = 0; i < el.size; i++){
		el.str[i] = "\0";
	}
	el.elementcount = 0;
}


and works just perfect, thanks.

But the original problem seems to be a mixture of the dumbass before th screen (that's me) and the compiler.

I wonder why it let me slip this code

1
2
3
4
5
6
elementtype test(char* str_contend){

	char *token, *tmp;
	int i = 0;
	elementtype element = InitializeElement(element);
	strcpy(tmp, str_contend);


in version without a loop and didn't when a loop is present.
Had to change it the way I normaly handle chararrays. Did thought could be lazy this time, big error. Its like helios said, no memory allocation by its own.

1
2
3
4
char *token, *tmp;
...
tmp = (char*)calloc(strlen(str_contend)+1, sizeof(char));
strncpy(tmp, str_contend, strlen(str_contend));


Thanks guestgulkan, I just realized this error because you wondered what I'm doing with strcpy().
Last edited on
I was thinking "uninitialised pointer" with regard to tmp
Yes, but strangly enough this works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
elementtype test(char* str_contend){

	char *token, *tmp;
	int i = 0;
	elementtype element = InitializeElement(element);
	strcpy(tmp, str_contend);

	token = strtok (tmp,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;
	i++;
	token = strtok (NULL,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;
	i++;
	token = strtok (NULL,";");
	element.str[i] = token;
	cout << "test: " << element.str[i] << endl;

	return element;
}


No memory allocation either.
It's working by nothing more than pure luck. Sooner or later, that code will fail.
Topic archived. No new replies allowed.