我需要以垂直方式遍历文件。如果假设文件内容是:
adg
beh
cfi
它应该将文件打印为:
abc
def
ghi
每条线的长度相同(即,上例中所有线的长度均为3)。我编写了一个代码,但它没有按要求遍历文件。
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
fstream fs;
fs.open("asd.txt",ios::in);
string str;
char *ch = new char();
int lineLen = 0, k = 0;
if(getline(fs,str))
{
lineLen = str.length();
}
fs.seekg(0);
if(lineLen > 0)
{
for(int i = 0;i<lineLen;i++)
{
fs.seekg(i+k*lineLen);
while(fs.read(ch,1))
{
k++;
fs.seekg(i+k*lineLen);
cout<<*ch;
}
k = 0;
}
}
fs.close();
cin.ignore();
}
我对文件处理有点新意,无法找到错误。此外,是否有更好的方法可以遵循这一点?
答案 0 :(得分:2)
如果您使用mmap(2)
,您可能会发现此任务更加简单。可能有一个C ++等价物或包装器,但我担心我在这方面的专家并不多。如果是这样的话,希望有人能得到更好的答案。
这是一个快速的C(不是++)示例。我会看看我是否可以谷歌和C ++ ify更多:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int fd = open("input", O_RDONLY);
struct stat s;
fstat(fd, &s);
// map the file as one big string
char *c = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
// calculate sizes
int columns = strchr(c, '\n') - c; // first newline delimits a row
int stride = columns + 1; // count the newline!
int rows = s.st_size / stride; // all rows are the same length
for (int x = 0; x < columns; x++)
{
for (int y = 0; y < rows; y++)
{
putchar(c[y*stride + x]);
}
putchar('\n');
}
munmap(c, s.st_size);
close(fd);
return 0;
}
编辑:据我所知,快速搜索并没有找到更好的方法来处理这个问题。我的意思是,我可以在mmap
行添加类型转换,并将putchar
调用更改为std::cout
,但这看起来并没有任何区别。
答案 1 :(得分:1)
未经测试的伪代码可能会给你一些想法。基本上,将整个文件加载到2d字符向量中以便于访问。它将使用比直接从文件中读取更多的内存,但除非文件非常大,否则无关紧要。
vector<vector<char>> filemap;
string line;
while (getline(filestream, line))
{
filemap.push_back(vector<char>(line.begin(), line.end()));
}
for (int x = 0; x < XSIZE; x++)
{
for (int y = 0; y < YSIZE; y++)
{
filestream << filemap[y][x]; // note x/y are opposite way round in 2d vectors
}
filestream << '\n';
}
答案 2 :(得分:1)
不是尝试在源文件中重复搜索(),而是简单地读取整个源文件然后从内存中的内容生成输出,这样更容易,更快。
这听起来很糟糕,就像课堂作业一样,所以我不会简单地为你写答案。但是,这应该指向正确的方式 - 包括一些PseodoCode
为了避免疼痛,假设在线长和最大线上有一些上限可能是安全的,即
const int MaxLines = 100;
const int MaxLength = 80;
int lineno, linelength;
// array of char pointers for each line
char *lines[] = (*lines[])malloc(Maxlines * sizeof(char*));
// ReadLoop
lineno = 0;
while (not eof)
{
getline(buffer);
if (++lineno++ == 1)
{
linelength = strlen(buffer);
}
else
{
if (linelength != strlen(buffer))
{
cout "Line # " << lineno << " does not match the expected length";
exit();
}
}
lines[lineno] = malloc(strlen(buffer)+1));
strcpy(lines[lineno], buffer);
}
int cc, linecnt = lineno;
// now all data in memory, output "vertical data"
for (cc = 0; cc < linelength; ++cc)
{
for (lineno=0; lineno<<linelength; ++lineno)
{
cout << lines[xx][yy]; // xx && yy left you to figure out
}
cout "\n";
}
答案 3 :(得分:1)
通过一些小调整来实现你的方式
//lines = no. of lines in file
fs.seekg(0,fs.beg);
fs.clear();
if(lineLen > 0)
{
for(;k<lineLen;k++){
for(int i = 0;i<lines;i++){
fs.seekg(k+i*(lineLen+2),fs.beg); //use lines+2
if(fs.read (ch,1));
cout<<*ch;
}
cout<<endl;
}
答案 4 :(得分:0)
你可以将所有行重新编入一个列表然后迭代两个循环并打印字符,第一个循环遍历单词的长度,第二个循环遍历文本文件的行。所以你将在每次迭代时打印每行的一个字符。
这是一个示例代码(虽然在c中仅使用字符串数组)
void print_vertically() {
const char* lines[3];
lines[0] = "adg";
lines[1] = "beh";
lines[2] = "cfi";
int num_lines = 3;
int max_len = 3;
for(int i = 0; i < max_len; i++) {
for(int j = 0; j < num_lines; j++) {
if(i < strlen(lines[j])) { // strlen in a loop should be avoided
// since it runs through all the chars of
// a string to count the length
printf("%c", lines[j][i]);
} else {
printf(" ");
}
}
printf("\n");
}
}
<强>输出强>
abc
def
ghi
答案 5 :(得分:0)
如果您的文件不是很大,那么没有理由不将整个内容淹没在内存中。在C ++中可能有更惯用的方法,但以下工作:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
while(std::getline(infile,line)) {
lines.push_back(line);
}
int m=lines.size();
int n=lines[0].length();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
std::cout << lines[j].at(i);
}
std::cout << std::endl;
}
return 0;
}
当然,文件中的所有行长度不同时会出现问题。
现在,一个“不使用任何额外内存”的版本(当然,它确实如此,但并不多):
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
std::getline(infile, line);
int n = line.length();
int m = 1+std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), '\n');
infile.clear();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
infile.seekg(j*m+i);
std::cout << char(infile.peek());
}
std::cout << std::endl;
}
return 0;
}