处理char整数

时间:2019-07-29 08:56:12

标签: c++ c

我有以下问题。将某个字符(作为整数)乘以-1两次可以保证保留初始值吗?

因此,我运行一些代码,通过将其乘以-1来标记已读字符(我生活在ASCII世界中,但是其他任何符号编码也将很有趣)。

例如,假设我已将英语字母'a'读入变量c中。为了防止进一步的代码检测到此,是将较低的字母I乘以-1。毕竟这是一个整数。

代码基本上是对某些问题的回溯解决方案,因此在检查了决策树分支之后,我想将字母的初始值返回给自身。

char c;
// some code gets the value
c *= -1;
// handle something
c *= -1;

面对的问题更多是我应该期待什么?,而不是某些事情无法按预期工作

>

我要转换的字符始终是英文字母,可能是大写或小写。

从我在ASCII表中看到的两个类都在0 .. 127范围内。

如果

1)char在我的计算机上签名,我希望字母不是常规字母。哪个好 2)char是unsigned。我没有线索。应该在-1中执行int的乘法运算,然后将其截断为char吗?

既然,该标准不要求符号为ASCII,其他编码的结果是否会有所不同?

5 个答案:

答案 0 :(得分:2)

  

是否将某个字符(作为整数)乘以-1两次以确保保留初始值?

嗯,仅考虑这个问题,是的,确实如此。在这两种情况下,都将发生有符号或无符号隐式整数提升(这是标准要求的),并且无论如何都将在int中进行计算(除非无符号char和signed int大小相同,然后{改为{1}}。

签名字符:unsigned int产生x * -1,结果值适合签名字符,很好,我们可以进行赋值( exception :-128;在这种情况下,我们会得到不确定的行为!但是,考虑到ASCII,我们可以排除这种情况作为输入,这很好...)。

未签名的char看起来有点困难:同样,我们得到-x作为结果,但需要将其放入-x中。根据C标准,我们需要多次添加unsigned char直到该值适合该变量为止,在给定情况下,我们得到UCHAR_MAX + 1。然后第二次相乘得到256 - x作为int值,再次加256,直到该值适合变量为止(请记住,x - 256本身已经这样做了)消除了负偏移...

旁注:将x添加多次,直到该值适合该变量,这只是切断了二进制补码机上多余的最高有效位...

仅数值[TYPE]_MAX +1会出现问题,因为它不会改变其值。再次提醒您,这并没有显示为有效输入。

  

既然,该标准不要求符号为ASCII,其他编码的结果是否会有所不同?

不,到目前为止,没有区别-char是带符号的还是无符号的。

但是:您要如何检测标识为无效的值?使用ASCII(和兼容),很简单,所有有问题的值(仅英文字母!)都在[0; 127],则通过检查0(对于带符号的字符)或< 0(对于无符号的字符)来识别无效的字符。这同样适用于仅对相关字母使用下半部或上半部的任何其他编码(这甚至适用于臭名昭著的EBCDIC编码,仅此一次相关字符位于upper half of the [0; 255]范围内,并且您需要反转支票)。但是,如果您遇到使用两个字节值范围的一半进行编码的情况,则这种简单的检查将不再起作用(我一无所知)。但是,使用EBCDIC,您可能会遇到用分隔符一词带来的麻烦:e。 G。简单的空格字符> 128,但大多数标点符号也已经位于字母的另一半(如果您完全使用这样的字母,则不会提到...)!

答案 1 :(得分:1)

  

是否将某些字符(作为整数)乘以-1两次以确保保留初始值?

对于0 .. 127范围内的输入,答案为

会发生两件事:

1)整数提升,即char提升为整数,然后乘以-1

2)从一种整数类型转换为另一种类型,即从intchar

如果您使用的系统具有带符号的字符,则没有什么特别的事情,因为标准要求范围必须至少为-127 .. 127

如果您使用的系统具有 unsigned 字符,则通过将UCHAR_MAX + 1加到乘法结果中以获得可以存储在您的无符号字符中的数字来完成转换。

当我们认为它以无限的精度完成时,它将看起来像这样。

// After first multiplication by -1
-c + UCHAR_MAX + 1

// After first multiplication by -1
-(-c + UCHAR_MAX + 1) + UCHAR_MAX + 1 --> c - UCHAR_MAX - 1 + UCHAR_MAX + 1 --> c

换句话说-在-1两次相乘之后,我们再次具有原始值。

顺便说一句:请注意,零(0)是一种特殊情况,因为0 * -10时算法将不起作用,即标记将不起作用。

答案 2 :(得分:0)

先看一下,然后再进行变换和变回

也许您会知道自己真正想要的东西

#include <stdio.h>
#include <stdlib.h>

int main(){


    int i;

    char c='a';
    int d=c;//Give char to int
    printf("%d\n",d);
    printf("c's Binary is:\n",d);
    for(i=8-1;i>-1;i--){
        printf("%d",(c&(1<<i))>>i);
    }
    printf("\n");

    printf("d's Binary is:\n",d);
    for(i=8*sizeof(int)-1;i>-1;i--){
        printf("%d",(d&(1<<i))>>i);
    }
    printf("\n");

    c*=-1;

    printf("c's Binary(after) is:\n",d);
    for(i=8-1;i>-1;i--){
        printf("%d",(c&(1<<i))>>i);
    }
    printf("\n");

    c*=-1;

    printf("c's Binary(after2) is:\n",d);
    for(i=8-1;i>-1;i--){
        printf("%d",(c&(1<<i))>>i);
    }
    printf("\n");

    c=d;

    printf("c's Binary(d back to c) is:\n",d);
    for(i=8-1;i>-1;i--){
        printf("%d",(c&(1<<i))>>i);
    }
    printf("\n");

    return 0;
}

答案 3 :(得分:0)

也许您可以在这里尝试使用std::bitset。遇到字符时,请使用std::bitset::test设置相应的位。要检查该位是否已设置,您必须使用std::bitset

此答案的界限:

1。您正在寻找对字符进行编码的方法。此答案不会那样做,而是添加一个#include <iostream> // std::cout #include <bitset> // std::bitset const int gAsciiLimit = 128; int main () { std::bitset<gAsciiLimit> foo; char letter = 'a'; std::size_t temp = (std::size_t)(letter); foo.set(temp); // will set the 97th bit to true. std::cout << foo.test(temp) << std::endl; /* Other operations handled */ foo.set(temp,false); std::cout << foo.test(temp) << std::endl; return 0; } 变量,以帮助您跟踪遇到的字符。

2。如果您不重置每个字符后的位,那么在遇到相同字符两次时,可能会导致错误的行为。

请在下面找到示例代码:

etat

答案 4 :(得分:0)

您正在触摸C标准中的一个非常敏感的区域:char默认签名。

您知道,char类型可能在各种目标平台上默认为带符号的或无符号的。这是一个可悲的历史事实,无论如何都要确保程序具有相同的行为。

C标准保证目标字符集中的字母和数字为正数,因此iI之类的小写和大写字母均为正数。但是请注意,如果对é类型进行了签名,则其他一些字符(例如在ISO-Latin-1中编码为0xE9的{​​{1}}和Windows代码页1252将为负)(-23) 。依靠否定char值来防止某些处理是有问题的,因为这样的负char值将变为正值,因此有可能进行转换。

char的值乘以char是使用类型-1(如果int是无符号的且大小与{{ 1}},仅在某些罕见的嵌入式处理器上才会发生)。如果类型unsigned int小于char,则该乘法运算不会溢出,但结果应存储在int中,以防在值超出{{ 1}},例如char是未签名的情况。实际上,在大多数情况下,两次int取反应该会产生原始值,但是如果将中间值存储到int中,则C标准不能保证这种行为。

还请注意,char返回一个char,它的负值char或从流中读取的字节的正值转换为char

对于您的方法,当您要使用否定作为防止某些特殊处理的技巧时,应将字符作为getc()值存储在int变量或EOF变量中。添加256可能会更安全,因为它也会更改unsigned char

unsigned char