Counting number of 'if' statements in SAS I am writing a C# script to count all the 'if...then' statements present in 4000 lines of SAS code. I am taking the SAS code as a text file and then performing my operation. Here's my C# code:

class Program
{

static void Main(string[] args)
{

    List&lt;String&gt; list = new List&lt;string&gt;();
    list = File.ReadAllLines(@"C:\Users\Dey\Documents\Trucks\file.doc").ToList();
    int count = CountIfs(list);
    Console.ReadKey();
}

static int CountIfs(List&lt;String&gt; list)
{
    int count = 0;
    var index = new List&lt;int&gt;();
    var value = new List&lt;String&gt;();

    for (int i = 0; i &lt; list.Count; i++)
    {
        if (list[i].Contains("if"))
        {
            if (list[i].Contains("then") || list[i + 1].Contains("then"))
            {
                count++;
                index.Add(i);
                String temp = null;

                if(list[i].Contains(";"))
                temp = list[i].Substring(0, list[i].IndexOf(";"));

                if (temp != null)
                {
                    value.Add(temp);
                }  
            }

        }
    }
    return count;
}
}


I'm essentially checking for "if" per line and if that is found, i'm checking for "then". And finally I'm also making sure its one line of code by checking for ";" . My logic is that if all these conditions satisfy, then I am indeed able to extract all the if-statements from the code. The list "value" would contain all the "if" statements found in the code. Now I've output "value" to a textfile in notepad and have manually cross-checked about 20 entries. And so far it seems to be working alright. I was hoping someone can proof-read my code and tell me if I can improve it somewhere perhaps? Or is this logic sufficiently accurate?
The code in question has some flaws which I will address here:

var index = new List&lt;int&gt;(); isn't really used and should be removed
var value = new List&lt;String&gt;(); isn't really used and should be removed
The method parameter List&lt;String&gt; list isn't used as a List&lt;T&gt; but rather like an array hence it should be an array.


Fixing these points leads to
private static int CountIfs(string[] linesOfCode)
{
    var count = 0;

    for (int i = 0; i &lt; linesOfCode.Length; i++)
    {
        var line = linesOfCode[i];
        if (line.Contains(&quot;if&quot;))
        {
            if (line.Contains(&quot;then&quot;) || line[i + 1].Contains(&quot;then&quot;))
            {
                count++;
            }
        }
    }
    return count;
}

Now the code looks much cleaner and smaller.


An if will always be the first statement in a line of code after removing any leading whitespace and will have a trailing whitespace. Using Contains() can lead to many false positives. Assume a line of code contains the following text:
&quot;I received the tif-file of this invoice from my partner in athen.&quot;

A then will always have a leading whitespace and either have a trailing whitespace or will be the first part of a line of code after removing leading whitespace.

Like mentioned in @Paparazzi's answer you could run into an IndexOutOfRangeException by accessing list[i + 1].


Let us introduce a new method which just handles the check for the if statement.
private static bool HasIfStatement(string line)
{
    return line.Trim().StartsWith(&quot;if &quot;);
}

No we need a method to check for a then.
private static string[] spaceArray = new string[] { &quot; &quot; };
private static bool HasThenStatement(string line)
{
    return line.Split(spaceArray , StringSplitOptions.RemoveEmptyEntries).Any(w =&gt; w == &quot;then&quot;);
}

Well this method is some kind of quick &amp; dirty because it will create a lot of strings. I will leave it to you to make it better.
By adding a flag for the case that the line had an if and doesn't had an then we can't get an IndexOutOfRangeException anymore. As a sideeffect we could now use a foreach loop and have an IEnumerable&lt;string&gt; as the methods parameter type.
Putting all together could look like so
private static int CountIfs(IEnumerable&lt;string&gt; linesOfCode)
{
    var count = 0;
    var lastLineHadIf = false;
    foreach (var line in linesOfCode)
    {
        if (lastLineHadIf)
        {
            lastLineHadIf = false;
            if (HasThenStatement(line))
            {
                count++;
            }
        }
        else if (HasIfStatement(line))
        {
            if (HasThenStatement(line))
            {
                count++;
            }
            else
            {
                lastLineHadIf = true;
            }
        }
    }
    return count;
}

private static bool HasIfStatement(string line)
{
    return line.Trim().StartsWith(&quot;if &quot;);
}

private static string[] spaceArray = new string[] { &quot; &quot; };
private static bool HasThenStatement(string line)
{
    return line.Split(spaceArray , StringSplitOptions.RemoveEmptyEntries).Any(w =&gt; w == &quot;then&quot;);
}  

I don't know about case-sensitivity of if and then so you may adjust the code to take this into account.
This code doesn't take comments into account, so you should adjust the code for comments as well.