我目前正试图操纵文本文件的文本(不使用向量):
(这是一份工程论文的作业,我不允许使用矢量)
变量numRows可以是任何整数(我只为此示例选择3)并且是输出文本文件'example.txt'中元素的方阵矩阵
这是我的代码:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
int numRows = 3;
ofstream myfile ("example.txt");
if (myfile.is_open())
{
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numRows; j++) {
myfile << "Test\t";
}
myfile << "\n";
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
文本文件如下:
Test Test Test
Test Test Test
Test Test Test
我的问题是,一旦我完成了所有这些 - 如何再次打开并编辑它?例如。说我想将第2行第2列编辑为“Hello”:
Test Test Test
Test Hello Test
Test Test Test
我该怎么做?我需要能够操作存储在这个文本文件中的字符串,并且不确定该怎么做,因为我已经用制表符分隔每个字符串
感谢您抽出宝贵时间提供帮助!
答案 0 :(得分:3)
在典型的文件系统上,您无法在任意位置插入字符。如果要在适当的位置“编辑”文件,则需要使用一种格式,其中每个记录占用一定量的空间。当然,每个记录的大小将受此固定金额的大小限制。例如,你可以使用每个记录10个字节,将最大大小限制为10.如果记录较短,你要用一些不可能发生的字节填充它(例如,制表符)或者你使用合适的字节数在记录的固定位置,如果使用的字符串,则指定大小。对于最多255个字节,将使用一个额外字节。
由于记录的大小固定,您可以寻找修改记录的位置:起点为(row * columns + column) * record_size
。您只需编写新值(如果您选择保存大小,则记录中字符串的大小)。
如果您需要支持没有上限的可变长度字符串,或者您需要使用紧凑表示,则上述方法不起作用。您需要完全重写该文件。你要
显然,如果您需要一次进行多次编辑,则可以根据需要继续复制/替换。不过,这种方法几乎保持不变。
我可以轻松地为你的家庭作业编写代码,但上面已经从所述作业中删除了所有思考。另外,我真的不需要练习编程,因此我将跳过提供代码。
答案 1 :(得分:1)
考虑“编辑”这样的文件并不是很实际,因为大多数文件系统(和标准文件I / O API)仅支持覆盖文件内容 - 您不能用不同的文本替换某些文本长度并使文件相应地调整剩余文件内容的位置。因此,最好将文件读入内存中的某些变量,在那里编辑,然后在完成当时所需的所有编辑后写出更新的内容(即覆盖整个文件)。要阅读该文件,您可以使用std::ifstream
。要将文件存储在内存中,std::vector<std::vector<std::string>>
- 外部vectors
表示行/行,以及该行/行中的内部vector
列值 - 似乎是一个自然匹配,因为您的问题说明,但您可以考虑std::vector<std::string>
,其中每个string
代表一个完整的行/行,包括制表符。
(如果您知道单个字符串宽度的上限(在您的示例中为"Text"
,"Hello"
),并且很乐意用空格而不是尾随制表符填充每个字符串,那么您可以覆盖文本和空格而不需要调整文件大小(只要你没有改变行数/行数或添加/删除列)。为此,你在"seek"中{ {1}}到您想要替换值的位置。)
除了评论中的讨论之外,如果您坚持直接更改文本文件,一个简单的选择是在阅读原始文件时编写更新的文件,然后将更新的输出文件移到原始文件上。实际生成的更新输出文件可能如下所示:
std::fstream
注意:
#include <fstream>
#include <iostream>
void edit_file(int line_to_change, int column_to_change, const std::string& change_to)
{
if (std::ifstream in{"txt_in"})
if (std::ofstream out{"txt_out"})
{
int line = 1, column = 1;
std::string word;
char whitespace;
while (in >> word && in.get(whitespace))
{
if (line == line_to_change && column == column_to_change)
word = change_to;
out << word << whitespace;
if (whitespace == '\n') // newline...
{
++line;
column = 1;
}
else // presumably a tab...
++column;
}
}
else
std::cerr << "unable to open output file\n";
else
std::cerr << "unable to open input file\n";
}
int main()
{
edit_file(2, 2, "Hello");
}
代替in.get(whitespace)
,因为后者会跳过空格,而这正是我们需要阅读的内容,以便将标签与新行区分开来
将输出发送到一个不同的文件可以防止在插入比以前包含的文件更长的“单词”时的麻烦,如果天真地完成将覆盖您将要编写的输入,并且如果正确完成需要内存中任意数量的缓冲