寻找 scanf 的 C# 等效项

问题描述 投票:0回答:10

我以前用C语言编写代码,我发现

scanf
函数非常有用。 不幸的是,C# 中没有等效的东西。

我正在使用它来解析半结构化文本文件。

我在

scanf
实现这里找到了一个有趣的例子。不幸的是,它看起来很旧而且不完整。

有人知道

scanf
C# 实现吗?或者至少可以作为反向
string.Format
工作?

c# scanf
10个回答
9
投票

既然文件是“半结构化”的,你不能使用 ReadLine() 和 TryParse() 方法的组合,或者 Regex 类来解析你的数据吗?


8
投票

如果正则表达式不适合您,我刚刚发布了 .NET 的

sscanf()
替代品。该代码可以在http://www.blackbeltcoder.com/Articles/strings/a-sscanf-replacement-for-net查看和下载。


5
投票

您可以直接从 C 运行时库使用 scanf,但如果您需要使用不同的参数计数来运行它,这可能会很困难。我建议您使用正则表达式来完成您的任务或在此处描述该任务,也许还有其他方法。


5
投票

我找到了一个比使用 C 中的 sscanf 或某人重写的部分更好的解决方案(无意冒犯)

http://msdn.microsoft.com/en-us/library/63ew9az0.aspx 看看这篇文章,它解释了如何创建命名组以从模式字符串中提取所需的数据。请注意文章中的小错误和下面更好的版本。 (结肠不属于该组)

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

4
投票

C# 中缺少类似 scanf 的函数是有充分理由的。 它很容易出错,而且不灵活。 使用正则表达式更加灵活和强大。

另一个好处是,如果您需要在代码的不同部分解析相同的内容,则可以更轻松地在整个代码中重用。


4
投票

您不应该尝试找到与

scanf
完全相同的内容。请改用 .NET 字符串 API,例如
String.Format
。但是,如果您确实想要,请尝试导入 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));
        }
    }
}

在 .NET Framework 上运行良好。但在 Mono 上,它显示错误消息:

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

如果需要 Mono 兼容性,则需要避免使用

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);
        }
    }
}

其中参数的数量是固定的。

编辑2018-5-24

arglist
也不适用于 .NET Core。看来调用 C vararg 函数已被弃用。您应该使用 .NET 字符串 API,例如
String.Format

编辑2024-06-07

声明不推荐使用。


2
投票

我认为您需要 C# 库函数 Parse 或 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());
}

0
投票

您可以使用 System.IO.FileStream 和 System.IO.StreamReader,然后从那里解析。


0
投票

这是纯 C# 的基本版本:

    public static ArrayList scan(string s, string fmt)
    {
        ArrayList result = new ArrayList();

        int ind = 0; // s upto ind has been consumed

        for (int i = 0; i < fmt.Length; i++)
        {
            char c = fmt[i];
            if (c == '%' && i < fmt.Length - 1)
            {
                char d = fmt[i + 1];
                if (d == 's')
                {
                    string schars = ""; 
                    for (int j = ind; j < s.Length; j++)
                    {  if (Char.IsWhiteSpace(s[j]))
                       { break; }
                       else 
                       { schars = schars + s[j]; }
                    }
                    result.Add(schars);
                    ind = ind + schars.Length; 
                    i++;
                }
                else if (d == 'f')
                {
                    String fchars = "";
                    for (int j = ind; j < s.Length; j++)
                    {
                        Char x = s[j];
                        if (x == '.' || Char.IsDigit(x))
                        { fchars = fchars + x; }
                        else
                        { break; }
                    }

                    try
                    {
                        double v = double.Parse(fchars);
                        ind = ind + fchars.Length;
                        result.Add(v);
                    }
                    catch (Exception _ex)
                    { Console.WriteLine("!! Error in double format: " + fchars);  }
                    i++;
                }
                else if (d == 'd')
                {
                    String inchars = "";
                    for (int j = ind; j < s.Length; j++)
                    {
                        Char x = s[j];
                        if (Char.IsDigit(x))
                        { inchars = inchars + x; }
                        else
                        { break; }
                    }

                    try
                    {
                        int v = int.Parse(inchars);
                        ind = ind + inchars.Length;
                        result.Add(v);
                    }
                    catch (Exception _ex)
                    { Console.WriteLine("!! Error in integer format: " + inchars); }
                    i++;
                }
            }
            else if (s[ind] == c)
            { ind++; }
            else
            { return result; }

        }
        return result;
    }

-3
投票

虽然这看起来有点粗糙,但确实完成了工作:

// 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(' ');

然后您可以使用数组 srVals 作为记录中的单独变量。

© www.soinside.com 2019 - 2024. All rights reserved.