C-char数组在memset之后获取幻象值
我的程序逐行读取文本文件,并打印出每行句子中最大的单词。然而,它有时会打印出前面最高的单词,尽管它们与当前句子无关,并且我在处理每一行的末尾重置了我的字符数组。有人能向我解释一下记忆中发生了什么使这一切发生吗?谢谢C-char数组在memset之后获取幻象值,c,arrays,char,C,Arrays,Char,我的程序逐行读取文本文件,并打印出每行句子中最大的单词。然而,它有时会打印出前面最高的单词,尽管它们与当前句子无关,并且我在处理每一行的末尾重置了我的字符数组。有人能向我解释一下记忆中发生了什么使这一切发生吗?谢谢 //Program Written and Designed by R.Sharpe //LONGEST WORD CHALLENGE //Purpose: Find the longest word in a sentence #include <stdio.h> #
//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
another
reallyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword
BillGatesSteveJobsWozWasMagnificantllyreallylongword //should be billy
有时,当我随意改变第五句的长度时,最后一个词也会改变
结果是“真正的长单词”,这很奇怪。
编辑:即使我对MEMSET进行注释,我仍然会得到相同的结果,因此它可能与MEMSET无关,但不能完全确定尾随空字节(\0)是字符串操作的祸根。您有一个复制序列,但它并不是您想要的:
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
句子被复制成子句,然后再复制回来。除此之外,strncpy不会从句子中复制“\0”。当您将字符串从sub复制回句子中时,您正在将未知长度的数据复制回句子中。因为堆栈被重用,而字符数组未初始化,所以数据可能在上一次迭代中驻留在那里,因此在下一次执行时可以看到
在两个strcpy之间添加以下内容可修复此问题:
sub[strlen(sentence) - 1] = '\0';
尾随的空字节(\0)是字符串操作的祸根。您有一个复制序列,但它并不是您想要的:
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
句子被复制成子句,然后再复制回来。除此之外,strncpy不会从句子中复制“\0”。当您将字符串从sub复制回句子中时,您正在将未知长度的数据复制回句子中。因为堆栈被重用,而字符数组未初始化,所以数据可能在上一次迭代中驻留在那里,因此在下一次执行时可以看到
在两个strcpy之间添加以下内容可修复此问题:
sub[strlen(sentence) - 1] = '\0';
您缺少一个空终止符
char sub[100];
char maxWord[100];
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
当您
strncpy
时,如果src大于要复制的字符数,则不会添加空终止符。您已经保证了这种情况,因此sub
没有终止符,您很快就会遇到不想要的行为。看起来您正试图从字符串中删除最后一个字符;更简单的方法是将索引strlen(句子)-1处的字符设置为'\0'
缺少空终止符
char sub[100];
char maxWord[100];
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
当您strncpy
时,如果src大于要复制的字符数,则不会添加空终止符。您已经保证了这种情况,因此sub
没有终止符,您很快就会遇到不想要的行为。看起来您正试图从字符串中删除最后一个字符;更简单的方法是将索引strlen(句子)-1中的字符设置为'\0'
这很糟糕:
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
如果源字符串不合适,strncpy
函数不为null并终止其缓冲区。通过执行strlen(句子)-1,您保证它不合适。然后,strcpy
会导致未定义的行为,因为sub
不是字符串
我的建议是不要使用strncpy,它几乎从来都不是解决问题的好方法。使用strcpy
或snprintf
在这种情况下,您甚至从不使用sub
,因此可以将这些行替换为:
sentence[ strlen(sentence) - 1 ] = 0;
其作用是删除fgets留下的一端的\n
。(如果输入长度超过100,则会删除输入的一个字符)。这是错误的:
strncpy(sub, sentence, strlen(sentence)-1);
strcpy(sentence, sub);
如果源字符串不合适,strncpy
函数不为null并终止其缓冲区。通过执行strlen(句子)-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;
}
确保文件在结尾处已关闭。这是一种很好的做法。在下面找到正确的代码
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;
}
确保文件在结尾处已关闭。这是一个很好的做法。我补充说,它没有改变任何东西。旁注,您可以更简单地将句子的最后一个字符设置为
\0
strncpy(sub,句子,strlen(句子)-1)代码>创建未终止的数组,因为您禁止它写入终止字符串所需的null。您不能将其传递给字符串函数,但这正是您在下一行所做的。我补充说,它没有改变任何内容。请注意,您可以更简单地将句子的最后一个字符设置为\0
strncpy(sub,句子,strlen(句子)-1)代码>创建未终止的数组,因为您禁止它写入终止字符串所需的null。您不能将其传递给字符串函数,但这正是您在下一行中所做的。因此,空终止符字符是否与换行符一起包含在字符数组的大小中?i、 e.strlen(句子)=对于所有字符+'/n'+'/0'?@user3312266在计算strlen
时,字符串中除了'\0'
之外的所有内容都包括在内,因此strlen(句子)=对于所有字符+'/n'。字符数组的大小中是否包括空终止符字符以及换行符?i、 e.strlen(句子)=所有字符+'/n'+'