【问题标题】:Looking for a given sentence in a file在文件中查找给定的句子
【发布时间】:2013-03-08 23:06:20
【问题描述】:

我正在用 c 训练自己,我的目标是读取文件并检查其中是否有给定的句子。如果给定的句子是否存在于文件中,该函数必须分别返回“找到”或“未找到”。 句子用/ 符号分隔。

Example of file:
1,2,3,4/
car, house, hotel/
2,age,12/
1,2/
1,2,3,5/
house, car/

Example of word to look for:
1,2/

我的想法是每次从文件中取出一个句子并将其放入一个数组(称为ary)中,检查数组(ary)是否等于包含给定句子的数组(称为句子) m 查找并重用该数组(ary)用于文件中的下一个句子。

我已经写了这段代码:

#include <stdio.h>

void main()
{
    char *sentence;
    FILE *my_file;
    char *ary;
    int size = 500;
    int got;
    int ind=0;
    int rest;
    int found=0;

    sentence="1,2";


    my_file=fopen("File.txt", "r");

    if(my_file==NULL)
    {
        printf("I couldn't open the file\n");
    }
    else
    {
        ary = (char*)malloc(500*sizeof(char));
        while((got=fgetc(my_file))!=EOF)
        {
            if(got!='/')
            {
                ary[ind++]=(char)got;
            }
            else
            {
                ary[ind++]='\0';
                rest = compare(sentence,ary);
                if(rest==0)
                {
                    found =1;
                    printf("found\n");
                    return;
                }
                ind=0;
                free(ary);
                ary = (char*)calloc(500, sizeof(char));
            }
        }
        if(found==0) 
        {
            printf("not found\n");
        }
        fclose(my_file);
    }
}




int compare(char str1[], char str2[])
{
    int i = 0;
    int risp;
    if(str1>str2 || str1<str2) 
    {
        risp=-1;
    }
    if(str1==str2)
    {
        while(str1[i++]!='\0')
        {
            if(str1[i]!=str2[i]) risp=1;
        }
    }

    return risp;
}

它可以编译,但不能正常工作,我不知道为什么。 有人可以指出我的错误或让我知道更好的解决方案吗?

编辑: 当我打印与句子相关的两个 str 时,可以,但第一次打印后的另一个 str 继续打印,单词前面有一个中断。像下面这样:

Str1:1,2
Str2:1,2,3,4
Str1:1,2
Str2:
car, house, hotel
Str1:1,2
Str2:
2,age,12
Str1:1,2
Str2:
1,2
Str1:1,2
Str2:
1,2,3,5
Str1:1,2
Str2:
house, car

这可能是我的问题之一吗?我试图解决它...

【问题讨论】:

  • 我建议您添加跟踪打印并学习如何使用调试器,例如GDB 及其 GUI 前端 DDD。尝试自己找出错误,学习如何调试自己和其他人的程序是作为程序员掌握的一项重要技能。
  • 看看strtokstrcmp。第一个可以让您更轻松地拆分句子,后者可以让您比较字符串。
  • 虽然调试很重要,但我觉得 OP 在进入调试器之前需要真正理解一些基本概念(指针、数组等)(其中充满了有关地址位置和内存等的信息) )。
  • @CookieOfFortune:我想我可以同意这一点。但是调试器的基本用法仍然是最好早日学习的东西。它也可能是更好地理解指针的工具。
  • @AxelOmega 好的,如果我也想学习 gdb,你知道一些好的教程吗?

标签: c function


【解决方案1】:

str1 和 str2 实际上是指针(它们指的是存储字符串第一个元素的内存位置)。因此,使用 > 和 == 比较 str1 和 str2 只会比较它们的内存位置。如果它们在不同的位置(它们会),str1 和 str2 永远不会相等。

您要做的是逐步遍历 str1 和 str2 并比较值。我把它作为海报的练习。

【讨论】:

  • +1,并且要实际比较一个字符串和另一个字符串,OP 应该寻找的函数是strcmp()。例如,参见stackoverflow.com/questions/7656475/strcmp-return-values-in-c
  • 我同意他最终应该学会使用库函数,但此刻我觉得他确实需要掌握字符串、指针和数组。
  • @CookieOfFortune 谢谢你的提示。我更改了函数int compare(char *str1[], char *str2[])。我以为调用是用指针,但函数采用char [],但比较仍然不起作用。
  • 我不知道在这些情况下我必须如何使用 gdb,但是当我打印 str1 和 str2 时,我总是得到两个奇怪的字符。
  • @DarkCoffee str1[] 和 str2[] 已经引用了一个内存位置。您可以这样想它们:char* str1 和 char* str2(尽管不要坚持这种想法,因为数组与指针根本不同)。因此,如果您对 str1 和 str2 进行比较,它实际上是 str1 和 str2 中第一个字符的内存位置(又名:&str1[0] == &str2[0])。这更有意义吗?
【解决方案2】:

在 C 中移动字符串片段肯定是可行的,但它很麻烦,因为你真的必须了解指针和分配在幕后是如何工作的。那么我可以建议另一种不涉及移动字符串的方法吗?

首先 - 让我们在伪代码中写下如何在文件中查找字符串的定义:

def file_contains_string(file, string):
   if (file is empty):
       return "not found"
   else if (initial_part_of_file_equals(file, string)):
       return "found it!!!"
   else
       return file_contains_string(drop_first_character(file), string)

即"如果文件的第一部分等于字符串,则文件包含字符串,或者文件后面的部分等于字符串。"

这里是C语言的翻译:

int file_contains_string(FILE *file, char *str)
{
    if (feof(file)) return 0;
    if (initial_part_of_file_equals(file, str)) return 1;
    fgetc(file);  /* discard leading character from the file */
    return file_contains_string(file, str);
}

现在我们如何实现initial_part_of_file_equals?好吧,如果第一个字符相等,则文件的初始部分匹配,然后字符串的其余部分匹配文件的第一个字符之后的初始部分:

def initial_part_of_file_equals(file, string):
   if is_empty(string):
      return True
   else if first_character(string) == first_character(file):
      return initial_part_of_file_equals(drop_first_character(file),
                                         drop_first_character(string))
   else return False

我们如何翻译它?在 C 中,“字符串”只是指向字符数组的指针,因此您只需通过推进指针即可“删除字符串的第一个字符”。您只需通过取消引用指针来比较字符串的第一个字符。

int initial_part_of_file_equals(FILE * file, char * str)
{
    if !(str*)      return 1;  /* Test for empty string */
    if (feof(file)) return 0;  /* Test for empty file */

    char c = fgetc(file);      /* get first character from file */

    int result = (c == *str)
                 && initial_part_of_file_equals(file, str++);

    ungetc(c, file);

    return result;
}

其中的ungetc 很重要 - 如果只有strfirst 部分匹配,我们要确保我们实际上不消耗输入流的相应部分。

【讨论】:

    【解决方案3】:

    慢慢地,我自己也找到了解决方案。 我知道这并不优雅,但这对我来说是一个小小的胜利。

    char c;
    char str[]="1,2/";
    FILE * f;
    int i=0; 
    
    f=fopen("File.txt", "r");
    if (f==NULL) perror ("Error opening file");
    else
    {
       while ((c=(char)fgetc(f)) != EOF) {
          if((c==str[i]))  {
              if (c=='/')
                {
                  printf("FOUND\n");
                  return;
                }
              i++;
          }
          else i=0;
          if(c=='/')
              i=0;
        }
        printf("NOT FOUND\n");
        fclose (f);
      }
    

    【讨论】:

      猜你喜欢
      • 2016-04-08
      • 1970-01-01
      • 2011-06-19
      • 2015-05-25
      • 2019-05-07
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多