C++ error invalid conversion from 'char' to 'const char*' - c

#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(){
char S[10007];
scanf("%[^\n]", S); getchar();
int i = 0;
char u;
while(S[i]){
u = toupper(S[i]);
if(strcmp(u, "I") == 0){
u = '1';
}
else if(strcmp(u, "R") == 0){
u = '2';
}
else if(strcmp(u, "E") == 0){
u = '3';
}
else if(strcmp(u, "A") == 0){
u = '4';
}
else if(strcmp(u, "S") == 0){
u = '5';
}
else if(strcmp(u, "G") == 0){
u = '6';
}
else if(strcmp(u, "T") == 0){
u = '7';
}
else if(strcmp(u, "B") == 0){
u = '8';
}
else if(strcmp(u, "P") == 0){
u = '9';
}
else if(strcmp(u, "O") == 0){
u = '0';
}
printf("%s", u);
i++;
}
return 0;
}
I got a case where i need to make an inputted string uppercase then change some of the uppercase alphabet to the following number, (example input: im waterswell, the otuput: 1M W4T325W33L) so i created the program but it returns to following error: invalid conversion from 'char' to 'const char*' [-fpermissive]. Can anyone help me? thank you

strcmp is used to compare strings, not single characters. Use simply if (u == 'I') and use that everywhere you have strcmp (notice the quote change - we want a character, not a string literal).
Also, printf("%s", u); is wrong, you need %c to print a char.

What source are you learning C++ from?
This is more like what I would expect from C++ :
#include <string>
#include <iostream>
#include <unordered_map>
// lookup table
static std::unordered_map<char, char> mapping
{
{'I','1'}, {'i','1'},
{'R','2'}, {'r','2'},
{'E','3'}, {'e','3'},
{'A','4'}, {'a','4'},
{'S','5'}, {'s','5'},
{'G','6'}, {'g','6'},
{'T','7'}, {'t','7'},
{'B','8'}, {'b','8'},
{'O','9'}, {'o','9'},
{'U','0'}, {'u','0'},
};
int main()
{
//std::string input;
//std::cin >> input;
std::string input{ "TESTcase" };
for (const char c : input)
{
// check if key can be found
auto it = mapping.find(c);
if (it == mapping.end())
{
// if not cast to upper, std::toupper doesn't return a char
// so cast it.
std::cout << static_cast<char>(std::toupper(c));
}
else
{
// structured binging
const auto&[key, value] = *it; // *it refers to an key value pair in the map
std::cout << value;
}
}
return 0;
}

To compare chars, you use == and a character literal, e.g.
if (u == 'O')
.
Also printing a single char with the format specifier for a null terminated string (%s) results in undefined behaviour.
You could just modify the inpur array instead and print everything in one go...
Since you tagged this C++, I'll present a C++ solution:
int main() {
char S[10007];
std::scanf("%[^\n]", S); getchar();
int i = 0;
// modify S to hold the content we want to print
for (auto& c : S)
{
if (c == '\0')
{
// end of string
break;
}
c = std::toupper(c);
switch (c)
{
case 'I':
c = '1';
break;
case 'R':
c = '2';
break;
case 'E':
c = '3';
break;
case 'A':
c = '4';
break;
case 'S':
c = '5';
break;
case 'G':
c = '6';
break;
case 'T':
c = '7';
break;
case 'B':
c = '8';
break;
case 'P':
c = '9';
break;
case 'O':
c = '0';
break;
}
}
std::printf("%s\n", S);
}

Related

How to convert a character into a number

I have a homework problem. It requires me to convert a word into uppercase and several characters have to be converted to decimal for example :
"Hello my NamE is FeLix" --> "H3LL0 MY N4M3 15 F3L1X". So, these characters had to be converted :
I = 1
S = 5
E = 3
O = 0
A = 4
etc.
How to convert it? I already tried to convert it to capslock but i cannot convert it into decimal.
I already tried to convert the words into uppercase, but have no idea how to convert the character into numbers.
int main()
{
char sentence[200];
int sentencelength = strlen(sentence);
// Ambil data user
scanf("%s",&sentence); getchar();
// Cek satu persatu pake for
for (int i= 1; i <= sentencelength; i++) {
if(sentence[i] >= 'a' && sentence[i] <= 'z') {
char uppercase = sentence[i] + 'A' - 'a';
printf("%c",uppercase);
}
}
getchar();
return 0;
}
There is no error, but I just have no idea how to convert it.
You can use switch as below.
switch(uppercase ) {
case 'I':
uppercase = '1';
break;
case 'S':
uppercase = '5';
break;
case 'E':
uppercase = '3';
break;
…
}
C arrays start at index 0, not 1, so change the for loop bounds to:
for (int i = 0; i < sentencelength; i++) {
You can use toupper (declared by #include <ctype.h>) to convert a character from lowercase to uppercase, leaving non-alphabetic characters alone. It is only defined for values representable by an unsigned char or for the value EOF.
char l33t = sentence[i];
if (l33t == (unsigned char)l33t)
l33t = toupper(l33t);
You can use a switch statement to replace certain uppercase letters with digits:
switch (l33t) {
case 'I':
l33t = '1';
break;
case 'S':
l33t = '5';
break;
case 'E':
l33t = '3';
break;
case 'O':
l33t = '0';
break;
case 'A':
l33t = '4';
break;
}
Rather than using scanf to read a whole word of input into a buffer, an alternative is to read the input a character at a time. Here is an example program that behaves as a filter:
#include <stdio.h>
#include <ctype.h>
static int convert(int ch)
{
if (ch == (unsigned char)ch)
ch = toupper(ch);
switch (ch) {
case 'I': ch = '1'; break;
case 'S': ch = '5'; break;
case 'E': ch = '3'; break;
case 'O': ch = '0'; break;
case 'A': ch = '4'; break;
}
return ch;
}
int main(void)
{
int ch;
while ((ch = getchar()) != EOF) {
ch = convert(ch);
putchar(ch);
}
return 0;
}
The above will convert the whole input until it sees end-of-file. To terminate after a single line, just add a check for a newline character to break out of the while loop.
create an array of characters: [4BCD3F....Z]
and an array of sources: [abcd...z]
run on your string, replace each character found in index I with the same character in the first array, if it's not found return the character as is.
crude, simple, works
Also, if someone complain on the calculation complexity, since you have fixed number of letters in the arrays A to Z , the complexity is O(N*M) when M is const, hence O(N) anyway

Calculator with Decimal, Octal and Hexadecimal Numbers

I want to make a calculator that is capable of calculation with decimal numbers and is able to return the decimal values in their respective binary, octal or hexadecimal representation.
So far in the main method the program reads the command line and I can invoke the program by two ways.
The first way would be with 3 values:
"number1" "operator" "number2".
And the second way would be with 4 values:
"wished numeral system for the output" "number1" "operator" "number2".
Where for the wished numeral system output b would stand for for binary, o for octal and h for hexadecimal. In both ways the user should be able to input decimal, octal and hexadecimal numbers for the inputs number1 and number2.
#include "zahlen.h"
#include <stdio.h>
#include "stringTOint.h"
int main(int argc, char *argv[]) {
char o,op,sx[DIGITS+1],sy[DIGITS+1],sz[DIGITS+1];
int x,y,z;
char flag_x,flag_y;
/* 1) Read Commandline */
if (argc != 4 && argc != 5) {
printf("Aufruf: %s -o <x> <op> <y> \n",argv[0]);
return 1;
} else if(argc == 4) {
x = stringTOint(argv[1]);
op = argv[2][0];
y = stringTOint(argv[3]);
} else if(argc == 5) {
o = argv[1][0];
x = stringTOint(argv[2]);
op = argv[3][0];
y = stringTOint(argv[4]);
if(o != 'b' && o != 'o' && o != 'h') {
printf("Wrong Operation\n");
return 1;
}
}
/* 2) Solve the equation */
if(argc==4) {
printf("solve: %s %c %s \n", argv[1], op, argv[3]);
z = solve(x, op, y);
} else if(argc==5) {
printf("solve: %s %c %s \n", argv[2], op, argv[4]);
z = solve(x, op, y);
}
/* 3) Calculate the Representation of the wished Numeral System */
switch(o) {
case 'b':
intTObinaer(x, sx);
intTObinaer(y, sy);
intTObinaer(z, sz);
break;
case 'o':
intTOoctal(x,sx);
intTOoctal(y,sy);
intTOoctal(z,sz);
break;
case 'h':
intTOhexal(x,sx);
intTOhexal(y,sy);
intTOhexal(z,sz);
break;
default:
intTObinaer(x, sx);
intTObinaer(y, sy);
intTObinaer(z, sz);
break;
}
/* 4) Return the results */
printf("\n %s %d\n%c %s %d\n= %s %d\n", sx,x,op,sy,y,sz,z);
return 0;
}
The methods intTObinaer, intTOoctal and intTOhexal only differ by the base with which the decimal number gets divided.
intTObinaer(int i, char str[]) {
unsigned int zahl = i;
int j;
/* Fill Array with zeros */
int x = 0;
for (x; x < DIGITS+1; x++) {
str[x] = '0';
}
/*Calculate the Binary representation of the given Decimal integer */
for (j = DIGITS-1; j > 0; j--) {
/* This base gets changed to 8 or 16 for octal and hexal representation */
str[j] = (char) (zahl % 2) + '0';
zahl = zahl / 2;
if (zahl == 0) {
break;
}
}
/* Set the end of the Array */
str[DIGITS] = '\0';
}
The actual equation gets solved in the solve method, where the right operation for number1 and number2 gets chosen by an switchcase where the different cases can be selected by the char op that the user had input between the two numbers.
#include <stdio.h>
int solve(int x, char op, int y) {
int ergebnis = 0;
switch(op) {
case '+':
ergebnis = x + y;
break;
case '-':
ergebnis = x - y;
break;
case '*':
ergebnis = x * y;
break;
case '/':
ergebnis = x / y;
break;
case '&':
ergebnis = x & y;
break;
case '|':
ergebnis = x | y;
break;
default:
printf("Wrong input\n");
}
return ergebnis;
}
My question now is due to the fact the the user should be able to input different numeral systems(e.g. decimal, octal or hexadecimal) how can I identify the different numeral systems and then transfer them into decimal so that I can calculate the result. After that these decimal Numbers have to be converted back into the desired numeral system that the user wanted.
Looks like you only need to add two lines to do that:
#include "stdlib.h"
#define stringTOint(arg) ((int)strtol(arg,NULL,0))
Or better yet, replace those invocations of stringTOint() with corresponding strtol() invocations (and add the #include, of course).
strtol() uses the same prefixes as for C literals: 0 for octal, 0x for hex, no prefix is decimal.
I would like to suggest another approach to this problem.
Many of the parsing you perform can be performed directly by the sscanf function, the only case is the binary case that needs to be implemented differently.
The implementation follows 3 main step:
Parse the input using the sscanf function (or the ConvCharToBinfor binary values) and store the values in the variables a and b;
Perform the operation and store the result in the res variable;
Print the output result by using the printf parsing (or loop for the binary case).
An implementation would be the following:
#include<stdio.h>
#include<string.h>
typedef struct stack {
unsigned char data[32];
int size;
} stack_t;
int ConvCharToBin(char* input);
int main(int argc, char *argv[]) {
char numSys = 'd', op;
char** param = argv;
int a, b, res;
param++;
//error case
if(argc != 4 && argc != 5) {
//not a valid input
printf("Not a valid input");
return -1;
}
if(argc == 5) {
numSys = param[0][0];
param++;
}
op = param[1][0];
switch(numSys) {
case 'b':
a = ConvCharToBin(param[0]);
b = ConvCharToBin(param[2]);
break;
case 'd':
sscanf(param[0], "%d", &a);
sscanf(param[2], "%d", &b);
break;
case 'h':
sscanf(param[0], "%x", &a);
sscanf(param[2], "%x", &b);
break;
case 'o':
sscanf(param[0], "%o", &a);
sscanf(param[2], "%o", &b);
break;
default:
//no viable number system
return -1;
}
switch(op) {
case '+':
res = a + b;
break;
case '-':
res = a - b;
break;
case '/':
res = a / b;
break;
case '*':
res = a * b;
break;
case '&':
res = a & b;
break;
case '|':
res = a | b;
break;
default:
//no valid operand
printf("invalid operation\n");
return -1;
}
stack_t tmp;
tmp.size = 0;
int i;
switch(numSys) {
case 'b':
while (res) {
if (res & 1) {
tmp.data[tmp.size] = '1';
tmp.size++;
} else {
tmp.data[tmp.size] = '0';
tmp.size++;
}
res >>= 1;
}
for(i = tmp.size - 1; i >= 0; i--) {
printf("%c", tmp.data[i]);
}
printf("\n");
break;
case 'd':
printf("%d\n", res);
break;
case 'h':
printf("%x\n", res);
break;
case 'o':
printf("%o\n", res);
break;
}
return 0;
}
int ConvCharToBin(char* input) {
char* idx;
int res = 0x00000000;
for(idx = input; idx < input + strlen(input); idx++) {
res <<= 1;
if(*idx == '1') {
res |= 0x00000001;
}
}
return res;
}
The sscanf reads formatted data from a string (in you case the argv strings)
This can be parsed using the following:
%d for decimal;
%x for hexadecimal;
%o for octal.
Unfortunately there is no C standard for parsing binary using sscanf, so this is done apart using the stdout.
I would also point out that this implementation has two limitation
Input/output limited to 32 bit unsigned (so from 0 to 4294967295), but with some slight modifications it can be extended;
No error checking for the input values, this can also be easily implemented.

Brainfuck interpreter in c printing trouble

I'm trying to code a very simple brainfuck interpreter in C, and I run into problems while trying to outprint certain characters by what I understand.
This is all my code:
#include <stdio.h>
int bla(char tabukaz[30000], int ukaz, int num) {
int sum = 0;
int index = ukaz;
while (sum > -1) {
index -= num;
if (tabukaz[index] == ']')
sum += num;
else if (tabukaz[index] == '[')
sum -= num;
}
return index;
}
int main () {
int tab[30000];
int tabukaz[30000];
int c;
int i = 0; int ukaz = 0;
unsigned char ch;
for (int i = 0; i < 30000; i++) {
tab[i] = 0;
tabukaz[i] = 0;
}
while ((c=getchar()) != EOF) {
ch = (unsigned char)c;
if (ch == '>' || ch == '<' || ch == '+' || ch == '-' || ch == '.' || ch == '[' || ch == ']')
{
tabukaz[ukaz] = ch;
}
switch (ch) {
case '>': i++; break;
case '<': i--; break;
case '+': tab[i]++;break;
case '-': tab[i]--; break;
case '.': putchar(tab[i]); break;
case '[':
if (tab[i]==0) {
ukaz = bla(tabukaz, ukaz, -1);
}
break;
case ']':
if (tab[i]!=0) {
ukaz = bla(tabukaz, ukaz, 1);
}
break;
default:
break;
}
ukaz++;
}
return 0;
}
This is the input in question (I tried to avoid the other text in the actual input (keep in mind everything down here is part of the input, even the unnecessary text) We were provided with a make file which will write the output into a text file, and compare it to a predefined text, the problem is my text file comes out as a binary file and I cant figure out why. The problem may be hidden in how I handle [ and ] as I didn't have that problem in the earlier tests without them
+++++ +++++ initialize counter (cell #0) to 10
[ use loop to set 70/100/30/10
> +++++ ++ add 7 to cell #1
> +++++ +++++ add 10 to cell #2
> +++ add 3 to cell #3
> + add 1 to cell #4
<<<< - decrement counter (cell #0)
]
> ++ . print 'H'
> + . print 'e'
+++++ ++ . print 'l'
. print 'l'
+++ . print 'o'
> ++ . print ' '
<< +++++ +++++ +++++ . print 'W'
> . print 'o'
+++ . print 'r'
----- - . print 'l'
----- --- . print 'd'
> + . print '!'
> . print '\n'
As a suggestion made by somebody I did this:
while ((c=getchar())!=EOF) {
ch = (unsigned char)c;
if (ch == '>' || ch == '<' || ch == '+' || ch == '-' || ch == '.' || ch == '[' || ch == ']')
{
tabukaz[ukaz]=ch;
stukaz++;
}
}
while (stukaz>0) {
switch (tabukaz[ukaz]) {
case '>': i++; break;
case '<': i--; break;
case '+': if(tab[i]==255) tab[i] = 0;
else tab[i]++;
break;
case '-': if (tab[i]==0) tab[i] = 255;
else tab[i]--;
break;
case '.': printf ("%c", tab[i]); break;
case '[':
if (tab[i]==0) {
ukaz = bla(tabukaz, ukaz, -1);
}
break;
case ']':
if (tab[i]!=0) {
ukaz = bla(tabukaz, ukaz, 1);
}
break;
default: break;
}
stukaz--;
ukaz++;
}
However the problem now extends to the tests before that, as it even outputs those as binary files, I'm thinking there's something wrong with the [ and ] code and thus it doesn't increment the fields properly printing unwanted characters, how this extended to tests without them only when putting another loop around it I have no idea.
EDIT: the problem with the above loop is not the while loop not going trough, the problem is that it will never get into the switch, any solution to that?
The test is wrong while scanning for a matching bracket.
while (sum > -1) {
index -= num;
if (tabukaz[index] == ']')
sum += num;
else if (tabukaz[index] == '[')
sum -= num;
}
You set num to 1 for a backwards scan, but to -1 for a forward scan.
case '[':
if (tab[i]==0) {
ukaz = bla(tabukaz, ukaz, -1);
}
break;
case ']':
if (tab[i]!=0) {
ukaz = bla(tabukaz, ukaz, 1);
}
break;
So the test should be (sum != 0) so it stops when the brackets are balanced from either direction. Of course, sum is initialized to 0, so I recommend a do { ... } while(); loop so the test is at the end.
Also, remember that you're incrementing the instruction pointer at the end of the loop.
ukaz++;
So you may want to set the pointer to bla(...) - 1, so the increment puts the pointer in the correct place.
You might also like to look at my own brainfuck interpreter, which is very similar to yours. One of my reviewers there gives an excellent explanation of optimizing the loop execution with a jump table.

Why does my C program print out the same output no matter what I put for the input?

I'm new to C and I've been working on this homework problem for about 2 hours to no avail. I'm attempting to create a program that takes an alphabetic phone number (ie; CALLATT or 1-800-COL-LECT) and turns it into the number form (2255288 or 1-800-265-5328). No matter what I put for input, though, I always get -4197680 for my output.
int main(void){
int c=0, len, a[len];
char n[len];
printf("Enter phone number: \n");
scanf("%c", n);
len = sizeof(n) / sizeof(n[0]);
while (len > c){
if (n[c] == 'A' || n[c] == 'B' || n[c] == 'C'){
a[c] = 2;
c++;
}
else if (n[c] == 'D' || n[c] == 'E' || n[c] == 'F'){
a[c] = 3;
c++;
}
else if (n[c] == 'G' || n[c] == 'H' || n[c] == 'I'){
a[c] = 4;
c++;
}
else if (n[c] == 'J' || n[c] == 'L' || n[c] == 'L'){
a[c] = 5;
c++;
}
else if (n[c] == 'M' || n[c] == 'N' || n[c] == 'O'){
a[c] = 6;
c++;
}
else if (n[c] == 'P' || n[c] == 'Q' || n[c] == 'R' || n[c] == 'S'){
a[c] = 7;
c++;
}
else if (n[c] == 'T' || n[c] == 'U' || n[c] == 'V'){
a[c] = 8;
c++;
}
else if (n[c] == 'W' || n[c] == 'X' || n[c] == 'Y' || n[c] == 'Z'){
a[c] = 9;
c++;
}
else {
a[c] = n[c];
c++;
}
}
printf("%d\n", a);
return 0;
}
EDIT: Revised. There were many comments pointing out problems, here is my answer which works with a reasonable length phone number. It skips any non-dialing characters, such as '-' which is not part of a phone number.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void){
int k, d, e, len;
char dial[20], entry[20] = {0};
printf("Enter phone number: ");
fgets(entry, 19, stdin);
len = strlen(entry);
d = 0; // dial string index of output
for (e=0; e<len; e++) { // entry string index of input
k = entry[e];
switch (toupper(k)) {
case 'A': case 'B': case 'C': dial[d++] = '2'; break;
case 'D': case 'E': case 'F': dial[d++] = '3'; break;
case 'G': case 'H': case 'I': dial[d++] = '4'; break;
case 'J': case 'K': case 'L': dial[d++] = '5'; break;
case 'M': case 'N': case 'O': dial[d++] = '6'; break;
case 'P': case 'Q': case 'R': case 'S': dial[d++] = '7'; break;
case 'T': case 'U': case 'V': dial[d++] = '8'; break;
case 'W': case 'X': case 'Y': case 'Z': dial[d++] = '9'; break;
default:
if (isdigit(k) || k=='*' || k=='#') dial[d++] = k;
}
}
dial[d] = 0; // terminate string
printf("Dial %s\n", dial);
return 0;
}
Here is some code:
char buf[32];
sscanf("%31s", buf);
size_t i;
for (i = 0; i < sizeof(buf) && buf[i]; ++i)
{
switch (buf[i])
{
case 'A': case 'B': case 'C':
buf[i] = '2'; break; // Note: character literal, not integer
case 'D': case 'E': case 'F':
buf[i] = '3'; break;
....
}
}
printf("%s", buf);
If you have a Posix-compliant library, you can use dynamic allocation:
char *buf;
scanf("%ms", &buf); //scanf would allocate memory
for (i = 0; buf[i]; ++i)
{
.....
}
printf("%s", buf);
free(buf);
There are so many problems in your code, it will almost need a re-write to make it work. I think you should start something small. Make sure it works before adding more functionality. I would suggest dividing the code in main into three sections -- reading the phone number, converting phone number and printing the converted phone number.
Here's a skeletal program that captures those three steps.
#define SIZE 50
void readPhoneNumber(char phoneNumber[])
{
}
void convertTextToNumber(char phoneNumber[], char dialedNumber[])
{
}
void printPhoneNumber(char phoneNumber[])
{
}
int main(void)
{
char phoneNumber[SIZE];
char dialedNumber[SIZE];
readPhoneNumber(phoneNumber);
convertTextToNumber(phoneNumber, dialedNumber);
printPhoneNumber(dialedNumber);
}
Now, you can start fleshing out the functions. For example, readPhoneNumber can be implemented as:
void readPhoneNumber(char phoneNumber[])
{
printf("Enter phone number: \n");
fgets(phoneNumber, SIZE, stdin);
}
printPhoneNumber can be implemented as:
void printPhoneNumber(char phoneNumber[])
{
printf("%s\n", phoneNumber);
}
I'll leave you to work out the implementation of convertTextToNumber.
Here you have undefined behavior, len is not initialized.
int c=0, len, a[len];
char n[len];
Use instead a constant value instead, i bet the phone number in your country has some kind of maximum length.
This way to read from the keyboard is not recommended, scanf does not check for length of string so you can do a faceroll on the keyboard and your program will crash. Instead use fgets( ) to read from stdin then go through the string char by char skipping the included \n
printf("Enter phone number: \n");
scanf("%c", n);
This makes no sense, you calculate the sizeof n i.e. of the integer that holds n. If you want the length of the string use strlen( n ); btw try to use more descriptive variable names.
len = sizeof(n) / sizeof(n[0]);
Instead of
while (len > c){
why not use a normal for-loop ? you seem to increment c++ everywhere.
this here will not do what you expect it to do
printf("%d\n", a);
but you assign 'a' integers e.g.
a[c] = 2;
printf can not magically print a number of your array, instead you want to print out is a string with the numbers. the ascii value of a digit is 48 + digit. e.g. '0' is 48, by knowing this have a character buffer and add the ascii values to it. make sure it ends with \0 which is end of string. then print out the string
buf[c++] = 48 + digit;
...
buf[c] = '\0';
puts( buf );

Convert hex char[] to int[] in C 2 chars in 1 byte

I am trying to convert a char[] in hexadecimal format to int[] in hexadecimal.
Something like this:
hello --> 68656C6C6F --> [68, 65, 6C, 6C, 6F]
This is my code:
#include <stdio.h>
#include <string.h>
uint8_t* hex_decode(unsigned char *in, size_t len, uint8_t *out);
int main(void){
unsigned char word_in[17], word_out[33];//17:16+1, 33:16*2+1
int i, len = 0;
uint8_t* out;
while(len != 16){
printf("Set new word:");
fgets( word_in, sizeof( word_in), stdin);
len = strlen( word_in);
if( word_in[len-1]=='\n')
word_in[--len] = '\0';
for(i = 0; i<len; i++){
sprintf(word_out+i*2, "%02X", word_in[i]);
}
if(len != 16){
printf("Please, use a word of 16 chars long\n\n");
}
}
printf("%s", word_in);
printf("\n");
hex_decode(word_out, sizeof(word_out), out);
return 0;
}
uint8_t* hex_decode(unsigned char *in, size_t len, uint8_t *out)
{
unsigned int i, t, hn, ln;
for (t = 0,i = 0; i < len; i+=2,++t) {
hn = in[i] > '9' ? (in[i]|32) - 'a' + 10 : in[i] - '0';
ln = in[i+1] > '9' ? (in[i+1]|32) - 'a' + 10 : in[i+1] - '0';
out[t] = (hn << 4 ) | ln;
printf("%s",out[t]);
}
return out;
}
But after printing the word, I got a segmentation fault.
That function works perfect in arduino so I think it should works fine at my computer... Where is the problem?
See #dasblinkenlight answer for seg fault. To decode 2 bytes:
My 50 Cent... (a short version)
char hex[3];
char * phex;
int result;
for(int i = 0; i < 256; i++)
{
sprintf(hex, "%02X", i);
phex = hex;
result = ((*phex > 64 ? (*phex & 0x7) + 9 : *phex - 48) << 4) | (*(phex+1) > 64 ? (*(phex+1) & 0x7) + 9 : *(phex+1) - 48);
if(result != i)
{
printf("err %s %02X\n", hex, result);
}
}
Code above does no validation. This procedure returns -1 when input was invalid.
int h2i(char * ph)
{
int result;
if(*ph > 96 && *ph < 103) result = *ph - 87;
else if(*ph > 64 && *ph < 71) result = *ph - 55;
else if(*ph > 47 && *ph < 59) result = *ph - 48;
else return -1;
result <<= 4;
ph++;
if(*ph > 96 && *ph < 103) result |= *ph - 87;
else if(*ph > 64 && *ph < 71) result |= *ph - 55;
else if(*ph > 47 && *ph < 59) result |= *ph - 48;
else return -1;
return result;
}
But wait? A char can also be -1. Yes, after casting.
char * x = "FF";
char y;
int result;
result = h2i(x);
// if (result == -1) ...error...
y = (char)result;
You get a segmentation fault because you are passing the pointer out before making any assignments to it. Either the hex_decode need to take uint8_t **out_ptr and assign it a dynamically allocated array, or the caller needs to provide an array sufficient to hold the output of the conversion.
The reason why it "works" on another platform is that it exhibits undefined behavior: in arduino, the arbitrary value placed in the uninitialized pointer out happens to point to an unused location in memory. Writing to that location does not trigger segmentation fault, creating an illusion of working code.
i will just share my own code for this:
it converts any 8 hexadecimal char string into a integer number from [-2147483648. 2147483647]
input(argument) is 1 string(8+'\0'), output(returns) is a long int, MODIFY AS NECESSARY
#define N 8
long int hex2dec(char* hex){ /*conversor HEX 2 DEC*/
int i,j,n[N],l,neg;
long int dec=0;
for(i=0;i<N;i++){
n[i]=0;
}
l=strlen(hex);
neg=0;
if(hex[0]>='8'){
neg=1;
for(i=0;i<N;i++){
if(hex[i]=='0'){
hex[i]='F';
continue;
}
if(hex[i]=='1'){
hex[i]='E';
continue;
}
if(hex[i]=='2'){
hex[i]='D';
continue;
}
if(hex[i]=='3'){
hex[i]='C';
continue;
}
if(hex[i]=='4'){
hex[i]='B';
continue;
}
if(hex[i]=='5'){
hex[i]='A';
continue;
}
if(hex[i]=='6'){
hex[i]='9';
continue;
}
if(hex[i]=='7'){
hex[i]='8';
continue;
}
if(hex[i]=='8'){
hex[i]='7';
continue;
}
if(hex[i]=='9'){
hex[i]='6';
continue;
}
if(hex[i]=='A'){
hex[i]='5';
continue;
}
if(hex[i]=='B'){
hex[i]='4';
continue;
}
if(hex[i]=='C'){
hex[i]='3';
continue;
}
if(hex[i]=='D'){
hex[i]='2';
continue;
}
if(hex[i]=='E'){
hex[i]='1';
continue;
}
if(hex[i]=='F'){
hex[i]='0';
continue;
}
}
}
for(i=0;i<N;i++){
switch(hex[i]){
case '0':
n[i]=hex[i]-48; /* Ascii '0'=48 48-48=0*/
break;
case '1':
n[i]=hex[i]-48; /* Ascii '1'=49 49-48=1*/
break;
case '2':
n[i]=hex[i]-48;
break;
case '3':
n[i]=hex[i]-48;
break;
case '4':
n[i]=hex[i]-48;
break;
case '5':
n[i]=hex[i]-48;
break;
case '6':
n[i]=hex[i]-48;
break;
case '7':
n[i]=hex[i]-48;
break;
case '8':
n[i]=hex[i]-48;
break;
case '9':
n[i]=hex[i]-48;
break;
case 'A':
n[i]=hex[i]-55; /* Ascii 'A'=65 65-55=10*/
break;
case 'B':
n[i]=hex[i]-55; /* Ascii 'B'=66 66-55=11*/
break;
case 'C':
n[i]=hex[i]-55;
break;
case 'D':
n[i]=hex[i]-55;
break;
case 'E':
n[i]=hex[i]-55;
break;
case 'F':
n[i]=hex[i]-55;
break;
}
}
for(i=0,j=l;i<l;i++,j--){
dec=dec+(n[j-1]*pow(16,i));
}
if(neg==1){
dec=0-dec;
dec=dec-1;
}
return dec;
}
change
uint8_t *out;//region is not ensured
to
uint8_t out[sizeof(word_out)/2];
change
hex_decode(word_out, sizeof(word_out), out);//sizeof(word_out) is 33, must to 32
to
hex_decode(word_out, strlen(word_out), out);//strlen(word_out) or len * 2 or sizeof(word_out) -1
change
printf("%s",out[t]);//out is not string
to
printf("%02X ",out[t]);
The program looks complicated comparing what you want to do.
if you want to print the hexadecimal ascii code of a charachter, you can simply use
printf("%02X",'K'); // this will display the code ascii of 'K' in hexadecimal
If you want to print your word in code ascii in another char array. you can use sprintf():
int main() {
char word_in[17]="hello", word_out[33];
char *pi = word_in, *po = word_out;
word_out[0]=0;
for (;*pi;po+=2,pi++)
sprintf(po,"%02X",*pi);
printf("%s\n", word_out);
}
A charachetr is saved in binary format in the memory. this binary format represent the code ascii of the charachter. And when you want to print its content:
when using "%d": this will print the code ascii as integer
when using "%x": this will print the code ascii as hexadecimal
when using "%c": this will print the charachter

Resources