Compress hex data - c

For university I have the exercise to compress a series of data. In one file there is the input data and I have to write another one with the compressed data. The task is only to store the difference between the numbers. Until now I have the written the code that stores the data in an array and stores the same in the output file. Now I want to start with the compression, but have no clue how to do it. Did I store the data type?
The input file could look like this:
C9 CB C7 C0 C0 C8 C9 C9 BE 00 04
So the output file has to look like this:
C9 C2 90 8C 81 08 BE 80 04
int main(int argc, char **argv) {
if (argc < 3)
{
fprintf(stderr, "Usage: input.txt output.txt\n");
return EXIT_FAILURE;
}
FILE *input, *output;
input = fopen(argv[1], "r");
output = fopen(argv[2], "w");
int c;
unsigned int values[100] = { 0 };
int i = 0;
if (input != NULL)
{
printf("Values:\n");
while ((c = fgetc(input)) != EOF)
{
values[i] = c;
putchar(c);
i++;
}
printf("\n");
fclose(input);
}
else
{
fprintf(stderr, "File could not be opened.\n");
return EXIT_FAILURE;
}
if (output != NULL)
{
int j = 0;
for (j; j < i; j++)
{
putc(values[j], output);
}
fclose(output);
}
else
{
fprintf(stderr, "Could not generate output file.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Related

File reading with fgetc in C

I have a simple file reading algorithm but it's not returning the values that are in the file. The below is the code. The input txt values are 200 53 65 98 183 37 122 14 124 65 67 but the code is returning 48 48 32 53 51 32 54 53 32 57 56 32 49 56 51 32 51 55 32 49 50 50 32 49 52 32 49 50 52 32 54 53 32 54 55 -1 and I'm not sure why.
It should be taking the read in values and putting it into the linked list.
int readInputFile(char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
int ch;
if (inputFile == NULL)
{
perror("Could not open file");
}
else
{
while (ch != EOF)
{
ch = fgetc(inputFile);
printf("%d", ch);
if (ferror(inputFile))
{
perror("Error reading from source file.");
}
else
{
//printf("%d", ch);
insertLast(list, ch);
}
}
}
}
Your code has undefined behavior because you test while (ch != EOF) with ch uninitialized the first time. You should write:
while ((ch = fgetc(inputFile)) != EOF) {
[...]
Yet the problem is you read individual bytes instead of parsing the file contents for numbers expressed as decimal integers. You should use fscanf() to convert the text into integers.
You also forgot to close the file, causing resource leakage.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int readInputFile(const char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
if (inputFile == NULL) {
fprintf(stderr, "Could not open file %s: %s\n",
fileName, strerror(errno));
return -1;
} else {
int value, count = 0;
char ch;
while (fscanf(inputFile, "%d", &value) == 1) {
printf("inserting %d\n", value);
insertLast(list, value);
count++;
}
if (fscanf(inputFile, " %c", &ch) == 1) {
fprintf(stderr, "File has extra bytes\n");
}
fclose(inputFile);
return count; // return the number of integers inserted.
}
}
You read a character with fgetc() but you want to read a number which you do with int d; fscanf(inputFile, "%d", &d).

Read numbers from txt file second line in a C Array

I do have a txt file which looks like this
10
41 220 166 29 151 47 170 60 234 49
How can I read only the numbers from the second row into an array in C?
int nr_of_values = 0;
int* myArray = 0;
FILE *file;
file = fopen("hist.txt", "r+");
if (file == NULL)
{
printf("ERROR Opening File!");
exit(1);
}
else {
fscanf(file, "%d", &nr_of_values);
myArray = new int[nr_of_values];
// push values from second row to this array
}
How can I read only the numbers from the second row into an array in C?
Ignore the first line by reading and discarding it.
You could use something like that:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input_file = fopen(filename, "r");
if (!input_file) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
int ch; // ignore first line:
while ((ch = fgetc(input_file)) != EOF && ch != '\n');
int value;
int *numbers = NULL;
size_t num_numbers = 0;
while (fscanf(input_file, "%d", &value) == 1) {
int *new_numbers = realloc(numbers, (num_numbers + 1) * sizeof(*new_numbers));
if (!new_numbers) {
fputs("Out of memory :(\n\n", stderr);
free(numbers);
return EXIT_FAILURE;
}
numbers = new_numbers;
numbers[num_numbers++] = value;
}
fclose(input_file);
for (size_t i = 0; i < num_numbers; ++i)
printf("%d ", numbers[i]);
putchar('\n');
free(numbers);
}

Reading from file in C including char and integer

How to read and store each column in the following text from a file into an array
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
The first column should be string and the rest should be integer
Here is a simple code that do the job.
First put your text inside a test.txt file, save it in C source code path.
test.txt
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
Code
#include <stdio.h>
int main (void)
{
FILE *fp = NULL;
char *line = NULL;
size_t len = 0;
size_t read = 0;
char string[10][32];
int a[10], b[10], c[10];
int count = 0;
fp = fopen("test.txt", "r");
if(fp != NULL){
while((read = getline(&line, &len, fp)) != -1){
sscanf(line, "%s%d%d%d", string[count], &a[count], &b[count], &c[count]);
printf("<%s> - <%d> - <%d> - <%d>\n", string[count], a[count], b[count], c[count]);
count++;
}
}else{
printf("File can't open\n");
}
return 0;
}
Compile, Run
gcc -Wall -Wextra te.c -o te
./te
If you have more than 10 lines you should increase the arrays dimension.
Hope this help you.

C - Reverse Converter Process

Context:
I'm trying to reverse the process of a c converter. This is the original converter:
#include <stdio.h>
int main(void) {
FILE *f = fopen("input.bin", "rb");
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("output.txt", "wb");
int i;
for(i = 0; i < s / 4; i++) {
unsigned int u;
fread(&u, sizeof(u), 1, f);
fprintf(o, "u32[%d] = 0x%08x;\n", i, u);
}
fclose(o);
fclose(f);
return 0;
}
What it does is it creates a new file called output.txt and converts the .bin file to bytes in a order like this:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
Question:
Now, what I'm trying to do is the opposite. So, I'm trying to convert the output bytes of the above converter to a .bin file again, like its original state.
I tried this, but I'm stuck on the loop part:
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
fseek(f, 0, SEEK_END);
int s = ftell(f);
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
// grab u32 bytes from loader.txt and convert into a .bin
}
fclose(o);
fclose(f);
return 0;
}
Can anyone help me out with this? Would be amazingly appriciated.
Edit
#include <stdio.h>
int main(void) {
FILE *f = fopen("loader.txt", "rb"); // INPUT
rewind(f);
FILE *o = fopen("loader.bin", "wb"); // OUTPUT
int i;
for(i = 0; i < s / 4; i++) {
fgets(f);
sscanf(f);
}
fclose(o);
fclose(f);
return 0;
}
Here is code which seems to do the job:
#include <stdio.h>
int main(void)
{
const char i_file[] = "loader.txt";
const char o_file[] = "loader.bin";
FILE *f = fopen(i_file, "rb"); // INPUT
if (f == 0)
{
fprintf(stderr, "failed to open file '%s' for reading\n", i_file);
return 1;
}
FILE *o = fopen(o_file, "wb"); // OUTPUT
if (o == 0)
{
fprintf(stderr, "failed to open file '%s' for writing\n", o_file);
return 1;
}
char line[1024];
int lineno = 0;
while (fgets(line, sizeof(line), f) != 0)
{
int u32num;
unsigned int value;
lineno++;
if (line[0] == '\n')
continue; // Blank lines ignored
if (sscanf(line, "u32[%d] = %x", &u32num, &value) == 2)
{
fseek(o, u32num * sizeof(value), SEEK_SET);
if (fwrite(&value, sizeof(value), 1, o) != 1)
{
fprintf(stderr, "Failed to write 0x%.8X to offset %d in %s\n",
value, u32num, o_file);
break;
}
}
else
{
fprintf(stderr, "Input line %d in %s is mal-formatted: %s", lineno, i_file, line);
break;
}
}
fclose(o);
fclose(f);
return 0;
}
When run on the sample data from the question (loader.txt):
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
the output file (loader.bin) is:
$ odx loader.bin
0x0000: 41 54 55 53 48 B8 73 63 65 4E 65 74 53 6F 48 83 ATUSH.sceNetSoH.
0x0010: EC 60 BE 0E 00 00 00 48 8D 5C 24 40 48 89 44 24 .`.....H.\$#H.D$
0x0020: 40 48 89 DA 48 8D 4C 24 10 BF 4F 02 00 00 31 C0 #H..H.L$..O...1.
0x0030: C7 44 24 48 63 6B 65 74 .D$Hcket
0x0038:
$
where odx is simply a home-grown hex dump program (you could use od or xxd or other programs to achieve similar results). Taking the original conversion code verbatim (it compiled cleanly under my stringent compilation options — well done), and copying loader.bin to input.bin, the output is:
u32[0] = 0x53555441;
u32[1] = 0x6373b848;
u32[2] = 0x74654e65;
u32[3] = 0x83486f53;
u32[4] = 0x0ebe60ec;
u32[5] = 0x48000000;
u32[6] = 0x40245c8d;
u32[7] = 0x24448948;
u32[8] = 0xda894840;
u32[9] = 0x244c8d48;
u32[10] = 0x024fbf10;
u32[11] = 0xc0310000;
u32[12] = 0x482444c7;
u32[13] = 0x74656b63;
This is the same as the original input file, so the pair of programs can round-trip their data (run the two programs in turn and get as final output the data stored as the original input). Note that the code has not been tested on a binary file with a length that is not a multiple of 4 bytes; there are issues to worry about there.

Parsing and splitting a string from txt file in C

I'm new into C and I got an assignment to read line by line from .txt file and parse some strings into matrix where first line is first row, second line is second row etc. This is what I have in my text.txt file:
07 45 C4 16 0F 02 19 0I 17 0G
09 45 C4 15 0E 03 11 0A 12 0B 13 0C
13 45 C4 13 0C 03 19 0I 11 0A 17 0G 14 0D 16 0F
05 45 C4 18 0H 01 12 0B
This is what I was able to do so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *Read(char filename[]);
void split(char *content);
int main(void){
char filename[] = "text.txt";
char *content = Read(filename);
split(content);
return 0;
}
char *Read(char filename[]){
char *buffer;
long size;
FILE *log = fopen("text.txt", "r");
fseek(log, 0, SEEK_END);
size = ftell(log);
rewind(log);
buffer = (char*) malloc(sizeof(char) * size);
fread(buffer, 1, size, log);
fclose(log);
return buffer;
}
void split(char *content){
char *buffer = strtok(content, " ");
while(buffer != NULL){
printf("%s\n", buffer);
buffer = strtok (NULL, " ");
}
}
I would really appreciate comments in code because I'm rookie and it would help me to better understand some things.
To give you an idea of how it works, I wrote this snippet which manually read the line in that array, supposing that we already know the desired results.
The following approach cannot be considered the right one. Ideally you would have a series of rules to split the string, in the following however you have to set the scanf format manually for each line that you want to read.
Remember to check the return value of scanf, here we should ensure that we have read 7 elements.
int main(void) {
FILE *log;
char buffer[SIZE];
char line[SIZE];
char array[10][10];
if ((log = fopen("text.txt", "r")) == NULL){
fprintf(stderr, "Can't open input file!\n");
return(1);
}
while(fgets(buffer, sizeof(buffer), log)){
int ret = sscanf(buffer, "%2s%2s%2s%4s%2s%4s%4s", array[0], array[1], array[2], array[3], array[4],array[5], array[6]);
printf("read %d elements\n", ret);
if (ret != 7) {
return(1);
}
printf("%s", buffer);
}
int i;
for (i=0; i < 6; i++)
printf("%s\n", array[i]);
fclose(log);
return 0;
}

Resources