[英]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
,这几乎永远不是解决问题的好方法。 使用strcpy
或snprintf
。
在这种情况下,您甚至都不会使用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.