Console.ReadLine 将 48 添加到 int

发布于 2025-01-02 23:41:51 字数 506 浏览 1 评论 0原文

当我向 ReadLine() 输入 0 时,我得到 48。

这是一个错误吗?

class Program
{
    static void Main(string[] args)
    {
        string name;
        int age;

        readPerson(out name, out age);
    }
    static void readPerson(out string name, out int age)
    {
        Console.Write("Enter name: ");
        name = Console.ReadLine();
        Console.Write("Enter age: ");
        age = Console.Read();
        Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString());
    }
}

I get 48 when I input 0 to a ReadLine().

Is this a bug?

class Program
{
    static void Main(string[] args)
    {
        string name;
        int age;

        readPerson(out name, out age);
    }
    static void readPerson(out string name, out int age)
    {
        Console.Write("Enter name: ");
        name = Console.ReadLine();
        Console.Write("Enter age: ");
        age = Console.Read();
        Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString());
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不忘初心 2025-01-09 23:41:52

不,这根本不是一个错误。

Console.Read() 返回输入的任何字符的 ASCII 字符代码。数字 0 的 ASCII 码是 48,数字 1 的 ASCII 码是 49,依此类推。它不是任意添加数字 48,也与 out 参数没有任何关系。

您需要读取一行并将输入相应地转换为整数:

Console.Write("Enter age: ");
age = Convert.ToInt32(Console.ReadLine());

如果您出于某种原因需要使用 Read() ,那么就像我在评论中所说的那样,您需要将结果转换为字符。您还需要将变量从 intage 更改为 charage

class Program
{
    static void Main(string[] args)
    {
        string name;
        char age;

        readPerson(out name, out age);
    }
    static void readPerson(out string name, out char age)
    {
        Console.Write("Enter name: ");
        name = Console.ReadLine();
        Console.Write("Enter age: ");
        age = (char) Console.Read();
        Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString());
    }
}

请记住,Read() 只能读取一个字符一个时间,所以如果您需要解析一个以上数字的年龄,这将不起作用,您最好使用 ReadLine() 来代替。

No, it's not a bug at all.

Console.Read() returns the ASCII character code for whatever character is entered. The ASCII code for the digit 0 is 48, and for the digit 1 is 49, and so on. It's not adding the number 48 arbitrarily, nor does it have anything to do with out parameters.

You need to read in a line and cast the input to an integer accordingly:

Console.Write("Enter age: ");
age = Convert.ToInt32(Console.ReadLine());

If you need to use Read() for whatever reason, then like I said in my comment you need to cast the result to a char. You'll also need to change your variable from int age to char age:

class Program
{
    static void Main(string[] args)
    {
        string name;
        char age;

        readPerson(out name, out age);
    }
    static void readPerson(out string name, out char age)
    {
        Console.Write("Enter name: ");
        name = Console.ReadLine();
        Console.Write("Enter age: ");
        age = (char) Console.Read();
        Console.WriteLine("Name: {0}; Age: {1}", name, age.ToString());
    }
}

Bear in mind that Read() can only read one character at a time, so if you need to parse an age with more than one digit, this won't work, and you're much better off just using ReadLine() instead.

霊感 2025-01-09 23:41:52

根据 MSDN 文档,Console.Read 方法返回:

输入流中的下一个字符,如果当前没有更多字符要读取,则为负数 (-1)。

因此,您实际上看到的只是当前流上的第一个字符(即,在最后两次 Enter 按下之间收到的字符)。

在单元测试期间,这些值看起来好像移动了 48,因为碰巧从“0”到“9”的字符的 ASCII 值是,您猜对了,“0”为 48,“0”为 49。 1'等:

ASCII Table

由于您没有指定转换,流内容被“自动”读取为char 值,并且您对 Read() 的调用显示了它们的 ASCII 十进制等值。

您可以使用这个简单的测试来验证这一点:

static void TestRead()
{
    int current = 0;

    Console.Write("Enter 1: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    Console.Write("Enter 22: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);
}

这将导致:

Output

您会注意到连续调用Read() 从流中抓取单个字符,并给出其 ASCII 十进制等效值。另外,请注意 Windows 如何为 Enter 键的每次敲击附加回车符 (ASCII 13) 和换行符 (ASCII 10) 序列,您的程序会忠实地向您回显这些序列。

对此测试方法稍作修改将有助于解决缺乏特定方向的问题,运行时会将输入流的内容解释为字符:

static void TestReadModified()
{
    int current = 0;

    Console.Write("Enter a: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);
}

正如预期的那样,上面的方法将返回字符“a”的 ASCII 值:

Output for a letter

正如其他人已经提到的,这很容易解决。只需通知运行时您希望将该值解释为 int 即可。至少检查收到的输入是否是一个数字可能也是一个好主意:

static void readPerson(out string name, out int age)
{
    Console.Write("Enter name: ");
    name = Console.ReadLine();

    Console.Write("Enter age: ");

    // in this case, we could simply use tempAge (defaults to 0)
    // but it's just practice to check TryParse's success flag
    int tempAge;
    var success = Int32.TryParse(Console.ReadLine(), out tempAge);

    age = success ? tempAge : 0;

    Console.WriteLine("Name: {0}; Age: {1}", name, age);
    Console.ReadLine();
}

According to the MSDN documentation, the Console.Read method returns:

The next character from the input stream, or negative one (-1) if there are currently no more characters to be read.

So, really what you're seeing is only the first character currently on the stream (i.e., characters received between the last two Enter pushes).

During your unit testing, it appeared as if the values were shifted by 48, because it so happens that the ASCII values for the characters from '0' to '9' are, you guessed it, 48 for '0', 49 for '1', etc:

ASCII Table

Since you didn't specify a conversion, stream contents were "automagically" read as char values, and your call to Read() displayed their ASCII decimal equivalents.

You can verify this using this simple test:

static void TestRead()
{
    int current = 0;

    Console.Write("Enter 1: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    Console.Write("Enter 22: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);
}

Which will result in:

Output

You will notice that back-to-back calls to Read() grab a single character from the stream, and give you its ASCII decimal equivalent. Also, note how Windows appends a carriage return (ASCII 13) and linefeed (ASCII 10) sequence for every stroke of the Enter key, which your program faithfully echoes back to you.

A slight modification of this test method would help drive the point that lacking specific directions, the runtime will interpret the contents of your input stream as characters:

static void TestReadModified()
{
    int current = 0;

    Console.Write("Enter a: ");
    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);

    current = Console.Read();
    Console.WriteLine("Next char: {0}", current);
}

As expected, the method above will return the ASCII value for character 'a':

Output for a letter

As others have already mentioned, this is easy to fix. Just inform the runtime that you want the value to be interpreted as an int. It's probably also a good idea to, at least, check that the input received is a number:

static void readPerson(out string name, out int age)
{
    Console.Write("Enter name: ");
    name = Console.ReadLine();

    Console.Write("Enter age: ");

    // in this case, we could simply use tempAge (defaults to 0)
    // but it's just practice to check TryParse's success flag
    int tempAge;
    var success = Int32.TryParse(Console.ReadLine(), out tempAge);

    age = success ? tempAge : 0;

    Console.WriteLine("Name: {0}; Age: {1}", name, age);
    Console.ReadLine();
}
彻夜缠绵 2025-01-09 23:41:52

正在打印数字的 ASCII 代码。请注意,Console.Read() 从标准输入读取下一个字符并返回一个 int。因此,当您输入字符 0(不是整数0)时,它会返回 ASCII 代码 48 等。此外,该 ASCII 代码是字符的整数代码(例如 0),因此将此代码转换为 int 是多余的。您将年龄作为字符串读取并将其转换为整数,这可以使用 Console.ReadLine 完成,然后使用 int.TryParse 等。

The ASCII codes for the numbers are being printed. Note that Console.Read() reads the next character from the standard input and returns an int. So, when you input character 0 ( not integer 0), it returns the ASCII code 48 and so on. Also, this ASCII code is the integer code for the character ( say 0) so converting to int of this code is redundant. You read in the age as string and convert it to integer, which can be done with Console.ReadLine and then using int.TryParse etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文