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 */
}
Related
I recently got a STM8 MCU and it has the built in function LCD_GLASS_DisplayString("STRING")
The problem with that function is, as you can see below, that I cannot directly display an integer on it:
void LCD_GLASS_DisplayString(uint8_t* ptr)
{
uint8_t i = 0x01;
LCD_GLASS_Clear();
/* Send the string character by character on lCD */
while ((*ptr != 0) & (i < 8))
{
/* Display one character on LCD */
LCD_GLASS_WriteChar(ptr, FALSE, FALSE, i);
/* Point on the next character */
ptr++;
/* Increment the character counter */
i++;
}
}
How could I modify it so I could send integers directly? Also, I'm not sure I can use any libraries, so just pure C would help.
I was thinking of something like this, but it didn't work:
void LCD_GLASS_DisplayINT(uint16_t integer)
{
uint8_t i = 0x01;
LCD_GLASS_Clear();
/* Send the string character by character on lCD */
while ((integer != 0) & (i < 8))
{
/* Display one number on LCD */
LCD_GLASS_WriteChar("0" + integer%10, FALSE, FALSE, i);
/* Point on the next number*/
integer=integer/10;
/* Increment the character counter */
i++;
}
}
Any idea on how to make it work? I need to either make a function to display the integers or a way to convert them to strings before I send them over to the LCD. The code is pure C, as what I'm programming are pure drivers right now.
You're not far off with "0" + integer%10 - but you need to treat it as a character - '0' + integer%10 - and you need to pass LCD_GLASS_WriteChar a pointer to this character.
One way to do this is:
char* digits = "0123456789";
LCD_GLASS_WriteChar(&digits[integer % 10], FALSE, FALSE, i);
Also, your loop condition - while ((integer != 0) & (i < 8)) should not use bitwise and (&), but rather logical and (&&).
while ((integer != 0) && (i < 8))
You'll want to store the digits in a buffer to get the left-to-right order. On a microcontroller you'll probably want to allocate that buffer in .bss so that it doesn't take up stack. Use static to make that happen. For a 16 bit number you'll have at most 5 digits + null term, so:
static char buf[5+1] = {0};
The conversion is essentially the code you've written, except you mixed up '0' and "0":
for(uint8_t i=0; i<5; i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
}
Note that this code always leaves item buf[5] untouched and leaves a zero null terminator there.
Complete code with tests in standard C. Obviously drop puts for your custom LCD routine.
#include <stdio.h>
#include <stdint.h>
void display_int (uint16_t val)
{
static char buf[5+1] = {0};
char* p;
for(uint8_t i=0; i<5; i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
}
// trim leading zeroes
for(p=buf; *p!='\0'; p++)
{
if(*p!='0' || // stop looking at first non zero or
p[1]=='\0') // in case there is only one zero character
break;
}
puts(p); // use whatever string printing routine you got
}
int main (void)
{
display_int(0);
display_int(5);
display_int(666);
display_int(12345);
}
Division on STM8 is very expensive. We can optimize the code a bit by not filling up the whole buffer if we don't have to. This saves us several DIV calls. Optimized version, faster but harder to read:
void display_int (uint16_t val)
{
static char buf[5+1] = {0};
char* p;
char* start;
for(uint8_t i=0;;i++)
{
buf[5-i-1] = val%10 + '0';
val/=10;
if(val==0)
{
start = &buf[5-i-1];
break;
}
}
// trim leading zeroes
for(p=start; *p!='\0'; p++)
{
if(*p!='0' || // stop looking at first non zero or
p[1]=='\0') // in case there is only one zero character
break;
}
puts(p); // use whatever string printing routine you got
}
I am facing some problems with the output of the following program. The program randomly generate words, first a random consonant then a random vowel, and then the same again for the maximum number of letters you want.
When I print the word generated right after it is generated it gives me a list of words, as intended. When I am out of the word generating and stacking loop, and print an output of the words again, I get all the words mashed up in one long chain, it is really bizarre. What is wrong?
#include <stdio.h>
#define MAXWORDS 10
#define MAXLETTERS 6
int lcg(int Xcur) /*linear congruential generator*/
{
int A = 445, C = 700001, M = 2097152;
int Xnext = (A * Xcur + C) % M;
return Xnext;
}
int main()
{
int x;
printf("input seed for linear congruential generator: ");
scanf("%d",&x);
char consonants[]="bcdfghjklmnprstvwxz";
char vowels[]="aeiou";
int i,j;
int turn;
char words[MAXWORDS][MAXLETTERS];
for(i=0;i<MAXWORDS;i++)
{
turn=1;
for(j=0;j<MAXLETTERS;j++,turn++)
{
x=lcg(x); /* random number generated */
if(turn%2) /* one consonant, one vowel, in turn */
words[i][j]=consonants[x%19];
else
words[i][j]=vowels[x%5];
}
words[i][j]='\0';
/* print each word generated */
printf("word %d: %s\n", i+1, words[i]);
}
/* print the first word again */
printf("\n\nthe 1st word again: %s\n",words[0]);
return 0;
}
output:
input seed for linear congruential generator: 23
word 1: wuduca
word 2: navozo
word 3: depiza
word 4: jukiti
word 5: raliwi
word 6: danila
word 7: cexewi
word 8: bamohu
word 9: jiruzi
word 10: temomo
the 1st word again: wuducanavozodepizajukitiraliwidanilacexewibamohujiruzitemomo
It is because is is getting stored in continuous manner without any null char.
Method 1:
If you just want to print it properly you can do it by writing below line:
printf("\n\nthe 1st word again: %s\n",words[0]);
as
printf("\n\nthe 1st word again: %.*s\n",MAXLETTERS, words[0]);
Method 2:
Declare words as
char words[MAXWORDS][MAXLETTERS+1];
and write the inside for loop as
for(j=0;j<MAXLETTERS;j++,turn++)
{
x=lcg(x); /* random number generated */
if(turn%2) /* one consonant, one vowel, in turn */
words[i][j]=consonants[x%19];
else
words[i][j]=vowels[x%5];
}
words[i][MAXLETTERS] = '\0';
There is no room in the array for the string terminator. Consequently writing the '\0' terminator is undefined behaviour. In practice (since a 2D array is contiguous), the terminator was written to the next string, which was then overwritten by its data.
Try changing
char words[MAXWORDS][MAXLETTERS];
to
char words[MAXWORDS][MAXLETTERS+1];
Also,
Watch out for int overflow.
Code does not insure 0 <= Xcur <= (INT_MAX - C)/A, so A * Xcur + C results can then exceed INT_MAX...
int A = 445, C = 700001, M = 2097152;
int Xnext = (A * Xcur + C) % M;
... resulting in UB: likely negative values can then return from the function.
x=lcg(x);
words[i][j]=consonants[x%19];
x%19 results then in -18 ... 18 leading to bad indexing.
Simple fix, yet does not address the root of the issue.
//Use %19u so the result is never < 0, unlike %19
words[i][j]=consonants[x%19u];
I would also use unsigned math to avoid UB of overflow and not generate negative results.
int lcg(int Xcur) /*linear congruential generator*/
{
unsigned A = 445, C = 700001, M = 2097152;
int Xnext = (A * Xcur + C) % M;
return Xnext;
}
Code also has issue with 16-bit int.
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.
I'm struggling with this programming assignment I have for one of my classes here. I'm an electrical engineering student so my programming is by no means amazing. I'm told to write a c program that takes a 12-bit number and extracts each of that 12 bit number's digits into a char array. I did the quick math and realized that the largest number we can obtain is 0xFFF or 4095 in decimal. I found an algorithm that I thought would work quite well but for some reason, my code isn't doing what I thought. I am continuing to try and troubleshoot this, but with my only way to run it being linux terminal window, I don't have a great debugging utility to step through the program. Any help would be greatly appreciated. Feel free to ask some questions as well and I'll do my best to field them. I am not a fluent programmer so bear that in mind. Also, if someone could explain integer division to me that would be helpful. I was under the assumption that something like 8/10 would return a result of 0 but I don't know that it's working that way when I run the program. Thank you.
I CANNOT USE FUNCTIONS TO DO THIS AND MUST DO IT MANUALLY.
Here is what I have thus far.
Attempt # Solution:
//12 bit value into string of decimal chars
//EX: 129 -> a '1' a '2' and a '9'
void main (void) {
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
//Initialize an array with 5 spaces, each space
//holds one character (accounts for largest number 4095)
char OUT[5];
uint8_t length = sizeof(char);
//Isolating each int value happens here
//initialize i to act as a counter to loop through array
uint8_t i=2;
//Initialize an input value to test the code;
uint16_t IN=549;
while (IN/10 > 0)
{
OUT[length-(i+1)] = '0' + (IN%10);
IN=IN/10;
if (IN <= 10)
{
if (IN = 10)
{
OUT[length-(i+1)] ='1';
//fixes infinite loop issue
IN=0;
}
else
{
OUT[length-(i+1)] ='0' + IN;
//fixes infinite loop issue
IN=0;
}
}
//Increment Counter to keep track of char array
i++;
}
//add the new line at the end of the array of chars
OUT[length-1]='\n';
printf("String is -> %s", OUT);
}
Couple of notes:
Using IN%10 is part of the algorithm that isolates the furthest right digit in decimal. I had to add some "fudge factors" to my counter to get the array to line up properly and account for the \n at the end of my char array. The conditional statements that I put inside my while loop were to catch some edge cases (mainly when IN became 10 or less).
It looks like you are bending over backwards to handle the fact that you have to print the leftmost character first. The logic is much simpler if you just generate the rightmost character first and then reverse it.
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
//12 bit value into string of decimal chars
//EX: 129 -> a '1' a '2' and a '9'
void main (void) {
char OUT[5];
memset(OUT, 0, 5);
int i=0;
int j;
uint16_t IN=549;
// Generate the string in reverse order.
while (IN != 0)
{
OUT[i++] = '0' + (IN%10);
IN/=10;
}
// Reverse the string
for (j = 0; j < i/2; j++) {
char temp = OUT[j];
OUT[j] = OUT[i-1-j];
OUT[i-1-j] = temp;
}
printf("String is -> %s\n", OUT);
}
This line is your problem:
uint8_t length = sizeof(char);
The sizeof function returns the size of the type between parentheses. In this case it returns 1, because a char is a 1 byte variable. Then when you try to access the elements of the array you get a negative number from length-(i+1).
Here is my final solution using the more complex way in case anyone is curious/stumbles into the problem later on.
void main (void) {
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
//Initialize an array with 5 spaces, each space holds one character (accounts for largest number 4095)
char OUT[5];
OUT[0] = '0';
OUT[1] = '0';
OUT[2] = '0';
OUT[3] = '0';
OUT[4] = '0';
uint8_t length =5; //sizeof(char) was giving me an error and thus not used.;
//Isolating each int value happens here
//initialize i to act as a counter to loop through array
uint8_t i=2;
//Initialize an input value to test the code;
uint16_t IN=4012;
//Initialize variable for % operator value
uint16_t mod=0;
while (IN/10 > 0)
{
mod=IN%10;
OUT[length-i] = '0' + mod;
IN=IN/10;
if (IN <= 10)
{
if (IN == 10)
{
OUT[length-(i+2)] ='1';
OUT[length-(i+1)] ='0';
//fixes infinite loop issue
IN=0;
}
else
{
OUT[length-(i+1)] ='0' + IN;
//fixes infinite loop issue
IN=0;
}
}
//Increment Counter to keep track of char array
i++;
}
//add the new line at the end of the array of chars
OUT[length-1]='\n';
printf("String is -> %s", OUT);
}
I am trying to convert a character to its binary representation (so character --> ascii hex --> binary).
I know to do that I need to shift and AND. However, my code is not working for some reason.
Here is what I have. *temp points to an index in a C string.
char c;
int j;
for (j = i-1; j >= ptrPos; j--) {
char x = *temp;
c = (x >> i) & 1;
printf("%d\n", c);
temp--;
}
We show up two functions that prints a SINGLE character to binary.
void printbinchar(char character)
{
char output[9];
itoa(character, output, 2);
printf("%s\n", output);
}
printbinchar(10) will write into the console
1010
itoa is a library function that converts a single integer value to a string with the specified base.
For example... itoa(1341, output, 10) will write in output string "1341".
And of course itoa(9, output, 2) will write in the output string "1001".
The next function will print into the standard output the full binary representation of a character, that is, it will print all 8 bits, also if the higher bits are zero.
void printbincharpad(char c)
{
for (int i = 7; i >= 0; --i)
{
putchar( (c & (1 << i)) ? '1' : '0' );
}
putchar('\n');
}
printbincharpad(10) will write into the console
00001010
Now i present a function that prints out an entire string (without last null character).
void printstringasbinary(char* s)
{
// A small 9 characters buffer we use to perform the conversion
char output[9];
// Until the first character pointed by s is not a null character
// that indicates end of string...
while (*s)
{
// Convert the first character of the string to binary using itoa.
// Characters in c are just 8 bit integers, at least, in noawdays computers.
itoa(*s, output, 2);
// print out our string and let's write a new line.
puts(output);
// we advance our string by one character,
// If our original string was "ABC" now we are pointing at "BC".
++s;
}
}
Consider however that itoa don't adds padding zeroes, so printstringasbinary("AB1") will print something like:
1000001
1000010
110001
unsigned char c;
for( int i = 7; i >= 0; i-- ) {
printf( "%d", ( c >> i ) & 1 ? 1 : 0 );
}
printf("\n");
Explanation:
With every iteration, the most significant bit is being read from the byte by shifting it and binary comparing with 1.
For example, let's assume that input value is 128, what binary translates to 1000 0000.
Shifting it by 7 will give 0000 0001, so it concludes that the most significant bit was 1. 0000 0001 & 1 = 1. That's the first bit to print in the console. Next iterations will result in 0 ... 0.
Your code is very vague and not understandable, but I can provide you with an alternative.
First of all, if you want temp to go through the whole string, you can do something like this:
char *temp;
for (temp = your_string; *temp; ++temp)
/* do something with *temp */
The term *temp as the for condition simply checks whether you have reached the end of the string or not. If you have, *temp will be '\0' (NUL) and the for ends.
Now, inside the for, you want to find the bits that compose *temp. Let's say we print the bits:
for (as above)
{
int bit_index;
for (bit_index = 7; bit_index >= 0; --bit_index)
{
int bit = *temp >> bit_index & 1;
printf("%d", bit);
}
printf("\n");
}
To make it a bit more generic, that is to convert any type to bits, you can change the bit_index = 7 to bit_index = sizeof(*temp)*8-1