我想在#
的文本文件中使用C更改包含heet
符号的行。
我已经尝试过这种方式,但它没有彻底运作,它只是取代了角色&不像我想要的那样覆盖整个字符串。
是否还有其他技巧可以从文件中删除或删除整行?所以,我们可以轻松地取代它。
myfile.txt: (执行前)
Joy
#Smith
Lee
Sara#
Priyanka
#Addy
代码:
#include <stdio.h>
#include <string.h>
int main() {
FILE *pFile;
fpos_t pos1, pos2;
int line = 0;
char buf[68]
char *p;
char temp[10] = "heet";
pFile = fopen("myfile.txt", "r+");
printf("changes are made in this lines:\t");
while (!feof(pFile)) {
++line;
fgetpos(pFile, &pos1);
if (fgets(buf, 68, pFile) == NULL)
break;
fgetpos(pFile, &pos2);
p = strchr(buf, '#');
if (p != NULL) {
printf("%d, " , line);
fsetpos(pFile, &pos1);
fputs(temp, pFile);
}
fsetpos(pFile, &pos2);
}
fclose(pFile);
return 0;
}
myfile.txt: (执行后)
Joy
heetth
Lee
heet#
Priyanka
heety
输出
changes are made in this lines: 2, 4, 6,
myfile.txt: (我想知道)
Joy
heet
Lee
heet
Priyanka
heet
答案 0 :(得分:6)
做你想做的最好的方法是使用像sed这样的实用程序。它比你(或我)写的任何内容都更快,占用的内存更少。
除此之外,让我们假设你想继续自己写下来。
文件就像一个长字节数组。如果要增加或减少一行的长度,它会影响文件其余部分中每个字节的位置。结果可能比原始结果更短(或更长)。由于结果可能更短,因此修改文件是一个坏主意。
以下伪代码说明了一种简单的方法:
open original file
open output file
allocate a line buffer that is large enough
read a line from the original file
do
return an error if the buffer is too small
manipulate the line
write the manipulated line to the output file
read a line from the original file
loop until read returns nothing
sed做得更聪明。我曾经看过关于sed如何工作的解释,但我的谷歌业力似乎无法找到它。
修改强> 如何使用sed:
sed -e 's/.*\#.*/heet/g' myfile.txt
sed
的s或者替换命令可以用另一个字符串替换一个字符串或正则表达式。
上述命令被解释为:
用#
替换其中某处heet
的任何行。最后的g告诉sed
全局执行此操作,即在整个文件中执行此操作。
<强> EDIT2:强>
默认情况下,sed写入标准输出。
要重写文件,您应该将输出重定向到文件,然后重命名它。
在linux中,执行以下操作(您可以使用system
从C运行命令行内容):
sed -e 's/.*\#.*/heet/g' myfile.txt > temp_file123.txt
rm myfile.txt
mv temp_file123.txt myfile.txt
来自C:
system("sed -e 's/.*\#.*/heet/g' myfile.txt > temp_file123.txt");
system("rm myfile.txt");
system("mv temp_file123.txt myfile.txt");
如果只想调用system
,只需将所有命令行内容放在shell脚本中即可。
答案 1 :(得分:1)
您应该像UNIX实用程序一样处理输入/输出,并通过读取整个输入并像sed
那样写出整个输出来替换该行。编辑线条会很麻烦,因为您需要将以下文本“向下”移动才能使其正常工作。
答案 2 :(得分:0)
您无法通过像在代码中那样就地覆盖文件来实现目标,因为heet
比#
长3个字节,并且没有标准函数可以在文件中间插入字节文件。
还要注意以下重要问题:
fopen()
是否成功打开文件。如果文件不存在或无法以读取+更新模式打开,则您的行为不确定。 while (!feof(pFile))
不会完全停止在文件末尾,因为feof()
返回的文件末尾指示符仅在读取操作失败时才设置,而不是在读取操作失败之前才设置。您应该改写:
while (fgets(buf, 68, pFile) != NULL) {
如果文件的行长超过66个字符,则行号将计算不正确。
有两种方法可以替换文件中的文本:
remove()
删除原始文件,并使用rename()
将临时文件重命名为原始名称。此方法会占用存储设备上的额外空间,并且要求您可以创建一个新文件并确定与现有文件名不冲突的文件名。这是使用第二种方法的修改版本:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
FILE *pFile;
int c, line, changes;
unsigned char *buf;
size_t pos, length, size;
char replacement[] = "heet";
/* open the file */
pFile = fopen("myfile.txt", "r+");
if (pFile == NULL) {
printf("cannot open myfile.txt\n");
return 1;
}
/* read the file */
buf = NULL;
length = size = 0;
while ((c = getc(pFile)) != EOF) {
if (length == size) {
size = size + size / 2 + 128;
buf = realloc(buf, size);
if (buf == NULL) {
printf("not enough memory to read myfile.txt\n");
fclose(pFile);
return 1;
}
}
buf[length++] = c;
}
/* write the modified contents */
rewind(pFile);
line = 1;
changes = 0;
for (pos = 0; pos < length; pos++) {
c = buf[pos];
if (c == '\n')
line++;
if (c == '#') {
if (changes++ == 0)
printf("changes are made in this lines:\t");
else
printf(", ");
printf("%d", line);
fputs(replacement, pFile);
} else {
putc(c, pFile);
}
}
free(buf);
fclose(pFile);
if (changes == 0)
printf("no changes were made\n");
else
printf("\n");
return 0;
}
答案 3 :(得分:-1)
要使用fwrite
或任何文件写入功能重写文件中的单词,请使用fgetpos
和fsetpos
。否则,仅寻求文件指针将无法工作。仍然可以完成这项工作,如果文件指针位于文件的末尾,则意味着可以追加。