【问题标题】:Fast Method of Converting Character Array to ASCII Key Value字符数组转ASCII键值的快速方法
【发布时间】:2016-03-01 01:06:25
【问题描述】:

我正在编写一个程序,它从一个由 a-z 和数字 0 组成的文件中按顺序读取大量字符。示例如下所示:

a0dgiw00cffn0ai0cbiwa0...

我相信我用这个将这个序列转换为一个字符数组:

strncpy(array, string.c_str(), sizeof(array));

现在我有一个应该如下所示的数组:

[a][0][d][g][i][w][0][0]...

所以我的问题是,将字符数组中的所有值转换为 ASCII 键值的最有效方法是什么?在尽可能少的时间内最有效。如果你不明白我所说的“ASCII 键值”是什么意思,那么最终的数组应该是这样的:

[97][48][100][103][105][119][48][48]...

旁注:可以在here 找到一个 ASCII 键值表。

旁注:我已经知道如何将数组值转换为 ASCII,我只是在寻找一种更快的方法。

提前谢谢你。

【问题讨论】:

  • 当您说“ASCII 键值”时,您指的是什么数据类型。因为 'a' 是 [97] 而 '0' 是 [48]。例如 if( 'a' == 97 ){ printf("'a' is 97"); }
  • 最快的方法是直接将文件读入字符数组(或std::vector<char>s),完全跳过std::strings的创建和转换……
  • @kuroineko 我从向量开始,然后决定坚持使用数组和字符串。我不是想加快将文件放入字符数组的过程,只是想更快地在字符和 ASCII 之间进行转换。
  • @Synthetic 除非您需要问题中未包含的其他内容,否则您似乎并不理解“字符”和“ASCII”已经完全相同。
  • @Synthetic 这就是我要告诉你的:字符已经存储在 ASCII 中。这就是您的计算机存储字符数组的方式。你可以运行这个来确认:printf("The character %c is the same as the number %d", 'a', 'a'); printf("The number %d is the same as the character %c", 97, 97);

标签: c++ arrays ascii


【解决方案1】:

假设您的语言环境有很多东西,它已经“在后台”存储为 ASCII 字符,如二进制中的 'a'==97 作为字符(或您的编译器/系统使用的任何内容)。要让您的系统将“a”视为整数值而不是字符,您只需执行(int)'a',并将字符串的任何部分视为(int)array[index]。

#include <iostream>
#include <string>

int main() {
    using namespace std;
    string sample = "abcdefghijklmnopqrstuvwxyz";
    for(char c : sample) {
        // NOTE: cast to (int) doesn't change value of 'c'.
        cout << c << '=' << (int)c << endl;
    }
    return 0;
}

输出:

a=97
b=98
c=99
d=100
e=101
f=102
g=103
h=104
i=105
j=106
k=107
l=108
m=109
n=110
o=111
p=112
q=113
r=114
s=115
t=116
u=117
v=118
w=119
x=120
y=121
z=122

【讨论】:

  • 好的,所以我了解您在这种情况下正在做什么,但在实施它时遇到了问题。你介意给我举个例子吗?谢谢。
  • @Synthetic MtRoad 指出您似乎已经完成了您所要求的一切。你能用什么不工作来更新原来的问题吗?
  • @MatthewCarlson 问题不在于它不起作用,就我而言,我需要将数组中的字符存储为实际整数,所以如果我要打印任何元素的值它会打印相应的 ASCII 码。
  • @Synthetic 这是 MtRoad 和我都想告诉你的。数组中的字符存储为实际整数( char 在大多数计算机上是 8 字节的整数值,尽管从技术上讲它可以更多。)cout &lt;&lt; char 的默认行为是将其打印为字符值,但 printf( "%d", char) 将其显示为数字,cout &lt;&lt; 0+char 也是如此。
  • @Synthetic,你混淆了逻辑和物理表示。从逻辑上讲,'a' 是一个字符,97 是一个 int!但是,在物理上,按位它们在处理英语和其他一些情况时是相同的,因为 ASCII(整数)字符代码是您表示字符的方式......
【解决方案2】:

对于初学者,如果您正在寻找效率,那么数组的初始strncpy() 绝对不会完成任何事情。我看不出它能给你带来什么。 string.c_str() 为您提供与数组获得的完全相同的 const char *。保持一切就位,避免不必要的复制开销。

然后,如果您正在寻找将 char 值转换为十进制的最有效方法,那么手动操作将很难胜过。

unsigned char c=  /* wherever you get the next char from */

int zero=0;

if (c >= 100)
{
    zero=1;
    *ptr++ = (c/100) + '0';

    c = c % 100;
}

if (c >= 10 || zero)
{
    *ptr++ = (c / 10) + '0';
}

*ptr++ = (c % 10) + '0';

这应该轻松击败 std::ostream 所做的事情,因为它不必担心 std::ostream 的输出格式必须做的所有包袱。

现在,如果原始 string 的长度为 n=size() 字节,则转换为十进制表示的整个事物的最长可能大小是每个值三个字符,或 n*3。然后,考虑到括号,还有两个,总计n*5。

所以:

 std::vector<char> output_buffer;

 output_buffer.resize(string.size()*5);

 auto ptr=&output_buffer[0];

 for (unsigned char c:string)
 {
       // the code segment above, with a few extra bits to append
       // the [ and the ], in the right place.
 }

完成后,ptr-&amp;output_buffer[0] 会为您提供实际写入的字符数。您可以修剪缓冲区,或将其复制到您自己的 std::string 中,您可以选择。

【讨论】:

  • 精明地讨论处理 std::ostream 的低效率。
  • 好吧,std::ostream 并不是真的那么低效,但是如果想要挤出每个可用的 CPU 周期,并且格式化需求很简单,那么滚动你自己的就是要走的路。 ..
  • 山姆,我完全同意。这将是一个有限的情况,在这种情况下,“自己动手”实际上可能比标准库更快。在大多数情况下,您是在浪费时间。
猜你喜欢
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 2016-07-04
  • 2014-09-08
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多