I need to scan the 32 hex number from command line and populated it into a uint8_t [16] array, I tried scanning the string and convert it to hex but its really a hassle since i cant find a function that does that, whats the best way to do this?
uint8_t get_int(char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
return -1;
}
int main(void)
{
char buff[33];
size_t size;
size_t i;
uint8_t *output;
fgets(buff, sizeof buff, stdin);
size = strlen(buff) / 2;
output = malloc(size);
for (i= 0; i < size; ++i)
output[i] = get_int(buff[2*i]) * 16 + get_int(buff[2*i+1]);
for (i= 0; i < size; ++i)
printf("%u ", output[i]);
return 0;
}
ideone link
Related
My professor gave me some exercises in C language... In one of them I have to pass a string as an argument to a function, this function will verify the existence of lower case letters in the array and convert it into upper case letter;
Actually there's a function to do such a thing, but I can't use string.h.
Does anyone have an idea to do it?
void converterup(char palavra[])
{
int i;
for(i = 0; i < 10; i++)
{
if(palavra[i] != 'a')
{
palavra[i] == 'A';
}
}
Would be something like this?
you need to include <ctype.h> before using function toupper, then use it like in example below (I edited your code, need to adjust it for your needs):
for(i = 0; i < 10; i++){
palavra[i] = toupper(palavra[i]);
}
this loop will convert 10 first characters to their upper ascii equivalents
or if you cannot use standard functions, you can use function like this:
char myUpperChar(char x){
const int delta = 'a' - 'A'; //'a' has ascii code 97 while 'A' has code 65
if(x <= 'z' && x >= 'a'){
x -= delta;
}
return x;
}
If a character is between 'a' and 'z', you could just add ('A' - 'a') to it to convert it to upper.
char input, output;
int diff = 'A' - 'a';
output = input;
if ('a' <= input && input <= 'z')
output += diff;
return output;
I guess your professor is expecting something more basic without external functions, like this.
char str[] = "hello";
int len = sizeof(str) / sizeof(char);
int i;
for(i = 0; i < len; i++) {
int ascii = str[i];
if(ascii >= 97 && ascii <= 122) {// 97 => 'a' and 122 => 'z' in ascii
str[i] = (char) (ascii - 32); // 32 is the ascii substraction of lower
} // and upper letters 'a' - 'A'
}
Then output would be:
HELLO
function will verify the existence of lower case letters in the
array and convert it into upper case letter;
I can't use string.h.
Then you have to do conversion yourself. Take a look at the ASCII chart.
Then you can notice that small and capital letters are 0x40 apart.
0x40 happens to be space ' ';
Loop through your array and convert only the small letters
arr[i] <= 'z' && arr[i] >= 'a'
remember that small and capital letters are ' ' apart.
arr[i] = arr[i] - ' ' ;
advance to next character in the array by increasing the index i++ and stop when you encounter the end of the string arr[i]=='\0'.
#include <stdio.h>
void converterup(char arr[])
{
size_t i = 0;
if(arr == NULL) return;
while(arr[i]) // loop till the '\0'; this is equivalent to `arr[i]!='\0'`
{
if(arr[i] <= 'z' && arr[i] >= 'a'){
arr[i] = arr[i] - ' ' ;
}
i++;
}
}
int main(void)
{
char str[] = "Hello World!";
converterup(str);
printf("%s",str);
return 0;
}
Test:
HELLO WORLD!
Check out my code guys, is it acceptable?
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
void strupr(char palavra[])
{
int i;
for(i = 0;palavra[i] > 60 && palavra[i] < 122; i++)
{
printf("%c", palavra[i] - 32);
}
}
int main(void)
{
setlocale(LC_ALL, "");
char palavra[10];
printf("Insira uma palavra maiúsculas: "); gets(palavra);
printf("Valor com conversão: ");
strupr(palavra);
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Pseudocode explanation of what I am attempting to do.
Convert a character array into an integer array
Iterate through each integer in that array and add q to it, unless that integer + q exceeds an upper bound. If it exceeds that number, return the modulus and add the modulus to a lower bound.
print the converted integer array in its ASCII sequence using %c.
Here is the example:
int main(void)
{
char char_message[] = "abcyzABCYZ";
int q = 10;
int i;
int message[10];
int n = strlen(char_message);
for(i = 0; i < n; i++) {
message[i] = atoi(&char_message[i]);
}
for(i = 0; i < n; i++) {
if(message[i] <= 90) {
if (message[i] + q <= 90) {
message[i] = message[i] + q;
}
else
message[i] = 65 + (message[i] % 90);
}
else if(message[i] >= 97) {
if (message[i] + q <= 122) {
message[i] = message[i] + q;
}
else
message[i] = 97 + (message[i] % 122);
}
}
for(i = 0; i < n; i++) {
printf("%c", message[i]);
}
return 0;
}
EDIT: Below is a second attempt at this problem --------------------------
int main(int argc, char *argv[]) {
if(argc != 3) {
printf("Enter an integer followed by a string \n\n");
return 1;
}
int i;
int offset = atoi(argv[1]);
char **p_message;
p_message = &argv[2];
char encrypt[strlen(*p_message)];
printf("You Entered: %d, %s \n", offset, *p_message);
for(i = 0; i < strlen(*p_message); i++)
{
encrypt[i] = ((*p_message[i] + offset) % 26);
}
for(i = 0; i < strlen(*p_message); i++)
{
printf("%c", encrypt[i]);
}
return 0;
}
I'm not doing your homework for you, but it is obvious that two things are clearly wrong.
Your use of atoi is incorrect. It should not be here at all.
Your calculation of the resulting enciphered character is wrong as well. The modulus placement is wrong in two different locations.
Your use of "magic numbers" in this code is rampant making it much, much more difficult to read than need-be. Avoid using magic numbers.
The following "enciphers" your test string via a simple forward scanning loop, output each resulting character one at a time. I've left the storage to a separate int array for you to handle. Of note the first if-block is expanded out statement by statement so you can see what is going on one step at a time. The second (lower case handling) is done in a single expression. Other than different ranges, the two methods of calculation are equivalent.
Note: this only works on platforms where character ranges A..Z and a..z are continuous. The language standard makes no enforcement of this; it only enforces it for digit characters 0..9. Thus, don't blame me if you run this on an AS/400 or OS/390 (both EBCDIC platforms) and it doesn't work.
#include <stdio.h>
#include <string.h>
int main()
{
char message[] = "abcyzABCYZ";
const int q = 10;
puts(message);
for(const char *p = message; *p; ++p)
{
int c = (unsigned char)*p;
if (c >= 'A' && c <= 'Z')
{
c -= 'A';
c += q;
c %= ('Z' - 'A' + 1);
c += 'A';
}
else if (c >= 'a' && c <= 'z')
c = ((c - ('a' - q)) % ('z' - 'a' + 1)) + 'a';
// else nothing. keep as-is
fputc(c, stdout);
}
fputc('\n', stdout);
return 0;
}
Output
abcyzABCYZ
klmijKLMIJ
Hi this is my first question here so I apologize if I didn't follow all the rules for posting. This is K&R exercise 2-3 and I'm getting a segmentation fault when compiling with GCC and I'm not familiar with the debugger to understand what's going on. I'd be grateful if anyone could glance over the code and help me with what went wrong.
#include <stdio.h>
#define HEX 16
unsigned int htoi(char s[]) {
int i, len, n, rp, v;
v = 0;
if (s[0] == '0')
if (s[1] == 'x' || s[1] == 'X')
s[1] = '0';
for (len = 0; len != '\0'; ++len) {
}
for (i = len; i >= 0; --i) {
if (s[i] >= '0' && s[i] <= '9')
n = s[i] - '0';
else if (s[i] >= 'A' && s[i] <= 'F')
n = s[i] - 'A' + 10;
else if (s[i] >= 'a' && s[i] <= 'f')
n = s[i] - 'a' + 10;
rp = len - i;
v += n * HEX^rp;
}
return v;
}
int main() {
int test = htoi("0x1a9f");
printf("%d\n", test);
return 0;
}
You are passing the address of a string literal which is read-only. Doing the following will get rid of the segmentation fault.
char temp[] = "0x1a9f";
int test = htoi(temp);
Also:
v += n * HEX^rp;
Is ^ is the XOR operator and not the power operator. For power you need the pow function in math.h
Also:
for (i = len; i >= 0; --i) should be for (i = len - 1; i >= 0; --i) because the value of len goes out of the bound of the array. (Notified by #Grijesh Chauhan and #simonc)
int test = htoi("0x1a9f");
passes the string literal "0x1a9f" to htoi. This may exist in read-only memory and cannot be modified. You therefore get undefined behaviour (with a crash a valid example of this) when you try to write to the string in the line
s[1] = '0';
The easiest fix is to copy the original string into a modifiable variable
char s[] = "0x1a9f";
int test = htoi(s);
As reported by Grijesh, further into htoi, you also read beyond the bounds of the string
for (i = len; i >= 0; --i)
should be:
for (i = len - 1; i >= 0; --i)
I have an input like
char *input="00112233FFAA";
uint8_t output[6];
What is the easiest way to convert input into output with sscanf? (prefer 1 line with no loop) The solution I have in mind doesn't scale to 20+ hex string.
sscanf(input, "%x%x%x%x%x",output[0], output[1]....output[5]);
Why scanf if this can be easily written by hand:
const size_t numdigits = strlen(input) / 2;
uint8_t * const output = malloc(numdigits);
for (size_t i = 0; i != numdigits; ++i)
{
output[i] = 16 * toInt(input[2*i]) + toInt(intput[2*i+1]);
}
unsigned int toInt(char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
return -1;
}
If you do not want to use a loop, then you need to explicitly write out all six (or twenty) array locations (although %x is not the correct conversion character - it expects a pointer to unsigned int as its corresponding argument). If you don't want to write them all out, then you need to use a loop - it can be quite simple, though:
for (i = 0; i < 6; i++)
sscanf(&input[i * 2], "%2hhx", &output[i]);
Here is an alternate implementation.
#include <stdio.h>
#include <stdint.h>
#define _base(x) ((x >= '0' && x <= '9') ? '0' : \
(x >= 'a' && x <= 'f') ? 'a' - 10 : \
(x >= 'A' && x <= 'F') ? 'A' - 10 : \
'\255')
#define HEXOF(x) (x - _base(x))
int main() {
char input[] = "00112233FFAA";
char *p;
uint8_t *output;
if (!(sizeof(input) & 1)) { /* even digits + \0 */
fprintf(stderr,
"Cannot have odd number of characters in input: %d\n",
sizeof(input));
return -1;
}
output = malloc(sizeof(input) >> 1);
for (p = input; p && *p; p+=2 ) {
output[(p - input) >> 1] =
((HEXOF(*p)) << 4) + HEXOF(*(p+1));
}
return 0;
}
#caf already had a good simple idea.
However I had to use %02x and now it's working fine:
for (i = 0; i < 6; i++)
sscanf(&input[i * 2], "%02x", &output[i]);
I am writing this code to convert a hex entry into its integer equivalent. So A would be 10 and B would be 11 etc. This code acts weirdly, in that it seg. faults at random locations and including an extra newline character at times will get it to work. I am trying to debug it, just so I can understand what I am doing wrong here. Can anyone take a look and help me here ? Thanks a lot for your time.
/* Fixed working code for anyone interested */
#include <stdio.h>
#include <stdlib.h>
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
int dec;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
if ( temp[i] == '\0')
{
return ;
}
if (temp[i] == '0' || temp[i] == 'x' || temp[i] == 'X' )
{
printf("0");
answer = temp[i];
}
// compare each temp[i] with all contents in hexchar[]
int j;
int a = temp[i];
for ( j=0; hexchar[j] != '\0'; j++)
{
if ( temp[i] == hexchar[j] )
{
answer *= 16;
answer = answer + 10 + (j/2);
// printf("%d\n",answer );
break;
}
}
}
return answer;
}
main()
{
char *test[] =
{ "bad",
"aabbdd"
"0100",
"0x1",
"0XA",
"0X0C0BE",
"abcdef",
"123456",
"0x123456",
"deadbeef",
"zog_c"
};
int answer=0;
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
printf("main():Number of chars = %d\n",numberOfChars);
int i;
// Go through each character and convert Hex to Integers.
for ( i = 0; i<numberOfChars;i++)
{
// Need to take the first char and then go through it and convert
it.
answer = hextoint(test[i]);
printf("%d\n",answer );
}
}
Let's take a look.
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
printf("In here");
printf("%c\t",temp[i] );
}
return answer;
}
This doesn't seem to even try to do any conversion. It should always return 0, since answer is never assigned any other value. Normally, you'd do something like:
for (i=0; input[i] != '\0'; i++) {
answer *= 16;
answer += digit_value(input[i]);
}
return answer;
Where digit_value (obviously enough) returns the value of an individual digit. One way to do this is:
int digit_value(char input) {
input = tolower(input);
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1; // signal error.
}
Then, looking at main:
main()
{
Depending on the "implicit int" rule is generally poor practice, at least IMO. It's much better to specify the return type.
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
This actually calculates the number of strings, not the number of chars.
for ( i = 0; i<=numberOfChars;i++)
Valid subscripts run from 0 through the number of items - 1, so this attempts to read past the end of the array (giving undefined behavior).
This'll work for any number within the unsigned int range, the nice thing is it does not use any other library functions so it is great for micro-controllers where space is tight.
unsigned int hexToInt(const char *hex)
{
unsigned int result = 0;
while (*hex)
{
if (*hex > 47 && *hex < 58)
result += (*hex - 48);
else if (*hex > 64 && *hex < 71)
result += (*hex - 55);
else if (*hex > 96 && *hex < 103)
result += (*hex - 87);
if (*++hex)
result <<= 4;
}
return result;
}
The problem is with calculating numberOfChars part. sizeof test is actually the size of the pointer, not the total length of all characters in your array, so the number returned in your code would be 1, which makes the for loop go to the second index of test (test[1]) which does not have a \0 at the end. Try using strlen for calculating numberOfChars.
This may not me the most optimal method, but it should work without problem.
unsigned int hex_to_int(const char* hex) {
unsigned int result = 0;
size_t len = strlen(hex);
for (size_t i = 0; i < len; ++i) {
char cur_char = tolower(hex[len - i - 1]);
// direct return if encounter any non-hex character.
if (!(isdigit(cur_char) && (cur_char >= 'a' && cur_char <= 'f'));)
return result;
unsigned int char_val = (isdigit(cur_char) ? cur_char - '0' : 10 + cur_char - 'a');
result += round(pow(16, i)) * char_val;
}
return result;
}