0

everytime I submit this code, I always encounter time limit exceeded. Any suggestion to fix the code?

this is the question:

Count the number of ASCII codes in a binary file. Enter a 2-digit hexadecimal number, count how many bytes in the binary file a.dat and whose value is exactly equal to the hexadecimal number, the statistical result must be written to the text in the format of "%d\n" in file b.txt. E.g: Let a.dat contain the following content (which has been converted to hexadecimal format for display):

0x01 0x02 0x03 0x41 0x42 0x43 0x0D 0x0A 0xFF 0xFE 0xFD 0x01 0x02 0x03 0x80 0x7F 0x0D 0x0A

###Input and output example:###

enter: 01 , output: 2 (Because there are 2 0x01 in the file.)

enter: FF , output: 1 (Because there is 1 0xFF in the file.)

this is the code:

#include <stdlib.h>

main(){
    FILE *in,*out;
    int a[100];
    int b,n=0,count=0,i;
    int *p=a;
 
    in=fopen("a.dat","rb");
    out=fopen("b.txt","wb");
    
    while (fscanf(in,"%x",p++)!=EOF){
        n++;
    }
    scanf("%x",&b);
 
    for (i=0;i<n;i++){
        if(b==a[i]){
            count++;
        }
    }
    
    fprintf(out,"%d\n",count);
 
    fclose(out);
    fclose(in);

    return 0;
}
cat
  • 33
  • 2
  • If you run this yourself, does it hang/crash or have any other symptoms of an endless loop? If yes, you are looking for a fundamental mistake. If no, "TLE" means "You get the right solutions, but your method is much to inefficient." Which is it? – Yunnosch Jun 07 '22 at 10:23
  • File `a.dat` contains binary data bytes, not text. The `fscanf` call on the binary file is meaningless. – Ian Abbott Jun 07 '22 at 10:23
  • `while (fscanf(in,"%x",p++)!=EOF)` What is this supposed to do? You are supposed to read binary data, not text represenations of binary data. You will not find hex strings but the raw data. Don't use text/string related functions for raw binary data. Besides that `%x` will not read byte values for read whatever is available for an `int`. – Gerhardh Jun 07 '22 at 10:25
  • The output file `b.txt` should be opened in text mode `"w"`, not binary mode `"wb"`. – Ian Abbott Jun 07 '22 at 10:26
  • You can use `fgetc` to read a byte from the input file. `fgetc` returns an `int`. If it is not `EOF` then you can compare that `int` to the value you are looking for and increment a counter when it matches. – Ian Abbott Jun 07 '22 at 10:30
  • 1
    Does the context of your classes past assignments allow you to describe how you can tell an "ASCII code" from any other binary byte? I ask because "Count the number of ASCII codes in a binary file." puzzles me. That requires some clarification details. The shown code might match "Count the number of occurences of a specific given ASCII code value in a binary file.".... but that is subtly different an assignment. – Yunnosch Jun 07 '22 at 10:30
  • `scanf("%x",&b);` is expecting a `unsigned int *` value where you have `&b`, so `b` should have type `unsigned int`. You could also use `scanf("%hx", &b);` for `unsigned char b`. Also, check that `scanf` returns 1. – Ian Abbott Jun 07 '22 at 10:34
  • Yes, the term "ASCII codes" in the question is misleading because ASCII is a 7-bit code and the question is asking you to search for a specified 8-bit value. The term "bytes of a specified value" would be better. – Ian Abbott Jun 07 '22 at 10:37
  • I don't see any guarantee in the problem statement that the input will be 100 bytes or smaller. – Steve Summit Jun 07 '22 at 10:47
  • What happens if you run it locally? – Gerhard Jun 07 '22 at 11:51
  • Note well: *which has been converted to hexadecimal format for display*. The file does **not** contain the 6 byte sequence 414243. It contains the *three* byte sequence `ABC`. Similarly for the other 2-digit hexadecimal codes, although the rest of them refer to nonprintable characters. – Steve Summit Jun 07 '22 at 15:00
  • So you do *not* want to read `41` from the file using `fscanf(in,"%x")`. You want to read *single bytes* from the file, using `getc`. – Steve Summit Jun 07 '22 at 15:01
  • (As an aside, if you *did* want to read `41` from the file, you would want to use `fscanf(in, "%2x")`, to limit the scan to two digits at a time. Otherwise it would try to read all the hexadecimal digits at once, giving you `0x414242` or 4276803, or worse.) – Steve Summit Jun 07 '22 at 15:02
  • I think you picked up my feedback and applied it to asking https://stackoverflow.com/questions/72540223/is-it-possible-to-count-specific-hex-number-in-a-file-using-fgetc Well done. – Yunnosch Jun 08 '22 at 05:55

1 Answers1

0

It's not really clear if the data is ASCII or binary. In case it is ASCII, you shouldn't be using "rb". I'm assuming the data is raw binary.

First of all, reading raw binary data with %x and storing it in an int will only work if you parse that int byte by byte. Otherwise you'll read 4 bytes at a time on a system with 32 bit int and that's 8 hex digits, not 2. For now, lets not complicate things by reading 4 bytes at a time since that would be a more advanced topic.

As a performance improvement, instead of storing the actual data of the file, you could store how frequently it appears:

size_t count[256] = {0}; // a byte can have 256 different value combinations
unsigned char input;

...

while(fscanf(in,"%hhu",&file_input) != 1)
{
  count[file_input]++; // increase counter for one particular byte value
}

...

unsigned char user_input;
scanf("%hhx",&user_input);
// now print count[user_input]

This way you only need to iterate over the data once.

Lundin
  • 195,001
  • 40
  • 254
  • 396