I am new to c++ and I need help when reading and changing lines from an input file to use the next lines and saving it into another output file.
I have an example of a single DNA sequence stored in .fastq format, with the following structure.
#Read_1
AGACUUUACGCT
+
++//187-,/02
So each DNA sequence has four lines worth of information.
My goal is to split up the DNA string (line 2, length 12) into different fragments of random length and save each fragment as a separate new sequence. But to keep the .fastq structure I need to keep the information from lines 3 and 4! So the ideal output would be:
#Read_1_1
AGAC
+
++//
#Read_1_2
UU
+
18
#Read_1_3
UACGCT
+
7-,/02
In this ideal output, line 4 from the input has been split to match each DNA fragment (but i can do this with substr, so that's not a problem). My problem is when i am splitting the DNA sequences (line 2) and saving them as a new read, i need the information from line 3 and 4.
I am coding in C++ and i have made some functions which works and made some different attempts which fails:
When I'm opening the file I have made a function (DNA_fragmentation) which randomly splits the DNA (line2) into some fragments, like so:
AGAC
UU
UACGCT
So when I am using this function I am reading line 2, then saving these fragments into a std::vectorstd::string and using a for loop to save these fragments and their read (from line 1) into a new file, giving me the input:
#Read_1_1
AGAC
#Read_1_2
UU
#Read_1_3
UACGCT
My issue is I don't know how to add line 3 and line 4 for each of the new fragments, since they are created when im opening and reading line 2 from the original file. How do i extract information from the next lines?
To read the file and seperate the functions im using this:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
std::string fafq_seq(std::string in_name, std::string out_name) {
std::ifstream myfile(in_name);
std::ofstream out_file(out_name);
if (myfile.is_open() && out_file.is_open())
{
std::string line;
while( std::getline(myfile,line) )
{
int ID = 1;
std::string read_ID;
// This is line 1, which always match with #
if (line.rfind("#",0) == 0) {
continue;
} // Then reading line 2 the DNA sequence
else if (line.rfind("A", 0) == 0 ||
line.rfind("T", 0) == 0 ||
line.rfind("G", 0) == 0 ||
line.rfind("C", 0) == 0){
std::string Seq = line;
// creating a vector with each of the DNA pieces using my DNA_fragmentation function
std::vector<std::string> Damage = DNA_fragmentation(Seq,2,8);
// For each fragment im adding a new read and saving the output
for (int i=0; i<Damage.size();i++){
// adding what corresponds to line 1 starting with #
out_file << "#Read_" << ID << "_" << i+1 << std::endl;
// adding the DNA pieces
out_file << Damage[i] << std::endl;
}
ID += 1;
}
else {
// iterating through line 3 and 4, which is where im not sure how to handle my problem
out_file << line << std::endl;
}
}
out_file.close();
myfile.close();
}
}
int main() {
std::string File = "TestSeq.fastq";
fafq_seq(File,"Test_out.fastq");
return 0;
}
I know its a long question and a bit difficult for me to explain further, but i hope this problem makes sense. But just any comments or help would be appreciated. Thanks.
I think you could make your task much easier overall by reading in the full fastq fragment first, then split it into multiple fragments, and then finally output it all again.
If you make a struct for the fragment and add input and output operators (operator>> and operator<<) for it, then you can do the reading and writing in a very simple way:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
struct FastqFragment
{
std::string ID;
std::string sequence;
std::string delim;
std::string quality_value;
};
std::istream& operator>>(std::istream& in, FastqFragment& frag)
{
std::getline(in, frag.ID);
if (frag.ID.size() == 0 || frag.ID[0] != '#') {
in.setstate(std::ios_base::failbit);
return in;
}
std::getline(in, frag.sequence);
std::getline(in, frag.delim);
if (frag.delim.size() == 0 || frag.delim[0] != '+') {
in.setstate(std::ios_base::failbit);
return in;
}
std::getline(in, frag.quality_value);
return in;
}
std::ostream& operator<<(std::ostream& out, const FastqFragment& frag)
{
out << frag.ID << '\n';
out << frag.sequence << '\n';
out << frag.delim << '\n';
out << frag.quality_value << '\n';
return out;
}
I tried to add some very basic validation to the read operator, as you can see. Now you can use it something like this:
int main()
{
std::ifstream in("sequence.txt");
std::vector<FastqFragment> frags;
for (FastqFragment tmp; in >> tmp;) {
frags.push_back(tmp);
}
// Insert code for mutating the fragments
for (const auto& f : frags)
std::cout << f;
// or
std::ofstream out("output.txt");
for (const auto& f : frags)
out << f;
}
Now your DNA_fragmentation code can take a FastqFragment struct as argument and split all the strings that needs to be split at the same time.
Related
I have two text files like these:
11.txt:
1 5.66
2 4.95
3 2.55
4 0.99
5 2.87
NB.txt:
1 2 3 4 5
4 5 3 2 1
3 4 5 1 2
I have written the below code to fine, for example, "1" from File 1, and search it in File 2, then substitute "1" with "5.66". and repeat it for other numbers, i.e. 2,3,4,5. but I don't know why it doesn't work. additionally, it doesn't read the first line of 11.txt.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
double AtomId, Atom_radius,search ;
ifstream AtomId_file ("11.txt");
string namefile;
if (AtomId_file.is_open()){
for (int linenox = 0; getline (AtomId_file,line) && linenox < 6; linenox++){
if (linenox == 0) AtomId_file>>AtomId>>Atom_radius;
}
cout<<"AtomId: "<<AtomId<<" Atom_radius: "<<Atom_radius<<endl;
cout<<namefile<<"\n";
}
ifstream NB("NB.txt");
size_t pos;
if (NB.is_open())
{
search = AtomId;
getline(NB,line);
pos=line.find(search);
if(pos!=string::npos)
{
search = Atom_radius;
cout <<"Found!";
}
}
ofstream myfile;
myfile.open ("12.txt");
myfile << search << "\n";
}
the output in 12.txt is:
2
instead of :
5.66 4.95 2.55 0.99 2.87
0.99 2.87 2.55 4.95 5.66
2.55 0.99 2.87 5.66 4.95
I understand that your are new to C++.
I analyzed your code and put in tons of comments, where the errors are. You need to change your design. Before starting to type in code, you must first write down, what should be done. Then, and this is most important, you think (without taking any language into consideration) how you can solve the problem. This is most important. Also for you later programming career. The design is most important. So think 3 hours, how it could be done. Search possible design solutions in the internet. Write it on a piece of paper or somewhere.
Then, after hours of thinking, select an apropriate language and check, how it could be implemented.
I show a standard C++ solution below. You will not understand it immediately. So please try to understand the design first. Then lookup all used C++-statements in the internet and try to understand.
Read some good C++ books, before starting to code.
Please see first your commented code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std; // You should not use this line at all. Use qualified names.
int main()
{
string line;
double AtomId, Atom_radius, search; // These variables are not initalized
ifstream AtomId_file("r:\\11.txt");
string namefile;
if (AtomId_file.is_open()) { // You should not use is_open but simply if (AtomId_file)
// Here you have a loop running from 0,1,2,3,4,5. That are 6 loops. But you have only 5 lines in your sourcefile
// The you read one line, each time the loops runs. So in the beginning, this will read the first line
for (int linenox = 0; getline(AtomId_file, line) && linenox < 6; linenox++) {
// And only for the first loop event, when linenox==0, you read then next line "2 4.95"
// So you read already lines. But not more.
// ypu need to read line by line (only one per loop) and then store the result in an appropriate STL Container
if (linenox == 0) AtomId_file >> AtomId >> Atom_radius;
}
// Since you assigned the data only once, the values will be 2, 4.95
// They will never change
cout << "AtomId: " << AtomId << " Atom_radius: " << Atom_radius << endl;
// The variable namefile has never been initailized and is always emtpy, So ""
cout << namefile << "\n";
}
ifstream NB("r:\\NB.txt");
size_t pos; // Not initialized
if (NB.is_open()) // Not recommended. Use "if (NB) instead". In general, use more meaningful variable names
{
search = AtomId; // search is now 2 and never somthing else
getline(NB, line); // Read exactly one (and only this one time) a line containing 1, 5.66
pos = line.find(search); // So, 2 will never be found
if (pos != string::npos) // Always false, can never be true
{
search = Atom_radius; // Will never be executed
cout << "Found!"; // Will never be executed
}
}
ofstream myfile; // You can write directly ofstream myfile("12.txt");
myfile.open("12.txt");
myfile << search << "\n"; // And the output will always be 2.
}
And here is a correct and working example:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <iterator>
int main() {
// Open the file 11.txt and check, if it could be opened
if (std::ifstream file11("11.txt"); file11) {
// Define variable id and attribute and initialize them to theire default values.
unsigned int id{};
double attribute{};
// Here we will store all values (id, attribute) of all lines that we read in the follwing loop
std::unordered_map<unsigned, double> replacement{};
// Read in a llop ALL lines and extract id and attribute, and, check if this worked
while (file11 >> id >> attribute) {
// Create a new replacement value for id
replacement[id] = attribute;
}
// So, now, all data from file 11.txt is read and stored.
// We will now read the next file and store the data
// Open next input file NB.txt and check, if that worked
if (std::ifstream fileNB("NB.txt"); fileNB) {
// And already now, open output file 12.txt and check, if open worked
if (std::ofstream myfile("12.txt"); myfile) {
// Read a complete line and check, if that worked. Read all lines in a loop
for (std::string line; std::getline(fileNB, line); ) {
// Put the line in a std::istringstream, so that we can extract each single value
std::istringstream iss(line);
// We will store the single values of the just read line into a vector
// This we do, because we do not know, how many values will be in that line
// We use a so called iterator, to iterate over all elements in the just read line
// The result will be stored in a vector
// The istream_iterator will call the ">>"-operator, until the line is empty
// For the vector, we use its range constructor
std::vector values(std::istream_iterator<unsigned>(iss), {});
// Now go through all values, replace them and out the result into the output file
for (const unsigned& u : values) myfile << replacement[u] << " ";
myfile << "\n";
}
}
}
}
return 0;
}
Of course there are many other possible solutions
I'm coding in C++ and I'm trying to read in a file that I'd like to access certain chars at later. As in, what is the char at (line x, char y), at any given point in the file.
My only thought right now is to look for a newline character, and somehow index them so that I can refer back to newline x, check the length of a line, and pull a char at whatever position given the line length.
I'm not sure if that is a good approach or not.
Try this (for character in line "lineNum" and column "columnNum"):
ifstream inf;
inf.open(filename); //filename being c-string
string str;
for (int i = 0; i < lineNum; i++)
{
std::getline(inf, str);
}
This way "str" stores the line you are interested in (automatically checks for newline character and stops).
Then you can use:
char chr = str[columnNum];
to store the character you want in "chr" variable. And don't forget:
inf.close();
Unfortunately, to my knowledge you need to repeat this process every time you want to access a character.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#define FILENAME "File.txt"
class FileGrid {
public:
typedef std::vector<std::string> Line;
typedef std::vector<std::string>::const_iterator LineIter;
typedef std::vector<std::vector<std::string>> StringMap;
typedef std::vector<std::vector<std::string>>::const_iterator StringMapIter;
void FillGrid(char* fileName) {
grid.clear();
std::ifstream in(FILENAME, std::ifstream::in);
if (!in.is_open()) {
std::cout << "problem reading " << FILENAME << std::endl;
return;
}
std::string words;
std::string word;
std::stringbuf buffer;
while (in.is_open() && std::getline(in, words)) {
std::stringstream ss(words);
Line line;
while (ss >> word) {
line.push_back(word);
}
grid.push_back(line);
}
}
void PrintGrid() {
StringMapIter b = grid.begin();
StringMapIter e = grid.end();
std::cout << "\t\tFile Content:" << std::endl;
while(b != e) {
for (unsigned int i = 0; i < b->size(); ++i) {
std::cout << b->operator[](i) << " ";
}
std::cout << std::endl;
++b;
}
}
char const & GetChar(int lineNo, int charNo) {
// LineNo checks etc
Line const & line = grid[lineNo];
for(std::string const & word : line ) {
if(charNo > word.size() + 1) {
charNo -= word.size() + 1;
}
else {
return word[charNo];
}
}
throw std::exception("charNo higher");
}
private:
StringMap grid;
};
void main() {
FileGrid grid;
grid.FillGrid(FILENAME);
grid.PrintGrid();
std::cout << grid.GetChar(0, 3); // should return first line, 4th character
}
Not the best code I've ever written but pretty much what I could do in a short time.
FileGrid handles reading and accessing the data. It reads the file line by line and stores it in a std::vector. When it finishes reading a line, it pushes that into another std::vector. In the end, we have a (sort of) 2D array of strings.
Again, not the best code and definitely not the most optimized code but the idea is still the same: read from the file line by line, separate each word and put them into an array of strings. If you can't use STL, you can dynamically create a 2D array for each line but since I don't know the specific requirements of your question, I just wrote something simple and bruteforce to show you the main way of storing grid of strings into the memory.
As long as it works. But reading the entire file into memory, if that's an option, would be simpler.
I couldn't find the answer to my question elsewhere, so I thought I'd make a new question. I have a text file and each line is a series of numbers. I need to add each line up. But I don't know how many elements are on each line. So something like:
1 2 3 3 1
3 2 1 2
2 3 1 5 2 1
should output:
Line 1: 10
Line 2: 8
Line 3: 14
I know how to do this when the amount of numbers per line is known, but can't seem to figure it out otherwise. Thanks for any help.
Let file be an std::ifstream object ready to use:
std::string line;
while (std::getline(file, line)) { // for each line
std::istringstream iss(line);
int i;
while (iss >> i) { // for each int in line
// use i
}
}
You can store integers in a std::vector if you wish. It'll grow dynamically when needed.
The typical approach is to read a line using std::getline() and then decoding that line. That's a bit boring as it needs another stream. It can be done without.
The easiest way to not first read a line is probably to create a manipulator which skips whitespace but fails upon detecting a newline ('\n'). You would then use the manipulator, read the int, and if that is succcessful process the value. For example:
std::istream& skip_non_newline(std::istream& in) {
for (int c; std::isspace(c = in.peek()); ) {
if (c == '\n') {
in.setstate(std::ios_base::failbit);
}
else {
in.ignore();
}
}
}
// ....
while (in) {
int total = 0, value = 0;
while (in >> skip_non_newline >> value) {
tota += value;
}
if (!in.eof()) {
in.clear(); // failure was due to a format error or a newline being hit...
if (in.peek() != '\n') {
in.setstate(std::ios_base::failbit); // OK, not due to a newline...
}
}
}
Take each line and store it as a stringstream, then use that to extract each element, you'll know when it's empty because the STL defines a member methed called empty that returns true in such a case.
If you need simply output the sum of numbers in each line then you can do it the following way
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <numeric>
#include <iterator>
//...
std::string line;
size_t n = 0;
while ( std::getline( file, line ) )
{
std::istringstream is( line );
std::cout << "Line " << ++n << ": "
<< std::accumulate( std::istream_iterator<int>( is ),
std::istream_iterator<int>(), 0 )
<< std::endl;
}
was wondering if someone could give me a hand im trying to build a program that reads in a big data block of floats with unknown size from a csv file. I already wrote this in MATLAB but want to compile and distribute this so moving to c++.
Im just learning and trying to read in this to start
7,5,1989
2,4,2312
from a text file.
code so far.
// Read in CSV
//
// Alex Byasse
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <stdlib.h>
int main() {
unsigned int number_of_lines = 0;
FILE *infile = fopen("textread.csv", "r");
int ch;
int c = 0;
bool tmp = true;
while (EOF != (ch=getc(infile))){
if(',' == ch){
++c;
}
if ('\n' == ch){
if (tmp){
int X = c;
tmp = false;
}
++number_of_lines;
}
}
fclose(infile);
std::ifstream file( "textread.csv" );
if(!file){
std:cerr << "Failed to open File\n";
return 1;
}
const int ROWS = X;
const int COLS = number_of_lines;
const int BUFFSIZE = 100;
int array[ROWS][COLS];
char buff[BUFFSIZE];
std::string line;
int col = 0;
int row = 0;
while( std::getline( file, line ) )
{
std::istringstream iss( line );
std::string result;
while( std::getline( iss, result, ',' ) )
{
array[row][col] = atoi( result.c_str() );
std::cout << result << std::endl;
std::cout << "column " << col << std::endl;
std::cout << "row " << row << std::endl;
col = col+1;
if (col == COLS){
std:cerr << "Went over number of columns " << COLS;
}
}
row = row+1;
if (row == ROWS){
std::cerr << "Went over length of ROWS " << ROWS;
}
col = 0;
}
return 0;
}
My matlab code i use is >>
fid = fopen(twoDM,'r');
s = textscan(fid,'%s','Delimiter','\n');
s = s{1};
s_e3t = s(strncmp('E3T',s,3));
s_e4q = s(strncmp('E4Q',s,3));
s_nd = s(strncmp('ND',s,2));
[~,cell_num_t,node1_t,node2_t,node3_t,mat] = strread([s_e3t{:}],'%s %u %u %u %u %u');
node4_t = node1_t;
e3t = [node1_t,node2_t,node3_t,node4_t];
[~,cell_num_q,node1_q,node2_q,node3_q,node_4_q,~] = strread([s_e4q{:}],'%s %u %u %u %u %u %u');
e4q = [node1_q,node2_q,node3_q,node_4_q];
[~,~,node_X,node_Y,~] = strread([s_nd{:}],'%s %u %f %f %f');
cell_id = [cell_num_t;cell_num_q];
[~,i] = sort(cell_id,1,'ascend');
cell_node = [e3t;e4q];
cell_node = cell_node(i,:);
Any help appreciated.
Alex
I would, obviously, just use IOStreams. Reading a homogeneous array or arrays from a CSV file without having to bother with any quoting is fairly trivial:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
std::istream& comma(std::istream& in)
{
if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type(',')) {
in.setstate(std::ios_base::failbit);
}
return in.ignore();
}
int main()
{
std::vector<std::vector<double>> values;
std::istringstream in;
for (std::string line; std::getline(std::cin, line); )
{
in.clear();
in.str(line);
std::vector<double> tmp;
for (double value; in >> value; in >> comma) {
tmp.push_back(value);
}
values.push_back(tmp);
}
for (auto const& vec: values) {
for (auto val: vec) {
std::cout << val << ", ";
}
std::cout << "\n";
}
}
Given the simple structure of the file, the logic can actually be simplified: Instead of reading the values individually, each line can be viewed as a sequence of values if the separators are read automatically. Since a comma won't be read automatically, the commas are replaced by spaced before creating the string stream for the internal lines. The corresponding code becomes
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::vector<std::vector<double> > values;
std::ifstream fin("textread.csv");
for (std::string line; std::getline(fin, line); )
{
std::replace(line.begin(), line.end(), ',', ' ');
std::istringstream in(line);
values.push_back(
std::vector<double>(std::istream_iterator<double>(in),
std::istream_iterator<double>()));
}
for (std::vector<std::vector<double> >::const_iterator
it(values.begin()), end(values.end()); it != end; ++it) {
std::copy(it->begin(), it->end(),
std::ostream_iterator<double>(std::cout, ", "));
std::cout << "\n";
}
}
Here is what happens:
The destination values is defined as a vector of vectors of double. There isn't anything guaranteeing that the different rows are the same size but this is trivial to check once the file is read.
An std::ifstream is defined and initialized with the file. It may be worth checking the file after construction to see if it could be opened for reading (if (!fin) { std::cout << "failed to open...\n";).
The file is processed one line at a time. The lines are simply read using std::getline() to read them into a std::string. When std::getline() fails it couldn't read another line and the conversion ends.
Once the line is read, all commas are replaced by spaces.
From the thus modified line a string stream for reading the line is constructed. The original code reused a std::istringstream which was declared outside the loop to save the cost of constructing the stream all the time. Since the stream goes bad when the lines is completed, it first needed to be in.clear()ed before its content was set with in.str(line).
The individual values are iterated using an std::istream_iterator<double> which just read a value from the stream it is constructed with. The iterator given in is the start of the sequence and the default constructed iterator is the end of the sequence.
The sequence of values produced by the iterators is used to immediately construct a temporary std::vector<double> representing a row.
The temporary vector is pushed to the end of the target array.
Everything after that is simply printing the content of the produced matrix using C++11 features (range-based for and variables with automatically deduced type).
As proposed here changing getline escape may help you with better reading of csv file but you need to change type from string to int.
For dealing with any number of rows and cols you may use multi dimensional vector (vector inside vector as described here), then you have each row in one vector and all rows in the bigger vectors
int fclose(infile);
This line is wrong. The compiler thinks you're trying to initialize the variable fclose with a FILE*, which is wrong. It should be this if you're simply trying to close the file:
fclose(infile);
I intended this as an edit to Dietmar Kuhl's solution, but it was rejected as too large an edit...
The usual reason given for converting Matlab to C++ is performance. So I benchmarked these two solutions. I compiled with G++ 4.7.3 for cygwin with the following options "-Wall -Wextra -std=c++0x -O3 -fwhole-program". I tested on a 32-bit Intel Atom N550.
As input I used 2 10,000 line files. The first file was 10 "0.0" values per line, the second file was 100 "0.0" values per line.
I timed from the command line using time and I used the average of the sum of user+sys over three runs.
I modified the second program to read from std::cin as in the first program.
Finally, I ran the tests again with std::cin.sync_with_stdio(false);
Results (time in seconds):
sync no sync
10/line 100/line 10/line 100/line
prog A 1.839 16.873 0.721 6.228
prog B 1.741 16.098 0.721 5.563
The obvious conclusion is that version B is slightly faster, but more importantly, you should disable syncing with stdio.
I would like to read a text file and input its contents into an array. Then I would like to show the contents of the array in the command line.
My idea is to open the file using:
inFile.open("pigData.txt")
And then to get the contents of the file using:
inFile >> myarray [size]
And then show the contents using a for loop.
My problem is that the file I am trying to read contain words and I don't know how to get a whole word as an element in the array. Also, let's say that the words are divided by spaces, thus:
hello goodbye
Could be found on the file. I would like to read the whole line "hello goodbye" into an element of a parallel array. How can I do that?
Should be pretty straightforward.
std::vector<std::string> file_contents;
std::string line;
while ( std::getline(inFile,line) )
file_contents.push_back(line);
std::vector<std::string>::iterator it = file_contents.begin();
for(; it!=file_contents.end() ; ++it)
std::cout << *it << "\n";
Edit:
Your comment about having "hello goodbye" as element zero and element one is slightly confusing to me. The above code snip will read each line of the file and store that as an individual entry in the array 'file_contents'. If you want to read it and split it on spaces that is slightly different.
For context, you could have provided a link to your previous question, about storing two lists of words in different languages. There I provided an example of reading the contents of a text file into an array:
const int MaxWords = 100;
std::string piglatin[MaxWords];
int numWords = 0;
std::ifstream input("piglatin.txt");
std::string line;
while (std::getline(input, line) && numWords < MaxWords) {
piglatin[numWords] = line;
++numWords;
}
if (numWords == MaxWords) {
std::cerr << "Too many words" << std::endl;
}
You can't have one parallel array. For something to be parallel, there must be at least two. For parallel arrays of words, you could use a declarations like this:
std::string piglatin[MaxWords];
std::string english[MaxWords];
Then you have two options for filling the arrays from the file:
Read an entire line, and the split the line into two words based on where the first space is:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
piglatin[numWords] = line.substr(0, space);
english[numWords] = line.substr(space + 1);
++numWords;
}
Read one word at a time, and assume that each line has exactly two words on it. The >> operator will read a word at a time automatically. (If each line doesn't have exactly two words, then you'll have problems. Try it out to see how things go wrong. Really. Getting experience with a bug when you know what the cause is will help you in the future when you don't know what the cause is.)
while (input && numWords < MaxWords) {
input >> piglatin[numWords];
input >> english[numWords];
++numWords;
}
Now, if you really one one array with two elements, then you need to define another data structure because an array can only have one "thing" in each element. Define something that can hold two strings at once:
struct word_pair {
std::string piglatin;
std::string english;
};
Then you'll have just one array:
word_pair words[MaxWords];
You can fill it like this:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
words[numWords].piglatin = line.substr(0, space);
words[numWords].english = line.substr(space + 1);
++numWords;
}
Notice how the code indexes into the words array to find the next word_pair object, and then it uses the . operator to get to the piglatin or english field as necessary.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
// This will store each word (separated by a space)
vector<string> words;
// Temporary variable
string buff;
// Reads the data
fstream inFile("words.txt");
while(!inFile.eof())
{
inFile>>buff;
words.push_back(buff);
}
inFile.close();
// Display
for(size_t i=0;i<words.size();++i) cout<<words[i]<<" ";
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main ()
{
vector<string> fileLines;
string line;
ifstream inFile("pigData.txt");
if ( inFile.is_open() ) {
while ( !inFile.eof() ) {
getline(inFile, line);
fileLines.push_back(line);
}
inFile.close();
} else {
cerr << "Error opening file" << endl;
exit(1);
}
for (int i=0; i<fileLines.size(); ++i) {
cout << fileLines[i] << "\n";
}
cout << endl;
return 0;
}