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

You'd think I would know how to use strings by now, but...

I'm getting an error (unhandled exception writing address so and so) trying to modify a string. It gets weirder though. Let me show what i've got:

--Main.c--

#include "stdafx.h"
#include "commands.h"

int main(int argc, char* argv[])
{
	char word[256];
	int id;

	strcpy(word, "move");
	strToUpper(word);
	printf("%s", word);
	id = getCommandId(word);

	if(id == -1)
		perror("Error");
	else if(id == 0)
		printf("No such command.");
	else
		printf("ID: %d\n", getCommandId("move"));

	getchar();
	return 0;
}


--commands.h--

#pragma once

#define COMMAND_MOVE 1
#define COMMAND_TAKE 2
#define COMMAND_LOOK 3

int getCommandId(char *word);
void strToUpper(char *str);


And --commands.c--

#include "stdafx.h"
#include "commands.h"

void strToUpper(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		str[i++] &= 0xDF; //reset bit 5
	}
}

int getCommandId(char *word)
{
	FILE *fp;
	char buf[256];
	char *tok;
	int i = 0;

	fp = fopen("commands.dat", "r");
	if(fp == NULL)
		return -1;
	
	strToUpper(word);

	while(++i)
	{
		if(fgets(buf, 255, fp) == NULL)
			break;

		tok = strtok(buf, " ");
		while(tok != NULL)
		{
			if(strcmp(tok, word) == 0)
				return i;

			tok = strtok(NULL, " ");
		}
	}

	return 0;
}


Nothing real exciting happens with the call to strToUpper in main, other than the string being capitalized. Then getCommandId is called, and therefore strToUpper is too, with the same pointer word as before. Only this time, I get the nasty error described at the top of my post. Thoughts?

death_oclock
Posting Whiz
393 posts since Apr 2006
Reputation Points: 129
Solved Threads: 45
 

>>str[i++] &= 0xDF; //reset bit 5
Programming is not about trying to be cute, but about writing code that you and everyone else in the world can easily comprehend.
str[i] = toupper(str[i]); ++i;

Ancient Dragon
Retired & Loving It
Team Colleague
30,043 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
 

"Being cute" was not my intention. I was thinking of efficiency at the time. And while I appreciate the suggestion, it doesn't help my immediate problem.

death_oclock
Posting Whiz
393 posts since Apr 2006
Reputation Points: 129
Solved Threads: 45
 

Do you still get the error if you remove:
* the file stuff? (replace it with a single buf load to tokenize)
* the token stuff?
Post a single file minimal version that recreates the error.

nucleon
Posting Pro in Training
478 posts since Oct 2008
Reputation Points: 163
Solved Threads: 91
 

I put your program all in one file and here is the result (using VC ++ 2008 Express)

#include <ctype.h>
#pragma warning(disable: 4996)


void strToUpper(char *str)
{
	int i = 0;
	while(str[i] != '\0')
	{
		str[i] = toupper(str[i]); //reset bit 5
        ++i;
	}
}

int getCommandId(char *word)
{
	FILE *fp;
	char buf[256];
	char *tok;
	int i = 0;

	fp = fopen("commands.txt", "r");
	if(fp == NULL)
		return -1;
	
	strToUpper(word);
    i = 0;
	while(fgets(buf, 255, fp) != NULL)
	{
        strToUpper(buf);
		tok = strtok(buf, " ");
        ++i;
		while(tok != NULL)
		{
			if(strcmp(tok, word) == 0)
				return i;

			tok = strtok(NULL, " ");
		}
	}

	return 0;
}

int main(int argc, char* argv[])
{
	char word[256];
	int id;

	strcpy(word, "move");
	strToUpper(word);
	printf("%s", word);
	id = getCommandId(word);

	if(id == -1)
		perror("Error");
	else if(id == 0)
		printf("No such command.");
	else
		printf("ID: %d\n", getCommandId("move"));

	getchar();
	return 0;
}


The main problem with the program is that main() calls getComandId() twice. In the printf() line, instead of calling getCommandId() again (line 60 of the code I posted) just use the return value from the previous call.

getCommandId() also needs to close the file before exiting, which I did NOT correct.

Ancient Dragon
Retired & Loving It
Team Colleague
30,043 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
 

Nice one AD! :)
I did not spot that call tucked away in there.
getCommandId is being called with a string literal (constant),
which it tries to modify in strToUpper:
getCommandId("move"));

nucleon
Posting Pro in Training
478 posts since Oct 2008
Reputation Points: 163
Solved Threads: 91
 

The real reason you're having problems with your code is you're trying to modify a string literal:
>printf("ID: %d\n", getCommandId("move"));

You never allocated space for "move", so who knows what strtok() and your strToUpper() function are trying to do with your computer's memory.

John A
Vampirical Lurker
Team Colleague
7,630 posts since Apr 2006
Reputation Points: 2,240
Solved Threads: 339
 

as an aside....

the plan to "reset bit 5" as a method to convert a string to uppercase will make for some fun times if the string ever contains a numeral or other non-alphabetical character.

It is indeed rather "cute".

:)


.

jephthah
Posting Maven
2,587 posts since Feb 2008
Reputation Points: 2,143
Solved Threads: 179
 

Oh wow, I forgot about the second call myself. Jepthah: point taken.

death_oclock
Posting Whiz
393 posts since Apr 2006
Reputation Points: 129
Solved Threads: 45
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You