为了仅打印文件中的重复单词,我应该怎么做。我是C的初学者。
这是我的代码:
#include <stdio.h>
#define max 100
main(){
FILE *fpointer;
char ch[max],str[max][max];
int i = 0,j = 0,count = 0;
int a,b;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," ");
count++;
}
for(a=0;a<count*2;a=a+2){
for(b=0;b<count*2;b=b+2){
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
fclose(fpointer);
return 0;
}
输入的一个例子是“闪耀的小星星在黑暗的星星中闪耀” 而这个节目的输出是“闪耀闪耀的小星星闪耀在黑暗的明星中闪耀着光芒”。请帮我打印 只有重复的单词。 Tnx
答案 0 :(得分:1)
你有几个问题。
仔细阅读并撰写评论。例如,将它们放在它们所属的位置:
// Open the file
// Read in the strings
// Compare the strings
如果你这样做,你会发现你有一些问题。例如,这行是什么?
strcat(str[i++]," ");
它不是用字符串读的。那它在做什么呢?
在最后一个循环中,您希望将每个字符串与所有其他字符串进行比较。很明显,你从第一个字符串开始,然后将它与所有其他字符串进行比较:
for (a=1; a<count; a++)
if(strcmp(str[0],str[a])==0)
{
printf("%s\n",str[0]);
break;
}
现在我们可以将第一个字符串与后面的每个字符串进行比较,如果它是重复的,则将其打印出来。 “休息”就在那里,所以我们只打印一次。
但这仅将第一个字符串与其他字符串进行比较。我们如何比较所有这些?当然是另一个循环。
// Compare each string against all the ones after it
for (target=0; target<count; target++)
for (a=target+1; a<count; a++)
// If the strings match AND they are not both null
// (why print out copies of null strings? - nobody wants that)
if(strcmp(str[target],str[a])==0) && strlen(str[a])
{
// Print it
printf("%s\n",str[target]);
// Why is this here?
strcpy(str[a],"");
for (copies=a+1; copies<count; copies++)
if(strcmp(str[copies],str[target])==0)
strcpy(str[copies],"");
// We got a match, stop checking for this string
break;
}
看看我们如何得到一个循环遍历每个字符串的大循环,以及一个逐步遍历所有剩余字符串的小循环(没有点通过我们已经看过的字符串)。
现在问你一个问题:为什么“strcpy(str [a],”“)和下一个for循环呢?它们的目的是什么?
答案 1 :(得分:0)
在内部循环中,不是从列表的开头开始,而是在当前循环之后启动一个元素。这样你就不会将元素与自身进行比较,也不会比较任何两个元素两次。
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ // b=a+2 instead of b=0
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
输出:
shine
star
答案 2 :(得分:0)
由于你写了duplicate
个单词,我猜测文件中的单词只会重复两次。
所以第二次嵌套for
循环每次都从头开始,那就是问题所在。您必须确保已经检查的单词不会再次迭代。为此,您可以稍微更改第二个for
循环
for(a=0;a<count*2;a=a+2){
for(b=a+2;b<count*2;b=b+2){ //notice b=a+2
if(strcmp(str[a],str[b])==0){
printf("%s\n",str[b]);
}
}
}
注意强>
对于单词重复两次以上的情况,我的建议是使用一些散列技术来存储单词是否已经出现。然后相应地进行比较和打印。
答案 3 :(得分:0)
这是一种方法。请启用警告 - 您遗漏了库标题。我还检查了数组限制。你需要找到一种更好的方法来限制字符串输入,而不仅仅是猜测一个大的数组大小。
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // included header
#define MAX 100
int main(void){ // correct function
FILE *fpointer;
int reported [MAX];
char ch[MAX], str[MAX][MAX];
int index = 0, a;
fpointer = fopen("1.txt","r");
if(fpointer == NULL){
printf("Error!");
return 0;
}
while(fscanf(fpointer,"%s",ch) == 1){ // testing for 1 item read
for(a=0; a<index; a++){
if(strcmp(ch, str[a])==0){
if (reported[a] == 0) // don't report twice
printf("%s ",ch);
reported[a]++;
break;
}
}
if(a >= index) { // check if loop completed
if (index >= MAX) { // check if array is full
printf("\nToo many words read\n");
exit(1);
}
strcpy(str[index], ch); // word was not found
reported[index] = 0;
index++; // keep tabs on array length
}
}
printf("\n",ch);
fclose(fpointer);
return 0;
}
节目输出:
shine star
答案 4 :(得分:0)
一个问题是,无论是否已经看过,您都要存储每个单词:
while(fscanf(fpointer,"%s",ch)!=EOF){
strcat(str[i++],ch);
strcat(str[i++]," "); // ??? what is this for
count++;
}
理想情况下,您只想存储一次的每个单词,并保持该单词出现在文件中的频率计数:
while ( fscanf( fpointer, "%s", ch ) != EOF ) // whitespace is your friend, use it
{
if ( ch_is_not_already_in_str )
{
strcpy( str[count++], ch );
}
else
{
update_count_for_that_string;
}
}
然后在结束时,您只需遍历ch
并打印每个计数大于1的字符串。
for ( i = 0; i < count; i++ )
{
if ( str[i]_occurs_more_than_once )
printf( "%s ", str[i] );
}
您需要弄清楚的是ch_is_not_already_in_str
,update_count_for_that_string
和str[i]_occurs_more_than_once
。您将如何搜索 str
数组,以查找ch
中字符串的出现情况?你会如何维护每个字符串的计数器?