cadavid4j
cadavid4j

Reputation: 171

Reading from file and avoiding white space in blank lines

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

Answers (2)

Jo&#227;o Augusto
Jo&#227;o Augusto

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

PiotrNycz
PiotrNycz

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

Related Questions