Writing binary in C - c

I am trying to write the value 0000 0100 (which is 4 in decimal) into a binary file in C. Here is my code:
FILE *fp = fopen("D:\\test.COM", "wb");
if (fp == NULL) {
printf("error creating file");
return -1;
}
int val = 100; // value 4
fwrite(&val, sizeof val, 1, fp);
fclose(fp);
return 0;
Can someone correct me? I don't want to assign 4 to val, I want to write actual binary in the code.
Thanks,

If you want the file to actually have the bits 0000 0010, then you want an 8-bit int, which is a char in C.
char val = (char) 4; // value 4
fwrite(&val, sizeof val, 1, fp);
Update: Based on the comments, it looks like the OP is asking how to convert a binary string of the form "00000010" into the bit representation. Yes, there is a way, but it requires you to do bit masking. The following should get you started.
char* input = "00000010";
char output = 0;
for (int i = 0; i < 8; i++)
if (input[i] == '1')
output |= (1 << (7-i)); // Set the appropriate sit of `output` to 1.
You can then use fwrite as in the first part of my answer.
Since BLUEPIXY did not write his own answer, I am incorporating his comment into this answer for completeness. While I think the above loop is instructive for a beginner, it is much faster to use the library function that he mentioned.
char val=strtol("00000100", NULL, 2);

You are trying to specify it in binary?
int val = 0b100; // value 4

Related

Writing an array of integers into a file using C [duplicate]

This question already has answers here:
How to write an array to file in C
(3 answers)
Closed 3 years ago.
I would like to write an array of integers into a file using C. However, I get some gibberish in the file.
The code is about a function that converts a decimal number into binary then stores it into a file.
int * decToBinary(int n) //function to transform the decimal numbers to binary
{
static int binaryNum[16]; // array to store binary number
int i = 0; // counter for binary array
while (n > 0) {
binaryNum[i] = n % 2; // storing remainder in binary array
n = n / 2;
i++;
}
return binaryNum;
}
int main()
{
FILE *infile;
int i;
int *p;
int decimal= 2000;
int written = 0;
infile = fopen("myfile.txt","w");
p = decToBinary(decimal);
written = fwrite(p,sizeof(int),sizeof(p),infile) ;
if (written == 0) {
printf("Error during writing to file !");
}
fclose(infile);
return 0;
}
This is what I get in my file:
This is what I get when I write a text as a test, it does not have any problem with the text, but it has with the array.
char str[] = "test text --------- \n";
infile = fopen("myfile.txt","wb");
p=decToBinary(decimal);
fwrite(str , 1 , sizeof(str) , infile);
written = fwrite(p,sizeof(int),sizeof(p),infile) ;
And this is what I get when I make this change:
written = fwrite(&p,sizeof(int),sizeof(p),infile) ;
First, be aware that there are two interpretations for 'binary':
int n = 1012;
fwrite(&n, sizeof(n), 1, file);
This writes out the data just as is; as it is represented in form of bits, output is considered "binary" (a binary file).
Your question and the code you provided, though, rather imply that you actually want to have a file containing the numbers in binary text format, i. e. 7 being represented by string "111".
Then first, be aware that 0 and 1 do not represent the characters '0' and '1' in most, if not all, encodings. Assuming ASCII or compatible, '0' is represented by value 48, '1' by value 49. As C standard requires digits [0..9] being consecutive characters (this does not apply for any other characters!), you can safely do:
binaryNum[i] = '0' + n % 2;
Be aware that, as you want strings, you chose the bad data type, you need a character array:
static char binaryNum[X];
X??? We need to talk about required size!
If we create strings, we need to null-terminate them. So we need place for the terminating 0-character (really value 0, not 48 for character '0'), so we need at least one character more.
Currently, due to the comparison n > 0, you consider negative values as equal to 0. Do you really intend this? If so, you might consider unsigned int as data type, otherwise, leave some comment, then I'll cover handling negative values later on.
With restriction to positive values, 16 + 1 as size is fine, assuming int has 32 bit on your system! However, C standard allows int to be smaller or larger as well. If you want to be portable, use CHAR_BIT * sizeof(int) / 2 (CHAR_BIT is defined in <limits.h>; drop division by 2 if you switch to unsigned int).
There is one special case not covered: integer value 0 won't enter the loop at all, thus you'd end up with an empty string, so catch this case separately:
if(n == 0)
{
binaryNum[i++] = '0';
}
else
{
while (n > 0) { /.../ }
}
// now the important part:
// terminate the string!
binaryNum[i] = 0;
Now you can simply do (assuming you changed p to char*):
written = fprintf(file, "%s\n", p);
// ^^ only if you want to have each number on separate line
// you can replace with space or drop it entirely, if desired
Be aware that the algorithm, as is, prints out least significant bits first! You might want to have it inverse, then you'd either yet have to revert the string or (which I would prefer) start with writing the terminating 0 to the end and then fill up the digits one by one towards front - returning a pointer to the last digit (the most significant one) written instead of always the start of the buffer.
One word about your original version:
written = fwrite(p, sizeof(int), sizeof(p), infile);
sizeof(p) gives you the size of a pointer; this one is system dependent, but will always be the same on the same system, most likely 8 on yours (if modern 64-bit hardware), possibly 4 (on typical 32-bit CPU), other values on less common systems are possible as well. You'd need to return the number of characters printed separately (and no, sizeof(binaryNum) won't be suitable as it always returns 17, assuming 32-bit int and all changes shown above applied).
You probably want this:
...
int main()
{
int decimal = 2000;
int *p = decToBinary(decimal);
for (int i = 0; i< 16; i++)
{
printf("%d", p[i]);
}
return 0;
}
The output goes to the terminal instead into a file.
For writing into a file use fopen as in your code, and use fprintf instead of printf.
Concerning the decToBinary there is still room for improvement, especially you could transform the number directly into an array of char containing only chars 0 and 1 using the << and & operators.

Swapping bytes of unsigned short integer

I have a partially working function which involves writing to a file.
I have an array, arr, of type unsigned short int and each element must be written to a file in binary format.
My inital solution was:
for(i = 0; i < ROWS; i++) {
fwrite(&arr[i], 1, sizeof(unsigned short int), source);
}
The code above works when writing unsigned short ints to the file. Also, source is a pointer to the file which is being written to in binary format. However, I need to swap the bytes, and am having trouble doing so. Essentially, what is written to the file as abcd should be cdab.
My attempt:
unsigned short int toWrite;
unsigned short int swapped;
for(i = 0; i < ROWS; i++) {
toWrite = &arr[i];
swapped = (toWrite >> 8) | (toWrite << 8);
fwrite(swapped, 1, sizeof(unsigned short int), source);
}
However I get a segmentation fault core dump as a result. I read and used the upvoted answer to this question - convert big endian to little endian in C [without using provided func] - but it doesnt seem to be working. Any suggestions? Thanks!
your attempt is very wrong (and the answers you copied from are okay, the problem isn't in the swapping itself)
First you're taking the address of the value to swap, then you're passing the value instead of the address to write. It should be:
unsigned short int toWrite;
unsigned short int swapped;
for(i = 0; i < ROWS; i++){
toWrite = arr[i];
swapped = (toWrite >>8) | (toWrite <<8); // that part is OK
fwrite(&swapped, 1 , sizeof(unsigned short int) , source);
}
I'm positive that the compiler warned you for this. Warnings are useful.
Welcome to the world of non portable binary formats.
Swapping the numbers is a hack that is error prone because it makes the program non portable: whether to swap the values or not depends on the endianness of the system where you compile and run the program. Your program has a very simple bug: you pass the value of swapped instead of its address. You can fix it with:
fwrite(&swapped, sizeof(swapped), 1, source);
Yet a better solution for your problem is to handle endianness explicitly in your program. This is a portable solution to write the numbers in big endian order:
/* writing 16 bit unsigned integers in big endian order */
for (i = 0; i < ROWS; i++) {
putc(arr[i] >> 8, source);
putc(arr[i] & 255, source);
}
This is the alternative version if you are expected to write in little endian order:
/* writing 16 bit unsigned integers in little endian order */
for (i = 0; i < ROWS; i++) {
putc(arr[i] & 255, source);
putc(arr[i] >> 8, source);
}
Note that it is somewhat confusing to name the stream variable for an output file source.

Bynary/Integer representation of file in C

I am trying to get some plain Ruby code ported to the C language for speed but I am not really being able to achieve that as C is not my primary language and I am struggling to understand what is causing it. Here is the code in Ruby for clarity of the purpose:
source_file = open("/tmp/image.jpg")
content = source_file.read
content_binary_string = content.unpack("b*")[0]
content_integer = content_binary_string.to_i(2)
I've been then playing around with several attempts in C to achieve the same results and somehow I am stuck on the binary comparison between the Ruby and C outputs. Here is the C code I've got so far:
// gcc -Wall -Wextra -std=c99 xxd.c
#include <stdio.h>
#include <string.h>
int main() {
char buffer[32];
FILE *image;
image = fopen("/tmp/image.jpg","rb");
while (!feof(image)) {
fread(buffer, sizeof(buffer), 1, image);
const size_t len = strlen(buffer);
for (size_t j = 0; j < len; j++ ) {
for (int i = 7; i >= 0; i--) {
printf(buffer[j] & (1 << i) ? "1" : "0");
}
}
}
return 0;
}
Please notice that the C code is not yet complete and that I am for now printing the binary value so I can compare the output with the current working code and I believe I am missing some basic concept that is abstracted by Ruby like byte size or something else that is not obvious to me yet. The output is quite different at this point.
After I get that step right, then the goal is to produce an integer based value from that.
Any clues towards understanding why that output isn't accurate is highly appreciated!
feof() should be used after an input function indicated a failed read . It distinguishes if the failure was due to End-of-File.
strlen() reports the length (not including null character) of a string. In C, a string is a sequence of characters up to and including the null character. Do no use this to determine how many bytes are in a buffer. Use the return value of fread(). #subin
Check the return value of input functions. #user694733
Avoid using a string that is not a format string as the first argument to printf().
Better to use unsigned like 1u with bit operations.
Minor: Avoid magic numbers like 7. CHAR_BIT is available in <limit.h>.
Minor: Use fclose() Put your toys away when done.
image = fopen("/tmp/image.jpg","rb");
if (image == NULL) Handle_OpenFailure();
size_t count;
while ((count = fread(buffer, sizeof buffer[0], sizeof buffer, image)) > 0) {
for (size_t j = 0; j < count; j++ ) {
for (int i = CHAR_BIT-1; i >= 0; i--) {
fputc(buffer[j] & (1u << i) ? '1' : '0', stdout);
}
}
}
fclose(image);

Understanding And Getting info of Bitmap in C

I am having a hard time understanding and parsing the info data present in a bitmap image. To better understand I read the following tutorial, Raster Data.
Now, The code present there is as follows, (Greyscale 8bit color value)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*-------STRUCTURES---------*/
typedef struct {int rows; int cols; unsigned char* data;} sImage;
/*-------PROTOTYPES---------*/
long getImageInfo(FILE*, long, int);
int main(int argc, char* argv[])
{
FILE *bmpInput, *rasterOutput;
sImage originalImage;
unsigned char someChar;
unsigned char* pChar;
int nColors; /* BMP number of colors */
long fileSize; /* BMP file size */
int vectorSize; /* BMP vector size */
int r, c; /* r = rows, c = cols */
/* initialize pointer */
someChar = '0';
pChar = &someChar;
if(argc < 2)
{
printf("Usage: %s bmpInput.bmp\n", argv[0]);
//end the execution
exit(0);
}
printf("Reading filename %s\n", argv[1]);
/*--------READ INPUT FILE------------*/
bmpInput = fopen(argv[1], "rb");
//fseek(bmpInput, 0L, SEEK_END);
/*--------DECLARE OUTPUT TEXT FILE--------*/
rasterOutput = fopen("data.txt", "w");
/*--------GET BMP DATA---------------*/
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
fileSize = getImageInfo(bmpInput, 2, 4);
nColors = getImageInfo(bmpInput, 46, 4);
vectorSize = fileSize - (14 + 40 + 4*nColors);
/*-------PRINT DATA TO SCREEN-------------*/
printf("Width: %d\n", originalImage.cols);
printf("Height: %d\n", originalImage.rows);
printf("File size: %ld\n", fileSize);
printf("# Colors: %d\n", nColors);
printf("Vector size: %d\n", vectorSize);
/*----START AT BEGINNING OF RASTER DATA-----*/
fseek(bmpInput, (54 + 4*nColors), SEEK_SET);
/*----------READ RASTER DATA----------*/
for(r=0; r<=originalImage.rows - 1; r++)
{
for(c=0; c<=originalImage.cols - 1; c++)
{
/*-----read data and print in (row,column) form----*/
fread(pChar, sizeof(char), 1, bmpInput);
fprintf(rasterOutput, "(%d, %d) = %d\n", r, c, *pChar);
}
}
fclose(bmpInput);
fclose(rasterOutput);
}
/*----------GET IMAGE INFO SUBPROGRAM--------------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char *ptrC;
long value = 0L;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i=1; i<=numberOfChars; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
/* calculate value based on adding bytes */
value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);
} /* end of getImageInfo */
What I am not understanding:-
I am unable the understand the 'GET IMAGE INTOSUBPROGRAM' part where the code is trying to get the image infos like no of rows,columns, etc. Why are these infos stored over 4 bytes and what is the use of the value = (long)(value + (*ptrC)*(pow(256, (i-1)))); instruction.
Why there unsigned char dummy ='0' is created and then ptrC =&dummy is assigned?
Why can't we just get the no of rows in an image by just reading 1 byte of data like getting the Greyscale value at a particular row and column.
Why are we using unsigned char to store the byte, isn't there some other data type or int or long we can use effectively here?
Please help me understand these doubts(confusions!!?) I am having and forgive me if they sound noobish.
Thank you.
I would say the tutorial is quite bad in some ways and your problems to understand it are not always due to being a beginner.
I am unable the understand the 'GET IMAGE INTOSUBPROGRAM' part where the code is trying to get the image infos like no of rows,columns, etc. Why are these infos stored over 4 bytes and what is the use of the value = (long)(value + (ptrC)(pow(256, (i-1)))); instruction.
The reason to store over 4 bytes is to allow the image to be sized between 0 and 2^32-1 high and wide. If we used just one byte, we could only have images sized 0..255 and with 2 bytes 0..65535.
The strange value = (long)(value + (*ptrC)*(pow(256, (i-1)))); is something I've never seen before. It's used to convert bytes into a long so that it would work with any endianness. The idea is to use powers of 256 to set the *ptrC to the value, i.e. multiplying first byte with 1, next with 256, next with 65536 etc.
A much more readable way would be to use shifts, e.g. value = value + ((long)(*ptrC) << 8*(i-1));. Or even better would be to read bytes from the highest one to lower and use value = value << 8 + *ptrC;. In my eyes a lot better, but when the bytes come in a different order, is not always so simple.
A simple rewrite to be much easier to understand would be
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char ptrC;
long value = 0L;
int i;
fseek(inputFile, offset, SEEK_SET);
for(i=0; i<numberOfChars; i++) // Start with zero to make the code simpler
{
fread(&ptrC, 1, 1, inputFile); // sizeof(char) is always 1, no need to use it
value = value + ((long)ptrC << 8*i); // Shifts are a lot simpler to look at and understand what's the meaning
}
return value; // Parentheses would make it look like a function
}
Why there unsigned char dummy ='0' is created and then ptrC =&dummy is assigned?
This is also pointless. They could've just used unsigned char ptrC and then used &ptrC instead of ptrC and ptrC instead of *ptrC. This would've also shown that it is just a normal static variable.
Why can't we just get the no of rows in an image by just reading 1 byte of data like getting the Greyscale value at a particular row and column.
What if the image is 3475 rows high? One byte isn't enough. So it needs more bytes. The way of reading is just a bit complicated.
Why are we using unsigned char to store the byte, isn't there some other data type or int or long we can use effectively here?
Unsigned char is exactly one byte long. Why would we use any other type for storing a byte then?
(4) The data of binary files is made up of bytes, which in C are represented by unsigned char. Because that's a long word to type, it is sometimes typedeffed to byte or uchar. A good standard-compliant way to define bytes is to use uint8_t from <stdint.h>.
(3) I'm not quite sure what you're trying to get at, but the first bytes - usually 54, but there are othzer BMF formats - of a BMP file make up the header, which contains information on colour depth, width and height of an image. The bytes after byte 54 store the raw data. I haven't tested yopur code, but there might be an issue with padding, because the data for each row must be padded to make a raw-data size that is divisible by 4.
(2) There isn't really a point in defining an extra pointer here. You could just as well fread(&dummy, ...) directly.
(1) Ugh. This function reads a multi-byte value from the file at position offset in the file. The file is made up of bytes, but several bytes can form other data types. For example, a 4-byte unsigned word is made up of:
uint8_t raw[4];
uint32_t x;
x = raw[0] + raw[1]*256 + raw[2]*256*256 + raw[3]*256*256*256;
on a PC, which uses Little Endian data.
That example also shows where the pow(256, i) comes in. Using the pow function here is not a good idea, because it is meant to be used with floating-point numbers. Even the multiplication by 256 is not very idiomatic. Usually, we construct values by byte shifting, where a multiplication by 2 is a left-shift by 1 and hence a multiplication by 256 is a left-shift by 8. Similarly, the additions above add non-overlapping ranges and are usually represented as a bitwise OR, |:
x = raw[0] | (raw[1]<<8) | (raw[2]<<16) | (raw[3]<<24);
The function accesses the file by re-positioning the file pointer (and leaving it at the new position). That's not very effective. It would be better to read the header as an 54-byte array and accessing the array directly.
The code is old and clumsy. Seeing something like:
for(r=0; r<=originalImage.rows - 1; r++)
is already enough for me not to trust it. I'm sure you can find a better example of reading greyscale images from BMP. You could even write your own and start with the Wikipedia article on the BMP format.

Change content of file

Can someone please break down this code for me? I know it changes text from a user file and I know it could be very useful to me. What is the purpose of "~"? How could I amend this code to read a user file word by word and then change it using the same kind of formula?
// first value in the file is the key
if ( fread(&key, sizeof(char), 1, infile) )
{
key = ~key;
}
while( fread(&fval ,sizeof(short), 1, infile) )
{
fputc( (fval / 2) - key, outfile );
}
key = ~key swaps all the bits of key
You know about bits?
ascii A (65) is 100 0001 in binary, so '~' of this is simply swaps each 1 for 0 and each 0 for 1 giving 011 1110 (62) which is >
So this will replace all the As in your document with > and similarly for every other character. The nice thing about ~ is that it's exactly the same process to decrypt - just swap each bit back.
ps. It's not exactly mil-spec encryption!
Comments inline!
#include <stdio.h>
int main(void)
{
/* Integer value of 'A' is 65 and
binary value is 01000001 */
char a='A';
printf("a=%d\n", a);
/* ~a is binary inverse of a so
~01000001 = 10111110 */
a=~a;
printf("a=%d\n", a);
/* easier example */
/* ~0 = 11111111 times # of bytes needed
to store int (whose value is nothing
but negative one) */
int i=0;
printf("i=%d\n", i);
i=~i;
printf("i=%d\n", i);
return 0;
}
$ ./a.out
a=65
a=-66
i=0
i=-1
$
With the above mentioned hint, could you please try and read the code and share your comments.
OTOH, what is crypt? what is its type? what is the value stored in it?!
For more bitwise operations, please refer this page!

Resources