user3312266
user3312266

Reputation: 189

C - char array getting phantom values after memset

My program reads in a text file line by line and prints out the largest word in each sentence line. However, it sometimes prints out previous highest words although they have nothing to do with the current sentence and I reset my char array at the end of processing each line. Can someone explain to me what is happening in memory to make this happen? Thanks.

//Program Written and Designed by R.Sharpe
//LONGEST WORD CHALLENGE
//Purpose: Find the longest word in a sentence

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

int main(int argc, char** argv)
{
    FILE* file;
    file = fopen(argv[1], "r");
    char* sentence = (char*)malloc(100*sizeof(char));
    while(fgets(sentence, 100, file) != NULL)
    {
        //printf("%s\n", sentence);
        char sub[100];
        char maxWord[100];
        strncpy(sub, sentence, strlen(sentence)-1);
        strcpy(sentence, sub);
        char* word;
        int maxLength = 0;
        word = strtok(sentence, " ");
        while(word != NULL)
        {
            if(strlen(word) > maxLength)
            {
                maxLength = strlen(word);
                strcpy(maxWord, word);
                //printf("%s\n", maxWord);
            }
            word = strtok(NULL, " ");
        }
        printf("%s\n", maxWord);
        memset(maxWord, 0, sizeof(char));
        maxLength = 0; //reset for next sentence;
    }
    free(sentence);
    return 0; 
}

my text file contains . .

some line with text
another line of words
Jimmy John took the a apple and something reallyreallylongword it was nonsense
test test BillGatesSteveJobsWozWasMagnificant
a b billy

the output of the program is . .

some
another
reallyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword //should be billy

Also when I arbitrarily change the length of the 5th sentence the last word sometimes comes out to be "reallyreallylongword" which is odd.

EDIT: Even when I comment MEMSET out I still get the same result so it may not have anything to do with memset but not completely sure

Upvotes: 1

Views: 661

Answers (4)

mahendiran.b
mahendiran.b

Reputation: 1323

Find the corrected code in below

int main(int argc, char** argv)
{
    FILE* file;
    file = fopen(argv[1], "r");
     char sub[100];
     char maxWord[100];
      char* word;
      int maxLength = 0;

    char* sentence = (char*)malloc(100*sizeof(char));

    while(fgets(sentence, 100, file) != NULL)
    {
        maxLength = 0;
        strncpy(sub, sentence, strlen(sentence)-1);
        sub[strlen(sentence) - 1] = '\0'; //Fix1
        strcpy(sentence, sub);
        word = strtok(sentence, " ");

        while(word != NULL)
        {

            if(strlen(word) > maxLength)
            {
                maxLength = strlen(word);
                strcpy(maxWord, word);

            }
                    word = strtok(NULL, " ");

        }
        printf("%s\n", maxWord);
        memset(maxWord, 0, sizeof(char));
        maxLength = 0; //reset for next sentence;
    }
    free(sentence);
    fclose (file); //Fix2
    return 0; 
}

Ensure that the file is closed at the end. It is good practice.

Upvotes: 0

M.M
M.M

Reputation: 141564

This is bad:

strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);

The strncpy function does not null-terminate its buffer if the source string doesn't fit. By doing strlen(sentence)-1 you guaranteed it doesn't fit. Then the strcpy causes undefined behaviour because sub isn't a string.

My advice is to not use strncpy, it is almost never a good solution to a problem. Use strcpy or snprintf.

In this case you never even use sub so you could replace these lines with:

sentence[ strlen(sentence) - 1 ] = 0;

which has the effect of removing the \n on the end that was left by fgets. (If the input was longer than 100 then this deletes a character of input).

Upvotes: 1

Mike Precup
Mike Precup

Reputation: 4218

You've got a missing null terminator.

char sub[100];
char maxWord[100];
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);

When you strncpy, if src is longer than the number of characters to be copied, no null terminator is added. You've guaranteed this is the case, so sub has no terminator, and you're rapidly running into behavior you don't want. It looks like you're trying to trim the last character from the string; the easier way to do that is simply set the character at index strlen(sentence)-1 to '\0'.

Upvotes: 1

Brian
Brian

Reputation: 2813

Trailing NULL bytes (\0) are the bane of string manipulation. You have a copy sequence that is not quite doing what you desire of it:

    strncpy(sub, sentence, strlen(sentence)-1);
    strcpy(sentence, sub);

Sentence is copied into sub, and then back again. Except, strncpy does not copy the '\0' out of sentence. When you copy the string from sub back into sentence, you are copying an unknown length of data back into sentence. Because the stack is being reused and the char arrays are uninitialized, the data is likely residing there from the previous iteration and thus being seen by the next execution.

Adding the following between the two strcpys fixes the problem:

sub[strlen(sentence) - 1] = '\0';

Upvotes: 3

Related Questions