Distinguish read char from integer read

I use the RLE algorithm in C and I have a big problem. I use @ as an identifier for compression / decompression. Let me use examples:

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

View @XY = repeat X, Y times. And the numbers range from 0 to 255 (unsigned char). But the number 64 wraps me up because it matches the "@".

The program reads 64 0 5

I expect: 64 0 5 (no decompression required)

What I get: 0 0 0 0 0 (64 is stored in a char variable, and then the program uses it as '@')

if (var == '@') { // decompress } 
+6
source share
5 answers

I assume that you are using some scanf function to scanf your input.

not to do. In this case, this will not work.

Instead, just read the input line, divide it with spaces into tokens (examples: "@ 0 4 1 2 @ 0 4" β†’ "@", "0", "4", "1", "2", "@", "0", "4" and "64 0 5" β†’ "64", "0", "5" ).

The next step is parsing. There you can snatch @ -s. It will be easy to distinguish them from 64 -s as strlen("@") == 1 and strlen("64") == 2 , you see;)

And when you come across a purely numeric string, you can use something like atoi to convert it to an integer (and after that you can convert it to unsigned char ).

+1
source

You need to select a sequence of characters that will definitely not be used as an evacuation mechanism. If you convert the input to @ <character> <count> , if there are at least 3 consecutive occurrences of the same character, the worst input that you do not convert has 2 consecutive @ characters.

Another worst case of input is the 64 @ characters that @ @ @ produces. So, we are sure that the output cannot contain more than three consecutive @.

In light of this, you can imagine a single @ character as @@@@ , which creates 4 characters. As you can see above, the RLE output cannot have 4 consecutive @ (or any other 4 consecutive characters, this way)

But instead, if you always convert @ to @ @ <count> , you can save the byte, and you only need to change the RLE creation parts of your project, as this format fits perfectly into the RLE parser.

+1
source

It may not be the best way to solve the problem, but it does the job. c will automatically convert int to char and char to int if necessary. If you can find a way to limit this behavior, the problem will be solved. I limited the behavior by converting the character to respective ASCII and comparing it to ASCII value @ .

The obvious problem with the program is that it reads individual characters, and it will never meet 64 in general, but even if we modify the program to separate numbers with a space as a separator, I don’t think it would be some kind of problem

  #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; } 
0
source

A very simple solution to speed up a repeat command has a repeating character.

Let me explain:

encode 0 0 0 0 as 0 0 2 (2 means repeat the previous character two more times)

just be careful 2 times reps:

3 4 4 5 must be encoded as 3 4 4 0 5 ,

0 means no longer follows "4".

When decoding just looks for a repeating character and when it is found, get the next character as the number of times to repeat it.

Unconfirmed example:

 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; } } 
0
source

Looking at this ascii table : you can see the range, which for numbers, use this to determine if you are reading a number or not:

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

Source: https://habr.com/ru/post/987541/


All Articles