使用C在文本中搜索单词,并在该单词后显示信息

时间:2012-12-27 22:34:52

标签: c++ c printf string-search fgetc

说我有这样的文本文件:

用户:约翰

设备:12345

日期:12/12/12

修改

我的代码可以成功搜索单词,并在该单词后显示信息。然而,当我尝试编辑代码以搜索2或3个单词并在其后显示信息而不是仅仅1个单词时,我无法使其工作。我已经尝试将代码添加到同一个while循环中,并为另一个单词创建一个新的while循环,但两者都不起作用。必须有一些我做错/不做的事。

请指教,谢谢!

这是我的代码:

 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 int main() {

char file[100];
char c[100];

printf ("Enter file name and directory:");
scanf ("%s",file);

    FILE * fs = fopen (file, "r") ;
    if ( fs == NULL )
    {
           puts ( "Cannot open source file" ) ;
           exit( 1 ) ;
    }

    FILE * ft = fopen ( "book5.txt", "w" ) ;
    if ( ft == NULL )
    {
           puts ( "Cannot open target file" ) ;
           exit( 1 ) ;
    }

while(!feof(fs)) {
   char *Data;
   char *Device;
   char const * rc = fgets(c, 99, fs);

   if(rc==NULL) { break; }

   if((Data = strstr(rc, "Date:"))!= NULL)
   printf(Data+5);

   if((Data = strstr(rc, "Device:"))!=NULL)
   printf(Device+6);
   }



    fclose ( fs ) ;
    fclose ( ft ) ;

return 0;

 }

8 个答案:

答案 0 :(得分:1)

我的建议是使用fread来读取所有文件。你可以逐个字符地阅读它,但是恕我直言(这里的个人品味)它更容易获得包含所有字符然后操纵它的字符串。

这是函数原型:

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

返回读取的元素数。

例如:

char buffer[100];
size_t n= fread(buffer, 1,100, fs);  

然后你可以操纵字符串并将其分成标记。

编辑

还有一个很好的参考,还有一个如何将字符串分成标记的示例:

http://www.cplusplus.com/reference/cstring/strtok/

答案 1 :(得分:1)

fgetc返回一个整数值,即字符,提升为int。 我想你的意思是fgets读取整行,但你需要为它保留记忆,例如:

#define BUF 100
...
char c[BUF];
fgets(c, BUF, fs);

部分helpful links

答案 2 :(得分:1)

您的代码中存在一些问题:基本上它从未编译过。

这是一个包含小清理的版本 - 至少可以编译:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    char file[100];
    char c[100];

    printf ("Enter file name and directory:");
    scanf ("%s",file);

    FILE * fs = fopen (file, "r") ;
    if ( fs == NULL ) {
       puts( "Cannot open source file" ) ;
       exit(1 ) ;
    }

    while(!feof(fs)) {
       char *Data;
       char const * rc = fgets(c, 99, fs);
       if(rc==NULL) { break; }
       if((Data = strstr(rc, "Device"))!= NULL)
       printf("%s", Data);
    }

    fclose ( fs ) ;

    return 0;
 }

我发现的问题:

  • 缺少exit()
  • 的内容
  • 缺少exit()
  • 的参数
  • 缺少while循环以运行整个输入文件。
  • 从未使用过输出文件。
  • 缺少'main'的返回值
  • Fancy Data[5]
  • fgetc()更改为fgets()

我只进行了极少量的编辑 - 它根本不是完美的......

恕我直言,我会选择C ++:很多事情都比较简单。

答案 3 :(得分:1)

如果printf()不是硬/快规则,输入要求真的很简单,我更喜欢状态机和常量内存输入:

int c, x = 0;                              // c is character, x is state
while(EOF!=(c=getchar())){                 // scanner entry point
  if(c == '\n') x=0;                       // newline resets scanner
  else if(x == -1) continue;               // -1 is invalid state
  else if (x < 7 && c=="Device:"[x])x++;   // advance state
  else if (x == 7 && isspace(c)) continue; // skip leading/trailing whitespace
  else if (x == 7) putchar(c);             // successful terminator (exits at \n)
  else x = -1;                             // otherwise move to invalid state
}

答案 4 :(得分:1)

我会用两个循环来做到这一点:一个从文件中获取一行,另一个从行读取中获取标记。

类似的东西:

#define BUFFSIZE 1024
int main()....

char buff[BUFFSIZE];
char delims[] = " ";
char *result = NULL;
int stop = 0;

fp = fopen("yourFile", "r");

while( fgets(buff, BUFFSIZE,fp) != NULL )  /*This returns null when the file is over*/
{
 result = strtok( buff, delims );   /*You just need to do reference to buff here, after this, strtok uses delims to know where to do the next token*/

   while(result != NULL){   /*Strtok returns null when finishes reading the given string*/
      if(strcmp(result,"Device")==0){   /*strcmp returns 0 if the strings are equal*/
         stop = 1;  /*Update the flag*/
         break;     /*Is now possible to break the loop*/
      }
      result = strtok(NULL,delims);  /*Get the next token*/
   }
   if(stop == 1) break; /*This uses the inside flag to stop the outer loop*/
}


result = strtok(NULL, delims); /*Result, now, has the string you want: 12345 */

...

这段代码不是很准确,我没有测试过,但那就是我会尝试做的。

希望这会有所帮助。

答案 5 :(得分:1)

好的,希望我这次能清除它。对不起,如果我有时会感到困惑,但我的英语不是最好的。

我将解释评论中的实现:

#define BUFFSIZE 1024
int main()....

char buff[BUFFSIZE];
char delims[] = " ";  /*Where your strtok will split the string*/
char *result = NULL;
char *device; /*To save your device - in your example: 12345*/
char *date; /*To save the date*/
int stop = 0;

fp = fopen("yourFile", "r");

while( fgets(buff, BUFFSIZE,fp) != NULL )  /*This returns null when the file is over*/
{
 result = strtok( buff, delims );   /*You just need to do reference to buff here, after this, strtok uses delims to know where to do the next token*/

   while(result != NULL){   /*Strtok returns null when finishes reading the given string*/
      if(strcmp(result,"Device")==0){   /*strcmp returns 0 if the strings are equal*/
         result = strtok(NULL, delims); /*this one gets the 12345*/
         device = (char*)malloc((strlen(result)+1)*sizeof(char)); /*Alocate the right amount of memory for the variable device*/
         strcpy(device, result); /*Now, device is "12345"*/
      }
       /*Here you do the same but for the string 'Date'*/
       if(strcmp(result,"Date")==0){   /*strcmp returns 0 if the strings are equal*/
         result = strtok(NULL, delims); /*this one gets the 12345*/
         date = (char*)malloc((strlen(result)+1)*sizeof(char)); /*Alocate the right amount of memory for the variable device*/
         strcpy(date, result); /*Now, device is "12/12/12"*/
      }
      /*And you can repeat the if statement for every string you're looking for*/
      result = strtok(NULL,delims);  /*Get the next token*/
   }
}

/*No strtok necessary here */

...

希望这有帮助。

答案 6 :(得分:0)

cData是char-pointers,指向(字符值列表的开头)的指针。

fgetc的原型是int fgetc ( FILE * stream );,意味着它返回(一个)整数值(一个整数可以转换为单个char值)。

如果fgetc的原型已经int * fgetc ( FILE * stream );,则警告不会出现。

答案 7 :(得分:0)

@Dave Wang 我的答案太大了,不能发表评论。所以这就是:

欢迎你。很高兴帮忙。

如果你创建一个新循环,fgets将无法工作,因为你已经在文本文件中“关闭”了。想象一下像指向文件的指针,每当你从文件指针'fget',你推进指针。你有重新加载文件或推送指针的功能,但效率不高,你已经传递了你想要的信息,必须有办法知道什么时候。

如果您正在使用我的实现,那么可以通过在循环内使用另一个字符串比较来完成: if(strcmp(result,“date”)== 0) 如果输入此if,则表示strtok的结果标记中的下一个值是实际日期。 由于您现在有两个要测试的条件,因此在同时使用它们之前不能破坏外部循环。这可以通过两种方式实现:

1 - 使用每次需要信息时递增的计数器而不是标志。如果该计数器具有您想要的相同数量的信息,则可以中断外部循环。

2 - 根本不打破外环! :)

但两者都有,因为有2个条件,请确保在ifs中对待它们,这样你就知道你正在处理正确的信息。

希望这会有所帮助。什么,只要问。