[英]conversion of multiple ascii characters in a char array to single int using their ascii values — c/c++
有谁知道这种转换的好方法?
例如,将char数组保存为ascii charcters“ABC”,我正在寻找的int转换会将这些字符更改为值为656667的单个int。
任何帮助将非常感谢。
编辑真的很感谢回复。 正如有人所说,我确实说过char数组,特别是这是一个字节数组,因此可能有多个'\\ 0'或NULL元素,后跟另外的ascii。 使用strlen等方法会导致问题。 再次感谢当前的输入。
在C:
#include <stdio.h>
#include <string.h>
int main(){
char start[]="ABC";
char output[100];
int i;
char* output_start=output;
for(i=0;i<3;i++){
output_start+=sprintf(output_start,"%d",start[i]);
}
printf("%s\n",output);
}
这使用sprintf
函数将每个字符分别打印到字符串中。 这避免了在char
的ASCII值不总是两位数时可能出现的其他方法可能出现的问题。
编辑 :根据您的最新更新,您可能希望使用%u
而不是%d
。
目前还不完全清楚最终结果是什么。 但在我看来,将“ABC”转换为整数656667具有很大的价值。 问题是结果不明确。 你可能不想将它转换为0x414243吗? 如果是这样,那么memcpy会起作用。
编辑:如果字符集不限于特定范围(特别是0-99),结果可能不明确。 我相信ASCII字符被认为是从0到127(0x7f)的所有字符。 通过将十进制值连接在一起将结果转换为整数会产生一个不明确的值。 例如,字符串"xy"
的单个十进制值为120,121。根据原始问题定义,结果将为120121.这可以解码为12,01,21或120,121。两者都导致有效的ASCII字符。 但是,再次,在不知道所有问题限制的情况下,这可能是完全有效的。
你真的更好,去字节(* 256)而不是十进制(* 100),因为它允许你使用字符集中的任何值。
使用unsigned int而不是int也更好,因为它将避免签名/未签名的问题。
如果您正在进行网络传输,那么将值转换为网络字节顺序,是非常好的建议。
unsigned int func(const char s[], size_t size)
{
const unsigned char *us = (const unsigned char *) s;
unsigned int result = 0;
size_t z;
for (z = 0; z < size; z++)
{
result *= 256;
result += us[z];
}
return result;
}
我还没有测试过上面的代码。
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "ABC";
int i, n;
for (i=0,n=0; i<strlen(str); i++, n*=100) {
n += str[i];
}
n /= 100;
printf("%d\n", n);
}
使用C ++,获取结果字符串并将其转换为int将留作OP的练习
std::string StringToDec( const char *inString )
{
if ( inString == NULL )
{
return "";
}
else
{
std::ostringstream buffer;
std::string String = inString;
for ( std::string::iterator it = String.begin(); it != String.end(); it++ )
{
buffer << std::setw(2) << std::dec << int(*it);
}
return std::string ( buffer.str().c_str() );
}
}
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char * input = "ABC";
char output[ 256 ];
int n = 0;
while( *input )
n += sprintf( output + n, "%d", *input++ );
printf( "%d\n", atoi( output ) );
return 0;
}
依赖于以null结尾的字符串。 必要时output
硬编码大小。
我在你的帖子中注意到你说“char数组” - 值得注意的是,不是一个字符串。 假设你实际上是指一个char数组而不是一个以null结尾的字符串,那么所有发布的sprintf-type解决方案都不会起作用。
这是一个不使用字符串处理的简单数学方法。
char str [] = {'A','B','C'};
int ret = 0;
for( int i = 0; i < sizeof(str); ++i )
{
ret *= 100;
ret += str[i];
}
更新:
如果您正在寻找一种不依赖于乘法的解决方案(也许是速度),您也可以使用班次:
int ret = 0;
for( int i = 0; i < sizeof(str); ++i )
{
ret = ((ret << 2) + ret) << 1; // ret *= 10
ret = ((ret << 2) + ret) << 1; // ret *= 10
ret += str[i];
}
其他人可能有另一个直接乘以100的移位操作序列 - 我没有。 另请注意,只需使用3个字节来表示字符而不是两个字符,就可以考虑不可打印字符0-256。 虽然你将很快用完C ++本机类型的空间:
char str [] = {0, 123, 'A'};
unsigned __int64 ret = 0;
for( int i = 0; i < sizeof(str); ++i )
{
ret = ((ret << 2) + ret) << 1; // ret *= 10
ret = ((ret << 2) + ret) << 1; // ret *= 10
ret = ((ret << 2) + ret) << 1; // ret *= 10
ret += str[i];
}
大多数小写字母的ASCII值超过99,因此您的问题仅对大写字母有效。 如果您确定系统中的字符是ASCII编码的(例如, 'A'
为65),则上述大多数解决方案都可以使用。 否则,为了最大程度的便携性:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int main(void)
{
static const char *const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int A = 65;
/* changed: since it's a char array, not necessarily a string */
const char in[3] = "ABC";
unsigned long long out = 0;
size_t i;
for (i=0; i < sizeof in; ++i) {
char *found = strchr(upper, in[i]);
if (found) {
if ((ULLONG_MAX - (A + (found - upper))) / 100 < out) {
fprintf(stderr, "Overflow at %c\n", in[i]);
return EXIT_FAILURE;
}
out = out * 100 + A + (found - upper);
} else {
fprintf(stderr, "Giving up at %c\n", in[i]);
return EXIT_FAILURE;
}
}
printf("%llu\n", out);
return EXIT_SUCCESS;
}
(我假设您想要一个值为"ABC"
的值为656667的数字,例如,您不仅要打印。)
由于它是用于网络协议,因此您必须指定字节顺序。 您将字节按特定顺序放入int
中,并询问该值。 字节以两个不同的顺序进入int
。 这在一台计算机上无关紧要,因为计算机不会随意改变字节序,但您可以轻松地在两台不同的计算机上获得两个不同的值。
话虽如此,有各种转换方式。 一个是使用union
,一个是在int *
(或unsigned int *
)和char *
。 只需确保使用一致的字节顺序。
大多数时候,人们必须看看实际问题。
解析数据包协议可能很容易,也可能不容易,具体取决于规范,但你通常可以把它全部放在一个字符串中...
如果您不了解它们,请查看Google Protocol Buffer
,它们不能按原样使用,但这个想法就在那里。
class UdpPacket
{
public:
UdpPacket(const char str[], size_t length);
uint16_t sourcePort() const { return mSourcePort; }
unit16_t destinationPort() const { return mDestinationPort; }
// ... The 3 other getters
private:
uint16_t mSourcePort;
uint16_t mDestinationPort;
uint16_t mLength;
uint16_t mCheckSum;
std::string mData;
}; // class UdpPacket
UdpPacket::UdpPacket(const char str[], size_t length):
mSourcePort(0), mDestinationPort(0), mLength(0), mCheckSum(0),
mData()
{
if (length < 8) throw IncompleteHeader(str, length);
memcpy(mSourcePort, str, 2);
memcpy(mDestinationPort, str, 2);
memcpy(mLength, str, 2);
memcpy(mCheckSum, str, 2);
mData = std::string(str+8, length-8);
} // UdpPacket::UdpPacket
净优势? 您现在拥有结构化数据。 当然, memcpy
可能会出现一些memcpy
...你必须检查它。
现在,我不知道你的mData
应该是什么,但当然如果它的结构也会更好。
使用一个简单的int
存储看起来不像int
的东西,我认为这真是一个坏主意......当然,除非它是一个int
开头。
看看这是否有效。 这将打印“AB \\ 0C”为6566067.如果要将其打印为656667,则删除if (!val) rv *= 10;
int asciiToInt(char *str, int len) {
int i;
int rv = 0;
for (i = 0; i < len; i++) {
int val = str[i];
if (!val)
rv *= 10;
while (val) {
rv *= 10;
val /= 10;
}
rv += str[i];
}
return rv;
}
这个怎么样:
#include <iostream>
#include <sstream>
#include <algorithm>
struct printer {
std::stringstream& s;
printer(std::stringstream& stream_) : s(stream_) { };
void operator()(char& c) { s << static_cast<int>(c); }
};
int main (int argc, char* argv[]) {
std::stringstream helper;
char* in = "ABC";
std::for_each(in, in+3, printer(helper));
int result;
helper >> result;
std::cout << result; // print 656667
return 0;
}
编辑:您要求转换为int。 我稍微改变了代码来做到这一点。
这样的事情会为你做“正确的事”吗?
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
int main()
{
// considering you know the size of buffer here's the buffer
const unsigned char buf[] = {'A', 'B', '\0', '\0', 'C', 'd', 'e', 'f'};
// 'conversion' happens here
const std::vector<int> data(buf, buf + sizeof buf/sizeof 0[buf]);
std::copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
结果:
65 66 0 0 67 100 101 102
当然没有什么大不了的把这个向量放到stringstream
然后从它到int
和int
,但它会很快溢出:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
struct PutElementToStream
{
PutElementToStream(std::stringstream &stream)
: stream_(stream)
{}
void operator()(int value)
{
stream_ << value;
}
private:
std::stringstream &stream_;
};
int main()
{
const unsigned char buf[] = {'A', 'B', '\0', '\0', 'C', 'd', 'e', 'f'};
const std::vector<int> data(buf, buf + sizeof buf/sizeof 0[buf]);
std::stringstream stream;
std::for_each(data.begin(), data.end(), PutElementToStream(stream));
std::cout << "stream: " << stream.str() << "\n";
int value = 0;
stream >> value; // the sample array would overflow an int
std::cout << "int value: " << value << "\n";
const std::string string_value(stream.str());
std::cout << "string value: " << string_value << "\n";
return 0;
}
结果:
stream: 65660067100101102
int value: 0
string value: 65660067100101102
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.