繁体   English   中英

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

[英]C - char array getting phantom values after memset

我的程序逐行读取一个文本文件,并打印出每个句子行中最大的单词。 但是,有时它们会打印出先前的最高单词,尽管它们与当前句子无关,并且我在处理每一行的最后都重置了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句的长度时,最后一个单词有时会变成“ reallyrelonglongword”,这很奇怪。

编辑:即使我注释掉MEMSET我仍然得到相同的结果,所以它可能与memset没有任何关系,但不能完全确定

尾随的NULL字节(\\ 0)是字符串操作的祸根。 您有一个复制序列不能完全满足您的期望:

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

句子被复制到sub中,然后再次返回。 除非strncpy不会从句子中复制'\\ 0'。 当您将字符串从sub中复制回句子中时,就是在将未知长度的数据复制回句子中。 由于堆栈已被重用且char数组未初始化,因此数据很可能驻留在先前的迭代中,因此可以在下一次执行时看到。

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

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

您缺少一个空终止符。

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

当您使用strncpy ,如果src大于要复制的字符数,则不添加空终止符。 您已经保证是这种情况,因此sub没有终结符,并且您会迅速遇到不需要的行为。 看起来您正在尝试修剪字符串中的最后一个字符; 更简单的方法是将索引strlen(sentence)-1处的字符设置为'\\0'

这不好:

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,则将删除输入字符)。

在下面找到更正的代码

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

确保文件最后关闭。 这是一个好习惯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM