【问题标题】:Understanding a Char to ASCII conversion function了解 Char 到 ASCII 的转换函数
【发布时间】:2016-10-03 05:21:41
【问题描述】:

我将如何在 C++ 中使用这个函数?它应该返回索引为 ip 的字符串 p 中字符的 ASCII 值。

#include <cstring>

int ascVal(size_t ip, const char* p)
{
    // Return the ASCII value of the char
    if(!p || ip > strlen(p))
        return -1;
    else
        return p[ip];
}

我很想学习如何使用这个功能。谢谢。

【问题讨论】:

  • int asciivalue = 'a';?
  • 您的代码的问题是您分配了一个字符,然后将指向该字符的指针用作数组并尝试在该数组中获取索引256。这 方式 超出了您分配的单个字符的范围。这会导致未定义的行为
  • 第二段代码看起来很混乱,有点像你把几行放在一起编译,根本不了解它们的作用。另外,“我没有得到我所期望的”,那你有什么期望呢?

标签: c++ char ascii


【解决方案1】:

您似乎误解了“字符”和“字符缓冲区”。

字符缓冲区是一个字符数组。 “ascval”函数中的“size_t”只不过是缓冲区中的字符数,从零开始索引。

为了您的理解,我调整了您的代码。它可以工作(未优化)

#include <iostream>
#include <cstring>


int ascVal(size_t ip, const char* p)
{
    // Return the ASCII value of the char
    if(!p || ip > strlen(p))
        return -1;
    else
        return p[ip];
}


int main()
{
    std::cout << ascVal(0,"a") << std::endl;

    char *letter = new char;
    *letter = 'a';
    size_t asciiSize = 0;

    int letterValue = letter[asciiSize];
    std::cout << letterValue << std::endl;



}

【讨论】:

    【解决方案2】:

    首先是函数的运行,因为您应该了解它所做的所有事情才能欣赏它。

    int ascVal(size_t ip, const char* p)
    {
        // Return the ASCII value of the char
        if(!p // if p is NULL there is not string ergo nothing vcan be done with it
           || // boolean OR means if either condition is met
           ip > strlen(p)) //the index of the requested character is NOT inside the string  
            return -1; // we can do nothing with input this bad. Return an error
        else
            return p[ip]; // get the ipth character in the string and return the character as 
                          // an integer. This makes the character look like a number. It's 
                          // really been a number the whole time but characters are treated 
                          // and displayed to the user differently than an int
    }
    

    现在 OP 正在做什么:

    char *letter = new char; // dynamically allocating a block of memory exactly one 
                             // character long
    *letter = 'a'; // assigning the letter a to that one character
    size_t asciiSize = 256;
    
    int letterValue = letter[asciiSize]; // get the asciiSizeth (256th) character in the block 
                                         // of memory. Unfortunately there is no 256th
                                         // character in that block of memory. This is bad.
    cout << letterValue << endl; // print value of 256th character in bloc of one character.
    

    与上述函数不同,OP 不会验证 letter 是否指向任何内容。这是一个有争议的问题,因为 OP 只是将它设置在上面几行并且很清楚 letter 是一个有效的指针。 OP也不保证asciiSize指定的数组位置在数组内。

    我认为,这就是我们遇到 OP 的概念问题的地方。 OP 似乎假设因为 ASCII 中有 256 个值,所以他们可以只要求值 256。

    问题 1:原点 0

    几乎所有编程都从 0 开始计数。如果您有 256 个可能的值,则这些值是 0 到 255。256 太大,会发生一些奇怪的事情。通常 256 会溢出并变为 0,但我不会在所有情况下都指望这一点。

    问题 2:ASCII 是 7 位

    ASCII 值只有 2 的 7 次方或 128 个。因为我们通常将 ASCII 值放在 8 位数字中,所以人们已经找到了使用未使用的 128 值的方法,但这通常由显示该值的任何内容的本地化或代码页设置定义。不要指望在没有先检查的情况下得到你想要的。

    问题 3:数组索引

    letter[asciiSize] 是对letter 之后的asciiSize 数组元素的请求。教科书是查找有关数组和索引的详细信息的更好地方,但这里重要的是您不应该要求您没有的内存,也不应该要求超出已使用的数据。这给我们带来了

    半题4:空终止

    *letter = 'a' 只是一个指向恰好是“a”的单独字符的指针。这不是一个字符串。要成为字符串,您需要有某种大小信息或终止符,以便您知道何时停止读取字符串。在 C 中,终止符是字符值 0。它从不在对话中使用,因此它是表示文本字符串结尾的完美标记。不要尝试将其用于二进制信息。二进制有非常不同的规则。通常二进制信息的确切大小是提前知道的,或者使用不可能出现在二进制流中的序列来标记结束,即终止符。在二进制中 0 很常见,因此您通常必须选择其他值。

    这里我们知道letter 正好指向一个字符,因为 OP 只在其中放置了一个字符。指针没有线索。这完全取决于程序员,如果程序员分配一个字符,然后要求第 100 个字符,那就是他们的问题。

    所以要把letter变成一个字符串

    char *letter = new char[2];
    *letter = 'a'; // same as letter[0] = 'a'
    letter[1] = '\0'; // same as *(letter + 1) = '\0'
    

    现在我们可以根据需要使用strlen 来确定字符串的长度。

    把所有这些放在一起,如果你想要一个具有给定值的字符,比如 42,你所要做的就是

    char val = 42;
    

    显示val 将导致'*',分配给42 的符号。为什么'*'?没有人知道,道格拉斯亚当斯死去试图找出答案。道格拉斯!我们向您致敬!

    这里不需要数组索引。您只需要一份 ASCII 表的副本。

    如果您确实需要字符串的第 256 个字符,则必须首先使字符串足够大,然后填充到第 256 个字符或更大。不要因为程序没有崩溃就假设没有第 256 个字符。首先像使用strlen 的原始函数一样进行测试。测试并祈祷提供字符串的人正确终止它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 2013-11-20
      • 2014-10-10
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多