System.Console 作为带有输入行的日志窗口

2024-04-28

我正在编写一个控制台应用程序,在文本滚动时需要用户在底行输入。这个想法是让文本滚动并在底部留下输入行。我想要文本编辑功能(箭头键、插入、删除等)。我也希望能够拥有静态“状态行”(不受滚动影响的行)。

A real world example would be Irssi: enter image description here

在我的代码中,我连接到 NLog 并将其输出写入屏幕,同时还向用户提供输入行。这是通过在写入时“暂停输入”来完成的:使用控制台.移动缓冲区 https://msdn.microsoft.com/en-us/library/zks4cwcf(v=vs.110).aspx向上移动文本、禁用光标、重新定位光标、写入日志文本、将光标重新定位回输入行以及启用光标。基本上可以用了,但是有一些问题:

  • 它非常慢。如果我编写 20-30 行,应用程序的速度会显着减慢。 (可以通过缓冲传入来解决,但不能解决滚动速度。)
  • 溢出的行(即异常堆栈跟踪)会在屏幕的最底部留下一行。
  • 当文本向上滚动时,溢出的行将被(部分)覆盖。这也会弄乱输入线。
  • 向上/向下滚动不起作用。

有图书馆可以帮助我做到这一点吗? 如果不是那么我该如何修复速度?如何修复滚动?

跨平台解决方案首选。

public class InputConsole
{
    private static readonly object _bufferLock = new object();

    private static int _windowWidth = Console.BufferWidth;
    private static int _windowHeight = Console.BufferHeight;
    private static int _windowLeft = Console.WindowLeft;
    private static int _windowTop = Console.WindowTop;

    public InputConsole()
    {    
        MethodCallTarget target = new MethodCallTarget();
        target.ClassName = typeof(InputConsole).AssemblyQualifiedName;
        target.MethodName = "LogMethod";
        target.Parameters.Add(new MethodCallParameter("${level}"));
        target.Parameters.Add(new MethodCallParameter("${message}"));
        target.Parameters.Add(new MethodCallParameter("${exception:format=tostring}"));
        target.Parameters.Add(new MethodCallParameter("[${logger:shortName=true}]"));

        SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Trace);

        try
        {

            Console.SetWindowSize(180, 50);
            Console.SetBufferSize(180, 50);
            _windowWidth = Console.BufferWidth;
            _windowHeight = Console.BufferHeight;
        }
        catch (Exception exception)
        {
            Console.WriteLine("Unable to resize console: " + exception);
        }

    }

    public void Run()
    {

        string input;
        do
        {
            lock (_bufferLock)
            {
                Console.SetCursorPosition(0, _windowHeight - 1);
                Console.Write("Command: ");
                Console.CursorVisible = true;
            }

            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.Yellow;

            input = Console.ReadLine();

            lock (_bufferLock)
            {
                Console.CursorVisible = false;
            }

        } while (!string.Equals(input, "quit", StringComparison.OrdinalIgnoreCase));
    }

    public static void LogMethod(string level, string message, string exception, string caller)
    {

        if (Console.BufferHeight == _windowHeight)
            Console.MoveBufferArea(_windowLeft, _windowTop + 1, Console.BufferWidth, Console.BufferHeight - 2, _windowLeft, _windowTop);

        var fgColor = ConsoleColor.White;
        var bgColor = ConsoleColor.Black;

        switch (level.ToUpper())
        {
            case "TRACE":
                fgColor = ConsoleColor.DarkGray;
                break;
            case "DEBUG":
                fgColor = ConsoleColor.Gray;
                break;
            case "INFO":
                fgColor = ConsoleColor.White;
                break;
            case "WARNING":
                fgColor = ConsoleColor.Cyan;
                break;
            case "ERROR":
                fgColor = ConsoleColor.White;
                bgColor = ConsoleColor.Red;
                break;
        }

        var str = string.Format("({0})  {1} {2} {3}", level.ToUpper(), caller, message, exception);
        WriteAt(_windowLeft, _windowHeight - 3, str, fgColor, bgColor);
    }

    public static void WriteAt(int left, int top, string s, ConsoleColor foregroundColor = ConsoleColor.White, ConsoleColor backgroundColor = ConsoleColor.Black)
    {
        lock (_bufferLock)
        {
            var currentBackgroundColor = Console.BackgroundColor;
            var currentForegroundColor = Console.ForegroundColor;
            Console.BackgroundColor = backgroundColor;
            Console.ForegroundColor = foregroundColor;
            int currentLeft = Console.CursorLeft;
            int currentTop = Console.CursorTop;
            var currentVisible = Console.CursorVisible;
            Console.CursorVisible = false;
            Console.SetCursorPosition(left, top);
            Console.Write(s);
            Console.SetCursorPosition(currentLeft, currentTop);
            Console.CursorVisible = currentVisible;
            Console.BackgroundColor = currentBackgroundColor;
            Console.ForegroundColor = currentForegroundColor;
        }

    }
}

对 Windows 中的文本控制台进行进一步研究,我似乎很难让它运行得更快。通过具有较低重绘率的自定义实现(更少写入控制台输出 https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx)与 Console.WriteLine 相比,我的速度提高了 10 倍多。

然而,由于 Console.WriteLine 强制执行“当我们到达底部时滚动所有内容”,我正在使用控制台.移动缓冲区 https://msdn.microsoft.com/en-us/library/zks4cwcf(v=vs.110).aspx。测试表明,我的 MoveBufferArea 实现(包含在我原来的问题中)比 Console.WriteLine 慢大约 90 倍。然而,通过使用 WriteConsoleOutput 的新实现,我能够得到速度比 MoveBufferedArea 提高 1356 倍.

由于找到有关它的信息有点困难,我在一篇文章中详细介绍了我的发现博客文章 http://blog.tedd.no/2015/08/02/better-text-console-for-c/。我还将代码附加到这个答案中,以供后代使用。

我编写了一个类,允许我滚动各个框。我还实现了一个线路输入系统来模拟标准的系统Console.ReadLine();。请注意,此实现缺少主/终端支持(但很容易修复)。

请注意,要从中获得任何速度提升,您必须设置box.AutoRedraw = false;并手动调用box.Draw();经常。和box.AutoRedraw = true;(调用Draw()在每一个Write())这个解决方案实际上比 Console.WriteLine 慢 30 倍,比 MoveBufferArea 快 3 倍。

如何使用示例:

_logBox = new InputConsoleBox(0, 0, (short)Console.BufferWidth, (short)(Console.BufferHeight - 2), InputConsoleBox.Colors.LightWhite, InputConsoleBox.Colors.Black);
_statusBox = new InputConsoleBox(0, (short)(Console.BufferHeight - 3), (short)Console.BufferWidth, 1, InputConsoleBox.Colors.LightYellow, InputConsoleBox.Colors.DarkBlue);
_inputBox = new InputConsoleBox(0, (short)(Console.BufferHeight - 2), (short)Console.BufferWidth, 1, InputConsoleBox.Colors.LightYellow, InputConsoleBox.Colors.Black);
_statusBox.WriteLine("Hey there!");
_inputBox.InputPrompt = "Command: ";

// If you are okay with some slight flickering this is an easy way to set up a refresh timer
_logBox.AutoDraw = false;
_redrawTask = Task.Factory.StartNew(async () =>
{
    while (true)
    {
        await Task.Delay(100);
        if (_logBox.IsDirty)
            _logBox.Draw();
    }
});

// Line input box
var line = _inputBox.ReadLine(); // Blocking while waiting for <enter>

Code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32.SafeHandles;

public class InputConsoleBox
{
    #region Output
    #region Win32 interop
    private const UInt32 STD_OUTPUT_HANDLE = unchecked((UInt32)(-11));
    private const UInt32 STD_ERROR_HANDLE = unchecked((UInt32)(-12));

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr GetStdHandle(UInt32 type);
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern SafeFileHandle CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] uint fileAccess,
        [MarshalAs(UnmanagedType.U4)] uint fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        [MarshalAs(UnmanagedType.U4)] int flags,
        IntPtr template);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool WriteConsoleOutput(
        SafeFileHandle hConsoleOutput,
        CharInfo[] lpBuffer,
        Coord dwBufferSize,
        Coord dwBufferCoord,
        ref SmallRect lpWriteRegion);

    [StructLayout(LayoutKind.Sequential)]
    private struct Coord
    {
        public short X;
        public short Y;

        public Coord(short X, short Y)
        {
            this.X = X;
            this.Y = Y;
        }
    };

    [StructLayout(LayoutKind.Explicit)]
    private struct CharUnion
    {
        [FieldOffset(0)]
        public char UnicodeChar;
        [FieldOffset(0)]
        public byte AsciiChar;
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct CharInfo
    {
        [FieldOffset(0)]
        public CharUnion Char;
        [FieldOffset(2)]
        public ushort Attributes;

        public CharInfo(char @char, ushort attributes)
        {
            this.Char = new CharUnion();
            Char.UnicodeChar = @char;
            Attributes = attributes;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SmallRect
    {
        public short Left;
        public short Top;
        public short Right;
        public short Bottom;
    }
    #endregion
    #region Colors Enum

    private const int HighIntensity = 0x0008;
    private const ushort COMMON_LVB_LEADING_BYTE = 0x0100;
    private const ushort COMMON_LVB_TRAILING_BYTE = 0x0200;
    private const ushort COMMON_LVB_GRID_HORIZONTAL = 0x0400;
    private const ushort COMMON_LVB_GRID_LVERTICAL = 0x0800;
    private const ushort COMMON_LVB_GRID_RVERTICAL = 0x1000;
    private const ushort COMMON_LVB_REVERSE_VIDEO = 0x4000;
    private const ushort COMMON_LVB_UNDERSCORE = 0x8000;
    private const ushort COMMON_LVB_SBCSDBCS = 0x0300;
    [Flags]
    public enum Colors : int
    {
        Black = 0x0000,
        DarkBlue = 0x0001,
        DarkGreen = 0x0002,
        DarkRed = 0x0004,
        Gray = DarkBlue | DarkGreen | DarkRed,
        DarkYellow = DarkRed | DarkGreen,
        DarkPurple = DarkRed | DarkBlue,
        DarkCyan = DarkGreen | DarkBlue,
        LightBlue = DarkBlue | HighIntensity,
        LightGreen = DarkGreen | HighIntensity,
        LightRed = DarkRed | HighIntensity,
        LightWhite = Gray | HighIntensity,
        LightYellow = DarkYellow | HighIntensity,
        LightPurple = DarkPurple | HighIntensity,
        LightCyan = DarkCyan | HighIntensity
    }

    #endregion // Colors Enum

    private readonly CharInfo[] _buffer;
    private readonly List<CharInfo> _tmpBuffer;
    private readonly short _left;
    private readonly short _top;
    private readonly short _width;
    private readonly short _height;
    private ushort _defaultColor;
    private int _cursorLeft;
    private int _cursorTop;
    private static SafeFileHandle _safeFileHandle;
    /// <summary>
    /// Automatically draw to console.
    /// Unset this if you want to manually control when (and what order) boxes are writen to consoles - or you want to batch some stuff.
    /// You must manually call <c>Draw()</c> to write to console.
    /// </summary>
    public bool AutoDraw = true;
    public bool IsDirty { get; private set; }

    public InputConsoleBox(short left, short top, short width, short height, Colors defaultForegroundColor = Colors.Gray, Colors defaultBackgroundColor = Colors.Black)
    {
        if (left < 0 || top < 0 || left + width > Console.BufferWidth || top + height > Console.BufferHeight)
            throw new Exception(string.Format("Attempting to create a box {0},{1}->{2},{3} that is out of buffer bounds 0,0->{4},{5}", left, top, left + width, top + height, Console.BufferWidth, Console.BufferHeight));

        _left = left;
        _top = top;
        _width = width;
        _height = height;
        _buffer = new CharInfo[_width * _height];
        _defaultColor = CombineColors(defaultForegroundColor, defaultBackgroundColor);
        _tmpBuffer = new List<CharInfo>(_width * _height); // Assumption that we won't be writing much more than a screenful (backbufferfull) in every write operation


        //SafeFileHandle h = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
        if (_safeFileHandle == null)
        {
            var stdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
            _safeFileHandle = new SafeFileHandle(stdOutputHandle, false);
        }

        Clear();
        Draw();
    }

    public void Clear()
    {
        for (int y = 0; y < _height; y++)
        {
            for (int x = 0; x < _width; x++)
            {
                var i = (y * _width) + x;
                _buffer[i].Char.UnicodeChar = ' ';
                _buffer[i].Attributes = _defaultColor;
            }
        }
        IsDirty = true;
        // Update screen
        if (AutoDraw)
            Draw();
    }

    public void Draw()
    {
        IsDirty = false;
        var rect = new SmallRect() { Left = _left, Top = _top, Right = (short)(_left + _width), Bottom = (short)(_top + _height) };
        bool b = WriteConsoleOutput(_safeFileHandle, _buffer,
            new Coord(_width, _height),
            new Coord(0, 0), ref rect);
    }

    private static ushort CombineColors(Colors foreColor, Colors backColor)
    {
        return (ushort)((int)foreColor + (((int)backColor) << 4));
    }

    public void SetCursorPosition(int left, int top)
    {
        if (left >= _width || top >= _height)
            throw new Exception(string.Format("Position out of bounds attempting to set cursor at box pos {0},{1} when box size is only {2},{3}.", left, top, _width, _height));

        _cursorLeft = left;
        _cursorTop = top;
    }

    public void SetCursorBlink(int left, int top, bool state)
    {
        Console.SetCursorPosition(left, top);
        Console.CursorVisible = state;
        //// Does not work
        //var i = (top * _width) + left;
        //if (state)
        //    _buffer[i].Attributes = (ushort)((int)_buffer[i].Attributes & ~(int)COMMON_LVB_UNDERSCORE);
        //else
        //    _buffer[i].Attributes = (ushort)((int)_buffer[i].Attributes | (int)COMMON_LVB_UNDERSCORE);

        //if (AutoDraw)
        //    Draw();
    }

    public void WriteLine(string line, Colors fgColor, Colors bgColor)
    {
        var c = _defaultColor;
        _defaultColor = CombineColors(fgColor, bgColor);
        WriteLine(line);
        _defaultColor = c;
    }

    public void WriteLine(string line)
    {
        Write(line + "\n");
    }

    public void Write(string text)
    {
        Write(text.ToCharArray());
    }

    public void Write(char[] text)
    {
        IsDirty = true;
        _tmpBuffer.Clear();
        bool newLine = false;

        // Old-school! Could definitively have been done more easily with regex. :)
        var col = 0;
        var row = -1;
        for (int i = 0; i < text.Length; i++)
        {

            // Detect newline
            if (text[i] == '\n')
                newLine = true;
            if (text[i] == '\r')
            {
                newLine = true;
                // Skip following \n
                if (i + 1 < text.Length && text[i] == '\n')
                    i++;
            }

            // Keep track of column and row
            col++;
            if (col == _width)
            {
                col = 0;
                row++;

                if (newLine) // Last character was newline? Skip filling the whole next line with empty
                {
                    newLine = false;
                    continue;
                }
            }

            // If we are newlining we need to fill the remaining with blanks
            if (newLine)
            {
                newLine = false;

                for (int i2 = col; i2 <= _width; i2++)
                {
                    _tmpBuffer.Add(new CharInfo(' ', _defaultColor));
                }
                col = 0;
                row++;
                continue;
            }
            if (i >= text.Length)
                break;

            // Add character
            _tmpBuffer.Add(new CharInfo(text[i], _defaultColor));
        }

        var cursorI = (_cursorTop * _width) + _cursorLeft;

        // Get our end position
        var end = cursorI + _tmpBuffer.Count;

        // If we are overflowing (scrolling) then we need to complete our last line with spaces (align buffer with line ending)
        if (end > _buffer.Length && col != 0)
        {
            for (int i = col; i <= _width; i++)
            {
                _tmpBuffer.Add(new CharInfo(' ', _defaultColor));
            }
            col = 0;
            row++;
        }

        // Chop start of buffer to fit into destination buffer
        if (_tmpBuffer.Count > _buffer.Length)
            _tmpBuffer.RemoveRange(0, _tmpBuffer.Count - _buffer.Length);
        // Convert to array so we can batch copy
        var tmpArray = _tmpBuffer.ToArray();

        // Are we going to write outside of buffer?
        end = cursorI + _tmpBuffer.Count;
        var scrollUp = 0;
        if (end > _buffer.Length)
        {
            scrollUp = end - _buffer.Length;
        }

        // Scroll up
        if (scrollUp > 0)
        {
            Array.Copy(_buffer, scrollUp, _buffer, 0, _buffer.Length - scrollUp);
            cursorI -= scrollUp;
        }
        var lastPos = Math.Min(_buffer.Length, cursorI + tmpArray.Length);
        var firstPos = lastPos - tmpArray.Length;

        // Copy new data in
        Array.Copy(tmpArray, 0, _buffer, firstPos, tmpArray.Length);

        // Set new cursor position
        _cursorLeft = col;
        _cursorTop = Math.Min(_height, _cursorTop + row + 1);

        // Write to main buffer
        if (AutoDraw)
            Draw();
    }
    #endregion

    #region Input
    private string _currentInputBuffer = "";
    private string _inputPrompt;
    private int _inputCursorPos = 0;
    private int _inputFrameStart = 0;
    // Not used because COMMON_LVB_UNDERSCORE doesn't work
    //private bool _inputCursorState = false;
    //private int _inputCursorStateChange = 0;
    private int _cursorBlinkLeft = 0;
    private int _cursorBlinkTop = 0;

    public string InputPrompt
    {
        get { return _inputPrompt; }
        set
        {
            _inputPrompt = value;
            ResetInput();
        }
    }

    private void ResetInput()
    {
        SetCursorPosition(0, 0);
        _inputCursorPos = Math.Min(_currentInputBuffer.Length, _inputCursorPos);

        var inputPrompt = InputPrompt + "[" + _currentInputBuffer.Length + "] ";

        // What is the max length we can write?
        var maxLen = _width - inputPrompt.Length;
        if (maxLen < 0)
            return;

        if (_inputCursorPos > _inputFrameStart + maxLen)
            _inputFrameStart = _inputCursorPos - maxLen;
        if (_inputCursorPos < _inputFrameStart)
            _inputFrameStart = _inputCursorPos;

        _cursorBlinkLeft = inputPrompt.Length + _inputCursorPos - _inputFrameStart;

        //if (_currentInputBuffer.Length - _inputFrameStart < maxLen)
        //    _inputFrameStart--;


        // Write and pad the end
        var str = inputPrompt + _currentInputBuffer.Substring(_inputFrameStart, Math.Min(_currentInputBuffer.Length - _inputFrameStart, maxLen));
        var spaceLen = _width - str.Length;
        Write(str + (spaceLen > 0 ? new String(' ', spaceLen) : ""));

        UpdateCursorBlink(true);

    }
    private void UpdateCursorBlink(bool force)
    {
        // Since COMMON_LVB_UNDERSCORE doesn't work we won't be controlling blink
        //// Blink the cursor
        //if (Environment.TickCount > _inputCursorStateChange)
        //{
        //    _inputCursorStateChange = Environment.TickCount + 250;
        //    _inputCursorState = !_inputCursorState;
        //    force = true;
        //}
        //if (force)
        //    SetCursorBlink(_cursorBlinkLeft, _cursorBlinkTop, _inputCursorState);
        SetCursorBlink(_left + _cursorBlinkLeft, _top + _cursorBlinkTop, true);
    }

    public string ReadLine()
    {
        Console.CursorVisible = false;
        Clear();
        ResetInput();
        while (true)
        {
            Thread.Sleep(50);

            while (Console.KeyAvailable)
            {
                var key = Console.ReadKey(true);

                switch (key.Key)
                {
                    case ConsoleKey.Enter:
                        {
                            var ret = _currentInputBuffer;
                            _inputCursorPos = 0;
                            _currentInputBuffer = "";
                            return ret;
                            break;
                        }
                    case ConsoleKey.LeftArrow:
                        {
                            _inputCursorPos = Math.Max(0, _inputCursorPos - 1);
                            break;
                        }
                    case ConsoleKey.RightArrow:
                        {
                            _inputCursorPos = Math.Min(_currentInputBuffer.Length, _inputCursorPos + 1);
                            break;
                        }
                    case ConsoleKey.Backspace:
                        {
                            if (_inputCursorPos > 0)
                            {
                                _inputCursorPos--;
                                _currentInputBuffer = _currentInputBuffer.Remove(_inputCursorPos, 1);
                            }
                            break;
                        }
                    case ConsoleKey.Delete:
                        {
                            if (_inputCursorPos < _currentInputBuffer.Length - 1)
                                _currentInputBuffer = _currentInputBuffer.Remove(_inputCursorPos, 1);
                            break;
                        }

                    default:
                        {
                            var pos = _inputCursorPos;
                            //if (_inputCursorPos == _currentInputBuffer.Length)
                            _inputCursorPos++;
                            _currentInputBuffer = _currentInputBuffer.Insert(pos, key.KeyChar.ToString());
                            break;
                        }
                }
                ResetInput();

            }

            // COMMON_LVB_UNDERSCORE doesn't work so we use Consoles default cursor
            //UpdateCursorBlink(false);

        }
    }

    #endregion

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

System.Console 作为带有输入行的日志窗口 的相关文章

  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • Blazor 与 Razor

    随着 Blazor 的发明 我想知道这两种语言之间是否存在显着的效率 无论是在代码创建方面还是在代码的实际编译 执行方面 https github com SteveSanderson Blazor https github com Ste
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • ASP .NET MVC,创建类似路由配置的永久链接

    我需要帮助在 MVC 网站中创建类似 URL 路由的永久链接 Slug 已设置为 www xyz com profile slug 代码为 routes MapRoute name Profile url profile slug defa
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 在 C# 中将位从 ulong 复制到 long

    所以看来 NET 性能计数器类型 http msdn microsoft com en us library system diagnostics performancecounter aspx有一个恼人的问题 它暴露了long对于计数器
  • 为什么 FTPWebRequest 或 WebRequest 通常不接受 /../ 路径?

    我正在尝试从 ftp Web 服务器自动执行一些上传 下载任务 当我通过客户端甚至通过 Firefox 连接到服务器时 为了访问我的目录 我必须指定如下路径 ftp ftpserver com AB00000 incoming files
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况

随机推荐