Reading Lines after a line in C++ not working - c++

I've spent like 2 hours trying to parse the following bytes from a file :
>Rosalind_6404
CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCC
TCCCACTAATAATTCTGAGG
>Rosalind_5959
CCATCGGTAGCGCATCCTTAGTCCAATTAAGTCCCTATCCAGGCGCTCCGCCGAAGGTCT
ATATCCATTTGTCAGCAGACACGC
>Rosalind_0808
CCACCCTCGTGGTATGGCTAGGCATTCAGGAACCGGAGAACGCTTCAGACCAGCCCGGAC
TGGGAACCTGCGGGCAGTAGGTGGAAT
I would like to store the word Rosalind_, and store every line, concatenate all, and have just one string having all the lines.
I tried the following code, but it still doesn't work probably, I always miss the last line.
int main()
{
std::ifstream infile("data_set.txt");
map < int, string > ID;
map < int, string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
std::string line;
std::vector<string> dataSetString;
std::string seqid;
while (!infile.eof() )
{
while(std::getline(infile, line))
{
if ( line.substr(0,1)== ">")
{
conct = "";
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
lineNumber = 0;
line.clear();
std::string data= "";
if(dataSetString.size()>0)
{
for (int i = 0; i<dataSetString.size(); i++)
{
data+=dataSetString[i];
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
}
dataSetString.clear();
}
if(!line.empty() )
{
dataSetString.push_back(line);
}
}
}
I'm trying to practice problems solving approaches, and that really gave me headache.
I'm looking for a better approach also.

This code does what you want:
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::istream& infile = std::cin;
std::map < int, std::string > ID;
std::map < int, std::string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
std::string line;
std::vector<std::string> dataSetString;
std::string seqid;
bool success = std::getline(infile, line);
while(success) {
if( line.substr(0,1) == ">" ) {
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
std::string data;
while(success = std::getline(infile, line)) {
if(line.substr(0,1) == ">") break;
data += line;
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
} else {
std::cout << "Invalid input file. It needs to start with >SOME_ID" << std::endl;
return 1;
}
}
std::cout << "Parsed data ----------------" << std::endl;
for(std::map<int,std::string>::const_iterator it = dataSetMap.begin(); it != dataSetMap.end(); ++it) {
std::cout << "Id: " << ID[it->first] << std::endl;
std::cout << (it->second) << std::endl;
}
}
It first reads a line from the input file and tries to parse it as an ID. If that fails, it returns an error. Then it reads the data until it finds another ID or EOF. It inserts the data and continues to parse the ID it found if it didn't encounter EOF.
Working demo: http://ideone.com/F4mcrc
Note: This fails when the file is empty, you might want to check for the empty string or a string containing only whitespaces in the else of the ID check and skip it.

EDITED I have corrected my answer and tested it. So no more downvote please!
int main()
{
using namespace std;
ifstream infile("data_set.txt");
map < int, string > ID;
map < int, string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
string line;
vector<string> dataSetString;
string seqid;
while ( true)
{
bool b=infile.eof();
if(!b)
std::getline(infile, line);
if ( line.substr(0,1)== ">" || b)
{
if(!b)
{
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
}
line.clear();
string data= "";
if(dataSetString.size()>0)
{
for (unsigned int i = 0; i<dataSetString.size(); i++)
{
data+=dataSetString[i];
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
}
dataSetString.clear();
if(b)
break;
}
if(!line.empty() )
{
dataSetString.push_back(line);
}
}
return 0;
}

Related

How do I tell program to skip comma between quotation in C++?

I have file that contains
Name Age FavSport
Michael, "18,0" , "Soc,cer", Cricket, Hockey
John, "18,0", Cricket
Mitchell, "19,0", Soccer, "Hoc,key"
I am trying to read it into vector of class objects
#include <string>
#include <vector>
#include <fstream>
class Student {
public:
std::string name;
int age;
std::vector<std::string> favSport;
};
class Team {
public:
std::vector<Student> teamVec;
};
When I try to split file by comma it splits commas between quotation like 18,0 it think 18 and 0 separate and gives me error. Also same for Soc,cer, it thinks they are seperate. How can i tell program not to split between quotation. Can any please have a look at code and tell me where i can edit or edit for me please thank you
(I can't use stringstream since i havn't been to that chapter yet, what I have coded is kind of knowledge I know)
int main() {
std::string line;
std::vector<std::string> teamVec;
std::ifstream myfile("team.txt");
if (!myfile)
{
std::cout << "Error" << std::endl;
return -1;
}
bool firstLine = true;
Team myTeam;
while (std::getline(myfile, line))
{
if(firstLine) {
firstLine = false;
} else {
Student temp;
int times = 0;
size_t pos = 0;
std::string token;
while ((pos = line.find(',')) != std::string::npos) {
token = line.substr(0, pos);
times++;
if(times == 1) {
temp.name = token.substr(1,token.size()-2);
} else if(times == 2) {
temp.age = stoi(token);
} else {
temp.favSport.push_back(token);
}
std::cout << token << std::endl;
line.erase(0, pos + 2);
}
temp.favSport.push_back(line);
myTeam.teamVec.push_back(temp);
}
}
// USE myTeam
return 0;
}

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++ - Counting Occurences and passing values in Vector

So I believe the values from the text file go into the vector 'com', what i'm trying to do is recognize the direction then take the value next to direction, set to tmp variable, continue to read, if the direction occurs again, add the combine variable then override tmp variable, set final tmp variable to be passed on to another class. If Repeat has been 'seen' it looks at the last direction used and take the repeat value and add it to last direction used, Any help will be appreciated, sorry for any confusion in questioning
file1.txt:
Forward 2
Left 20
Forward 1
Repeat 3
fileReader.cpp
#include <iostream>
#include <float>
#include <vector>
using namespace std;
int main()
{
ifstream file("text1.txt");
string word;
vector<float> com;
while (file >> word)
{
if(std::find(std.begin(com), std.end(com), Forward) != com.end())
{
}
if(std::find(std.begin(com), std.end(com), Jump) != com.end())
{
}
if(std::find(std.begin(com), std.end(com), Left) != com.end()))
{
}
if(std::find(std.begin(com), std.end(com), Right) != com.end()))
{
}
if ((std::find(std.begin(com), std.end(com), Repeat) != com.end()))
{
}
}
}
You can use a map for parsing your input:
int main()
{
ifstream file("text1.txt"); //open file
if(!file) { /* file could not be opened */ } //and check whether it can be used
std::map<std::string, float> com;
std::string lastCom; //last command for use in "Repeat"
std::string line;
while (std::getline(file, line)) //read a line at once until file end
{
if(line.empty()) continue; //and continue if it is empty
std::string tempCom;
float tempVal;
std::stringstream ss(line); //extract command and value
ss >> tempCom;
ss >> tempVal;
if(tempCom == "Repeat")
{
com[lastCom] += tempVal; //add the value to the last command
}
else
{
com[tempCom] += tempVal; //add the value to the current command
lastCom = tempCom; //and update last command
}
}
}
The code is untested.
Well, I prefered to rewrite your code from scratch using a different container instead of filling the blanks:
#include <iostream>
#include <map>
#include <fstream>
#include <string>
int main() {
std::map<std::string,int> moves{{"Forward", 0}, {"Left", 0}, {"Right", 0},
{"Jump", 0 }, {"Repeat", 0}};
auto iRepeat = moves.find("Repeat");
auto iold = moves.end();
std::ifstream iFile("text1.txt");
if ( !iFile.good() ) return 1;
std::string s;
int x; // There aren't floats in your file...
while ( iFile >> s >> x ) {
auto im = moves.find(s);
if ( im == iRepeat ) {
if ( iold == moves.end() ) continue; // there must be a move to repeat
iold->second += x;
} else if ( im != moves.end() ){
im->second += x; // update the move
iold = im;
}
}
iFile.close();
for ( auto i = moves.begin(); i != moves.end(); i++ ) {
if ( i != iRepeat ) // shows only the moves
std::cout << i->first << ": " << i->second << std::endl;
}
return 0;
}
The output is:
Forward: 6
Jump: 0
Left: 20
Right: 0

Returning string from a function causing formatting issues

It's supposed to look like this: http://i.imgur.com/gko501E.png
Instead it looks like this: http://i.imgur.com/ISwqyD8.png
When I take the code out of the function and use it in the main class it works properly. However once I put it in this function the formatting problems occur, it also isn't filtering like it's supposed to. This program is supposed to take user input, store it in a string, remove all non-alphabetical characters, capitalize the vowels, and then space it out based on user defined variables given in the command line. It's also supposed to accept files as input in the command line, such as: 'program 5 8 < file'.
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
using namespace std;
//make vowels uppercase
string filter(string input)
{
size_t found = input.find_first_of("aeiou");
while (found != string::npos)
{
if (islower(input[found]))
{
input[found] = toupper(input[found]);
found = input.find_first_of("aeiou", found + 1);
}
}
//Make consonants lowercase
size_t foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ");
while (foundLower != string::npos)
{
if (isupper(input[foundLower]))
{
input[foundLower] = tolower(input[foundLower]);
foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ", foundLower + 1);
}
}
//remove punctuation
for (int i = 0, len = input.size(); i < len; i++)
{
if (!isalnum(input[i]))
{
input.erase(i--, 1);
len = input.size();
}
}
return input;
}
int main(int argc, char* argv[])
{
int wordSize;
int wordSizeCounter;
int wordCounter = 0;
int rowSize;
//char letter;
wordSize = atoi(argv[1]);
rowSize = atoi(argv[2]);
ifstream inFile;
inFile.open(argv[3]);//open the input file
stringstream strStream;
strStream << inFile.rdbuf();//read the file
string test = strStream.str();//str holds the content of the file
if (!inFile) test = cin.get() ; // Read first character
//Begin filter for files
while (!test.empty())
{
filter(test);
if (test.length() < wordSize) //make sure we don't go out-of-bounds
{
wordSize = test.length();
}
cout << test.substr(0, wordSize);
cout << " ";
if (test.length() >= wordSize) //again, make sure we don't go out-of-bounds
{
test = test.substr(wordSize);
}
else
{
test = " ";
}
wordCounter++;
if (wordCounter == rowSize)
{
cout << std::endl;
wordCounter = 0;
}
if(test.empty())
{
test = cin.get();
}
}
cout << endl;
return 0;
}

Printing input string words in reverse order

Using if and while/do-while, my job is to print following user's inputs (string value) in reverse order.
For example:
input string value : "You are American"
output in reverse order : "American are You"
Is there any way to do this?
I have tried
string a;
cout << "enter a string: ";
getline(cin, a);
a = string ( a.rbegin(), a.rend() );
cout << a << endl;
return 0;
...but this would reverse the order of the words and spelling while spelling is not what I'm going for.
I also should be adding in if and while statements but do not have a clue how.
The algorithm is:
Reverse the whole string
Reverse the individual words
#include<iostream>
#include<algorithm>
using namespace std;
string reverseWords(string a)
{
reverse(a.begin(), a.end());
int s = 0;
int i = 0;
while(i < a.length())
{
if(a[i] == ' ')
{
reverse(a.begin() + s, a.begin() + i);
s = i + 1;
}
i++;
}
if(a[a.length() - 1] != ' ')
{
reverse(a.begin() + s, a.end());
}
return a;
}
Here is a C-based approach that will compile with a C++ compiler, which uses the stack to minimize creation of char * strings. With minimal work, this can be adapted to use C++ classes, as well as trivially replacing the various for loops with a do-while or while block.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 1000
#define MAX_WORD_LENGTH 80
void rev(char *str)
{
size_t str_length = strlen(str);
int str_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx = 0;
for (str_idx = str_length - 1; str_idx >= 0; str_idx--)
word_buffer[word_buffer_idx++] = str[str_idx];
memcpy(str, word_buffer, word_buffer_idx);
str[word_buffer_idx] = '\0';
}
int main(int argc, char **argv)
{
char *line = NULL;
size_t line_length;
int line_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx;
/* set up line buffer - we cast the result of malloc() because we're using C++ */
line = (char *) malloc (MAX_LINE_LENGTH + 1);
if (!line) {
fprintf(stderr, "ERROR: Could not allocate space for line buffer!\n");
return EXIT_FAILURE;
}
/* read in a line of characters from standard input */
getline(&line, &line_length, stdin);
/* replace newline with NUL character to correctly terminate 'line' */
for (line_idx = 0; line_idx < (int) line_length; line_idx++) {
if (line[line_idx] == '\n') {
line[line_idx] = '\0';
line_length = line_idx;
break;
}
}
/* put the reverse of a word into a buffer, else print the reverse of the word buffer if we encounter a space */
for (line_idx = line_length - 1, word_buffer_idx = 0; line_idx >= -1; line_idx--) {
if (line_idx == -1)
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s\n", word_buffer);
else if (line[line_idx] == ' ')
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s ", word_buffer), word_buffer_idx = 0;
else
word_buffer[word_buffer_idx++] = line[line_idx];
}
/* cleanup memory, to avoid leaks */
free(line);
return EXIT_SUCCESS;
}
To compile with a C++ compiler, and then use:
$ g++ -Wall test.c -o test
$ ./test
foo bar baz
baz bar foo
This example unpacks the input string one word at a time,
and builds an output string by concatenating in reverse order.
`
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string inp_str("I am British");
string out_str("");
string word_str;
istringstream iss( inp_str );
while (iss >> word_str) {
out_str = word_str + " " + out_str;
} // while (my_iss >> my_word)
cout << out_str << endl;
return 0;
} // main
`
This uses exactly one each of if and while.
#include <string>
#include <iostream>
#include <sstream>
void backwards(std::istream& in, std::ostream& out)
{
std::string word;
if (in >> word) // Read the frontmost word
{
backwards(in, out); // Output the rest of the input backwards...
out << word << " "; // ... and output the frontmost word at the back
}
}
int main()
{
std::string line;
while (getline(std::cin, line))
{
std::istringstream input(line);
backwards(input, std::cout);
std::cout << std::endl;
}
}
You might try this solution in getting a vector of string's using the ' ' (single space) character as a delimiter.
The next step would be to iterate over this vector backwards to generate the reverse string.
Here's what it might look like (split is the string splitting function from that post):
Edit 2: If you don't like vectors for whatever reason, you can use arrays (note that pointers can act as arrays). This example allocates a fixed size array on the heap, you may want to change this to say, double the size when the current word amount has reached a certain value.
Solution using an array instead of a vector:
#include <iostream>
#include <string>
using namespace std;
int getWords(string input, string ** output)
{
*output = new string[256]; // Assumes there will be a max of 256 words (can make this more dynamic if you want)
string currentWord;
int currentWordIndex = 0;
for(int i = 0; i <= input.length(); i++)
{
if(i == input.length() || input[i] == ' ') // We've found a space, so we've reached a new word
{
if(currentWord.length() > 0)
{
(*output)[currentWordIndex] = currentWord;
currentWordIndex++;
}
currentWord.clear();
}
else
{
currentWord.push_back(input[i]); // Add this character to the current word
}
}
return currentWordIndex; // returns the number of words
}
int main ()
{
std::string original, reverse;
std::getline(std::cin, original); // Get the input string
string * arrWords;
int size = getWords(original, &arrWords); // pass in the address of the arrWords array
int index = size - 1;
while(index >= 0)
{
reverse.append(arrWords[index]);
reverse.append(" ");
index--;
}
std::cout << reverse << std::endl;
return 0;
}
Edit: Added includes, main function, while loop format
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
// From the post
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
int main ()
{
std::string original, reverse;
std::cout << "Input a string: " << std::endl;
std::getline(std::cin, original); // Get the input string
std::vector<std::string> words = split(original, ' ');
std::vector<std::string>::reverse_iterator rit = words.rbegin();
while(rit != words.rend())
{
reverse.append(*rit);
reverse.append(" "); // add a space
rit++;
}
std::cout << reverse << std::endl;
return 0;
}
This code here uses string libraries to detect the blanks in the input stream and rewrite the output sentence accordingly
The algorithm is
1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero.
2. Look for the first space in the input stream
3. If no space is found, the input stream is the output
4. Else, get the position of the first blank after pos1, i.e. pos2.
5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence.
6. Pos1 is now at the first char after the blank.
7. Repeat 4, 5 and 6 untill no spaces left.
8. Add the last sub-string to at the beginning of the newSentence. –
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string sentence;
string newSentence;
string::size_type pos1;
string::size_type pos2;
string::size_type len;
cout << "This sentence rewrites a sentence backward word by word\n"
"Hello world => world Hello"<<endl;
getline(cin, sentence);
pos1 = 0;
len = sentence.length();
pos2 = sentence.find(' ',pos1);
while (pos2 != string::npos)
{
newSentence = sentence.substr(pos1, pos2-pos1+1) + newSentence;
pos1 = pos2 + 1;
pos2 = sentence.find(' ',pos1);
}
newSentence = sentence.substr(pos1, len-pos1+1) + " " + newSentence;
cout << endl << newSentence <<endl;
return 0;
}