简体   繁体   中英

Print the line after a matching word from a text file (C#)

I am reading from a text file which basically looks like:

>Name
>12345

>Name2
>32458

>Name3
>82745

and so on. I want it so once the program detects Name it prints both Name and the line after it: 12345 to the console.

Here is my code so far:

if (args[0] == "prog1")
{
    List<string> lines = File.ReadAllLines(filename).ToList();

        foreach (var line in lines)
        {
            if (line.Contains("Name"))
            {
                Console.WriteLine(line);
            }
        }
}

So far this only prints "Name" to the console and I am unsure of how to get it to print the line after it as well.

You can't access the next line if you're using a foreach loop (behind the scenes a foreach loop sets up an enumerator but you can't access it see the third solution for a way to make your own enumerator that you can control directly), but you can either:

  • Switch to using a for loop, and print the n+1 line
         if (args[0] == "prog1")
         {
            string[] lines = File.ReadAllLines(filename);

            for(int i = 0; i< lines.Length; i++)
            {
                var line = lines[i];
                if (line.Contains("Name"))
                {
                    Console.WriteLine(line);
                    Console.WriteLine(lines[++i]); // ++i means "increment i, then use it" so it is incremented first then used to access the line
                }
            }
        }
  • Keep using the foreach and toggle a boolean to true, that will cause the next line to print even though it doesn't contain "Name", then toggle it off when you do the print

        if (args[0] == "prog1")
        {
            List<string> lines = File.ReadAllLines(filename).ToList();

            bool printLine = false;
            foreach (var line in lines)
            {
                if (line.Contains("Name"))
                {
                    printLine = true;
                    Console.WriteLine(line);
                }
                else if(printLine){
                    Console.WriteLine(line);
                    printLine = false;
                }
            }
        }
  • Set up your own enumerator so you can move it onto the next thing yourself
      string[] lines = File.ReadAllLines(filename);

      var enumerator = lines.GetEnumerator(); //the enumerator starts "before" the first line of the file

      while (enumerator.MoveNext()){ //moveNext returns true until the enumerator reaches the end
        if(enumerator.Current.Contains("Name")){
          Console.WriteLine(enumerator.Current);   //print current line
          if(enumerator.MoveNext())                //did we move to next line?
            Console.WriteLine(enumerator.Current); //print next line
        }
      }

For what it's worth, I'f use the classic for loop as i find it easiest to read, understand, maintain..


Other notes:

You should add some error checking that prevents the ++i version causing a crash if the last line of the file contains "Name" - currently the code will just increment past the end of the array and then try to access it, causing a crash.

Handling this could take the form of something as simple as running to i < Length - 1 so it stops on the second to last line

Similarly the enumerator version would need protecting against this if the last line is a match for "Name" - I handled this by seeing if MoveNext() returned false


Strictly speaking you don't need to use a List<string> - File.ReadAllLines returns an array, and turning it to a list is a relatively expensive operation to perform if you don't need to. If all you will do is iterate it or change the content of individual lines (but not add or remove lines), leave it as an array of string. Using a List would make your life easier if you plan to manipulate it by inserting/removing lines though

You can implement FST ( F inite S tate M achine); we have 2 states to consider:

  • 0 - line doesn't contain "Name"
  • 1 - line contains "Name"

Code:

if (args[0] == "prog1")
{
    int state = 0;

    // ReadLines - we don't have to read the entire file into a collection
    foreach (var line in File.ReadLines(filename)) {
      if (state == 0) {
        if (line.Contains("Name")) { 
          state = 1;

          Console.WriteLine(line); 
        }
      }
      else if (state == 1) {
        state = 0;

        Console.WriteLine(line); 
      }
    }
}
List<string> lines = File.ReadAllLines(filename).ToList();

for (int i = 0; i < lines.Count - 1; i++)
{
   if (lines[i].Contains("Name"))
   {
      Console.WriteLine(lines[i]);
      Console.WriteLine(lines[i + 1]);
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM