【问题标题】:Distinguish read char from read integer区分读取字符和读取整数
【发布时间】:2015-05-20 03:40:21
【问题描述】:

我正在用 C 实现 RLE 算法,但我遇到了一个很大的问题。我使用 @ 作为压缩/解压缩的标识符。让我举个例子:

0 0 0 0 1 2 0 0 0 0 = @ 0 4 1 2 @ 0 4

@ X Y 的种类 = 重复 X、Y 次。数字从 0 到 255(无符号字符)不等。但是,数字 64 搞砸了我,因为它和“@”是一样的。

程序读取 64 0 5

我预计:64 0 5(无需解压)

我得到的是:0 0 0 0 0(64 存储在一个 char 变量中,然后,程序将其用作 '@')

if (var == '@') {
    // decompress
}

【问题讨论】:

  • 如何将unsigned char 转换为整数?

标签: c char


【解决方案1】:

我猜你正在使用类似scanf 的函数来解析你的输入。

不要。在这种情况下它不起作用。

相反,只需读取输入字符串,用空格将其拆分为标记(例如:"@ 0 4 1 2 @ 0 4" --> "@", "0", "4", "1", "2", "@", "0", "4""64 0 5" --> "64", "0", "5")。

下一步是解析。在那里你可以清除@-s。除了64-s 和strlen("@") == 1strlen("64") == 2 之外,很容易将它们区分开来,你看;)

当您遇到纯数字字符串时,您可以使用atoi 之类的东西将其转换为整数(之后您可以随意将其转换为unsigned char)。

【讨论】:

    【解决方案2】:

    您需要选择一个绝对不会用作转义机制的字符序列。如果您将输入转换为 @ <character> <count>,并且至少连续出现 3 次相同的字符,那么您未转换的最差输入有 2 个连续的 @ 字符。

    输入中的另一个最坏情况是有 64 个 @ 字符,这会产生 @ @ @。所以,我们确定输出不能包含超过 3 个连续的@。

    鉴于此,您可以将单个@ 字符表示为@@@@,即产生4 个字符。如上所示,RLE 的输出不能有 4 个连续的 @(或任何其他 4 个连续的字符,以这种方式)

    但是,如果您总是将 @ 转换为 @ @ <count>,则可以节省一个字节,并且您只需要修改项目的 RLE 创建部分,因为这种格式完全可以根据到 RLE 解析器。

    【讨论】:

      【解决方案3】:

      这可能不是解决问题的最佳方法,但确实可以。 c 编译器在需要时自动将 int 转换为 char 并将 char 转换为 int。如果你能找到一种方法来限制这种行为,那么问题就解决了。我通过将字符转换为 respective ASCII 并将其与 @ASCII value 进行比较来限制行为。

      该程序的明显问题是它读取单个字符,并且它永远不会遇到 64 作为一个整体,但即使我们修改程序以使用空格作为分隔符分割数字,我认为这不会有什么问题

          #include<stdio.h>
          #include<string.h>
          int main()
          {
              char s[]= "64 0 5 @ 0 5";
              int length = strlen(s);
              int i = 0;
              char ch;
              while((ch = s[i]) != '\0')
              {
                  int charASCII = ch;
                  if(charASCII == 64)
                      printf("Perform Algorithm\n");
                  else
                      printf("Do not Perform Algorithm\n");
                  i++;
              }
              return 0;
          }
      

      【讨论】:

        【解决方案4】:

        转义重复指令的一个非常简单的解决方案是使用重复字符。

        让我解释一下:

        0 0 0 0 编码为0 0 2(2 表示将前一个字符再重复2 次)

        小心重复2次:

        3 4 4 5应编码为3 4 4 0 5

        0 表示后面没有“4”。

        解码时只寻找一个重复的字符,找到后,将下一个字符作为重复次数。

        未经测试的示例:

        int input_char(void);
        void output_char(int);
        
        void encode(void) {
            int c, previous_c = EOF;
            int repeating = 0, repetitions;
        
            while ((c = input_char()) != EOF) {
                if (repeating) {
                    if (c == previous_c && repetitions < 255) {
                        ++repetitions;
                    } else {
                        output_char(repetitions);
                        output_char(c);
                        repeating = 0;
                    }
                } else {
                    output_char(c);
                    if (previous_c == c) {
                        repeating = 1;
                        repetitions = 0;
                    }
                }
                previous_c = c;            
            }
        }
        
        void decode(void)
        {
            int c, previous_c = EOF;
        
            while ((c = input_char()) != EOF) {
                output_char(c);
                if (c == previous_c) {
                    int repetitions = (unsigned char) input_char();
        
                    while (repetitions--) {
                        output_char(c);
                    }
                }
                previous_c = c;            
            }
        }
        

        【讨论】:

          【解决方案5】:

          看看这个ascii table:你可以看到数字的范围,用它来确定你是否在读一个数字:

          if (var >= 48 && var <= 57) {/* I'm an integer */}
          

          【讨论】:

            猜你喜欢
            • 2018-12-20
            • 1970-01-01
            • 2022-06-16
            • 2016-08-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多