I had used this code from https://oku.edu.mie-u.ac.jp/~okumura/compression/lzss.c
This code was for file compression. I had modified it for a given string. For example :
d(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):WritingModule:SecurityConfigD/6LoWPANd(2306):WritingModule:RunCoordinatorD/6LoWPANd(2306):RequestingmoduleaddressD/6LoWPANd(2306):WritingModule:GetAddressD/smartcard-jni(2781):SmartCard_state_update_callback:status=6D/SmartCardNative(2781):status=6D/smartcard(2781):PN532Smartcard_loop_threadexitD/smartcard-jni(2781):SmartCard_loop_thread:SMARTCARD_STATUS_ABORTD/smartcard(2781):Smartcard_loop_uninitD/smartcard(2781):2D/serialcomm_pn532(2781):PN532:Readingfrom/dev/ttyUSB0-->D/smartcard(2781):Received(0x3)fromPN532:(dataBuf[0]:0x1)(0x1f5988)D/smartcard(2781):ReceivedStatusfromPN532:OK(cmd:0x2)D/smartcard-jni(2781):SmartCard_listener_update_callbackD/smartcard(2781):Received(0x1c2)fromPN532:(dataBuf[0]:0x32)(0x1f5988)D/smartcard(2781):vd(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):
The problem I am facing is, if I want to compress a file containing this , the code is able to do that. But the modified code that I had done having little bit of problem. The last 2 bits of compressed files are different. Though the content of file and the buffer both are exactly same.
The original code was reading from file. Here, I provided the string of same content.
The code goes here :
/* LZSS encoder-decoder (c) Haruhiko Okumura */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EI 11 /* typically 10..13 */
#define EJ 4 /* typically 4..5 */
#define P 1 /* If match length <= P then output one character */
#define N (1 << EI) /* buffer size */
#define F ((1 << EJ) + P) /* lookahead buffer size */
int bit_buffer = 0, bit_mask = 128;
unsigned long codecount = 0, textcount = 0;
unsigned char buffer[N * 2];
FILE *infile, *outfile, *outfile2, *outfile3;
/*----*/
unsigned long payload_i = 0;
int tt = 0;
unsigned int buf_load[16000];
unsigned char *string_buf= "d(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):WritingModule:SecurityConfigD/6LoWPANd(2306):WritingModule:RunCoordinatorD/6LoWPANd(2306):RequestingmoduleaddressD/6LoWPANd(2306):WritingModule:GetAddressD/smartcard-jni(2781):SmartCard_state_update_callback:status=6D/SmartCardNative(2781):status=6D/smartcard(2781):PN532Smartcard_loop_threadexitD/smartcard-jni(2781):SmartCard_loop_thread:SMARTCARD_STATUS_ABORTD/smartcard(2781):Smartcard_loop_uninitD/smartcard(2781):2D/serialcomm_pn532(2781):PN532:Readingfrom/dev/ttyUSB0-->D/smartcard(2781):Received(0x3)fromPN532:(dataBuf[0]:0x1)(0x1f5988)D/smartcard(2781):ReceivedStatusfromPN532:OK(cmd:0x2)D/smartcard-jni(2781):SmartCard_listener_update_callbackD/smartcard(2781):Received(0x1c2)fromPN532:(dataBuf[0]:0x32)(0x1f5988)D/smartcard(2781):vd(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):";
/*----*/
void error(void)
{
printf("Output error\n"); exit(1);
}
void putbit1(void)
{
outfile2 = fopen("file2.lzss", "a");
bit_buffer |= bit_mask;
if ((bit_mask >>= 1) == 0) {
/*----*/
buf_load[payload_i] = bit_buffer;
if (fputc(buf_load[payload_i], outfile3) == EOF) error();
payload_i++;
/*----*/
if (fputc(bit_buffer, outfile2) == EOF) error();
if (fputc(bit_buffer, outfile) == EOF) error();
bit_buffer = 0; bit_mask = 128; codecount++;
}
fclose(outfile2);
}
void putbit0(void)
{
outfile2 = fopen("file2.lzss", "a");
if ((bit_mask >>= 1) == 0) {
/*----*/
buf_load[payload_i] = bit_buffer;
if (fputc(buf_load[payload_i], outfile3) == EOF) error();
payload_i++;
/*----*/
if (fputc(bit_buffer, outfile2) == EOF) error();
if (fputc(bit_buffer, outfile) == EOF) error();
bit_buffer = 0; bit_mask = 128; codecount++;
}
fclose(outfile2);
}
void flush_bit_buffer(void)
{
outfile2 = fopen("file2.lzss", "a");
if (bit_mask != 128) {
if (fputc(buf_load[payload_i], outfile3) == EOF) error();
if (fputc(bit_buffer, outfile2) == EOF) error();
if (fputc(bit_buffer, outfile) == EOF) error();
codecount++;
}
fclose(outfile2);
}
void output1(int c)
{
int mask;
putbit1();
mask = 256;
while (mask >>= 1) {
if (c & mask) putbit1();
else putbit0();
}
}
void output2(int x, int y)
{
int mask;
putbit0();
mask = N;
while (mask >>= 1) {
if (x & mask) putbit1();
else putbit0();
}
mask = (1 << EJ);
while (mask >>= 1) {
if (y & mask) putbit1();
else putbit0();
}
}
void encode(void)
{
int i, j, f1, x, y, r, s, bufferend, c;
for (i = 0; i < N - F; i++) buffer[i] = ' ';
for (i = N - F; i < N * 2; i++) {
if ((c = fgetc(infile)) == EOF) break;
if((c = string_buf[tt++]) == '\0') break;
buffer[i] = c; textcount++; //tt++;
}
bufferend = i; r = N - F; s = 0;
while (r < bufferend) {
f1 = (F <= bufferend - r) ? F : bufferend - r;
x = 0; y = 1; c = buffer[r];
for (i = r - 1; i >= s; i--)
if (buffer[i] == c) {
for (j = 1; j < f1; j++)
if (buffer[i + j] != buffer[r + j]) break;
if (j > y) {
x = i; y = j;
}
}
if (y <= P) output1(c);
else output2(x & (N - 1), y - 2);
r += y; s += y;
if (r >= N * 2 - F) {
for (i = 0; i < N; i++) buffer[i] = buffer[i + N];
bufferend -= N; r -= N; s -= N;
while (bufferend < N * 2) {
if ((c = fgetc(infile)) == EOF) break;
if((c = string_buf[tt++]) == '\0') break;
//tt++;
buffer[bufferend++] = c; textcount++;
}
}
}
flush_bit_buffer();
printf("text: %ld bytes\n", textcount);
printf("code: %ld bytes (%ld%%)\n",
codecount, (codecount * 100) / textcount);
}
int getbit(int n) /* get n bits */
{
int i, x;
static int buf, mask = 0;
x = 0;
for (i = 0; i < n; i++) {
if (mask == 0) {
if ((buf = fgetc(infile)) == EOF) return EOF;
mask = 128;
}
x <<= 1;
if (buf & mask) x++;
mask >>= 1;
}
return x;
}
void decode(void)
{
int i, j, k, r, c;
for (i = 0; i < N - F; i++) buffer[i] = ' ';
r = N - F;
while ((c = getbit(1)) != EOF) {
if (c) {
if ((c = getbit(8)) == EOF) break;
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
} else {
if ((i = getbit(EI)) == EOF) break;
if ((j = getbit(EJ)) == EOF) break;
for (k = 0; k <= j + 1; k++) {
c = buffer[(i + k) & (N - 1)];
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
}
}
}
}
int main(int argc, char *argv[])
{
int enc;
char *s;
memset(buf_load, '\0', sizeof(buf_load));
outfile3 = fopen ("file1.lzss", "wb");
if (argc != 4) {
printf("Usage: lzss e/d infile outfile\n\te = encode\td = decode\n");
return 1;
}
s = argv[1];
if (s[1] == 0 && (*s == 'd' || *s == 'D' || *s == 'e' || *s == 'E'))
enc = (*s == 'e' || *s == 'E');
else {
printf("? %s\n", s); return 1;
}
if ((infile = fopen(argv[2], "rb")) == NULL) {
printf("? %s\n", argv[2]); return 1;
}
if ((outfile = fopen(argv[3], "wb")) == NULL) {
printf("? %s\n", argv[3]); return 1;
}
if (enc) encode(); else decode();
fclose(infile); fclose(outfile);
fclose(outfile3);
return 0;
}
Looks like the issue lies in buffer reading-writing vs file read write. In file read-write the pointer is increased to next mem loc and reading and writing the same way. In string, each array is being read by incrementing index and then the compressed value is written in file in file write. In file, it is read as binary (wb), In string it is being read as array element. Can there be a problem for that ? Need expert's advice on that.
void flush_bit_buffer(void)
{
outfile2 = fopen("file2.lzss", "a");
if (bit_mask != 128) {
flush_bit[payload_i] = bit_buffer; /*This last bit should be put which I missed. It solved my issue*/
if (fputc(buf_load[payload_i], outfile3) == EOF) error();
if (fputc(bit_buffer, outfile2) == EOF) error();
if (fputc(bit_buffer, outfile) == EOF) error();
codecount++;
}
fclose(outfile2);
}
I solved it by adding the line in the code snippet. I needed to add last bit of bit buffer which solved the problem.
Related
I have a program which solves maze, so that it finds possible route from Start(S) to Exit(E).Here is my Maze:
1111S11110
0000010001
110100010d
t001111110
0100000001
0111111101
1111111101
00000D01T1
0111110001
0000E01110
The possible route to it is :
Start S W W S S S E E E E E E S S S S W W N W W W W W W S S E E E E Exit
which is correct and i get it on CodeBlocks, However when i compile my code on dev through putty i get this:
Start S S S S S W N N W S W N N N W N Exit
Here is my whole code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Global Variables for use
int matrixSize,startX,startY,exitX,exitY;
char src[1500] = " ";
char Ndirection[50] = " N ";
char Sdirection[50] = " S ";
char Edirection[50] = " E ";
char Wdirection[50] = " W ";
// Function for finding the array length
int numOfLines(FILE *const mazeFile) {
int c, count;
count = 0;
for (;; ) {
c = fgetc(mazeFile);
if (c == EOF)
break;
if (c == '\n')
++count; // end of line => increment line counter
}
rewind(mazeFile);
return count+1;
}
int capLetter(char ch){
int result = 0;
if(ch >= 'A' && ch <= 'Z'){
result = 1;
}
return result;
}
int lowLetter(char ch){
int result = 0;
if(ch >= 'a' && ch <= 'z'){
result = 1;
}
return result;
}
int isSafe(char Mazearray[matrixSize][matrixSize],int x,int y){
if(x >= 0 && x < matrixSize && y >= 0 && y < matrixSize && Mazearray[x][y] != '1'){
return 1;
}
return 0;
}
void MazeSolution(char Mazearray[matrixSize][matrixSize],int x,int y,char pathArray[matrixSize][matrixSize],char wasHereArray[matrixSize][matrixSize]){
if(recursiveMaze(Mazearray,x,y,pathArray,wasHereArray) == 0){
printf("There does not exist a possible solution!!!");
}
else{
pathArray[startX][startY] = 'S';
}
}
int recursiveMaze(char Mazearray[matrixSize][matrixSize],int x,int y,char pathArray[matrixSize][matrixSize],char wasHereArray[matrixSize][matrixSize]){
if(x == startX && y == startY){
pathArray[x][y] = 'S';
}
if(x == exitX && y == exitY){
pathArray[x][y] = 'E';
return 1;
}
// check if the coordinate is safe to go(not 1)
if(isSafe(Mazearray,x,y) == 1 && wasHereArray[x][y] != '1'){
wasHereArray[x][y] = '1';
// Move North
if(recursiveMaze(Mazearray,x-1,y,pathArray,wasHereArray) == 1){
pathArray[x][y] = 'R';
strcat(src,Ndirection);
return 1;
}
// Move South
if(recursiveMaze(Mazearray,x+1,y,pathArray,wasHereArray) == 1){
pathArray[x][y] = 'R';
strcat(src,Sdirection);
return 1;
}
// Move East
if(recursiveMaze(Mazearray,x,y+1,pathArray,wasHereArray) == 1){
pathArray[x][y] = 'R';
strcat(src,Edirection);
return 1;
}
// Move West
if(recursiveMaze(Mazearray,x,y-1,pathArray,wasHereArray) == 1){
pathArray[x][y] = 'R';
strcat(src,Wdirection);
return 1;
}
}
return 0;
}
// Main Function
int main( int argc, char **argv )
{
// Opening the Matrix File
FILE *mazeFile;
mazeFile = fopen(argv[1], "r" );
if( mazeFile == NULL )
return 1;
matrixSize = numOfLines( mazeFile );
// Reading text file into 2D array
int i,j;
char mazeArray [matrixSize][matrixSize];
for (i = 0; i<matrixSize; i++) {
for (j = 0; j<matrixSize; j++) {
fscanf(mazeFile, "%c", &mazeArray[i][j]);
}
char eol;
fscanf(mazeFile, "%c", &eol);
}
// Variables
//Creating path array
char pathArray[matrixSize][matrixSize];
for (i = 0; i < matrixSize; i++){
for (j = 0; j < matrixSize; j++){
pathArray[i][j] = '0';
}
}
// CheckPoint array
char wasHereArray[matrixSize][matrixSize];
for (i = 0; i < matrixSize; i++){
for (j = 0; j < matrixSize; j++){
wasHereArray[i][j] = '0';
}
}
// Finding start and exit indexes
for (i = 0; i<matrixSize; i++) {
for (j = 0; j<matrixSize; j++) {
if(mazeArray[i][j] == 'S'){
startX = i;
startY = j;
}
if(mazeArray[i][j] == 'E'){
exitX = i;
exitY = j;
}
}
}
MazeSolution(mazeArray,startX,startY,pathArray,wasHereArray);
char *data = src;
int length=strlen(data);
char bytes[length];
int n=0;
while(n<=length)
{
bytes[n] = data[length-n-1];
n++;
}
FILE *f = fopen("path.txt", "w");
fprintf(f, "Start %s Exit",bytes);
fclose(mazeFile);
fclose(f);
return 0;
}
I don't know what is wrong and where to start?
DOS line endings are CR-LF ("\r\n") and *nix line endings are just LF ("\n"). Change these lines main:
char eol;
fscanf(mazeFile, "%c", &eol);
to:
int c = fgetc(mazefile); // Slurp a '\r' carriage return or '\n' linefeed character.
if ('\r' == c) {
c = fgetc(mazefile); // slurp the '\n' linefeed character.
}
I want to write below code with proper if clause.
int main()
{
float a,b;
printf("Enter Two number with space:\n");
scanf("%f %f",&a,&b);
//if(%a || b are char%)
printf("Not correct format!")
else
printf("a and b: %.2f %.2f",a,b);
return 0;
}
#define INT_CONVERTED (1 << 0)
#define FLOAT_CONVERTED (1 << 1)
int ReadNumber(const char *str, double *db, int *in)
{
int result = (str == NULL || db == NULL || in == NULL) * -1;
int len = 0;
char *tmp;
if (result != -1)
{
tmp = (char *)malloc(strlen(str) + 1);
strcpy(tmp, str);
for (int i = strlen(str) - 1; i >= 0; i--)
{
if (isspace(tmp[i]))
{
tmp[i] = 0;
continue;
}
break;
}
if (strlen(tmp))
{
if (sscanf(tmp, "%lf%n", db, &len) == 1 && strlen(tmp) == len)
{
result |= FLOAT_CONVERTED;
}
if (sscanf(tmp, "%d%n", in, &len) == 1 && strlen(tmp) == len)
{
result |= INT_CONVERTED;
}
}
free(tmp);
}
return result;
}
I am using Okamura's implementation of lzss : https://oku.edu.mie-u.ac.jp/~okumura/compression/lzss.c
int enc_i = 0;
int getbit(int n, unsigned char *enco_buf) /* get n bits */
{
int i, x;
static int buf, mask = 0;
x = 0;
for (i = 0; i < n; i++) {
if (mask == 0) {
//if ((buf = fgetc(infile)) == EOF) return EOF;
//if ((buf = fgetc(infile)) == EOF) return EOF;
if((buf = enco_buf[enc_i]) == '\0') break;
//buf = enco_buf[enc_i];
enc_i++;
//printf("\nValue of enc : %d\n", enc_i);
mask = 128;
}
x <<= 1;
if (buf & mask) x++;
mask >>= 1;
}
return x;
}
void decode(unsigned char *enco_buf)
{
int i, j, k, r, c;
outfile = fopen ("test_lib.txt", "wb");
for (i = 0; i < N - F; i++) buffer[i] = ' ';
r = N - F;
while ((c = getbit(1, enco_buf)) != '\0') {
if (c) {
if ((c = getbit(8, enco_buf)) == '\0') break;
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
} else {
if ((i = getbit(EI, enco_buf)) == '\0') break;
if ((j = getbit(EJ, enco_buf)) == '\0') break;
for (k = 0; k <= j + 1; k++) {
c = buffer[(i + k) & (N - 1)];
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
}
}
}
fclose(outfile);
}
Rather than taking the input from file, I am taking an encoded buffer which I am passing to the function decode() which in-turns passes to getbit(). But it is decoding upto a certain number of bits ie. 43. What I am guessing is I put '\0' instead of EOF (as it was in file end marker) to detect string end. and that might be the problem where break statement is executed finding '\0'. It might not be true but It might be the case. The encoding part has no problem as I verified it with the original code. Can anyone suggest where might be the problem?
EDIT : source code:
/* LZSS encoder-decoder (Haruhiko Okumura; public domain) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "lzss_lib.h"
#define EI 11 /* typically 10..13 */
#define EJ 4 /* typically 4..5 */
#define P 1 /* If match length <= P then output one character */
#define N (1 << EI) /* buffer size */
#define F ((1 << EJ) + 1) /* lookahead buffer size */
int bit_buffer = 0, bit_mask = 128;
unsigned long codecount = 0, textcount = 0;
unsigned char buffer[N * 2];
int payload_i = 0;
int enc_i = 0;
FILE *infile, *outfile;
void error(void)
{
printf("Output error\n"); exit(1);
}
void putbit1(unsigned char *put_buf0)
{
bit_buffer |= bit_mask;
if ((bit_mask >>= 1) == 0) {
put_buf0[payload_i] = bit_buffer;
payload_i++;
bit_buffer = 0; bit_mask = 128; codecount++;
}
}
void putbit0(unsigned char *put_buf1)
{
if ((bit_mask >>= 1) == 0) {
put_buf1[payload_i] = bit_buffer;
payload_i++;
bit_buffer = 0; bit_mask = 128; codecount++;
}
}
void flush_bit_buffer(unsigned char *flush_bit)
{
if (bit_mask != 128) {
flush_bit[payload_i] = bit_buffer;
codecount++;
}
}
void output1(int c, unsigned char *buf_output1)
{
int mask;
putbit1(buf_output1);
mask = 256;
while (mask >>= 1) {
if (c & mask) putbit1(buf_output1);
else putbit0(buf_output1);
}
}
void output2(int x, int y, unsigned char *buf_output2)
{
int mask;
putbit0(buf_output2);
mask = N;
while (mask >>= 1) {
if (x & mask) putbit1(buf_output2);
else putbit0(buf_output2);
}
mask = (1 << EJ);
while (mask >>= 1) {
if (y & mask) putbit1(buf_output2);
else putbit0(buf_output2);
}
}
void encode(unsigned char *string_buf, unsigned char *out_buf, unsigned long *out_buf_len)
{
int i, j, f1, x, y, r, s, bufferend, c, tt;
tt = 0;
for (i = 0; i < N - F; i++) buffer[i] = ' ';
for (i = N - F; i < N * 2; i++) {
if((c = string_buf[tt]) == '\0') break;
buffer[i] = c; textcount++; tt++;
}
bufferend = i; r = N - F; s = 0;
while (r < bufferend) {
f1 = (F <= bufferend - r) ? F : bufferend - r;
x = 0; y = 1; c = buffer[r];
for (i = r - 1; i >= s; i--)
if (buffer[i] == c) {
for (j = 1; j < f1; j++)
if (buffer[i + j] != buffer[r + j]) break;
if (j > y) {
x = i; y = j;
}
}
if (y <= P) { y = 1; output1(c, out_buf); }
else output2(x & (N - 1), y - 2, out_buf);
r += y; s += y;
if (r >= N * 2 - F) {
for (i = 0; i < N; i++) buffer[i] = buffer[i + N];
bufferend -= N; r -= N; s -= N;
while (bufferend < N * 2) {
if((c = string_buf[tt]) == '\0') break;
buffer[bufferend++] = c; textcount++; tt++;
}
}
}
flush_bit_buffer(out_buf);
*out_buf_len = codecount;
printf("text: %ld bytes\n", textcount);
printf("code: %ld bytes (%ld%%)\n", codecount, (codecount * 100) / textcount);
}
int getbit(int n, unsigned char *enco_buf) /* get n bits */
{
int i, x;
static int buf, mask = 0;
x = 0;
for (i = 0; i < n; i++) {
if (mask == 0) {
//if ((buf = fgetc(infile)) == EOF) return EOF;
//if ((buf = fgetc(infile)) == EOF) return EOF;
if((buf = enco_buf[enc_i]) == '\0') break;
//buf = enco_buf[enc_i];
enc_i++;
printf("\nValue of enc : %d\n", enc_i);
mask = 128;
}
x <<= 1;
if (buf & mask) x++;
mask >>= 1;
}
return x;
}
void decode(unsigned char *enco_buf)
{
int i, j, k, r, c;
outfile = fopen ("test_lib.txt", "wb");
for (i = 0; i < N - F; i++) buffer[i] = ' ';
r = N - F;
while ((c = getbit(1, enco_buf)) != '\0') {
if (c) {
if ((c = getbit(8, enco_buf)) == '\0') break;
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
} else {
if ((i = getbit(EI, enco_buf)) == '\0') break;
if ((j = getbit(EJ, enco_buf)) == '\0') break;
for (k = 0; k <= j + 1; k++) {
c = buffer[(i + k) & (N - 1)];
fputc(c, outfile);
buffer[r++] = c; r &= (N - 1);
}
}
}
fclose(outfile);
}
and the test example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "lzss_lib.h"
unsigned char compr_data[4096];
unsigned long pw = 0;
unsigned long payload_len = 0;
volatile int errno;
unsigned char *unc_data = "d(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):WritingModule:SecurityConfigD/6LoWPANd(2306):WritingModule:RunCoordinatorD/6LoWPANd(2306):RequestingmoduleaddressD/6LoWPANd(2306):WritingModule:GetAddressD/smartcard-jni(2781):SmartCard_state_update_callback:status=6D/SmartCardNative(2781):status=6D/smartcard(2781):PN532Smartcard_loop_threadexitD/smartcard-jni(2781):SmartCard_loop_thread:SMARTCARD_STATUS_ABORTD/smartcard(2781):Smartcard_loop_uninitD/smartcard(2781):2D/serialcomm_pn532(2781):PN532:Readingfrom/dev/ttyUSB0-->D/smartcard(2781):Received(0x3)fromPN532:(dataBuf[0]:0x1)(0x1f5988)D/smartcard(2781):ReceivedStatusfromPN532:OK(cmd:0x2)D/smartcard-jni(2781):SmartCard_listener_update_callbackD/smartcard(2781):Received(0x1c2)fromPN532:(dataBuf[0]:0x32)(0x1f5988)D/smartcard(2781):vd(2306):AuthorisationScheme:RADIUSserveratfd04:bd3:80e8:1::1usingPAPD/6LoWPANd(2306):";
FILE *outfile;
int main(void) {
memset (compr_data, '\0', sizeof(compr_data));
encode(unc_data, compr_data, &payload_len);
decode(compr_data);
return 0;
}
I'm recently new to programming but this assignment has proven to be my most difficult. The program is suppose to read in a .txt file with the following format
input_base number output_base
and outputs the results. the bases can only range from 2-36 For example:
input: 2 10 4
output: 2
My program reads in each part of the line and stores them respectively. I then go through the steps to convert the number into the output base and then print it backwards. My problem is that the program runs fine and prints all the stored values and calculated values, but once I add in my "base_conversion" function the program no longer works and my friend even said it gave him a segmentation fault. I don't really know what could be causing it. Any help would be appreciated. Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void read_file_to_buffer(FILE *file);
char *buffer = NULL;
void string_check(char *buffer);
int char_to_int(char c);
int int_conversion(int x, int y);
void base_conversion(int end_number, int out_base);
int main(int argc, char *argv[]){
FILE *file = NULL;
if ( argc != 2 ){
fprintf(stderr, "Error: To many/few arguments\n");
exit(EXIT_FAILURE);
}
else {
file = fopen(argv[1], "rb");
if (file == NULL) {
fprintf(stderr, "Error: could not open file '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
else{
printf("File %s opened!\n", argv[1]);
}
}
read_file_to_buffer(file);
string_check(buffer);
fclose(file);
free(buffer);
buffer = NULL;
exit(EXIT_SUCCESS);
}
void read_file_to_buffer(FILE *file) {
long file_size = 0;
if(buffer != NULL){
fprintf(stderr, "buffer in use\n");
exit(EXIT_FAILURE);
}
rewind(file);
if (fseek(file, 0, SEEK_END) != 0){
perror("Could not seek to end of file");
exit(EXIT_FAILURE);
}
file_size = ftell(file);
if (file_size < 0){
perror("could not tell size of file");
exit(EXIT_FAILURE);
}
rewind(file);
buffer = (char *)malloc(sizeof(char) * (file_size + 1));
if (buffer == NULL){
fprintf(stderr, "Could not allocate memory");
exit(EXIT_FAILURE);
}
if(fread(buffer, sizeof(char), (size_t)file_size, file) != file_size){
fprintf(stderr, "Could not read file\n");
exit(EXIT_FAILURE);
}
buffer[file_size] = '\0';
return;
}
void string_check(char *buffer){
int i = 0;
int j = 0;
char base_in[2];
char number[50];
char base_out[2];
int actual_number[100];
int end_number = 0;
int x = 0;
int y = 0;
int in_base;
int out_base;
while( buffer[i] != '\0'){
if (buffer[i] != '#' && buffer[i] != ' ' && buffer[i] != '\n' && buffer[i] != '\r'){
while (buffer[i] != ' '){
base_in[j] = buffer[i];
i++;
j++;
}
j = 0;
i++;
if (base_in[1] != '\0'){
x = char_to_int(base_in[0]);
y = char_to_int(base_in[1]);
in_base = int_conversion(x, y);
x = 0;
y = 0;
}
else{
in_base = char_to_int(base_in[0]);
}
while (buffer[i] != ' '){
number[j] = buffer[i];
i++;
j++;
}
int q;
q=j;
j=0;
while (number[j] != '\0'){
actual_number[j] = char_to_int(number[j]);
end_number = end_number + pow(in_base, q-1) * actual_number[j];
j++;
q--;
}
j = 0;
i++;
while (buffer[i] != '\n' && buffer[i] != '\0'){
base_out[j] = buffer[i];
i++;
j++;
}
if (base_out[1] != '\0'){
x = char_to_int(base_out[0]);
y = char_to_int(base_out[1]);
out_base = int_conversion(x, y);
x = 0;
y = 0;
}
else{
out_base = char_to_int(base_out[0]);
}
j = 0;
i++;
base_conversion(end_number, out_base);
}
else{
while (buffer[i] != '\n' && buffer[i] != '\0'){
i++;
}
}
i++;
}
return;
}
int char_to_int(char c){
char map[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int result = -1;
char *next = map;
while(*next != '\0'){
if(*next == c){
result = next - map;
break;
}
next++;
}
return result;
}
int int_conversion(int x, int y){
int value;
value = (x * 10) + y;
return value;
}
void base_conversion(int end_number, int out_base){
int remainder[100];
char map[] = "0123456789abcdefghijklmnopqrstuvwxyz";
int index = 0;
int i;
while (end_number != 0){
remainder[index] = end_number % out_base;
end_number = end_number / out_base;
index++;
}
for (i=0; i<index; i++){
printf("%c", map[remainder[index-1]]);
}
printf("\n");
return;
}
OP's base_conversion() is messed.
Loop prints same character repeatedly.
for (i=0; i<index; i++){
printf("%c", map[remainder[index-1]]); // Why same character?
}
Code is using signed math and % and can create negative remainders which may be used as array index.
remainder[index] = end_number % out_base; // result may be negative.
...
printf("%c", map[remainder[index-1]]); // accessing out of bounds with negative
Suggested simplification.
void base_conversion_helper(unsigned end_number, int out_base){
if (end_number >= out_base) base_conversion_helper(end_number/out_base, out_base);
putchar("0123456789abcdefghijklmnopqrstuvwxyz"[end_number % outbase]);
}
void base_conversion(unsigned end_number, int out_base){
assert(out_base >= 2 && out_base <= 36);
base_conversion_helper(end_number, out_base);
putchar('\n');
}
I'm so tired of debugging and changing my code but every time it gives me:
No newline at end of file
when I try:
diff main.c output.txt
My program encrypts/decrypts the input textfile and it gives a correct output when it converts but when I enter diff main.c output.txt then it would always point me to that error. What should I do to prevent that? Any help would be appreciated!
int encryptFile(FILE *input, FILE *output){
char c;
char p;
int r = 0;
char p1 = 0;
char c1 = 0;
int index = 0;
char line[100];
// while((p = fgetc(input)) != EOF){
while(fgets(line, sizeof(line), input) != NULL){
for(index = 0; line[index] != 0; index++){
p = line[index];
r = rand() % 97;
if(p == 't'){
p1 = 0;
}
else if(p == '\n'){
p1 = 1;
}
else{
p1 = p - 30;
}
c1 = p1 ^ r;
if(c1 == 0){
c = 't';
}
else if(c1 == 1){
c = '\n';
}
else{
c = c1 + 30;
}
//Write
fputc(c, output);
}
}
return 1;
}
Try adding a new line at the end of your output file:
int encryptFile(FILE *input, FILE *output)
{
char c = 0;
char p;
int r = 0;
char p1 = 0;
char c1 = 0;
int index = 0;
char line[100];
while (fgets(line, sizeof(line), input) != NULL) {
for (index = 0; line[index] != 0; index++) {
p = line[index];
r = rand() % 97;
//change all displayable characters [0...96]
if (p == 't') {
p1 = 0;
} else if (p == '\n') {
p1 = 1;
} else {
p1 = p - 30;
}
c1 = p1 ^ r;//bitwise xor
if (c1 == 0) {
c = 't';
} else if (c1 == 1) {
c = '\n';
} else {
c = c1 + 30;
}
//Write
fputc(c, output);
}
}
if (c != '\n') {
fputc('\n', output);
}
return 1;
}
Or use:
diff --ignore-all-space file1 file2