需要将文本的特定行写入新文本

Need to write specific lines of a text into a new text

本文关键字:文本 新文本      更新时间:2023-10-16

我有数值文本数据行范围在1mb - 150mb之间的大小,我需要写与高度相关的数字行,例如:高度=4,新的文本必须包括行:1,5,9,13,17,21....必然地。

我一直在试图找到一种方法来做到这一点,现在,尝试使用列表而不是向量,最终导致编译错误。

我已经按照建议清理了代码。现在,它编写所有行sample2文本,全部在这里完成。谢谢大家

我是开放的方法改变,只要它提供了我需要的,谢谢你的时间和帮助。

下面是我到目前为止写的:

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
int h,n,m;
int c=1;
int main () {
cout<< "Enter Number Of Heights: ";
cin>>h;
ifstream myfile_in ("C:\sample.txt");
ofstream myfile_out ("C:\sample2.txt");
string line;
std::string str;
vector <string> v;
if (myfile_in.is_open()) {
myfile_in >> noskipws;
int i=0;
int j=0;
while (std::getline(myfile_in, line)) {
v.push_back( line );
++n;
if (n-1==i) {
myfile_out<<v[i]<<endl;
i=i+h;
++j;
}
    }
cout<<"Number of lines in text file: "<<n<<endl;
}
else cout << "Unable to open file(s) ";
cout<< "Reaching here, Writing one line"<<endl;
system("PAUSE");
return 0; 
}

您需要使用seekg来设置文件开头的位置,一旦您读取了它(您已经读取了一次,以计算行数(我认为您实际上不需要,因为这个大小从未使用过,至少在这段代码中)

如果内部的while有什么意义?在每个循环中,都有

int i=1;
myfile_out<<v[i]; //Not writing to text
i=i+h;

所以在每个循环中,i得到1,所以你一直输出索引为1的元素。这不是第一个元素,因为索引从0开始。因此,一旦您放入seekg或删除第一个while,您的程序将开始崩溃。

所以,让i0开始。把它从两个while循环中取出,就在if-statement的开头。

啊,第二个while也是不必要的。只留下第一个。


编辑:添加

myfile_in.clear();

seekg之前清除标志。

还有,你的算法是错误的。如果h> 1,就会出现segfault,因为会超出(向量的)范围。我建议这样做:读取while中的文件,计算行数。并将每条直线存储在向量中。这样你就可以去掉第二篇阅读,seekg, clear等等。此外,由于您已经将文件的内容存储到vector中,因此不会丢失任何内容。然后使用for循环与步骤h


再次编辑,关于你的编辑:不,它与任何标志无关。比较i==jif在while之外。把它加进去。另外,在if之外增加j。或者只是删除j并使用n-1代替。像

if ( n-1 == i )

几件事。

首先完整地读取文件,只是为了计算行数,然后你再读一遍来处理它,在内存中建立一个图片在v。为什么不第一时间读完,然后做所有的事情呢还有其他内存图像吗?然后v.size()会给你号码行,所以你不必计算它们)

你从来没有真正使用计数。

第二,一旦你第一次到达文件的末尾设置failbit;所有进一步的操作都是无操作的,直到它被重置。如果您必须读取文件两次(例如,因为您取消了v)完全),然后你必须在第一个之后做myfile_in.clear()循环,但在开始查找之前。

您只在读取文件一次之后测试is_open。这个测试应立即打开。

您也可以设置noskipws,尽管您不做任何格式化的输入谁会受到它的影响。

最终的while是高度可疑的。因为你还没有clear,你可能永远不会进入循环,但如果你做了,你会非常快速开始访问出界:读取n行后,大小v的索引将为n,但您读取索引i时,索引将为n * h

最后,您应该显式地关闭输出文件并检查之后的错误,以防万一。

我不清楚你想做什么。如果你只想在每个现有行之间插入h空行,例如:
std::string separ( h + 1, 'n' );
std::string line;
while ( std::getline( myfile_in, line ) ) {
    myfile_out << line << separ;
}

就可以了。不需要在内存中存储完整的输入。(就此而言,您甚至不必为此编写程序。像sed 's:$:nnnn:' < infile > outfile一样简单的东西就可以了诀窍。)

编辑:

看了别人的回答,我想我可能误解了问题,并且他只想输出每个h -th行。如果这是例:
std::string line;
while ( std::getline( myfile_in, line ) ) {
    myfile_out << line << 'n';
    for ( int count = h - 1; h > 0; -- h ) {
        std::getline( myfile_in, line );
        //  or myfile_in.ignore( INT_MAX, 'n' );
    }
}

但是,其他工具似乎更合适。(我会跟随他的建议并使用AWK。)为什么要用你不懂的语言写程序呢

如果没有绝对令人信服的理由在c++中这样做,那么您使用的编程语言是错误的。在awk中,整个程序是:

{ if ( FNR % 4 == 1 ) print; }

或者,给出整个命令行,例如在sh中过滤第1、5、9、13、…行:

awk '{ if ( FNR % 4 == 1 ) print; }' a.txt > b.txt