Question

I used to code in C language in the past and I found the scanf function very useful. Unfortunately, there is no equivalent in C#.

I am using using it to parse semi-structured text files.

I found an interresting example of scanf implementation here. Unfortunately, it looks old and incomplete.

Does anyone know a scanf C# implementation ? Or at least something that would work as a reversed string.Format?

Was it helpful?

Solution

If regular expressions aren't working for you, I've just posted a sscanf() replacement for .NET. The code can be viewed and downloaded at http://www.blackbeltcoder.com/Articles/strings/a-sscanf-replacement-for-net.

OTHER TIPS

Since the files are "semi-structured" can't you use a combination of ReadLine() and TryParse() methods, or the Regex class to parse your data?

You can use scanf directly from C runtime libraries, but this can be difficult if you need to run it with different parameters count. I recommend you to regular expressions for you task or describe that task here, maybe there is another ways.

I have found a better solution than using sscanf from C or some rewritten part by someone (no offence)

http://msdn.microsoft.com/en-us/library/63ew9az0.aspx have a look at this article, it explains how to make named groups to extract the wanted data from a patterned string. Beware of the little error in the article and the better version below. (the colon was not part of the group)

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string url = "http://www.contoso.com:8080/letters/readme.html";
      Regex r = new Regex(@"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/",RegexOptions.None, TimeSpan.FromMilliseconds(150));
      Match m = r.Match(url);
      if (m.Success)
         Console.WriteLine(r.Match(url).Result("${proto}:${port}")); 
   }
}
// The example displays the following output: 
//       http::8080

Try importing msvcrt.dll

using System.Runtime.InteropServices;

namespace Sample
{
    class Program
    {
        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int printf(string format, __arglist);

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int scanf(string format, __arglist);

        static void Main()
        {
            int a, b;
            scanf("%d%d", __arglist(out a, out b));
            printf("The sum of %d and %d is %d.\n", __arglist(a, b, a + b));
        }
    }
}

which works well on .NET Framework. But on Mono, it shows the error message:

Unhandled Exception:
System.InvalidProgramException: Invalid IL code in Sample.Program:Main (): IL_0009: call      0x0a000001


[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidProgramException: Invalid IL code in Sample.Program:Main (): IL_0009: call      0x0a000001

If you need Mono compatibility, you need to avoid using arglist

using System.Runtime.InteropServices;

namespace Sample
{
    class Program
    {
        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int printf(string format, int a, int b, int c);

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int scanf(string format, out int a, out int b);

        static void Main()
        {
            int a, b;
            scanf("%d%d", out a, out b);
            printf("The sum of %d and %d is %d.\n", a, b, a + b);
        }
    }
}

in which the number of arguments is fixed.

Edit 2018-5-24

arglist doesn't work on .NET Core either. It seems that calling the C vararg function is deprecated. You should use the .NET string API such as String.Format instead.

There is good reason why a scanf like function is missing from c#. It's very prone to error, and not flexible. Using Regex is much more flexible and powerful.

Another benefit is that it's easier to reuse throughout your code if you need to parse the same thing in different parts of the code.

I think you want the C# library functions either Parse or Convert.

// here's an example of getting the hex value from a command line 
// program.exe 0x00080000

static void Main(string[] args)
{
    int value = Convert.ToInt32(args[1].Substring(2), 16);
    Console.Out.WriteLine("Value is: " + value.ToString());
}

You could use System.IO.FileStream, and System.IO.StreamReader, and then parse from there.

Although this looks sort of crude it does get the job done:

// Create the stream reader
sr = new StreamReader("myFile.txt");

// Read it
srRec = sr.ReadLine();

// Replace multiple spaces with one space
String rec1 = srRec.Replace("          ", " ");
String rec2 = rec1.Replace("         ", " ");
String rec3 = rec2.Replace("        ", " ");
String rec4 = rec3.Replace("       ", " ");
String rec5 = rec4.Replace("      ", " ");
String rec6 = rec5.Replace("     ", " ");
String rec7 = rec6.Replace("    ", " ");
String rec8 = rec7.Replace("   ", " ");
String rec9 = rec8.Replace("  ", " ");

// Finally split the string into an array of strings with Split
String[] srVals = rec9.Split(' ');

You can then use the array srVals as individual variables from the record.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top