I am new programmer in general and I have start working now with c. I am trying to decode the IDEv3 mp3 tag and I came across with a variety of problems. While I was using the fread() and strncpy() commands I have noticed that both need to have the \n character as the end reference point. (Maybe I am wrong this is only an observation)
When I am printing the output they produce a non readable character. As a solution to overcome the problem I am using fread() for 4 Bytes instead of 3 in order to produce (8)\n characters (whole Byte), and a second step I am using strncpy() with 3 Bytes to an allocated memory which then I am using for printing. In theory when I am using fread() I should not encounter this problem.
A sample of code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
unsigned char header_id[3]; /* Unsigned character 3 Bytes (24 bits) */
}mp3_Header;
int main (int argc, char *argv[]) {
mp3_Header first;
unsigned char memory[4];
FILE *file = fopen( name.mp3 , "rb" );
if ( (size_t) fread( (void *) memory , (size_t) 4 , (size_t) 1 , (FILE *) file) !=1 ) {
printf("Could not read the file\n");
exit (0);
} /* End of if condition */
strncpy( (char *) first.header_id , (char *) memory , (size_t) 3);
printf ("This is the header_ID: %s\n", first.header_id);
fclose(file);
} /* End of main */
return 0;
There are 2 correct ways of handling the header. I'm assuming the MP3 file has a IDV3 tag, so the file starts with "TAG" or "TAG+". So the part you want to read has 4 bytes.
a) You think of
char *memory
being a C "string", and first.header_id as well. Then do it this way (omitted everything else to show the important parts):After the fread, your memory looks like this:
The 5th byte, at index 4, is not defined, because you read only 4 bytes. If you use a string function on this string (for example
printf("%s\n", memory)
); the function doesn't know where to stop, because there is no terminating \0, and printf will continue to output garbage until the next \0 it finds somewhere in your computer's RAM. That's why you domemory[4]='\0'
next so it looks like this:Now, you can use strncpy to copy these 5 bytes to first.header_id. Note you need to copy 5 bytes, not just 4, you want the \0 copied as well.
(In this case, you could use strcpy (without n) as well - it stops at the first \0 it encounters. But these days, to prevent buffer overflows, people seem to agree on not using strcpy at all; instead, always use strncpy and explicitly state the length of the receiving string).
b) You treat
memory
as binary data, copy the binary data to the header, and then turn the binary data into a string:In this case, there is never a \0 at the end of memory. So it's sufficient to use a 4-byte-array now. In this case (copying binary data), you don't use strcpy, you use memcpy instead. This copies just the 4 bytes. But now,
first.header_id
has no end marker, so you have to assign it explicitly. Try drawing images like i did above if it isn't 100% clear to you.But always remember: if you use operators like '+', you do NOT work upon the string. You work on the single characters. The only way, in C, to work on a string as a whole, is using the str* functions.