Reputation: 171
I'm currently working on a project where I'm reading in commands and I need to avoid whitespace on lines that are blank. I've done good up to this point but for some reason I just can't seem to figure out how to make it work. I thought if(opcode == "\t" || opcode == " ")continue;
would take care of, but it didn't. If someone could please have a look and help me out that'd be great.
Here's a small sample of the commands I'm reading in. They are in [label] opcode [arg1][,arg2] format.
#Sample Input
LA 1,1
LA 2,2
\t <<<<<<<Here just to show that it's a blank line with only a tab
TOP NOP
Here is my code:
int counter = 0;
int i = 0;
int j = 0;
int p = 0;
while (getline(myFile, line, '\n'))
{
if (line.length() == 0)
{
continue;
}
if (line[0] == '#')
{
continue;
}
// If the first letter isn't a tab or space then it's a label
if (line[0] != '\t' && line[0] != ' ')
{
string delimeters = "\t ";
int current;
int next = -1;
current = next + 1;
next = line.find_first_of( delimeters, current);
label = line.substr( current, next - current );
Symtablelab[i] = label;
Symtablepos[i] = counter;
if(next>0)
{
current = next + 1;
next = line.find_first_of(delimeters, current);
opcode = line.substr(current, next - current);
if (opcode != "WORDS" && opcode != "INT")
{
counter += 3;
}
if (opcode == "INT")
{
counter++;
}
if (next > 0)
{
delimeters = ", \n\t";
current = next + 1;
next = line.find_first_of(delimeters, current);
arg1 = line.substr(current, next-current);
if (opcode == "WORDS")
{
counter += atoi(arg1.c_str());
}
}
if (next > 0)
{
delimeters ="\n";
current = next +1;
next = line.find_first_of(delimeters,current);
arg2 = line.substr(current, next-current);
}
}
i++;
}
// If the first character is a tab or space then there is no label and we just need to get a counter
if (line[0] == '\t' || line[0] == ' ')
{
string delimeters = "\t \n";
int current;
int next = -1;
current = next + 1;
next = line.find_first_of( delimeters, current);
label = line.substr( current, next - current );
if(next>=0)
{
current = next + 1;
next = line.find_first_of(delimeters, current);
opcode = line.substr(current, next - current);
if (opcode != "WORDS" && opcode != "INT")
{
counter += 3;
}
if (opcode == "INT")
{
counter++;
}
if (next > 0)
{
delimeters = ", \n\t";
current = next + 1;
next = line.find_first_of(delimeters, current);
arg1 = line.substr(current, next-current);
if (opcode == "WORDS")
{
counter += atoi(arg1.c_str());
}
}
if (next > 0)
{
delimeters ="\n\t ";
current = next +1;
next = line.find_first_of(delimeters,current);
arg2 = line.substr(current, next-current);
}
}
}
}
Upvotes: 1
Views: 2766
Reputation: 2305
You should probably try to make the reading of commands more "generic". Assuming a line to be valid must start with a label and your labels can only contain "letters", instead of checking for '\t', '\n', '\r', '#', (...) Why don't you just use the function isalpha ?
Then you need to get the arguments, and assuming they are delimited by ',' your best approach is to split the line according to the ',' delimiter.
Some sample code, that gets you the "label" and a vector with the "arguments", I suggest that you also validate the label (ex. check if the label is only consisted with letters, and assuming that you know the "commands" validate the number and type of arguments that you are retrieving for a specific label.
std::ifstream inStream("c:\\data\\dump.txt");
if(!inStream.fail())
{
while(!inStream.eof())
{
std::string strLine;
std::getline(inStream, strLine);
// Label ?
if( isalpha(strLine[0]))
{
int iIndexOf = strLine.find(" ");
if(iIndexOf != string::npos)
{
std::string strLabel = strLine.substr(0, iIndexOf);
// Arguments ?
std::vector<std::string> vArguments;
std::stringstream ss(strLine.substr(iIndexOf, strLine.size() - iIndexOf));
std::string strArgument;
while(std::getline(ss, strArgument, ','))
{
if(strArgument.size()!=0)
vArguments.push_back(strArgument);
}
std::cout << "label: " << strLabel << std::endl << "arguments list: ";
for(size_t i=0; i<vArguments.size(); i++)
std::cout << vArguments[i] << ";";
std::cout << std::endl;
}
else
{
// No Arguments
std::string strLabel = strLine;
std::cout << "label: " << strLabel << std::endl;
}
}
}
inStream.close();
}
Upvotes: 0
Reputation: 24412
Use std::stringstream and read from your line to std::string variables. In this way the blank will be omitted.
[UPDATE] If you want to remove blank whitespace from the beginning:
s.erase(s.find_last_not_of(" \n\r\t")+1);
[UPDATE2] Or just count words while reading:
Like in this example:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string line;
while (std::getline(std::cin, line))
{
std::string lineNoWS = line;
lineNoWS.erase(lineNoWS .find_last_not_of(" \n\r\t")+1);
if (lineNoWS.empty())
std::cout << "EMPTY LINE\n";
std::string word;
unsigned words = 0;
std::istringstream line_is(line);
while(line_is >> word)
{
std::cout << '\'' << word << "'\n";
++words;
}
std::cout << "(" << words << ")ENDLINE\n";
}
}
Just replace std::cin with your ifstream(file)
.
Upvotes: 1