Numerical operations between int and char in C - c

I would like to know how are data really stored, because in example beyond is intuition weak.
I believed, that any value has it's numerical recognition; as 'a' has value of 48; so I assumed, that in any situation I can decrement 48 as 'a' (eg. (100 - 'a' == 52)).
Reality seems to be different.
So;
when can I decrement with 'a' to get int-like value?
what should I use here, so it would looks like more intuitively?
...
program is barely finished, however function takes array of chars and it needs to get int of value (3) from one of chars. /* for this scenario */
Thank you for help!
/* command reader */
int cr (char a[])
{
printf("%s\n", a);
/* command sequence */
char co[350]; /* <-- change later */
for (int cri = 0, coi = 0; a[cri]; cri++, coi++)
{
printf("%c ", a[cri]);
co[coi] = a[cri];
}
int ec (char co[])
{
printf("\n%s co\n", co);
printf("\n%c co1\n", co[1]);
co[1] = co[1];
printf("\n basic: %d\n\n", co[1]); /* 51 */
co[2] = co[1] - 'a';
printf("\n charred out: %d\n\n", co[2]); /* -46 */
co[3] = co[1] - 48;
printf("\n numbered out: %d\n\n", co[3]); /* 3 */
return 0;
}
ec(co);
return 0;
}
cr("F3 R B");

The "value" of 'a', that is its numerical representation, actually depends on the character set. In most cases that is the American Standard Code for Information Interchange (ASCII) or a character set where the first 128 codepoints are identical to ASCII. However, the ASCII value for 'a' is actually 97 and not 48.

As WhozCraig said, I was looking for (- "0"), where numeric value of "0" is 48.

Related

what's meant by converting an ASCII character to alphabetical index and how can i do that?

in Caesar (CS50) it says that i need to convert an ASCII character to alphabetical index in one of the steps. what does that mean? i saw a video that said that i "need to find the relationship between a number's ASCII value and its actual index in the alphabet", but i haven't really understood how I might implement this* and *what exactly is the relationship.
please elaborate in your answer because I'm new to this.
string plaintext = get_string("plaintext;");
As you may or may not know ASCII characters are encoded as 8-bit values and character constants, in reallity, have int type in C.
Using this knowledge you can perform character arithmetic as if they are regular numbers, take the following example:
printf("%d\n", 'a');
This prints 'a''s int value which is 97.
Now this:
printf("%d\n", 'g' - 'a');
This will print 6 which is the result of 103 - 97.
Now your string:
const char* plaintext = "plaintext";
for(size_t i = 0; i < strlen(plaintext); i++){
printf("%c - %d\n",plaintext[i], plaintext[i] - 'a' + 1);
}
The result:
p - 16
l - 12
a - 1
i - 9
n - 14
t - 20
e - 5
x - 24
t - 20
As you can see the printed results are the indexes of the letters in the alphabet 1...26, I added 1 to the result because, as you know, in C indexing starts at 0 and you would have 0...25.
So the bottom line is that you can use this character arithmetic to find the indexes of characters, this also aplies to caps, but you can't mix both.
Note that there are other character encodings that do not allow for this kind of arithmetic because the alphabetic characters are not in sequencial order, like, for example, EBCDIC.
It means that a single char variable is nothing but an integer containing an ASCII code, such as 65 for 'A'. It might be more convenient for an algorithm to work with the interval 0 to 25 than 65 to 90.
Generally, if you know that a char is an upper-case letter, you can do a naive conversion to alphabetical index by subtracting the letter 'A' from it. Naive, because strictly speaking the letters in the symbol (ASCII) table need not be located adjacently. For a beginner-level program, it should be ok though:
char str[] = "ABC";
for(int i=0; i<3; i++)
printf("%d ", str[i] - 'A'); // prints 0 1 2
Wheras a 100% portable converter function might look something like this:
int ascii_to_int (char ch)
{
const char LOOKUP_TABLE [128] =
{
['A'] = 0,
['B'] = 1,
...
};
return LOOKUP_TABLE[ch];
}
Here you have an example. It is portable as it does not depend if the char encoding.
const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ";
int getIndex(const char *alphabet, int c)
{
int result = -1;
const char *res;
res = strchr(alphabet, c);
if(res)
{
result = res - alphabet;
}
return result;
}
int main(void)
{
char *str = "Hello World!!!";
while(*str)
{
printf("Index of %c is %d\n", *str, getIndex(alphabet, *str));
str++;
}
}
https://godbolt.org/z/rw2PK9

Convert ASCII string array into its hex value array

I have a char array which contains ASCII characters. I need to know how to get the hex value of each character and save it in a uint8_t array.
E.g. if I have
array[5] = "ABCDE"
The output should be
output[5] = {0x41, 0x42, 0x43, 0x44, 0x45}
I tried using strtol but didn't work.
for(unsigned i = 0; i < 32; i++) {
message[i] = (uint8_t)strtol(&incoming_message[i], NULL, 16);
}
Output:
A 0 0 0 0 0 0 0 0 0 F 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Update: This is for a program I'm writing for a Cortex-M0+ processor. I'm not just viewing incoming data, I'm processing this data in the next step. Therefore, no use of printf
First of all, strtol like all other string functions expects a null-terminated byte string, not single characters.
Secondly, the characters encoded value is the actual value of the elements in your string. If you print the decimal value 65 (for example) using the correct format specifier, then the character A will be printed:
printf("%c\n", 65); // Will print an A
Similarly, printing the character 'A' as a decimal integer will print the value 65:
printf("%d\n", 'A'); // Will print the value 65
So all you need to do is to print the values in your array in the correct format.
Furthermore... All values on computers the last few decades are stored in binary. All of them.
Decimal, octal or hexadecimal are just how you present the values. Storing 0x41, 61, 0101 or 0b01000001 (for compilers with binary notation extension) doesn't matter since in the end it will be the binary value that is stored. If you want to show a value as hexadecimal to a user through some output, you have to format the binary value as such when printing or writing it.
Talking C a char is the smallest integer value available.
Talking C and ASCII a character literal (like 'A') is just another representation of an int value (65 here).
Talking Math there are other ways to represent the very same value, aside the decimal way (using base 10). One common is using the base of 16, the hexadecimal way.
Putting the above together it proves that:
int i = 'A';
char c = i;
is the same as:
int i = 65;
char c = i;
and the same as:
int i = 0x41;
char c = i;
and the same as:
char c = 'A';
and the same as:
char c = 65;
and the same as:
char c = 0x41;
So
char a[5] = "ABCDE";
in fact already is an integer array of five (small) integers.
If printed using the correct conversion specifier and length modifier you see what you are after.
for (size_t i = 0; i < 5; ++i)
{
printf("%hhx ", a[i]);
}
Output:
41 42 43 44 45
To indicate to the reader this should be taken as hexadecimal values one could prefix the value using the common 0x notation
printf("0x%hhx ", a[i]);
which gave you
0x41 0x42 0x43 0x44 0x45
If you would show this to Pascal guys you perhaps would use
printf("$%hhx ", a[i]);
which gave you
$41 $42 $43 $44 $45
To see the characters themselves just us:
printf("%c ", a[i]);
and get
A B C D E
To see the decimal values use
printf("%d ", a[i]);
and get
65 66 67 68 69
The conclusion is, that it's all just matter of how you represent ("print") the same values (the content of a's elements) . The "conversion" happens when creating the representation of a very same value (via printing and passing the right "instructions"), that is during output only.
As you refer to ASCII only, this implies all value are <128, so you can just plain copy the array's values using either a loop
char src[5] = "ABCDE";
uint8_t dst[5];
for (size_t i = 0 i < 5; ++i)
{
dst[i] = src[i];
}
or by copying the related memory block at once
memcpy(dst, src, 5);
you can convert the value to hexadecimal using the basic algorithm i.e division by 16.
I have created the following function where you can pass the string to be converted and a an array of strings where you will get the response.
void hexCon(char str[],char result[][5]){
int i,check,rem = 0;
char res[20],res2[20];
int len = 0;
char temp;
for(i=0; i < strlen(str) ; i++){
len=0;
check = str[i];
while(check > 0){
rem = check%16;
switch(rem){
case 10:temp='A';break;
case 11:temp='B';break;
case 12:temp='C';break;
case 13:temp='D';break;
case 14:temp='E';break;
case 15:temp='F';break;
default:temp=rem + '0';
}
res[len] = temp;
check = check /16;
len++;
}
reverse(res,len,res2); //reversing the digits
res2[len] = '\0'; //adding null character at the end of string
strcpy(result[i],res2); //copying all data to result array
}
}
where reverse function is :
void reverse(char str[], int size, char rev[])
{
int i=0,j=0;
for(i=size-1 , j=0 ; i >= 0; i-- , j++ ){
rev[j] = str[i];
}
}
you can call it like :
void main(){
char str[]="ABCDE";
char result[strlen(str)][5];
int i;
hexCon(str,result);
for(i =0 ;i < strlen(str); i++){
printf("%s\n",result[i]);
}
}
the algorithm used is explained here :-
https://www.permadi.com/tutorial/numDecToHex/
Hope this helps :)

Getting a value from a char array

I have written a function below to take a char array and manipulate its values (namely, convert the char to an int if it is a number). However, I have a question with how the char array is managed. When I look at input[i], it is the correct value (the value that was placed in the array. However, &input[i] gives a capital letter, and I don't know why it does that. For example, if I enter "11" and trace the variables, I might get the following result:
input[0] is 1
&input[0] is D
input[1] is 1
&input[1] is E
On to my code, if I try to use input[i], I get the error of "passing argument makes pointer from integer without cast". If I use &input[i], the code compiles but I get the wrong result. What's going on with this, and how do I access the value I'm trying to get?
Below is my code:
void myFunction(char *input) {
Queue* numberQueue = queue_new();
Queue* opQueue = queue_new();
int i = 0;
int j;
for (j = 0; j < strlen(input); j++) {
printf("input[%d] is %c\n", i, input[i]);
printf("&input[%d] is %c\n", i, &input[i]);
int number = (int)input[i];
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR */
/* rest of code omitted */
i++;
}
}
If I understand that you want to push each digit in the input character string into queue_push_tail, as an integer value then you want your loop to do something like this:
for (j = 0; j < strlen(input); j++) {
if ( input[j] >= '0' && input[j] <= '9')
{
number = input[j] - '0';
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR - FIXED*/
/* rest of code omitted */
}
}
Recall, ASCII characters are themselves unsigned integers. You simply need to adjust the value for each character by subtracting the value of ASCII '0'. If you need to collect all numbers from the string into a single number (e.g. ac7f9gh3 => 793) then simply store the values unadjusted in a temp string, and then call atoi (temp).

Array manipulation in C

I am like 3 weeks new at writing c code, so I am a newbie just trying some examples from a Harvard course video hosted online. I am trying to write some code that will encrypt a file based on the keyword.
The point is each letter of the alphabet will be assigned a numerical value from 0 to 25, so 'A' and 'a' will be 0, and likewise 'z' and 'Z' will be 25. If the keyword is 'abc' for example, I need to be able to convert it to its numerical form which is '012'. The approach I am trying to take (having learned nothing yet about many c functions) is to assign the alphabet list in an array. I think in the lecture he hinted at a multidimensional array but not sure how to implement that. The problem is, if the alphabet is stored as an array then the letters will be the actual values of the array and I'd need to know how to search an array based on the value, which I don't know how to do (so far I've just been returning values based on the index). I'd like some pseudo code help so I can figure this out. Thanks
In C, a char is an 8-bit integer, so, assuming your letters are in order, you can actually use the char value to get the index by using the first letter (a) as an offset:
char offset = 'a';
char value = 'b';
int index = value - offset; /* index = 1 */
This is hard to answer, not knowing what you've learned so far, but here's a hint to what I would do: the chars representing letters are bytes representing their ASCII values, and occur sequentially, from a to z and A to Z though they don't start at zero. You can cast them to ints and get the ascii values out.
Here's the pseudo code for how I'd write it:
Cast the character to a number
IF it's between the ascii values of A and Z, subtract it from A
ELSE Subtract it from the ASCII value of a or A
Output the result.
For what it's worth, I don't see an obvious solution to the problem that involves multidimensional arrays.
char '0' is the value 48
char 'A' is the value 65
char 'a' is the value 97
You said you want to learn how to search in the array:
char foo[26]; //your character array
...
...
//here is initialization of the array
for(int biz=0;biz<26;biz++)
{
foo[biz]=65+biz; // capital alphabet
}
...
...
//here is searching 1 by 1 iteration(low-yield)
char baz=67; //means we will find 'C'
for(int bar=0;bar<26;bar++)
{
if(foo[bar]==baz) {printf("we found C at the index: %i ",bar);break;}
}
//since this is a soted-array, you can use more-yield search algortihms.
Binary search algortihm(you may use on later chapters):
http://en.wikipedia.org/wiki/Binary_search_algorithm
The use of a multidimensional array is to store both the lower case and upper case alphabets in an array so that they can be mapped. An efficient way is using their ASCII code, but since you are a beginner, I guess this example will introduce you to handle for loops and multidimensional arrays, which I think is the plan of the instructor as well.
Let us first set up the array for the alphabets. We will have two rows with 26 alphabets in each row:
alphabetsEnglish[26][2] = {{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'},
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}};
Now we can map elements of both cases.
int main()
{
int c,i,j;
char word[10];
printf("Enter a word:");
scanf("%s",word);
c=strlen(word);
printf("Your word has %d letters ", c);
for (i = 0; i < c; i++) //loop for the length of your word
{
for (j = 0; j <= 25; j++) //second loop to go through your alphabet list
{
if (word[i] == alphabetsEnglish[0][j] || word[i] == alphabetsEnglish[1][j]) //check for both cases of your alphabet
{
printf("Your alphabet %c translates to %d: ", word[i], j);
}
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *conv(char* str){
static const char* table = "abcdefghijklmnopqrstuvwxyz";
int size, *ret, *p;
if(NULL==str || *str == '\0') return NULL;
size = strlen(str);
ret=p=(int*)malloc(size*sizeof(int));
while(*str){
char *pos;
pos=strchr(table, tolower(*str++));
*p++ = pos == NULL ? -1 : pos - table;
}
return ret;
}
int main(void){
char *word = "abc";
int i, size = strlen(word), *result;
result = conv(word);
for(i=0;i<size;++i){
printf("%d ", result[i]);//0 1 2
}
free(result);
return 0;
}

How does one convert ASCII to binary?

I have the following string:
char * strIn = "f2";
When I look at strIn[0] I would like to get 1111 instead of 'f'.
How do i do it?
Thanks
You mean a hex string to binary conversion?
strtol with a base of 16 should do the trick
...Someone said earlier
and f in binary would be 11001100
All I can say is wow... no, F in binary equals 1111 (15 decimal)
If I understood your question correctly, you want to get the binary value for any ascii character... ie.
When I look at strIn[0] I would like
to get 1111 instead of 'f'.
So... here is a little function that will do that...
int ConvertHexAsciiValue(char c)
{
if(isalpha(c))
{
char r = tolower(c);
if(r > 'f')
{
// - Handle error here - character is not base 16
return 0;
}
int nIndex = (int)('a' - r);
nIndex = -nIndex;
nIndex += 10;
return nIndex;
}
else if(isdigit(c))
{
int nIndex = c - '0';
return nIndex;
}
// Handle error here - character is not A-F or 0-9
return 0;
}
If I didn't understand you correctly, you should know that you cannot read a string "1111" for a character strIn[0]. You can however, get a binary value for each character (interpreted as a hexidecimal value) using the function I provided...
for(int x = 0; x < strlen(strIn); x++)
{
int val = ConvertHexAsciiValue(strIn[x]);
printf("Value %d: %d\n", x, val);
}
If strIn were set to "f2", this code would produce the following output on the console
Value 0: 15
Value 1: 2
To get the binary code one must take the decimal number in question, take it and divide it by two repeatedly, save the remainder (which will become the binary number), save the whole number, divide by two, and repeat the whole process until 0 is reached.
Heres a small application I had in my collection that converts a string into binary.
/********************************************************/
/* Binary converter */
/* By Matt Fowler */
/* philosopher150#yahoo.com */
/* converts text into binary using the division method */
/* through ASCII code */
/*compiled with the Dev-C++ compiler (www.bloodshed.net)*/
/********************************************************/
#include <iostream>
using namespace std;
#include <cstring>
#include <cstdlib>
char *entry, letter, choice[2];
int ascii, len, binary[8], total;
void prog();
int main()
{
prog();
return 0;
}
void prog()
{
entry = new char[501];
/* entry should be dynamic, otherwise a new string entry of 501 chars would be created each time function is called! Talk about memory hog! */
cout<<"Enter string to convert (up to 500 chars): ";
cin.getline(entry, 500);
len = strlen(entry); /* get the number of characters in entry. */
/* this loop is executed for each letter in the string. */
for(int i = 0; i<len; i++)
{
total = 0;
letter = entry[i]; /* store the first letter */
ascii = letter; /* put that letter into an int, so we can see its ASCII number */
while(ascii>0) /* This while loop converts the ASCII # into binary, stores it backwards into the binary array. */
{
/* To get the binary code one must take the decimal number in
question, take it and divide it by two repeatedly, save
the remainder (which will become the binary number), save
the whole number, divide by two, and repeat the whole
process until 0 is reached. This if-else statement serves
this functionality, by getting the remainder of the ascii
code, storing it in the array and then dividing the int
ascii by two */
if((ascii%2)==0)
{
binary[total] = 0;
ascii = ascii/2;
total++; /* increasing by one each time will yeild the
number of numbers in the array. */
}
else
{
binary[total] = 1;
ascii = ascii/2;
total++;
}
}
total--; /* due to data type factors, the program will actually
add a 0 at the end of the array that is not supposed
to be there, decrementing total will solve this
problem, as that 0 will not be displayed. */
/* this while loop displays the binary code for that letter. */
while(total>=0)
{
cout<<binary[total];
total--;
}
}
delete[] entry; /* free up the memory used by entry */
cout<<endl<<"Do again(1 = yes, 2= no)?: ";
cin.getline(choice,3);
if(choice[0] == '1')
prog(); /* program is recursive, it calls itself. It's kinda
like a function loop of sorts. */
else
exit(0); /* quits the program */
}

Resources