C# 控制台输入和输出

控制台窗口是一种简单的命令提示窗口,允许程序显示文本并从键盘接受输人。

使用 Console.ReadLine() 方法获取输入,使用 Console.WriteLine() 方法输出。

从控制台获取输入

可用 System.Console.ReadLine() 方法获取控制台输入的文本。程序执行到这一行代码时,它将暂停程序执行并等待用户输入。用户输入内容后(也可以不输入)按回车键,程序将继续执行。System.Console.ReadLine() 方法的输出,也称为返回值,就是用户输入的文本字符串。

static void Main(string[] args)
{
    // 定义变量
    string firstStr, secondStr;

    // 输出内容到控制台
    Console.WriteLine("请输入第一个字符串:");

    // 接收用户输入,为变量赋值
    firstStr = Console.ReadLine();

    // 输出内容到控制台
    Console.WriteLine("请输入第二个字符串:");

    // 接收用户输入,为变量赋值
    secondStr = Console.ReadLine();

    // 输出内容到控制台
    Console.WriteLine("你输入的第一个字符串是:{0};第二个字符串是:{1}",firstStr,secondStr);
}

展示一段“价值上亿”的 AI 核心代码

using System;

namespace ConsoleApp
{
    class Program
    {

        static void Main()
        {
            while (true)
            {
                string str = Console.ReadLine();

                if (string.IsNullOrWhiteSpace(str))
                {
                    continue;
                }

                str = str.Replace("吗", "");
                str = str.Replace("?", "!");
                str = str.Replace("?", "!");

                Console.WriteLine(str);
            }
        }
    }
}

效果

可以智能应答,很厉害是不是?

其实就是几个字符替换!抖了个机灵,也顺便黑了把当下某些言必称 AI 的风气。你别说,当年区块链概念火爆的时候,还真有人代码里放了个“Hello World”就出来诓钱了。风口之下,什么样的妖魔鬼怪都有。

将输出写入控制台

Console.Write()

Console.Write() 方法把一个文本字符串发送到程序的控制台窗口。最简单的情况下,Console.Write() 将文本的字符串字面量发送到窗口,字符串必须使用双引号括起来。如下面的代码:

Console.Write("这是一个文本字符串字面量");

输出

这是一个文本字符串字面量

另外一个示例是下面的代码,发送了 3 个文本字符串到程序的控制台窗口:

Console.Write("第一个字符串");
Console.Write("第二个字符串");
Console.Write("第三个字符串");

输出

第一个字符串第二个字符串第三个字符串

Console.Write() 方法没有在字符串后面添加换行符,所以三条语句都输出到同一行。

Console.WriteLine()

Console.WriteLine() 方法和 Console.Write() 实现相同的功能,但会在每个输出字符串的结尾添加一个换行符。如下面的代码:

Console.Write("第一个字符串");
Console.Write("第二个字符串");
Console.Write("第三个字符串");

输出

第一个字符串
第二个字符串
第三个字符串

格式字符串

Console.Write()Console.WriteLine()的常规形式中可以有一个以上的参数。如果不只一个参数,参数间用逗号分隔,第一个参数必须总是字符串,称为格式字符串。格式字符串可以包含替代标记。

  • 替代标记在格式字符串中标出位置,在输出串中该位置将用一个值来替代。
  • 替代标记由一个整数及括住它的一对大括号组成,其中整数就是替换值的数字位置。

跟着格式字符串的参数称为替换值,这些替换值从 0 开始编号。语法如下:

Console.WriteLine(格式字符串(含替代标记),替换值0,替换值1,替换值2,...);

例如,下面的语句有两个替代标记,编号 0 和 1;以及两个替换值,它们的值分别是 3 和 6。

Console.WriteLine("两个整数示例是 {0} 和 {1}",3,6);

输出

两个整数示例是 3 和 6

其中 "两个整数示例是 {0} 和 {1}" 是格式字符串,{0}{1} 是替代标记,36 是替换值。

多重标记和值

可以使用任意数量的替代标记和任意数量的值。

  • 值可以以任何顺序使用。
  • 值可以在格式字符串中替换任意次。

例如,下面的语句使用了 3 个标记但只有两个值。

Console.WriteLine("三个整数是 {1}、{0} 和 {1}", 3, 6);

输出

三个整数是 6、3 和 6

标记不能引用超出替换值列表长度以外位置的值。如果引用了,虽然不会产生编译错误,但会产生运行时错误(称为异常)。

例如,在下面的语句中有两个替换值,在位置 0 和 1。而第二个标记引用了位置 2,位置 2 并不存在。这将会产生一个运行时错误。

Console.WriteLine("两个整数示例是 {0} 和 {2}",3,6);

输出错误信息

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
  at System.Text.StringBuilder.AppendFormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args) <0x25629e8 + 0x00208> in <67a88994620f4374b07defa73dd07570>:0 
  at System.String.FormatHelper (System.IFormatProvider provider, System.String format, System.ParamsArray args) <0x255aec8 + 0x00050> in <67a88994620f4374b07defa73dd07570>:0 
  at System.String.Format (System.IFormatProvider provider, System.String format, System.Object arg0, System.Object arg1) <0x2dd0038 + 0x00020> in <67a88994620f4374b07defa73dd07570>:0 
  at System.IO.TextWriter.WriteLine (System.String format, System.Object arg0, System.Object arg1) <0x2dcffd8 + 0x0001e> in <67a88994620f4374b07defa73dd07570>:0 
  at System.IO.TextWriter+SyncTextWriter.WriteLine (System.String format, System.Object arg0, System.Object arg1) <0x2dcff18 + 0x00018> in <67a88994620f4374b07defa73dd07570>:0 
  at (wrapper synchronized) System.IO.TextWriter+SyncTextWriter.WriteLine(string,object,object)
  at System.Console.WriteLine (System.String format, System.Object arg0, System.Object arg1) <0x2dcfb98 + 0x00016> in <67a88994620f4374b07defa73dd07570>:0 
  at Program.Main () <0x2de2270 + 0x00014> in <eb71b37b85e34ec398032577572312ee>:0 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x23eabf8 + 0x000d2> in <67a88994620f4374b07defa73dd07570>:0 
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x23eabf8 + 0x000fe> in <67a88994620f4374b07defa73dd07570>:0 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) <0x23ea670 + 0x00016> in <67a88994620f4374b07defa73dd07570>:0 
  at System.CommandLine.Invocation.ModelBindingCommandHandler.InvokeAsync (System.CommandLine.Invocation.InvocationContext context) <0x2dcacf8 + 0x000b6> in <6793e93bcbca41a69b5ad876f7ba42b9>:0 
  at System.CommandLine.Invocation.InvocationPipeline+<>c__DisplayClass2_0.<InvokeAsync>b__0 (System.CommandLine.Invocation.InvocationContext invocationContext, System.Func`2[T,TResult] next) <0x2dc4538 + 0x0018e> in <6793e93bcbca41a69b5ad876f7ba42b9>:0 
  at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync (System.CommandLine.IConsole console) <0x2db5980 + 0x00216> in <6793e93bcbca41a69b5ad876f7ba42b9>:0 
  at System.CommandLine.Invocation.InvocationExtensions.InvokeAsync (System.CommandLine.Parser parser, System.CommandLine.ParseResult parseResult, System.CommandLine.IConsole console) <0x2db4790 + 0x000fc> in <6793e93bcbca41a69b5ad876f7ba42b9>:0 
  at System.CommandLine.Invocation.InvocationExtensions.InvokeAsync (System.CommandLine.Parser parser, System.String[] args, System.CommandLine.IConsole console) <0x2d4ef48 + 0x00110> in <6793e93bcbca41a69b5ad876f7ba42b9>:0 
  at MLS.WasmCodeRunner.CodeRunner.ExecuteRunRequest (MLS.WasmCodeRunner.WasmCodeRunnerRequest runRequest, System.Int32 sequence) <0x2cc69f0 + 0x0011c> in <d9fa2833845c4c548df55c8997a5a46d>:0 

格式化字符串

在很多时候,我们希望以更合适的格式而不是一个简单的数字来呈现文本字符串的输出。例如,把值作为货币或者某个小数位数的定点值来显示。这些都可以通过格式化字符串来实现。

例如,下面的代码由两条打印值 500 的语句组成。第一行没有使用任何其他格式化来打印数字,而第二行的格式化字符串指定了数字应该被格式化成货币。

// 输出数字
Console.WriteLine("数字:{0}", 500);

//格式为货币
Console.WriteLine("格式化成货币的表现形式:{0:C}", 500);

输出

数字:500
格式化成货币的表现形式:¥500.00

两条语句的不同之处在于,格式项以格式说明符形式包括了额外的信息。大括号内的格式说明符的语法由 3 个字段组成:索引号、对齐说明符和格式字段(format field)。语法如下:

{index[,alignment][:formatString]}
  • index:必需,指定值列表中的某一项
  • alignment:可选,指定字段宽度,以及是否是右对齐或左对齐
  • formatString:可选,指定项的格式

注意: 对齐使用逗号,格式使用冒号

索引

格式说明符的第一项是索引号。索引指定了之后的格式化字符串应该格式化值列表中的哪一项。

Console.WriteLine("小于 10 的质数:{0},{1},{2},{3}", 2, 3, 5, 7);

输出

小于 10 的质数:2,3,5,7

对齐说明符

对齐说明符表示了字段中字符的最小宽度。对齐说明符有如下特性。

  • 对齐说明符是可选的,并且使用逗号来和索引号分离。
  • 它由一个正整数或负整数组成。
    • 整数表示了字段使用字符的最少数量。
    • 符号表示了右对齐或左对齐。正数表示右对齐,负数表示左对齐。

例如,如下格式化 int 型变量 myInt 的值的代码显示了两个格式项。在第一个示例中,myInt 的值以在 10 个字符宽度的字符串中右对齐的形式进行显示;第二个示例中则是左对齐。格式项放在两个竖杠中间,这样在输出中就能看到它们的左右边界。

int myInt = 500;

//右对齐
Console.WriteLine("|{0, 10}|", myInt);

//左对齐
Console.WriteLine("|{0,-10}|", myInt);

输出

|       500|
|500       |

值的实际表示可能会比对齐说明符指定的字符数多-些或少一 些:

  • 如果要表示的字符数比对齐说明符中指定的字符数少,那么其余字符会使用空格填充
  • 如果要表示的字符数多于指定的字符数,对齐说明符会被忽略,并且使用所需的字符进行表示
int myInt = 500;
int myInt2 = 5000000;

//右对齐
Console.WriteLine("|{0, 5}|", myInt);

//左对齐
Console.WriteLine("|{0,-5}|", myInt2);

输出

|  500|
|5000000|

格式字段

格式字段指定了数字应该以哪种形式表示。例如,应该被当做货币、十进制数字、十六进制数字还是定点符号来表示。

格式字段有三部分。

  • 冒号后必须紧跟着格式说明符,中间不能有空格。
  • 格式说明符是一个字母字符,是 9 个内置字符格式之一。 字符可以是大写或小写形式。大小写对于某些说明符来说比较重要,而对于另外一些说明符来说则不重要。
  • 精度说明符是可选的,由 1 ~ 2 位数字组成。它的实际意义取决于格式说明符。

如下代码是格式字符串组件语法的一个示例:

Console.WriteLine("{0:F4}", 12.345678);

输出

12.3457

其中,F 表示使用浮点数来表示。4 表示 4 位精度(保留小数点后 4 位)

如下代码给出了不同格式字符串的一些示例:

double myDouble = 12.345678;

Console.WriteLine("|{0,-10:G}| -- 常规,左对齐", myDouble);

Console.WriteLine("|{0,-10}| -- 常规,左对齐", myDouble);
                    
Console.WriteLine("|{0,10:F4}| -- 保留小数点后 4 位,右对齐", myDouble);
                    
Console.WriteLine("|{0,-10:C}| -- 货币", myDouble);
                    
Console.WriteLine("|{0,-10:E3}| -- 科学计数法", myDouble);
                    
Console.WriteLine("|{0,-10:x}| -- 十六进制", 1194719);

输出

|12.345678 | -- 常规,左对齐
|12.345678 | -- 常规,左对齐
|   12.3457| -- 保留小数点后 4 位,右对齐
|¥12.35    | -- 货币
|1.235E+001| -- 科学计数法
|123adf    | -- 十六进制

标准数字格式说明符

下表总结了 9 种标准数字格式说明符,如果说明符字符根据它们的大小写会有不同的输出,就会标注为区分大小写。

格式说明符 说明 示例 结果
C 或 c 货币
使用货币符号把值格式化为货币,货币符号取决于程序所在 PC 的区域设置
精度说明符:小数位数
Console.WriteLine("{0:C}", 12.5);
Console.WriteLine("{0:C5}", 12.5);
¥12.50
¥12.50000
D 或 d 十进制数字字符串,需要的情况下可以有负数符号。只能和整数类型配合使用
精度说明符:输出字符串中的最少位数。如果实际数字的位数更少,则在左边以 0 填充
Console.WriteLine("{0:D5}", 25);
00025
E 或 e 科学计数法,区分大小写
具有尾数和指数的科学记数法。指数前面加字母 E。E 的大小写和说明符一致
精度说明符:小数的位数
Console.WriteLine("{0:E2}", 250000); 2.50E+005
F 或 f 定点 Console.WriteLine("{0:F4}", 12.345678); 12.3457
G 或 g 常规
在没有指定说明符的情况下,会根据值转换为定点或科学记数法表示的紧凑形式
精度说明符:根据值
Console.WriteLine("{0:G5}", 12.1234567890123456789);
Console.WriteLine("{0:G5}", 123456789.1234567890123456789);
12.123
1.2346E+08
N 或 n 数字
和定点表示法相似,但是在每三个数字的一组中间有逗号或空格分隔符。从小数点开始往左数。
使用逗号还是空格分隔符取决于程序所在 PC 的区域设置
精度说明符:小数的位数
Console.WriteLine("{0:N6}", 123456789.123456789);
123,456,789.123457
P 或 p 百分比
表示百分比的字符串。数字会乘以 100
精度说明符:小数的位数
Console.WriteLine("{0:P2}", 0.123456789); 12.35%
R 或 r 往返过程
保证输出字符串后如果使用 Parse 方法将字符串转化成数字,那么该值和原始值一样。
精度说明符:忽略
Console.WriteLine("{0:R}", 123.123456789); 123.123456789
X 或 x 十六进制,区分大小写
十六进制数字 A ~ F 会匹配说明符的大小写形式
精度说明符:输出字符串中的最少位数。如果实际数的位数更少,则在左边以 0 填充
Console.WriteLine("{0:X}", 250);
Console.WriteLine("{0:X4}", 250);
FA
00FA

$ 字符串插值

从 C# 6.0 开始引入的字符串插值功能。下面的代码在 Console.WriteLine() 调用中为字符串字面量附加的 $ 前缀,它表明使用了字符串插值。

static void Main(string[] args)
{
    // 定义变量
    string firstStr, secondStr;

    // 输出内容到控制台
    Console.WriteLine("请输入第一个字符串:");

    // 接收用户输入,为变量赋值
    firstStr = Console.ReadLine();

    // 输出内容到控制台
    Console.WriteLine("请输入第二个字符串:");

    // 接收用户输入,为变量赋值
    secondStr = Console.ReadLine();

    // 输出内容到控制台
    Console.WriteLine($"你输入的第一个字符串是:{firstStr};第二个字符串是:{secondStr}");
}

若要将字符串标识为内插字符串,可在该字符串前面加上 $ 符号。 字符串文本开头的 $" 之间不能有任何空格。

左大括号和右大括号({})指示内插表达式。可将任何返回值的 C# 表达式置于大括号内(包括 null)。

与使用字符串复合格式设置功能创建格式化字符串相比,字符串内插提供的语法更具可读性,且更加方便。 下面的示例使用了这两种功能生成同样的输出结果:

static void Main(string[] args)
{
    string name = "Mark";
    var date = DateTime.Now;

    // 复合格式化
    Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);

    // 字符串插值
    Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
}

输出

Hello, Mark! Today is Sunday, it's 12:34 now.
Hello, Mark! Today is Sunday, it's 12:34 now.

当表达式结果的类型不是字符串时,会按照以下方式将其解析为字符串:

  • 如果内插表达式的计算结果为 null,则会使用一个空字符串(""String.Empty)。
  • 如果内插表达式的计算结果不是 null,通常会调用结果表达式的 ToString 方法。

总结

本篇文章介绍了用于从控制台获取输入的 Console.ReadLine() 方法,以及将输出写入控制台的 Console.Write() 方法和 Console.WriteLine() 方法。它们的区别是 Console.WriteLine() 会在每个输出字符串的结尾添加一个换行符。

另外,还介绍了字符串复合格式化的设置和用法,用于将数字输出到不同的格式。从 C# 6 开始可以使用字符串插值功能,与使用字符串复合格式设置功能创建格式化字符串相比,字符串内插提供的语法更具可读性,且更加方便。

原文链接:https://www.vinanysoft.com/c-sharp-basics/introducing/console-input-and-output/

原文地址:https://www.cnblogs.com/vin-c/p/12007933.html