seekp() position at the beginnig of new line in file - c++

I have a file "first.txt":
Chun mee |Wuyi |Genmai |
Pu-erth |Green |Flower mix |
Lightly sweet|Strong,smooth|Fresh, strong|
Here '|' is delimiter, the first line has 10 symbols in each block (block is the space between delimiters), the second - 11, the third - 13.
I`d like to combinate these lines like this and write it ("rec.txt"):
Chun mee '\t'Pu-erth '\t'Lightly sweet
Wuyi '\t'Green '\t'Strong,smooth
Genmai '\t'Flower mix '\t'Fresh, strong
Here is my code:
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <limits>
using namespace std;
fstream& go_line(fstream& file, unsigned int num){
for(int i=0; i < num - 1; ++i){
file.ignore(numeric_limits<streamsize>::max(),'\n');
}
return file;
}
void func(int iter_num){
fstream file;
fstream file_exist;
string str;
file_exist.open("first.txt");
file.open("rec.txt", ios::in | ios::out | ios:: trunc | ios::binary);
if (iter_num < 3){ //iter_num - num of iterations (lines)
for(int i = 0; i < iter_num; i++ ){
for(int t = 1; t< 4; t++ ){ //t-num of columns
if(i>0 && t==1){
file<<endl;
}
if(i == 0){
go_line(file_exist, t);
getline (file_exist, str, '|');
file_exist.seekp(0, ios::beg);
file<<str<<'\t';
}
else{
switch(t){
case 1:
//cout<<"case1 "<<endl;
file_exist.seekp((i*10)+1, ios::beg);
go_line(file_exist, t);
getline (file_exist, str, '|');
file<<str<<'\t';
break;
case 2:
//cout<<i<<endl;
go_line(file_exist, t);
file_exist.seekp((i*11)+1, ios::beg);
getline (file_exist, str, '|');
file<<str<<'\t';
case 3:
//cout<<i<<endl;
go_line(file_exist, t);
file_exist.seekp((i*13)+1, ios::beg);
getline (file_exist, str, '|');
file<<str<<'\t';
}//switch
}//else
}//for
}//for
}//if
}//func
int main(){
int n = 3;
func(n);
return 0;
}
The problem is:
for example, in case 2 seekp() is not at the beginnig of new line, it`s on the first one. But the idea is - set it at the beginnig of new line and get "Green " for "Wuyi ". So, It works incorrect, I have no ideas.
Thank you for help!

You could use setw and left from iomanip for formating.
A quick example:
#include <string>
#include <vector>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <sstream>
using namespace std;
int main()
{
ifstream to_format("test/test.txt");
ofstream formatted("test/formatted.txt");
vector<vector<string>> item_matrix; //
// Populating the matrix.
for (string line; getline(to_format, line);)
{
item_matrix.push_back({});
stringstream line_(line); // string stream used for split the line according to the separator '|'
for (string item; getline(line_, item, '|');)
{
item_matrix.back().push_back(item); // Add items to the last row.
}
}
// Output the matrix to file.
// This assume all lines in the original file have the same number of blocks.
vector<string> new_lines;
for (int i = 0; i < item_matrix[0].size(); i++)
{
new_lines.push_back({});
for_each(item_matrix.begin(), item_matrix.end(), [&](vector<string> row){
formatted << setw(25) << left << row[i];
});
formatted << endl;
}
return 0;
}
Example input:
Chun mee |Wuyi |Genmai |
Pu-erth |Green |Flower mix |
Lightly sweet|Strong,smooth|Fresh, strong|
Example ouput:
Chun mee Pu-erth Lightly sweet
Wuyi Green Strong,smooth
Genmai Flower mix Fresh, strong

Well the go_line function which u use continue reading until the end of file is reached so that loop has no effect read this

Related

Why the output not show up according to my txt file?

Why can't I retrieve all of the data from a txt file using c++?
This is the data in the txt file:
Standard ;40 90 120
Delux ;70 150 200
VIP ;110 200 300
This is my coding:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <bits/stdc++.h>
#include <vector>
using namespace std;
struct Room
{
string roomType;
float tripleBed;
float doubleBed;
float singleBed;
};
void displayRoom(Room []);
void inputRoom(ifstream &, Room []);
int main()
{
Room choice[3];
ifstream room("Room.txt");
if(room.fail())
{
cout<<"File does not exist\n";
cout<<"Press any key to exit the program\n";
return -1;
}
inputRoom(room, choice);
displayRoom(choice);
room.close();
return 0;
}
void displayRoom(Room choice[])
{
cout<<"\n\n************** ROOMS SECTION ***************\n"<<endl;
cout<<"ROOM TYPE"<<"\t"<<"TRIPLE BEDDED"<<"\t"<<"DOUBLE BEDDED"<<"\t"<<"SINGLE BEDDED"<<endl;
for(int i=0; i<3; i++)
{
cout<<choice[i].roomType;
cout<<"RM"<<choice[i].tripleBed<<"\t\tRM"<<choice[i].doubleBed<<"\t\tRM"<<choice[i].singleBed<<endl;
}
}
void inputRoom(ifstream &room, Room choice[])
{
string tokens[4];
string line;
int j = 0;
while (room.good())
{
int i = 0;
getline(room, line);
stringstream ss (line);
string temp;
while (getline (ss, temp, ';'))
{
tokens[i] = temp;
i++;
}
choice[j].roomType = tokens[0];
choice[j].tripleBed = atof(tokens[1].c_str());
choice[j].doubleBed = atof(tokens[2].c_str());
choice[j].singleBed = atof(tokens[3].c_str());
j++;
}
}
This is the output
************** ROOMS SECTION ***************
ROOM TYPE TRIPLE BEDDED DOUBLE BEDDED SINGLE BEDDED
Standard RM40 RM0 RM0
Delux RM70 RM0 RM0
VIP RM110 RM0 RM0
--------------------------------
Process exited with return value 0
Press any key to continue . . .
As you can see, at double bedded and single bedded column should have a value that has been defined by me but why the value of the columns zero? can someone help me? Thank you in advance for helping me.
Look at your input loop
while (getline (ss, temp, ';'))
{
tokens[i] = temp;
i++;
}
that reads tokens separated by semicolons.
Look at you actual input
Standard ;40 90 120
Only the first and second token are separated by a semicolon. The rest are separated by spaces.
The simple thing to do would be to edit your data so that it matches your code. E.g.
Standard;40;90;120

How to start reading file from a particular position c++

I am reading a file using fstream and getline functions. I want to give a starting position e.g. my file has 13 lines I want to start reading it from 7th line for example. Here is my code:
#include<iostream>
#include <stdlib.h>
#include <string>
#include <vector>
#include<iterator> // for iterators
#include<map>
using namespace std;
int main()
{
string line;
int start= 7;
unsigned long int index;
For( int z=1; z<=13; z++){
if (f_node.is_open())
{
getline(f_node, line);
if ((line.find("$EndNodes") != string::npos))
{
cout << "$EndNodes found file closed .... " << endl;
f_node.close();
return false;
}
// Point index.
int i = 0;
int j = line.find_first_of(" ", i);
index = strtoul((line.substr(i, j)).c_str(), NULL, 0);//
}
}
I am reading only indexes and I want to start it from 7th index How to do it?
To discard some number of lines, something like:
#include <fstream>
#include <string>
int main() {
std::ifstream infile{"myfile.txt"};
std::string line;
int starting_line = 7;
// Read and discard beginning lines
for (int n = 1; n < starting_line; n += 1) {
if (!std::getline(infile, line)) {
// Error or premature end of file! Handle appropriately.
}
}
while (std::getline(infile, line)) {
// Do something with the lines you care about.
}
return 0;
}
Except with actual error checking and handling and such.
"there is no way to tell code the starting position like seekg and tellg?" No. NL is just like any other character, it does not receive any special treatment.
You simply must scan the stream, counting the new-line character:
std::istream& seek_line(std::istream& is, const int n, std::ios_base::seekdir way = std::ios_base::beg)
{
is.seekg(0, way);
int i = 0;
char c;
while (is.get(c) && i < n)
if (c == '\n')
++i;
is.putback(c);
return is;
}
And this is how you use the above function:
int main()
{
using namespace std;
ifstream is{ "c:\\temp\\test.txt" };
if (!is)
return -1;
if (!seek_line(is, 3))
return -2;
string s;
getline(is, s);
cout << s << endl;
return 0;
}

C++ Problem with space detection in an Array String

I'm currently writting a program where I try to filter extra spaces so if there are more than 1 spaces in a row, I discard the rest leaving only one
But this is only the first step because the aim of the program is to parse a txt file with mips assembly instructions.
So far I've opened the file, stored the content in a vector and then stored the vector content in an array. Then I check, if you find a char 2 times in a row shift the array to the left.
The problem is that the code works well for any other letter, except for the space character. (On the code below I test it with the 'D' character and it works)
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
class myFile {
vector<string> myVector;
public:
void FileOpening();
void file_filter();
};
void myFile::FileOpening() {
string getcontent;
ifstream openfile; //creating an object so we can open files
char filename[50];
int i = 0;
cout << "Enter the name of the file you wish to open: ";
cin.getline(filename, 50); //whatever name file the user enters, it's going to be stored in filename
openfile.open(filename); //opening the file with the object I created
if (!openfile.is_open()) //if the file is not opened, exit the program
{
cout << "File is not opened! Exiting the program.";
exit(EXIT_FAILURE);
};
while (!openfile.eof()) //as long as it's not the end of the file do..
{
getline(openfile, getcontent); //get the whole text line and store it in the getcontent variable
myVector.push_back(getcontent);
i++;
}
}
void myFile::file_filter() {
unsigned int i = 0, j = 0, flag = 0, NewLineSize, k, r;
string Arr[myVector.size()];
for (i = 0; i < myVector.size(); i++) {
Arr[i] = myVector[i];
}
//removing extra spaces,extra line change
for (i = 0; i < myVector.size(); i++) {
cout << "LINE SIZE" << myVector[i].size() << endl;
for (j = 0; j < myVector[i].size(); j++) {
//If I try with this character for example,
//it works (Meaning that it successfully discards extra 'Ds' leaving only one.
// But if I replace it with ' ', it won't work. It gets out of the loop as soon
//as it detects 2 consecutive spaces.
if ((Arr[i][j] == 'D') && (Arr[i][j + 1] == 'D')) {
for (k = j; k < myVector[i].size(); k++) {
Arr[i][k] = Arr[i][k + 1];
flag = 0;
j--;
}
}
}
}
for (i = 0; i < myVector.size(); i++) {
for (j = 0; j < myVector[i].size(); j++) //edw diapernw tin kathe entoli
{
cout << Arr[i][j];
}
}
}
int main() {
myFile myfile;
myfile.FileOpening();
myfile.file_filter();
}
My question is, why does it work with all the characters except the space one, and how do I fix this?
Thanks in advace.
Wow. Many lines of code. I can only recomend to learn more about the STL and algorithms.
You can read the complete file into a vector using the vectors "range"-constructor and std::istream_iterator. Then you can replace one or more spaces in a string by using a std::regex. This is really not complicated.
In the below example, I do all the work, with 2 lines of code in function main. Please have a look:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
#include <fstream>
#include <regex>
using LineBasedTextFile = std::vector<std::string>;
class CompleteLine { // Proxy for the input Iterator
public:
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; }
// Cast the type 'CompleteLine' to std::string
operator std::string() const { return completeLine; }
protected:
// Temporary to hold the read string
std::string completeLine{};
};
int main()
{
// Open the input file
std::ifstream inputFile("r:\\input.txt");
if (inputFile)
{
// This vector will hold all lines of the file. Read the complete file into the vector through its range constructor
LineBasedTextFile text{ std::istream_iterator<CompleteLine>(inputFile), std::istream_iterator<CompleteLine>() };
// Replace all "more-than-one" spaces by one space
std::for_each(text.begin(), text.end(), [](std::string& s) { s = std::regex_replace(s, std::regex("[\\ ]+"), " "); });
// For Debug purposes. Print Result to std::out
std::copy(text.begin(), text.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
I hope, I could give you some idea on how to proceed.

Insertion and Deletion in list <string>

I am currently writing a small program to insert or delete a row in a list of string read from an input text file.
This is my code
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <list>
using namespace std;
int main()
{
list <string> buffer;
string fileName = "input.txt";
ifstream file(fileName);
if (file.is_open())
{
string line;
while (getline(file, line))
{
//store each line in the buffer
buffer.push_back(line);
}
}
list<string>::const_iterator it;
it = buffer.begin();
int position = 1;
for (int n = 0; n < position; ++n)
{
++it;
}
string input("This is a new line");
buffer.insert(it, 1, input);
//I can then use erase function to delete a line
system("pause");
return 0;
}
The buffer list has
This is line 1
This is line 2
This is line 3
This is line 4
I want to know if there are other ways (maybe more efficient) to insert or delete a line in the buffer. Thank you!
There are several versions of list<>::insert(). One of them inserts a single element, so you can replace this:
buffer.insert(it, 1, input);
with:
buffer.insert(it, input);
You can also use list<>::emplace() to create the string in place :
buffer.emplace(it, "This is a new line");
You can simplify this:
list<string>::const_iterator it;
it = buffer.begin();
int position = 1;
for (int n = 0; n < position; ++n)
{
++it;
}
to:
auto it = buffer.begin();
advance(it, 1);

Loop won't stop at end of file

I'm working on file io, and i've managed to get the data from the file into the vector i made, but when i print the values, i get garbage numbers after the last part of the data. So i'm guessing its pushing values that don't exist into the vector, or its trying to print parts of the vector that don't exist. Any help would be great.
main.cpp
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include "store.h"
using namespace std;
int main ()
{
store data;
ifstream inFile ("C:/Users/Owner/Desktop/Albums.csv");
string line;
string item;
int num;
int itemnum;
int linenum = 1;
ostringstream convert;
string temp;
while (!inFile.eof())
{
while (getline (inFile, line) )
{
istringstream linestream(line);
itemnum = 0;
num = 0;
convert << linenum;
temp = convert.str();
data.addtovectv(temp);
while (getline (linestream, item, ',') )
{
if (itemnum == 1 || itemnum == 2 || itemnum == 3 || itemnum == 5)
{
num++;
data.addtovectfullline(0, item);
}
itemnum++;
}
linenum++;
}
}
data.print();
inFile.close();
return 0;
}
store.h
#ifndef STORE_H
#define STORE_H
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
class store
{
public:
store();
void addtovectv(string);
void addtovectfullline(int, string);
void print();
private:
vector<string> v;
vector< vector<string> > fullline;
};
#endif
store.cpp
#include "store.h"
store::store()
{
}
void store::addtovectv(string a)
{
v.push_back(a);
fullline.push_back(v);
}
void store::addtovectfullline(int a, string c)
{
fullline[a].push_back(c);
}
void store::print()
{
for(unsigned int i=0; i<fullline.size(); i++)
{
for(unsigned int j=0; j<fullline[i].size(); j++)
{
cout << fullline[i][j] << endl;
}
cout << endl;
}
}
edit: some sample data
RS 500 compilations, Various Artists, The Sun Records Collection, 308
Both lists, A Tribe Called Quest, The Low End Theory, 1991, 154, Jive, Skeff Anselm, Zombart JK, USA, 48:08:52
Both lists, AC/DC, Back in Black, 1980, 73, ATCO, Robert John Lange, Bob Defrin, Australia / UK, 41:36:52
Both lists, AC/DC, Highway to Hell, 1979, 199, Albert Productions, Robert John Lange, Bob Defrin Australia / UK, 41:53:52
i need to read the lines, but only put the second, third, fourth, and sixth piece of info into the vectors, which is what it should end up printing, with each individual piece on a new line. All the data is stored in a .csv file
with this sample data, my output is this screenshot: http://puu.sh/bHtHM.png
however, none of those numbers at the bottom should be there, and there is a weird space after the first set of data
edit2: realized that odd space was an absence of the data i asked for, so its fine
In.good() is not the appropriate way to tell if the file is done.
(From http://www.cplusplus.com/reference/ios/ios/good/)
Ios::eof() checks for end of file.
Ios::Good() checks for no errors in opening. It probably exits the loop when an error occurs from reading past EOF.