C - char数组在memset之后获取幻像值

时间:2014-08-04 03:49:02

标签: c arrays char

我的程序逐行读入文本文件,并打印出每个句子行中最大的单词。但是,它有时打印出以前最高的单词,尽管它们与当前句子无关,我在处理每一行时重置了我的char数组。有人可以向我解释记忆中发生了什么来实现这一目标吗?感谢。

//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; 
}

我的文字文件包含。 。

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

程序的输出是。

some
another
reallyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword //should be billy

当我随意改变第5个句子的长度时,有时也会使用最后一个词 出现了&#34;真正的长篇大论&#34;这很奇怪。

编辑:即使我评论MEMSET,我仍然得到相同的结果,因此它可能与memset没有任何关系但不完全确定

4 个答案:

答案 0 :(得分:3)

尾随空字节(\ 0)是字符串操作的祸根。你有一个复制序列,它不是你想要的那样:

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

句子被复制到sub中,然后再次返回。除此之外,strncpy不会复制&#39; \ 0&#39;出于句子。将字符串从子句复制回句子时,您将未知长度的数据复制回句子。因为堆栈正在被重用并且char数组未初始化,所以数据可能位于前一次迭代中,因此可以在下次执行时看到。

在两个strcpys之间添加以下内容可以解决问题:

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

答案 1 :(得分:1)

你有一个缺少的空终止符。

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

当你strncpy时,如果src长于要复制的字符数,则不添加空终止符。你已经保证会出现这种情况,因此sub没有终止符,你很快就会遇到你不想要的行为。看起来你正试图修剪字符串中的最后一个字符;更简单的方法是将索引strlen(sentence)-1处的字符设置为'\0'

答案 2 :(得分:1)

这很糟糕:

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

如果源字符串不适合,strncpy函数不会空终止其缓冲区。通过strlen(sentence)-1,你保证它不适合。然后strcpy导致未定义的行为,因为sub不是字符串。

我的建议是不使用strncpy,它几​​乎不是解决问题的好方法。使用strcpysnprintf

在这种情况下,您甚至不会使用sub,因此您可以将这些行替换为:

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

具有删除fgets留下的\n的效果。 (如果输入超过100,则删除输入字符。)

答案 3 :(得分:0)

在下面找到更正后的代码

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; 
}

确保文件最后关闭。这是一种很好的做法。