PDA

View Full Version : strings aaaaaaaaaaarghhhhhhhhh


stefanhendriks
08-04-2004, 00:31
I am getting nuts of this! Especially because i do the same thing twice, and one works one does not.

Okay, let me explain. I have a string, 80 characters, declared as:


class cChatEngine
{
public:
// variables
tReplyBlock ReplyBlock[MAX_BLOCKS]; // 100 reply blocks reserved in memory
float fThinkTimer; // The chatengine has a 'think timer'.
char sender[30];
char sentence[80];

// functions
void init(); // initialize database/blocks
void load(); // load database (loads blocks)
void think(); // make the chat engine think
bool cChatEngine::CompareNames(char name[30], char name2[30], int length);
// add sentence from any player/bot into memory to handle
void set_sentence(char *sender, char *sentence);
// handles a sentence, decides to reply on it or not.
void handle_sentence();
};


As you can see above, there is:

char sentence[80];

this one gets initialized:

sentence[0] = '\0';

in init();

So far so good, it gets filled in when a user says something (intercepting SayText, this also works okay (btw, code partially just copied from podbot source as i wont invent the wheel twice):


void BotClient_CS_SayText(void *p, int bot_index)
{
static unsigned char ucEntIndex;
static int state = 0; // current state machine state
if (state == 0)
{
ucEntIndex = *(unsigned char *)p;
}
else if (state == 1)
{
cBot *pBot=&bots[bot_index];
if(ENTINDEX(pBot->pEdict) != ucEntIndex)
{
char sentence[80];
char chSentence[80];
char netname[30];
strcpy(sentence,(char *)p);
// remove first part of sentence.
int length = strlen (sentence) - strlen (strstr (sentence, " : "));

int tc=0;
for (int c=length; c < 80; c++)
{
chSentence[tc] = sentence[c];
tc++;
}
//strncpy (chSentence, (char *)sentence[length], 80-length);
strcpy(netname, STRING(pBot->pEdict->v.netname));

ChatEngine.set_sentence(netname, chSentence);
}
}
state++;
}



Now do not ask me why i use so many different types of 'copying the string'. THis is because my problem will be described soon and i tried multiple manners of copying/reading strings.

Okay, now, the set_sentence function:

void cChatEngine::set_sentence(char csender[30], char csentence[80])
{
if (sender[0] == '\0')
{
sprintf(sender, "%s", csender);
sprintf(sentence, "%s", csentence);
}
else
SERVER_PRINT("Tried to set sentence while we did not handle it yet");
}


Works fine as well,

here is the problem!!!:

as soon as i try to read ONE character from the line, it does not work, ie:


sprintf(msg, "%s", sentence[1]);


this will compile fine, but will CRASH in half-life/steam in this line!. When you try to do this:

sprintf(msg, "%s", &sentence[1]);


it compiles, and it will simply give me the string starting from 1. This does NOT crash:

Now here is a little code that should check the sentence PER CHARACTER, and then copy characters into words. I know it should work, because i have a function working almost the same way (it reads out the character the same way) and i do not have trouble there.


// Scan the message so we know in what block we should be to reply:
char word[20];
int c=0;
for (c=0; c < 20; c++)
word[c] = '\0';
c=0;
int wc=0;
int length = strlen(sentence);
if (length == 0 || length > 80)
{
SERVER_PRINT("PROBLEM!");
return;
}
int WordBlockScore[MAX_BLOCKS];
for (int wbs=0; wbs < MAX_BLOCKS; wbs++)
WordBlockScore[wbs] = -1;
char chSentence[80];
sprintf(chSentence, "%s", sentence);

// C
while (c < length)
{
// get out
if (c >= length)
break;
if (c < 0)
break;
if (sentence[c] == '\0')
{
c++;
SERVER_PRINT("Found weird thingy, breaking out");
break;
}

//////////// PROOOOBBBBLLEEEEEM
///// here i get tons of messages "this is not a good word". It says word is zero length!
//// It seems like the sentence is read out entirely with empty strings or something? The sentence starts with a letter and still it goes into this IF block (after several checks).
// SOMEHOW I NEED TO READ THE CHARACTER AND I GET NUTS, IT SHOULD BE SIMPLE AND STILL IT DOES NOT WORK , I GET FUCKING NUTS ABOUT THIS. I SPENT THE FREAKING WHOLE DAY ON THIS MINOR PROBLEM AND IT SHOULD JUST WORK ARH. Its getting late. darn.
if (sentence[c] == ' ');
{
// done with this word, find it in one of our blocks and give the block
// that score:
if (strlen(word) <= 0)
{
SERVER_PRINT("This is not a good word!\n");
}
else
{
for (int iB=0; iB < MAX_BLOCKS; iB++)
{
if (ReplyBlock[iB].bUsed)
{
for (int iBw=0; iBw < 10; iBw++)
{
// add score
if (strcmp(ReplyBlock[iB].word[iBw], word) == 0)
{
char msg[80];
sprintf(msg, "Compared words: %s and %s -> added score to block %d\n", ReplyBlock[iB].word[iBw], word, iB);
SERVER_PRINT(msg);

WordBlockScore[iB]++;

}
}
}
}
}
// new word:
word[0] = '\0';
wc=0;
c++;
continue;
}
// fill in the word:
word[wc] = sentence[c];
c++;
wc++;
}
// now loop through all blocks and find the one with the most score:
int iMaxScore=-1;
int iTheBlock=-1;
for (int rB=0; rB < MAX_BLOCKS; rB++)
{
if (WordBlockScore[rB] > iMaxScore)
{
iMaxScore = WordBlockScore[rB];
iTheBlock = rB;
}
}
if (iTheBlock > -1)
{
char msg[80];
sprintf(msg, "Choosen to reply from Block %d", iTheBlock);
SERVER_PRINT(msg);
}


okay, obvious question:
- does anybody know what is wrong?
- does anybody know why this function does work, but the above not?:

void
INI_Word (char input[80], char word[25])
{
int pos = 0;
int word_pos = -1;
// clear out entire string
for (int i = 0; i < 25; i++)
word[i] = '\0';
while (pos < 79)
{
if (input[pos] == '=')
{
word_pos = pos;
break;
}
pos++;
}
if (word_pos > -1 && word_pos < 23)
{
for (int wc = 0; wc < word_pos; wc++)
word[wc] = input[wc];
word[word_pos] = '\0'; // terminate string
}
}

KickBot
08-04-2004, 01:01
Just scanned your code and found this typo where you seem to have located your problem:

if (sentence[c] == ' ');
{
...

the extra ; might be a nuisance 8o :D

I didn't check the code seriously but if all you do is string copying you could just use strcpy() instead of the combo sprintf(sTo,"%s",sFrom).

Hope this helps. I'm going to bed now too. Goodnight :)

MusicMan
08-04-2004, 01:02
Now I am not a geek at C++ but it looks like you declared "word[c]" to be '\0' and your problem comes when "strlen(word)" is less than or equal to "0" which is NULL right?. Just trying to help but dont think that I am:D

MusicMan

Artello
08-04-2004, 01:08
Hm, you are declared word[c] initialized it to be zero-string, never changed its value ... it always be with zero length :) That is why you are gettin tons of messages "this is not a good word"

Pierre-Marie Baty
08-04-2004, 10:43
You're tired, Stefan... Get more sleep :)
here is the problem!!!:

as soon as i try to read ONE character from the line, it does not work, ie:sprintf(msg, "%s", sentence[1]);...might work better if you were doing
sprintf (msg, "%c", sentence[1]);
instead, hmmm ? :)

If you do
sprintf (msg, "%s", sentence[1]);
and your "sentence" is something like "Hello my name is Stefan\n", you ask printf() to print out the STRING ("%s") that starts at the ADDRESS described by the 2nd element in the sentence[] array, that is, sentence[1] being 'ello' (since an int does 4 bytes), printf() will go and look for a string at address 0x656c6c7f (which is "ello" in hex) in memory, which is probably not what you want it to do !!!

stefanhendriks
08-04-2004, 11:20
Kickbot, i love ya. PMB you too!

The ; already caused tons of problems. I removed the ; and it already gives me only a few "not a good word" thingies. PMB, the character printing now works too so it does not crash. phew.

Okay, now i know the function grabs words okay, it only does not recognize them yet. but i think i can manage from here. If not i'll let ya know :)

Cheeseh
08-04-2004, 14:17
always use char pointers (char*) in function parameters, makes it easier for me :P

stefanhendriks
08-04-2004, 16:29
In writing its easier, but i'd rather know what i allocate instead of using pointers and 'can be any size' chars.

Rick
08-04-2004, 19:05
sprintf (msg, "%c", sentence[1]);
Actually I think msg[0] = sentence[1] is more efficient :)

@$3.1415rin
08-04-2004, 19:28
as long as you don't wanna change msg any more ...

botmeister
08-04-2004, 19:29
If you are into C++ programming, then why not make use of the standard string class? It works nicely and is far simpler than using character arrays.

Rick
08-04-2004, 19:44
as long as you don't wanna change msg any more ...
Why?? I think its basicly just the same but you save a function call.

@$3.1415rin
08-04-2004, 20:57
oops, sorry, I was thinking in terms of pointers :)

and stefan : don't be so stupid to implement some kind of 1337 chat generator in your chat system ;) I still get mails of users telling me about this "bug" :D *g* but I leave it there ... somehow it looks cool :)