说我有这样的文本文件:
用户:约翰
设备: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;
}
答案 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);
然后你可以操纵字符串并将其分成标记。
编辑
还有一个很好的参考,还有一个如何将字符串分成标记的示例:
答案 1 :(得分:1)
fgetc
返回一个整数值,即字符,提升为int。
我想你的意思是fgets
读取整行,但你需要为它保留记忆,例如:
#define BUF 100
...
char c[BUF];
fgets(c, BUF, fs);
答案 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()
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)
c
和Data
是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中对待它们,这样你就知道你正在处理正确的信息。
希望这会有所帮助。什么,只要问。