从C中的文件打印所有重复的单词

时间:2015-09-01 12:48:12

标签: c

为了仅打印文件中的重复单词,我应该怎么做。我是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

5 个答案:

答案 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_strupdate_count_for_that_stringstr[i]_occurs_more_than_once。您将如何搜索 str数组,以查找ch中字符串的出现情况?你会如何维护每个字符串的计数器?