[英]How can I modify the code to accept string as user input and use strcmp to compare with the contents of the text file then delete that line?
[英]how can i delete a whole line containing a string provided by the user in a file
我需要删除包含用户插入的字符串的整行,我很难弄清楚如何删除这一行这是我到目前为止所绑定的。
例如,如果u.txt包含:
1 你好世界
2 你在哪里
*用户输入:你*
u.txt现在包含
1.你好世界
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *tr1, *tr2;
char *p;
char chr;
char scanner [10];
int t = 1;
int sc;
tr1 = fopen("u.txt", "r");
chr = getc(tr1);
while (chr != EOF)
{
printf("%c", chr);
chr = getc(tr1);
}
printf("input your word to search:");
scanf("%s",scanner);
rewind(tr1);
tr2 = fopen("replica.txt", "w");
chr = 'A';
while (chr != EOF)
{
//expect the line to be deleted
sc= strstr(chr,scanner);
if (!sc)
{
//copy all lines in file replica.txt
putc(chr, tr2);
}
fclose(tr1);
fclose(tr2);
remove("u.txt");
rename("replica.txt", "u.txt");
tr1 = fopen("u.txt", "r");
chr = getc(tr1);
while (chr != EOF)
{
printf("%c", chr);
chr = getc(tr1);
}
fclose(tr1);
return 0;
}
通过将面向字符的输入与fgetc()
结合使用需要面向行的输入和输出的操作,您正在给自己制造麻烦。 此外,在您的方法中,您将删除文件中包含单词的每一行,其中you
是较少包含的子字符串,例如:
为了确保您不会删除包含单词"you"
的行的简单方法,您可以简单地检查以确保单词前后的字符是whitespace 。 您可以使用ctype.h
中提供的isspace()
宏来简化检查。
当您遇到面向行的问题时,请使用面向行的输入和输出函数,例如fgets()
或 POSIX getline()
用于输入, puts()
或fputs()
用于输出。 唯一需要注意的是,面向行的输入函数读取尾随'\n'
并将其包含在它们填充的缓冲区中。 只需在必要时删除,方法是用空终止字符'\0'
(或简称0
)覆盖尾随'\n'
。
使用面向行的方法将极大地简化您的任务,并提供一种方便的方式将您保留的行写入输出文件中,而不是逐个字符地循环。 使用面向字符的方法并没有错,而且它本身并不比面向行的方法慢——只是不太方便。 使工具与工作相匹配。
以下示例读取"u.txt"
并写入"v.txt"
,删除不需要的行,同时保留单词是所查找单词的较少包含子字符串的行。 ( rename()
和remove()
留给你,因为你现有代码的那部分没有任何问题)
简单地使用足够大小的固定缓冲区是进行面向行输入的最简单方法。 您通常会知道最大的预期行是多少,只需使用足以处理它的缓冲区(不要吝啬! )。 大多数行的长度不超过 80-120 个字符。 一个 1024 个字符的固定数组绰绰有余。 只需声明一个数组用作缓冲区来保存读取的每一行,例如:
#define MAXW 32 /* max chars in word to find */
#define MAXC 1024 /* max chars for input buffer */
int main (int argc, char **argv) {
char buf[MAXC], /* buffer to hold each line */
word[MAXW]; /* user input to find/delete line */
size_t wordlen = 0; /* length of user input */
FILE *ifp, *ofp; /* infile & outfile pointers */
您可以验证是否在命令行上为输入和输出文件名提供了足够的参数,然后打开并验证每个文件,例如
if (argc < 3) { /* validate at least 2 program arguments given */
printf ("usage: %s infile outfile\n", strrchr (argv[0], '/') + 1);
return 1;
}
if (!(ifp = fopen (argv[1], "r"))) { /* open/validate open for reading */
perror ("fopen-ifp");
return 1;
}
if (!(ofp = fopen (argv[2], "w"))) { /* open/validate open for writing */
perror ("fopen-ofp");
return 1;
}
现在只需从用户那里获取输入并删除尾随'\n'
。 使用strcspn
您可以获得用户输入的长度,同时在一次调用中覆盖尾随'\n'
。 请参阅: man 3 strspn ,例如
fputs ("enter word to find: ", stdout); /* prompt for input */
fflush (stdout); /* optional (but recommended) */
if (!fgets (word, MAXW, stdin)) { /* read/validate word to find */
fputs ("(user canceled input)\n", stdout);
return 1;
}
/* get wordlen, trim trailing \n from find */
word[(wordlen = strcspn (word, "\n"))] = 0;
现在只需一次读取一行并在行内搜索word
并验证它是一个完整的单词而不是更大单词的一部分。 将所有不包含word
的行单独写入输出文件:
while (fgets (buf, MAXC, ifp)) { /* read each line */
char *p = strstr (buf, word); /* search for word */
if (!p || /* word not in line */
(p != buf && !isspace (*(p - 1))) || /* text before */
(!isspace (p[wordlen]) && p[wordlen] != 0)) /* text after */
fputs (buf, ofp); /* write line to output file */
}
(注意:用于检查字符是否为空白的isspace()
宏在头文件ctype.h
中提供)
关闭这两个文件,除了您的remove()
和rename()
之外,您就完成了。 但是,请注意,您应该始终在写入后验证fclose()
以确保您捕获与关闭时刷新文件流相关的任何错误,这些错误不会通过单独验证每个写入来捕获,例如
if (fclose (ofp) == EOF) { /* validate EVERY close-after-write */
perror ("fclose-ofp");
remove (argv[2]);
}
fclose (ifp); /* close input file */
}
添加所需的头文件,您就有了一个工作示例。 您可以按如下方式使用该示例:
示例输入文件
$ cat dat/u.txt
hello world
how are you
show yourself
you're missing
使用示例
$ ./bin/filermline dat/u.txt dat/v.txt
enter word to find: you
生成的输出文件
$ cat dat/v.txt
hello world
show yourself
you're missing
查看所有内容并将面向行的方法与您对fgetc()
的面向字符的使用进行比较。 如果您还有其他问题,请告诉我。
由于标记为C ++,因此应使用std::string
和std::getline
:
#include <fstream>
#include <string>
int main()
{
std::cout << "Enter keyword to search: ";
std::string keyword;
std::cin >> keyword;
std::ifstream text_file("u.txt");
std::ofstream result_file("u_modified.txt");
std::string text_from_file;
while (std::getline(text_file, text_from_file)
{
if (text_from_file.find(keyword) == std::string::npos)
{
result_file << text_from_file << "\n";
}
}
text_file.close();
result_file.close();
return EXIT_SUCCESS;
}
如果是以上代码,将从源文件中读取文本行。 如果不存在关键字,则将文本写入结果文件。
编辑1:C样式字符数组
C样式字符数组的一个问题是溢出。 例如,如果char
数组的容量为16个字符,并且文件中的文本行为100,则输入将溢出字符数组。 如果缓冲区太大,那是在浪费空间。 如果数组太小,您将无法将整行包含在数组中(或更糟糕的是,关键字可能在读取之间分开)。
使用字符数组,您将不得不重新分配以扩展它。 这意味着分配一个更大的数组(从动态内存),将旧数组复制到新数组,然后删除旧数组。 这种内存管理是使用std::string
类型为您执行的。
你没有给chr
任何值,它总是A
至少在第一个循环中。 是否遗漏了任何代码行? 我建议您检查每一行,直到找到将其保存在字符串中的EOL
。 然后用它调用strstr()
,如果结果为 NULL,您只需将其复制到另一个文件中。 如果有必要将它保存在同一个文件中,它将更加困难,因为您必须保存指向每一行开头的指针。 如果您正在研究的这一行实际上是必须删除的一行,则您必须从该指针重新复制后面的每一行。 这种方式更难。
祝你好运!
PS:也许这可以帮助,不确定: How do I delete a specific line from text file in C?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.