I am writing a program to compress a file consisting of hexadecimal values into run-length code. For example, given a file:
46 6f 6f 20 62 61 72 21 21 21 20 20 20 20 20
my code should produce the following file:
01 46 02 6f 01 20 01 62 01 61 01 72 03 21 05 20
I don't know why the program I've written gets stuck. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int main(void){
int a, b, c, count=1, flag=TRUE;
FILE *file;
FILE *out;
file = fopen("input.txt", "r");
if(file){
out = fopen("input.txt.out", "a");
fscanf(file, "%x", &a);
while(fscanf(file, "%x", &c)){
while(flag==TRUE){
if(c==a){
count= count+1;
}else{
flag = FALSE;
}
b=a;
a=c;
}
fprintf(out, "%d %02x ", count, b);
count = 1;
flag = TRUE;
}
}else{
printf("ERROR: file not found.");
}
}
EDIT: I updated the code removing the !feof(file) argument and replacing it with an actual I/O function instead. Thanks for the insight. However, my program still doesn't work.
I don't know why your program "gets stuck" but this might work better. Note I have dumped the meaningless a, b, c and the truth stuff.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int lastchar, thischar, count;
FILE *finp;
FILE *fout;
finp = fopen("input.txt", "r");
fout = fopen("output.txt", "w"); // changed "a" to "w"
if(fout == NULL || finp == NULL) {
puts("Error opening file(s)");
exit(1);
}
count = 1;
fscanf(finp, "%x", &lastchar);
while(fscanf(finp, "%x", &thischar) == 1) { // func value better then feof
if(thischar == lastchar) {
count++;
}
else {
fprintf(fout, "%02X %02X ", count, lastchar);
count = 1;
}
lastchar = thischar;
}
fprintf(fout, "%02X %02X ", count, lastchar); // discharge remaining
fclose(fout);
fclose(finp);
return 0;
}
Program input: 46 6f 6f 20 62 61 72 21 21 21 20 20 20 20 20
Program output: 01 46 02 6F 01 20 01 62 01 61 01 72 03 21 05 20
A better way of implementing RLE is to choose an "escape" value to define when a compression follows. Thus 3 values will encode a compression sequence, and so it is only worth compressing 3 or more the same. All other characters are verbatim, except the escape character itself.
Related
I have an assignment where I'm suppose to read input lines such as
2
67 5 100 1 11 97 98 10 1 110
15 72 10 101 47 67 88 20 94 6 22 11
4
61 11 93 4 73 39 78 34 17 104
23 43 11 93 65 52 20 96 66 31 86 24 40 61 102 13 50 51
73 43 28 73 8 89 31 68 77 27 24 77 42 72 15 24 64 51
25 75 7 90 10 111 17 16
.....
process every two integers (the first line in a block only tells us how many words we will process), add them then match
them to their corresponding ASCII char. The example above would be two blocks.
The output should be:
Decoded messages:
Hello World!
Happy Bhutanese teacher's day!
I'm having problems when it comes to dealing with a file with multiple blocks, more than 20 and so forth following the same format on one input text. I can handle one block fine, two blocks okay but not fine because my program doesn't seem to end. No line will be longer than 256 characters. numOfPuzzl refers to how many words we process per block.
I'd greatly appreciate any help. I attached my code and commented as much as I can too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
//user will type in file name they choose to process and we allocated in filename[]
char filename[256];
printf("Enter filename: ");
scanf("%s", filename);
//process filename username typed in
FILE *pFile;
pFile = fopen(filename, "r");
//if there's nothong to read
if (pFile == NULL){
exit(1);
}
printf("Decoded messages:\n");
//create array we will putting lines into
char myString[256];
//simply gets the first line, which is always a lone integer
fgets(myString, 256, pFile);
int numOfPuzzl;
sscanf(myString, "%d", &numOfPuzzl);
//printf("puzzles to solve: %d\n", numOfPuzzl);
int wordsProcessed = 0;
//just remember that myString has entire line
//start processing the lines that follow, a line is a word
while (fgets(myString, 256, pFile) != NULL){
int num = 0; //first integer in line
int secondNum = 0; //second int. in line
int tot = 0; //how many bytes
int bytes_read = 0; //bytes processed
char *endOfStrAdr = strchr(myString, '\0'); //returns address of end terminating char.
int endOfStrIdx = endOfStrAdr - myString; //this will give me the index of where the terminating char. occurs within my array
//start scanning integers within array making sure to not sccan out of bounds
while (tot < endOfStrIdx){
//first integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &num, &bytes_read);
tot += bytes_read; //keeps tab so we don't have to read from the begn. of array everytime
//second integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &secondNum, &bytes_read);
tot += bytes_read; ////keeps tab so we don't have to read from the begn. of array everytime
printf("%c", (char) num + secondNum); //add the two integers and cast them to char
//we want to check if we are the end of the string, our word
if (tot == endOfStrIdx){
printf(" ");
wordsProcessed++;
//we want to print a new line char. if we finished processing all the words for the puzzle
if (wordsProcessed == numOfPuzzl){
printf("\n");
fgets(myString, 256, pFile);
}
}
}
}
fclose(pFile);
}
Ignore blank lines between puzzles.
Reset parameters (numOfPuzzl and wordsProcessed) before processing new puzzles.
To archive that, change
if (wordsProcessed == numOfPuzzl) {
printf("\n");
fgets(myString, 256, pFile);
}
into
if (wordsProcessed == numOfPuzzl) {
printf("\n");
while ( fgets(myString, 256, pFile) != NULL ){
if ( sscanf(myString, "%d", &numOfPuzzl) == 1 )
break;
}
wordsProcessed = 0;
}
I suggest like this:
#include <stdio.h>
#include <stdlib.h>
//stringize macro
#define S_(x) #x
#define S(x) S_(x)
int main(void){
char filename[FILENAME_MAX + 1];
printf("Enter filename: ");
scanf("%" S(FILENAME_MAX) "[^\n]", filename);
FILE *pFile;
if(NULL==(pFile = fopen(filename, "r"))){
perror("can't opne file");
exit(EXIT_FAILURE);
}
printf("Decoded messages:\n");
int numOfLines;
while(1==fscanf(pFile, "%d", &numOfLines)){
for(int i = 0; i < numOfLines; ++i){
int num1, num2, state;
char ck;
while(3==(state=fscanf(pFile, "%d %d%c", &num1, &num2, &ck)) || 2 == state){
putchar(num1 + num2);
if(state == 2 || state == 3 && ck == '\n')
break;
}
putchar(' ');
}
putchar('\n');
}
fclose(pFile);
return 0;
}
I am a beginner programmer taking a class and I cannot get my output strings to print with spaces in between words. Here is my code below. It is supposed to take a string that I input and either change to all caps or all lower case as I specify when I run the program. If I put in MY CODE DOES NOT WORK, it outputs mycodedoesnotwork. Why is it removing the spaces?
1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6
7 int shout(char * msgIn, char * msgOut) {
8
9 if (!msgIn || !msgOut)
10 return -1;
11 while (*msgIn != '\0') {
12 if ('a' <= *msgIn && *msgIn <= 'z')
13 *msgOut = *msgIn + ('A' - 'a');
14 else
15 *msgOut = *msgIn;
16 msgIn++;
17 msgOut++;
18 }
19 *msgOut = '\0';
20
21 return 0;
22 }
23
24
25 int whisper(char const * msgIn, char * msgOut) {
26 if (!msgIn || !msgOut)
27 return -1;
28 while (*msgIn != '\0') {
29 if ('A' <= *msgIn && *msgIn <= 'Z')
30 *msgOut = *msgIn + ('a' - 'A');
31 else
32 *msgOut = *msgIn;
33 msgIn++;
34 msgOut++;
35 }
36 *msgOut = '\0';
37 return 0;
38 }
39
40 int main(int argc, char ** argv) {
41 char in[128], out[128];
42 int i;
43 for (i = 1; i < argc; i++) {
44 if (strcmp("-w", argv[i]) == 0)
45 while (scanf("%s", in) != EOF) {
46 whisper(in, out);
47 printf("%s", out);
48 }
49 else if (strcmp("-s", argv[i]) == 0)
50 while (scanf("%s", in) != EOF) {
51 shout(in, out);
52 printf("%s", out);
53 }
54 }
55 printf("\n");
56 return 0;
57 }
~
~
The scanf calls are reading in just the words (no spaces) and you are not adding spaces back in when you output your strings.
If you don't mind a trailing space, just change lines 47 and 52 to printf("%s ", out)
while (scanf("%s", in) != EOF)==> scanf() takes input up to space and send to function
and then in next iteration again takes word after space.
You need to use fgets() instead.
It is not problem with your shout() or wisper() functions, but problem with scanf().
When you specify %s to read string, the string will terminate at any white space chars - space, tab etc.
And that will not be included in the string. So space that you enter between the strings are not stored in in variable.
You may want to think of different approach to solve that.
The space is a string terminator for scanf() and scanf() does not include it in the acquired string. man 3 scanf
I have wrote a program that takes two integers(m and n) as input and then writes to a file all the prime numbers between them. I wanted the output to look neat so I print each number 7 spaces wide using the field-width modifier and only print 10 per line. The output is as expected apart from the first line, where only 9 numbers are printed.
Here is the code:
#include <stdio.h>
#include <math.h>
#define SIZE 100000000
char primes[SIZE];
void seive(void)
{
int i, j;
primes[1] = primes[0] = 1;
for (i=3;i<=sqrt(SIZE);i+=2)
if (primes[i] == 1)
continue;
else
for (j=i*i;j<SIZE;j+=2*i)
primes[j] = 1;
}
int main()
{
int n, m, count;
FILE *fp;
fp = fopen("test.txt", "w");
seive();
scanf("%d %d", &m, &n);
count = 0;
if (m <= 2) {
fprintf(fp, "%7d ", 2);
count++;
}
if (!(m & 1))
m++;
for (m;m<=n;m+=2) {
if (!primes[m]) {
count++;
if (count == 10) {
fprintf(fp, "\n");
count = 0;
}
fprintf(fp, "%7d ", m);
}
}
return 0;
}
This is the output for the input 1 300:
2 3 5 7 11 13 17 19 23
29 31 37 41 43 47 53 59 61 67
71 73 79 83 89 97 101 103 107 109
113 127 131 137 139 149 151 157 163 167
173 179 181 191 193 197 199 211 223 227
229 233 239 241 251 257 263 269 271 277
281 283 293
As you can see only nine numbers are printed on the first line, but after it does as it should. I'm baffled. Thanks in advance.
I think it has something to do with the fact that you print your newline before you print your output in the loop.
change it to:
for (m;m<=n;m+=2) {
if (!primes[m]) {
count++;
fprintf(fp, "%7d ", m);
if (count == 10/*&& you're going to print more numbers*/) {
fprintf(fp, "\n");
count = 0;
}
}
}
count = 0;
if (m <= 2) {
fprintf(fp, "%7d ", 2);
count++;
}
This starts a line, prints an entry, and increments count to 1.
if (!primes[m]) {
count++;
if (count == 10) {
fprintf(fp, "\n");
count = 0;
}
fprintf(fp, "%7d ", m);
This starts a line, prints an entry, and sets count to zero.
Since the two code sections set count to different values (off by one), the produce different numbers of entries per line (off by one).
Using fgets() to read in strings.
But the print statement that prints the size prints out 4 when my input is a 3 character string "abc".
This ruins my methods completely because it adds a space to the char array making arrange not work.
Input file:
2
abc
bca
I'm sure there is no space after the strings.
int main(){
FILE * inF;
inF = fopen ("input2.txt", "r");
//Find number of Strings
int numWords = 0;
fscanf(inF, "%d", &numWords);
printf("%d\n", numWords);
int i = 0;
int counter = 0;
char string[10000];
//Run fgets so it starts at second line
fgets(string, 20, inF);
while(i< numWords) {
string[10000] = 0;
fgets(string, 20, inF);
printf("char: %s", string);
//find and print permutations
counter = strlen(string);
printf("size: %d\n", counter);
arrange(string, 0, counter - 1);
i++;
}
return 0;
}
Any help would be great, thanks!
The first fscanf reads the number, but leaves the newline. So when you later call fgets it is this empty line that fgets reads.
Use only fgets to get complete lines, and if you need to use a scanf like function then use sscanf on that line.
Don't mix fscanf() and fgets().
Read a whole line for the first line, then use sscanf() to parse out the number from that line, before continuining with more fgets() to read remaining lines.
You may print what's in the buffer string[] after fgets, like this:
...
while(i< numWords) {
string[10000] = 0; // !!! Do you mean string[9999] = 0;
fgets(string, 20, inF);
printf("char: %s", string);
// add printf here
for (j = 0; j < 20; j++)
printf("%02X ", (unsigned char)string[j]);
printf("\n");
...
}
and you would see the result like this:
2
char: abc
61 62 63 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
size: 4
char: bca
62 63 61 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
size: 4
As you can see, there is a 0A, i.e., \n, after every fgets. Then it would be obvious why the size is 4.
$ man fgets
...
If a newline is read, it is stored into the buffer.
...
So you may have to remove the newline manually.
There I have this assignment where I am suppose to emulate the hexdump function from unix. I got my program to dump files into hex but i am having trouble printing the offset and the printable characters.
Here is my code:
/*performs a hex and an octal dump of a file*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LINESIZE 512
void hexdump(FILE *fp);
void octaldump(FILE *fp);
int main(int argc, char * argv[])
{
FILE *fp;
if((fp = fopen(argv[1], "rb+")) == '\0')
{
perror("fopen");
return 0;
}
hexdump(fp);
return 0;
}
void hexdump(FILE *fp)
{
char temp [LINESIZE];
size_t i = 0;
size_t linecount = 1;
long int address = 0;
while(fscanf(fp," %[^\n] ", temp) == 1)
{
printf("%5d", address);
for(i = 0; i < strlen(temp); i++)
{
printf("%02x ", temp[i]);
if(linecount == 16)
{
printf("\n");
linecount = 0;
}
linecount++;
}
printf(" | ");
for(i = 0; i < strlen(temp); i++)
{
if(temp[i] < 32)
{
printf(".");
}
else
{
printf("%c", temp[i]);
}
}
printf("\n");
}
}
As i said above, my program is suppose to print the offset then the hex value of the file padded with 0's, then the printable characters of the file like so.
0000000 7f 2a 34 f3 21 00 00 00 00 00 00 00 00 00 00 00 | test file
I managed to print out the printable characters, but they appear after the hex part. So if one line of hexcode extends to the next line, it prints the printable characters on the nextline.
For example:
2a 3b 4d 3e 5f
12 43 23 43 | asfdg df
How do i get it to print whatever character appears after one line of the hex characters?
PS: For some reason my program doesn't pad 0's for some reason.
EDIT1: I got the offset part, i just keep adding 16 to my address variable and keep printing
Since this is homework, I'll just give you some pointers on how to approach your problem. I'll be as vague as I can so as to not interfere with your learning.
First of all, don't use fscanf if you're writing a hex dumper, use fread instead. The scanf family of functions are meant for text and hex dumpers are usually used with binary data.
If you use fread and read just enough bytes at a time to fill one line of output, then you can produce your desired output with two for loops (one for hex, one for characters) followed by a single newline.
As far as your zero padding problem goes, read the printf man page, your "%5d" format string needs a little bit more.