How do I hold hexidecimal letter values in an int? [C] - c

I am writing a cache lab in C and I have got the whole input file to print in a char array, but any and all help for my cache lab online uses int to hold the input file, so I am thinking I need that too.
I have a three input files. One holds:
10
20
22
18
E10
210
12
I can get 10, 20, 22, 18 to print:
FILE* file;
int address;
file = fopen("address01" , "r");
while (fscanf(file, "%d", &address)) {
printf("%d\n", address);
}
fclose(file);
but it stops after 18 since the next input is a char. I know characters can be held as an int on their own, so how can I also do this with the E and the 10 being together?

You can use the %x format specifier to read hexadecimal values into an int. For example:
int address;
if (fscanf(file, "%x", &address) == 1) {
printf("%d\n", address);
}
This will read the hexadecimal value E10 into the int variable address.

Related

How to convert string of hex to insert into binary file in C

I need to take in some input that is a string and turn it into its equal hex number and put it in place in a binary file.
char *fpath = argv[3];
FILE *f = fopen(fpath, "wb+");
char buf[1000];
char *input = "46AB";
unsigned int value = strtol(input , NULL, 16);
sprintf(buf, "\\x%x", value);
fseek(f, 2, SEEK_SET);
fputs(buf, f);
In the file it produces
5C 78 34 36 61
while i need it look like
46 AB
Is there an elegant way of doing this?
Your sprintf call created the string
\x46ab
and you wrote those six characters to the file without further interpretation, so that's what you saw in the file (hex bytes 5c 78 34 36 61 62).
To get the hex-to-binary conversion you want, while avoiding byte order issues and anticipating the possibility of an arbitrary-length input string, you can do this one byte at a time with code like this:
char *p;
for(p = input; *p != '\0'; p += 2) {
unsigned int x;
if(sscanf(p, "%2x", &x) != 1) break;
putc(x, f);
}
This uses sscanf to convert the input string to hexadecimal, two characters (two hexadecimal digits, or one output byte) at a time.
I also tested it with a longer input string:
input = "0102034a4b4c";
This is quick-and-dirty, imperfect code. It will misbehave if input contains an odd number of characters, and it doesn't deal particularly gracefully with non-hexadecimal characters, either.
An improvement is to use the mildly obscure %n format specifier to scanf to discover exactly how many characters it consumed each time:
for(p = input; *p != '\0'; ) {
unsigned int x;
int n;
if(sscanf(p, "%2x%n", &x, &n) != 1) break;
putc(x, f);
p += n;
}
This should be more robust against malformed input strings, although I have not tested it exhaustively. (I hardly ever use functions in the scanf family, let alone the more obscure format specifiers like %n, but this is one of the few problems I know of where it's attractive, the alternatives being considerably more cumbersome.)
P.S. I got rid of your fseek call, because I wasn't sure what it was there for and it confused my testing. You can put it back in if you need it.

Reading the first line of a txt and converting it to int, but returning another value [C]

I've been trying to read a txt which has a specific structure:
The first line indicates the n-1 lines the whole txt file has.
All the other lines have the "structure" of a card (it's number and it's pattern).
ex: I have a txt which stores 13 cards, so the file in itself has 14 lines:
13
A T
2 P
3 D
13 P
2 P
4 C
8 D
11 T
8 C
9 C
10 T
9 T
7 P
(Note: T stands for clubs, D for diamonds, C for hearts and P for spades, it's in spanish).
I've tried extracting the first line to then create a dynamic array with the number given so that I can store each line in that array, but I fail to get the first value.
My code is:
#include <stdio.h>
#include <stdlib.h>
int leerLinea(){
char contenido[1];
FILE* pArchivo;
pArchivo = fopen("Mazo.txt","r");
if (pArchivo == NULL){
printf("No hay nada aqui!\n");
return 0;
}
else{
fgets(contenido,3,pArchivo);
printf("%s\n", contenido);
}
fclose(pArchivo);
return contenido[0];
}
int main(){
int a;
a = leerLinea();
printf("a's value is: %d\n",a);
return 0;
}
But when I run it I get:
13
a's value is: 49
Why is it returning other value, when it should be returning 13?
With fgets(contenido,3,pArchivo), you read in a string into a buffer that is to small for capturing at least 2 digits and the string termination character; For that statement, it should be at least char contenido[3].
The main issue is, however, that you mix strings with "pure" integral values, i.e. you read in a string but expect it to be converted correctly to a number simply by accessing the first digit of that string; Note that if contenido containded "13", contenido[0] would give character value '1', which in ASCII is 49.
To overcome this, read in the value as a number, i.e. using "%d"-format:
int leerLinea(){
int contenido = 0;
FILE* pArchivo;
pArchivo = fopen("Mazo.txt","r");
if (pArchivo == NULL){
printf("No hay nada aqui!\n");
return 0;
}
else{
fscanf(pArchivo,"%d",&contenido);
printf("%d\n", contenido);
}
fclose(pArchivo);
return contenido;
}
1 - Read a line of text with sufficient space for each character in the line, the line-feed and a null character. The below is 4 characters, so a buffer of 6 is needed.
13 P
Further, there is little gained by being so stingy with line buffers. Suggest 2x the maximize anticipated size to allow for some growth, leading/trailing whitespace.
#define LINE_MAX (4 + 1 + 1)
char contenido[LINE_MAX * 2];
2 - When reading a line, do not hard code in the 3, use sizeof() for consistent, easier to maintain code.
// fgets(contenido,3,pArchivo);
fgets(contenido, sizeof contenido, pArchivo);
3 - Rather than return the first character of a string (the code for the character '1' is 49), convert the string into an int/long with strtol() or atol(), etc. #Nicolas Guerin
// return contenido[0];
return atoi(contenido);
// or
return strtol(contenido, NULL, 10); // better
return atoi(contenido[0]);
The probleme you've got is that you return a char in an int function, every char as an integer value. That's true but not the decimal value of the char, the ascii value.
Atoi convert a char into an int.
ps: the way you do, it will only return 1 in the exemple

How do I read 0s and 1s from text input file and perform bit manipulation (shifting)

I have a text file input which has two columns with the first column having a binary number and the second column has the string width (which will be used when outputting data). I need to perform bit manipulation after reading the binary input.
I'm reading the input file using the below code and declared input as unsigned int.
while ((fscanf(fp,"%s %d", input, &count) != EOF))
After taking the input when I'm trying to perform bit manipulations I'm getting a "invalid operands to binary" error message. So I'm doing any declaration wrong or do I need to convert the binary to decimal to perform bit manipulations? I need to send output to a file as a bit sequence after manipulation.
It would be easier if you added an input file example, but you first need to get the input correct. I suggest you first try something like this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char input[80];
int count;
int bin;
fp = fopen("infile.txt", "r");
while ((fscanf(fp,"%s %d", input, &count) != EOF)) {
bin = strtol(input, NULL, 2);
printf("input: %s, count %d, bin %d\n", input, count, bin);
}
fclose(fp);
return 0;
}
on an input file named "infile.txt" looking something like this:
0011101 10
1001011 20
0101011 30
1001010 40
This would give following output:
input: 0011101, count 10, bin 29
input: 1001011, count 20, bin 75
input: 0101011, count 30, bin 43
input: 1001010, count 40, bin 74
So if I'm not on the right track, let me know!

C fread binary number and convert it to Ascii code

I'm trying to read the following binary (01100001) from a file and convert it to ascii code (97), but when using fread i'm getting a very big numbers.
the file "c:/input.txt" contain only the following line -01100001
printf of the array values print big numbers, such as 825241648
My code:
int main()
{
unsigned int arr[8];
int cnt,i,temp=0;
FILE * input;
if(!(input=fopen("C:/input.txt","r")))
{
fprintf(stderr,"cannot open file\n");
exit(0);
}
cnt = fread(arr,1,8,input);
for(i=0;i<cnt;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}
any idea why?
arr is an array of integers. But you read only 8 bytes into it. So your first integer will have some large value, and so will your second, but after that they will have garbage values. (You made arr an "automatic" variable, which is allocated on the stack, so it will have random garbage in it; if you made it a static variable it would be pre-initialized to zero bytes.)
If you change the declaration of arr so that it is of type char, you can read your string in, and your for loop will loop over those bytes one at a time.
Then you can write a string-to-binary translator, or alternatively you could use strtol() to do the conversion with the base set to 2. strtol() is not available in all compilers; GCC is fine but Microsoft C doesn't have it.
Pl. see if the code (Compiled using gcc on Linux) below works for this.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char arr[8];
int cnt,i,temp=0;
FILE * input;
if((input=fopen("data","r"))==NULL)
{
fprintf(stderr,"cannot open file\n");
exit(1);
}
//Read the 8 bytes in a character array of size 8
cnt = fread(arr,1,8,input);
for (i = 0; i < cnt; i++)
{
//Now change it to 0/1 form by substracting 48
arr[i] = arr[i] - '0';/* Ascii of 0 = 48*/
//Also Left shift..
arr[i] = arr[i] << (cnt - (i+1));
//Now Bit wise OR with the integer...
temp = temp | arr[i];
}
printf("The ascii value is %d and the character is %c\n", temp, temp);
return 0;
}
You first declare unsigned int arr[8]; which means 8 integers or more precisely 8*4=32 bytes. After that you read 8 bytes and then again try to output 8 integers. I suppose you want to read 8 bytes and output them as numbers? If you change type int to char, code might work. If file size is 32 bytes and contains integers, you may want to change fread() like this: fread(arr,sizeof(int),8,input);

Conversion from Byte to ASCII in C

Can anyone suggest means of converting a byte array to ASCII in C? Or converting byte array to hex and then to ASCII?
[04/02][Edited]: To rephrase it, I wish to convert bytes to hex and store the converted hex values in a data structure. How should go about it?
Regards,
darkie
Well, if you interpret an integer as a char in C, you'll get that ASCII character, as long as it's in range.
int i = 97;
char c = i;
printf("The character of %d is %c\n", i, c);
Prints:
The character of 97 is a
Note that no error checking is done - I assume 0 <= i < 128 (ASCII range).
Otherwise, an array of byte values can be directly interpreted as an ASCII string:
char bytes[] = {97, 98, 99, 100, 101, 0};
printf("The string: %s\n", bytes);
Prints:
The string: abcde
Note the last byte: 0, it's required to terminate the string properly. You can use bytes as any other C string, copy from it, append it to other strings, traverse it, print it, etc.
First of all you should take some more care on the formulation of your questions. It is hard to say what you really want to hear. I think you have some binary blob and want it in a human readable form, e.g. to dump it on the screen for debugging. (I know I'm probably misinterpreting you here).
You can use snprintf(buf, sizeof(buf), "%.2x", byte_array[i]) for example to convert a single byte in to the hexadecimal ASCII representation. Here is a function to dump a whole memory region on the screen:
void
hexdump(const void *data, int size)
{
const unsigned char *byte = data;
while (size > 0)
{
size--;
printf("%.2x ", *byte);
byte++;
}
}
Char.s and Int.s are stored in binary in C. And can generally be used in place of each other when working in the ASCII range.
int i = 0x61;
char x = i;
fprintf( stdout, "%c", x );
that should print 'a' to the screen.

Resources