Currently learning c++ and I'm pretty stumped. I want to count the instances of a character in a text file - but not including lines that start with a certain character. Specifically, I'm counting instances of Gs and Cs in a text file, but not including lines that begin with "*"
Example
*metadata information
atgctaatgcaggtcagtcagtcagtcatgcg
atgcagtcagtcactgactgactgactgaata
*metadata information
atgtagcagctagtcagtcagtcagcatatat
gatcgactagctgactgacgtactgactgaat
char Z;
long GC=0;
string Line;
while(getline(InFile, Line))
{
if(Line[0]=='*')
{
InFile.get(Z);
while(InFile.get(Z))
{
if(Z=='G' || Z=='C' || Z=='g' || Z=='c')
{
++GC;
}
}
}
}
I'm able to count the instances of g and c across the entire text, but just haven't been able to limit the function to lines that do not begin in >
My understanding of your requirements, you want to ignore lines starting with '*'.
while (getline(InFile, Line))
{
if (Line[0] == '*')
{
continue; // ignore the line
}
for (int i = 0; i < Line.length(); ++i)
{
const char c = std::toupper(Line[i]);
if ((c == 'G') || (c == 'C`))
{
++GC;
}
}
}
In the above code, if the first line character is '*', the line is ignored.
Otherwise, the string is searched for 'G' or 'C' characters.
InFile.get(Z);
while(InFile.get(Z))
You don't want those lines. At this point in your code, the whole string has already been read in string Line;
You probably want
for(auto c: Line) // go over every char in Line
{
And you probably want to fix:
if(Line[0] != '*')
because
but not including lines that start with a certain character.
Related
I am trying to loop through a text file, scan it and find multi comments that starts with #| and end with |# and print it out. I am using get function to loop through each characters and the peek function to check for the next character. currently my code is not recognizing the ending comments. Please help.
I have tried looping through each characters comparing it with the multi comments and store it in a vector
void Scanner::readingThroughTheFiles(ifstream& inFile)
{
lineNumber = 0;
inFile.open(fileName);
while (!inFile.eof()) {
char c = '\0';
while (inFile.get(c)) { // loop getting single characters
tokens = c;
isAText(inFile);
isAWord(inFile);
// isAComment(inFile);
if (c == '\n') {
lineNumber++;
}
if (c == '#' && inFile.peek() == '|') {
char next = inFile.peek();
multipleComment += c;
multipleComment += next;
char c = tokens;
while (inFile.get(c)) {
multipleComment += c;
if (tokens == '|' && next == '#') {
tokenTypes.push_back(multipleComment);
values.push_back("COMMENT");
// lineNumbers.push_back(lineNumber);
multipleComment.clear();
}
}
}
The problem in your code is here:
if (tokens == '|' && next == '#') {
This condition can never be true, becasue you're setting next only once (a few lines above) and it's value is always |. See this line:
char next = inFile.peek();
And the second problem is that the variable tokens has always the value #. Maybe you want to do something like?
if (c == '|' && inFile.peek() == '#') {
// rest of your code
}
Edit: If you want to save the line number you should also check for \n in the second while loop. Otherwise your line number won't be increased if you comment spans over multiple lines.
But then you should store the line number temporarly before your enter the second while loop. If you don't do that the line number which is stored in your vector lineNumbers would be always the last line number.
int lineNumberSave = lineNumber;
while (inFile.get(c)) {
multipleComment += c;
if (c == '|' && inFile.peek() == '#') {
// rest of your code
lineNumbers.push_back(lineNumberSave);
}
}
I am learning c++ so bear with me and apologize for any idiocy beforehand.
I am trying to write some code that matches the first word on each line in a file called "command.txt" to either "num_lines", "num_words", or "num_chars".
If the first word of the first line does not match the previously mentioned words, it reads the next line.
Once it hits a matching word (first words only!) it prints out the matching word.
Here is all of my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream comm_in("commands.txt"); // opens file
string command_name = "hi"; // stores command from file
bool is_command() {
if (command_name == "num_words" || command_name == "num_chars" || command_name == "num_lines") {
return true;
} else {
return false;
}
}
// FIND a first word of a line in file THAT MATCHES "num_words", "num_chars" or "num_lines"
void get_command() {
string line;
char c;
while (!is_command()) { // if command_name does not match a command
// GET NEXT LINE OF FILE TO STRING
getline(comm_in, line);
// SUPPOSED TO GET THE FIRST WORD OF A STRING (CANT USE SSTREAM)
for (int i = 0; i < line.size(); i++) { // increment through line
c = line[i]; // assign c as index value of line
if (c == ' ' || c == '\t') { // if c is a space/tab
break; // end for loop
} else {
command_name += c; // concatenate c to command_name
} // if
} // for
} // while
return;
}
int main() {
get_command();
cout << command_name; // supposed to print "num_lines"
}
The contents of the command.txt file:
my bear is happy
and that it
great ha
num_lines sigh
It compiles properly, but when I run it in my terminal, nothing shows up; it doesn't seem to ever stop loading.
How can I fix this?
Unless you really want to hate yourself in the morning (so to speak) you want to get out of the habit of using global variables. You'll also almost certainly find life easier if you break get_command into (at least) two functions, one specifically to get the first word from the string containing the line.
I'd write the code more like this:
bool is_cmd(std::string const &s) {
return s == "num_words" || s == "num_chars" || s == "num_lines";
}
std::string first_word(std::istream &is) {
std::string line, ret;
if (std::getline(is, line)) {
auto start = line.find_first_not_of(" \t");
auto end = line.find_first_of(" \t", start);
ret = line.substr(start, end - start);
}
return ret;
}
void get_command(std::istream &is) {
std::string cmd;
while (!(cmd = first_word(is)).empty())
if (is_cmd(cmd)) {
std::cout << cmd;
break;
}
}
This still isn't perfect (e.g., badly formed input could still cause it to fail) but at least it's a move in what I'd say is a better direction.
If something goes wrong and you reach the end of file the loop will never stop. You should change getline(comm_in, line) to if(!getline(comm_in, line)) break;, or better yet, use that as the condition for the loop.
You also have to reset command_name for each pass:
while(getline(comm_in, line))
{
command_name = "";
for(int i = 0; i < line.size(); i++)
{
c = line[i];
if(c == ' ' || c == '\t')
break;
else
command_name += c;
}
if(is_command())
break;
}
// FIND a first word of a line in file THAT MATCHES "num_words", "num_chars" or "num_lines"
void get_command()
{
string line;
char c;
while (!is_command()) { // if command_name does not match a command
// GET NEXT LINE OF FILE TO STRING
if(getline(comm_in, line),comm_in.fail()){
// end reading
break;
}
//clear
command_name = "";
// SUPPOSED TO GET THE FIRST WORD OF A STRING (CANT USE SSTREAM)
for (int i = 0; i < line.size(); i++) { // increment through line
c = line[i]; // assign c as index value of line
if (c == ' ' || c == '\t') { // if c is a space/tab
break; // end for loop
} else {
command_name += c; // concatenate c to command_name
} // if
} // for
} // while
return;
}
The key of this problem is that you didn't clear the command_name.
What's more, you have to add a judge about whether reaching the end of the file.
ps: if(getline(comm_in, line),comm_in.fail()) is equal to if(getline(comm_in, line)),
I will keep it short and simple. After making sure that user is able to open a file succesfully, I have written the following piece of code to take a line from the inputFile.
string line;
int counter = 0;
DynIntStack stack;
while (!inputFile.eof())
{
getline(inputFile, line);
stringstream inputLine(line);
counter++;
//I NEED TO DO IT HERE
}
This will be used to write program to check balanced paranthesis in an input cpp file and I have to use stacks. Classic CS homework as I understand from the topics I have checked :)
counter is updated after every line and the line number(counter) is to be pushed to the stack if it has a opening bracket and it must be popped from the stack if it is a closing bracket. after these, the output should look something like this:
block: 3 - 3
block: 12 - 14
block: 10 - 14
block: 5 - 16
Syntax error in line 21.
But I do not know how to check the line I got char by char. I need a loop to check the chars and apply the previously mentioned things if an opening or closing bracket is found. How can I check the line char by char.
using any data container other than stacks is forbidden.
thank you very much :)
But I do not know how to check the line I got char by char
Is this what you want?
string line;
int counter = 0;
DynIntStack stack;
while (getline(inputFile, line))
{
counter++;
for(size_t i = 0; i < line.length(); i++) {
// line[i] is i'th character
if(line[i] == '(') {
// do stuff
}
else if(line[i] == ')') {
// do stuff
}
}
}
In addition to the correct answer by Kaidul Islam, a std::string support range based for loops.
string line;
int counter = 0;
DynIntStack stack;
while (getline(inputFile, line))
{
++counter;
for (char const c : line)
{
if (c == '(')
{
// do stuff
}
else if (c == ')')
{
// do stuff
}
}
}
I came across a problem in which I need to load data from a text file, and than save it into an array of string type. My approach is to consider the array as a 2D array, but of char type.
This is my code:
string *rollno;
rollno=new string[2];
string line;
ifstream in("file.txt",ios::app);
int i=0;
char single;
in.get(single);
while (single != '.') {
for (int j=0; single!=',' || single!='.'; j++) {
rollno[i][j]=single;\\saving in array character wise
}
in.get(single);\\getting the next line
i++;
}
cout<<rollno[0]<<endl<<rollno[1];\\checking
Could anyone help me figure out what I'm doing wrong?
Hmm... Not entirely sure what you're trying to do, but from the looks of it, wouldn't this be what you're looking for?
(Assuming i is the array index, and j is for std::string.operator[], as appears to be the case.)
// ...
while (single != '.') {
while (single != ',' && single != '.') {
rollno[i] += single; // appending to string.
}
in.get(single); //getting the next line
i++;
}
You can append a char to a std::string with operator+=, as described here.
Also, correct me if I'm wrong, but (single != ',' || single != '.') will always evaluate to true; if single == ',', then single != '.', and vice versa. If you want it to stop processing once it encounters either delimiter, then you use a logical AND to make sure it stops if either check fails.
(Apologies for any typoes or mistakes I may have missed.)
I'm trying to parse a file that has the following information
test_wall ; Comments!!
je,5
forward
goto,1
test_random;
je,9
I'm supposed to ignore comments after the ";" and move on to the next line. When there is a comma I'm trying to ignore the comma and store the second value.
string c;
int a;
c=getChar();
ifstream myfile (filename);
if (myfile.is_open())
{
while ( c != ';' && c != EOF)
{
c = getchar();
if( c == ',')
{
a= getChar();
}
}
}
myfile.close();
}
Here's some code. I'm not entirely sure I've understood the problem correctly, but if not hopefully this will set you on the right direction.
ifstream myfile (filename);
if (myfile.is_open())
{
// read one line at a time until EOF
string line;
while (getline(myFile, line))
{
// does the line have a semi-colon?
size_t pos = line.find(';');
if (pos != string::npos)
{
// remove the semi-colon and everything afterwards
line = line.substr(0, pos);
}
// does the line have a comma?
pos = line.find(',');
if (pos != string::npos)
{
// get everything after the comma
line = line.substr(pos + 1);
// store the string
...
}
}
}
I've left the section commented 'store the string' blank because I'm not certain what you want to do here. Possibly you are asking to convert the string into an integer before storing it. If so then add that code, or ask if you don't know how to do that. Actually don't ask, search on stack overflow, because that question has been asked hundreds of times.