I have been banging my head about this for days. I have to make a program for University that used Run Length Encoding to either compress or decompress an ASCII art file depending on the first character in the string a ‘C’ or an ‘E’. The compression part is working like a charm. BUT the expansion is just ever so slightly off on 2/60 lines. And I just cannot figure out why. Belo is the code for my expand() function and main() I didn’t include my compress() because it is working correctly
I have tried to check for memory leaks/ buffer overflows but to no avail, As far as I know Im freeing memory correctly. and making sure that strings from a new line are not being read as the previous.
ASCII Art input:
(E for expansion)
E
20###05
12###07 06#**#!!###03
11#**#!!!04## 03#***04#!!!04#
10#***04###03!!!03# #***05#!!!04#
10#***07#!!!03# #***06#!!!04#
10#***09#!###03!*!*!*#!!!05# 08--
10#!*!*!*!*!*!#!###0A!!!04# 06/_
10###0B!##!!!0A#!!!03# 05//__
0D###03!!!0B#!!!0D#!!!03###04///03 \
03\ 07##!#!!!0B#!!!0F#!!!07#
03_\ 04##!!#!!!0B#!!!0B###06!!!07*#
04\\ ##!!#!!!0C#!!!04###07 05#!!!06***03#
___03\\#!!!03###13***05 07#...03!!***05#
/ 03\#!!!03.# 07***05 # 05***03 08#...04***07#
05#*...04# 08***03 03# 0E#...07***05#
04#**...05## 0A***05 0A##...08!!***04#
04#!...08## 07***07###09...06#...03!!!05*#
03#!...0B###07.***05...0F#.#..!!!04**#
#*...05##...0D#..#...0F#...03#.!!***04#
#*...04#.#...0C#...04#...0C##...06!***05#
#*...07##...07###03...06###03...08#...07!!!03***04#
#*...09###07...06!!...04###08...07!!!05***03#
03#!!!03...11!!!08...0D!!!03***07#
04#!!!04...0C!!!1B***06#
05#***07!!!1C***03!!!04***05#
06#***06!!!19***08!!***04#
07##***05!!!15#***0D###03
09##***04!!!15###03***06###04
0B###04!!!18###06!#
0F#!!!1E*#
0F#!!!1D***03##
0E#!!!1D***06#
0D#!!!1D***07#
0C#!!!20***05#
0B#!!!23**#
0A#!!!27##
09#!!!29*##
08#!!!2B***03#
08#!!!21###04!!!06***04##
07#!!!1F###03***04##!!!04***06##
07#!!!1D##**!!***05#!!!03***08#
07#!!!08#!!!0B#!!!07#***03!!!04***03!!!04***0A#
06#!!!0A#!!!09#!!!07#***04!!!05*!!!0A***05#
06#!!!0B#!!!07#!!!07#*!!***03!!!11***03#
06#!!!0C#!!!06#!!!06#*!!!05*!!!0F***05#
06#!!!0C#!!!06#!!!05#***03!!!11***08#
05#!!!0D#!!!06#!!!05#***04!!!0E***0A#
05#!!!0D#!!!06#!!!05#***05!!!0E***09#
05#!!!0D#!!!06#!!!05#***03!!!11***08##
04##!!!0D#!!!06#!!!05#*!!!15***05#!*##
03#!#!!!08###06!!!06#!!!05#**!!!0A###09!!!04*#!!**##
#!#!#!!!06#!!!0C#!!!05#***03!!!05###04***06!!!03###07!!**#
#!#!!##!!!04#!!!0B###0C*!!!03#***08!!!0F**#
#!#!!#!#!!#!!!03#!!!07#!!!0F#***0B!!!0F#
#!#!!!03#!#!#!!#!!!07#!!!04#!!!04#!!!05#***0A!!!0F**#
#!!#!!!03#!##!!#!!!06#!!!04#!!!04#!!!06#***0C!!!0A***04#
###09 ###0A!!!04#!!!04#!!!06#***0A!!!0C***03#
16###11***0C!!!0A**#
26#***0A!!!05###09
27###0F
Expected output ASCII art:
#####
####### #**#!!###
#**#!!!!## #****#!!!!#
#****###!!!# #*****#!!!!#
#*******#!!!# #******#!!!!#
#*********#!###!*!*!*#!!!!!# --
#!*!*!*!*!*!#!##########!!!!# /_
###########!##!!!!!!!!!!#!!!# //__
###!!!!!!!!!!!#!!!!!!!!!!!!!#!!!####/// \
\ ##!#!!!!!!!!!!!#!!!!!!!!!!!!!!!#!!!!!!!#
_\ ##!!#!!!!!!!!!!!#!!!!!!!!!!!######!!!!!!!*#
\\ ##!!#!!!!!!!!!!!!#!!!!####### #!!!!!!***#
___\\#!!!###################***** #...!!*****#
/ \#!!!.# ***** # *** #....*******#
#*....# *** # #.......*****#
#**.....## ***** ##........!!****#
#!........## *******#########......#...!!!!!*#
#!...........#######.*****...............#.#..!!!!**#
#*.....##.............#..#...............#...#.!!****#
#*....#.#............#....#............##......!*****#
#*.......##.......###......###........#.......!!!****#
#*.........#######......!!....########.......!!!!!***#
#!!!.................!!!!!!!!.............!!!*******#
#!!!!............!!!!!!!!!!!!!!!!!!!!!!!!!!!******#
#*******!!!!!!!!!!!!!!!!!!!!!!!!!!!!***!!!!*****#
#******!!!!!!!!!!!!!!!!!!!!!!!!!********!!****#
##*****!!!!!!!!!!!!!!!!!!!!!#*************###
##****!!!!!!!!!!!!!!!!!!!!!###******####
####!!!!!!!!!!!!!!!!!!!!!!!!######!#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!***##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!******#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*******#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*****#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!**#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!***#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!####!!!!!!****##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!###****##!!!!******##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!##**!!*****#!!!********#
#!!!!!!!!#!!!!!!!!!!!#!!!!!!!#***!!!!***!!!!**********#
#!!!!!!!!!!#!!!!!!!!!#!!!!!!!#****!!!!!*!!!!!!!!!!*****#
#!!!!!!!!!!!#!!!!!!!#!!!!!!!#*!!***!!!!!!!!!!!!!!!!!***#
#!!!!!!!!!!!!#!!!!!!#!!!!!!#*!!!!!*!!!!!!!!!!!!!!!*****#
#!!!!!!!!!!!!#!!!!!!#!!!!!#***!!!!!!!!!!!!!!!!!********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#****!!!!!!!!!!!!!!**********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#*****!!!!!!!!!!!!!!*********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#***!!!!!!!!!!!!!!!!!********##
##!!!!!!!!!!!!!#!!!!!!#!!!!!#*!!!!!!!!!!!!!!!!!!!!!*****#!*##
#!#!!!!!!!!######!!!!!!#!!!!!#**!!!!!!!!!!#########!!!!*#!!**##
#!#!#!!!!!!#!!!!!!!!!!!!#!!!!!#***!!!!!####******!!!#######!!**#
#!#!!##!!!!#!!!!!!!!!!!############*!!!#********!!!!!!!!!!!!!!!**#
#!#!!#!#!!#!!!#!!!!!!!#!!!!!!!!!!!!!!!#***********!!!!!!!!!!!!!!!#
#!#!!!#!#!#!!#!!!!!!!#!!!!#!!!!#!!!!!#**********!!!!!!!!!!!!!!!**#
#!!#!!!#!##!!#!!!!!!#!!!!#!!!!#!!!!!!#************!!!!!!!!!!****#
######### ##########!!!!#!!!!#!!!!!!#**********!!!!!!!!!!!!***#
#################************!!!!!!!!!!**#
#**********!!!!!#########
###############
Actual output(Difference is surrounded by ((eg))
(((###############¶ ¶¶¶¶¶¶ #####)))
####### #**#!!###
#**#!!!!## #****#!!!!#
#****###!!!# #*****#!!!!#
#*******#!!!# #******#!!!!#
#*********#!###!*!*!*#!!!!!# --
#!*!*!*!*!*!#!##########!!!!# /_
###########!##!!!!!!!!!!#!!!# //__
###!!!!!!!!!!!#!!!!!!!!!!!!!#!!!####/// \
\ ##!#!!!!!!!!!!!#!!!!!!!!!!!!!!!#!!!!!!!#
_\ ##!!#!!!!!!!!!!!#!!!!!!!!!!!######!!!!!!!*#
\\ ##!!#!!!!!!!!!!!!#!!!!####### #!!!!!!***#
___\\#!!!###################***** #...!!*****#
/ \#!!!.# ***** # *** #....*******#
#*....# *** # #.......*****#
#**.....## ***** ##........!!****#
#!........## *******#########......#...!!!!!*#
#!...........#######.*****...............#.#..!!!!**#
#*.....##.............#..#...............#...#.!!****#
#*....#.#............#....#............##......!*****#
#*.......##.......###......###........#.......!!!****#
#*.........#######......!!....########.......!!!!!***#
#!!!.................!!!!!!!!.............!!!*******#
#!!!!............!!!!!!!!!!!!!!!!!!!!!!!!!!!******#
#*******!!!!!!!!!!!!!!!!!!!!!!!!!!!!***!!!!*****#
#******!!!!!!!!!!!!!!!!!!!!!!!!!********!!****#
##*****!!!!!!!!!!!!!!!!!!!!!#*************###
##****!!!!!!!!!!!!!!!!!!!!!###******####
####!!!!!!!!!!!!!!!!!!!!!!!!######!#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!***##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!******#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*******#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*****#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!**#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!***#
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!####!!!!!!****##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!###****##!!!!******##
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!##**!!*****#!!!********#
#!!!!!!!!#!!!!!!!!!!!#!!!!!!!#***!!!!***!!!!**********#
#!!!!!!!!!!#!!!!!!!!!#!!!!!!!#****!!!!!*!!!!!!!!!!*****#
#!!!!!!!!!!!#!!!!!!!#!!!!!!!#*!!***!!!!!!!!!!!!!!!!!***#
#!!!!!!!!!!!!#!!!!!!#!!!!!!#*!!!!!*!!!!!!!!!!!!!!!*****#
#!!!!!!!!!!!!#!!!!!!#!!!!!#***!!!!!!!!!!!!!!!!!********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#****!!!!!!!!!!!!!!**********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#*****!!!!!!!!!!!!!!*********#
#!!!!!!!!!!!!!#!!!!!!#!!!!!#***!!!!!!!!!!!!!!!!!********##
##!!!!!!!!!!!!!#!!!!!!#!!!!!#*!!!!!!!!!!!!!!!!!!!!!*****#!*##
#!#!!!!!!!!######!!!!!!#!!!!!#**!!!!!!!!!!#########!!!!*#!!**##
((!!!!***#)) #!#!#!!!!!!#!!!!!!!!!!!!#!!!!!#***!!!!!####******!!!#######!!**#
#!#!!##!!!!#!!!!!!!!!!!############*!!!#********!!!!!!!!!!!!!!!**#
#!#!!#!#!!#!!!#!!!!!!!#!!!!!!!!!!!!!!!#***********!!!!!!!!!!!!!!!#
#!#!!!#!#!#!!#!!!!!!!#!!!!#!!!!#!!!!!#**********!!!!!!!!!!!!!!!**#
#!!#!!!#!##!!#!!!!!!#!!!!#!!!!#!!!!!!#************!!!!!!!!!!****#
######### ##########!!!!#!!!!#!!!!!!#**********!!!!!!!!!!!!***#
#################************!!!!!!!!!!**#
#**********!!!!!#########
###############((¶))
And this is my expand() and main() method:
// Function to expand a compressed string
char* expand(const char *input) {
// Allocate memory for the output string
char *output = (char *)malloc(2 * strlen(input) + 1);
char *result = output; // Pointer to store the output
char currentChar;
int count;
char hexCount[3];
// Iterate through the input string
for (size_t i = 0; i < strlen(input); i++) {
currentChar = input[i];
// Check if a character of the input has a hex digit one and 2 places in front of it -- meaning it's been compressed
if (i + 4 < strlen(input) && input[i + 1] == currentChar && input[i + 2] == currentChar && isxdigit(input[i + 3]) && isxdigit(input[i + 4])) {
// Copy the hex number from compressed string into the hexCount buffer
strncpy(hexCount, &input[i + 3], 2);
hexCount[2] = '\0';
// Convert the hex count to decimal
count = strtol(hexCount, NULL, 16);
// Append the character 'count' times to the output
for (int j = 0; j < count; j++) {
strncat(output, ¤tChar, 1);
}
i += 4;
} else {
// Append the character to the output
strncat(output, ¤tChar, 1);
}
}
return result;
}
int main() {
// Read each line from stdin, apply the compress/expand function
char line[MAX_LINE_LEN];
fgets(line, sizeof(line), stdin); // Consume the newline after reading excomp
char excomp = line[0];
int lineNum = 0;
if (excomp == 'C') {
while (fgets(line, sizeof(line), stdin) != NULL) {
// Remove the newline character
line[strcspn(line, "\n")] = '\0';
char *modifiedLine = compress(line);
char *finalLine = modifiedLine;
// Print the modified line to the command line
printf("%s\n", finalLine);
// Free the memory allocated by FUNCTION
free(modifiedLine);
}
} else if (excomp == 'E') {
while (fgets(line, sizeof(line), stdin) != NULL) {
// Remove the newline character
line[strcspn(line, "\n")] = '\0';
char *modifiedLine = expand(line);
char *finalLine = modifiedLine;
// Print the modified line to the command line
printf("%s\n", finalLine);
// Free the memory allocated by FUNCTION
free(modifiedLine);
}
}
return 0;
}
Thank you so much for any help, Cheers!!
>Solution :
Firstly, the allocation
char *output = (char *)malloc(2 * strlen(input) + 1);
is wrong. For example, a short input
###20
can be expanded into a long output (more than double of the input length)
################################
You have to allocate enough space. For example:
char *output = malloc(MAX_LINE_LEN + 1);
Also note that casting results of malloc() family is considered as a bad practice.
Secondly, you have to initialize the allocated buffer before using strncat().
Otherwise, undefined behavior will be invoked by using values in buffer allocated via malloc() and not initialized.
You can do this by adding
output[0] = '\0';
before the for loop in the function expand.