how to convert a character array to decibel - c

I have some problems in my code:
UINT8 PoWerSignal = MyScanResults.signal;
char Signal[8];
sprintf(Signal, "%d", PoWerSignal);
float decibel = 0;
decibel = 10 * log(Signal);
dbgwrite("SIGNAL: ");
_dbgwrite(decibel);
There is one error:
error: incompatible type for argument 1 of 'logf'
I don't know how to fix this or what it means.

Your are passing a char array (aka "string", here: Signal, the alphanumerical representation of the value stored in PoWerSignal) to log(), which most likely does not expect such input, but a number.
You might like to pass the numerical representation of the function log()like so:
#include <stdio.h> /* To have the prototypes foe the printf family of functions. */
...
UINT8 PoWerSignal = MyScanResults.signal;
char Signal[8] = "";
snprintf(Signal, sizeof(Signal), "%d", PoWerSignal);
float decibel = 10. * log(PoWerSignal);
...
The function _dbgwrite() seems to expect an char array on the other hand. To conform to this create the a "string" using snprintf() out of decibel to pass into it, like so:
...
char descibel_str[64] = "";
snprintf(decible_str, sizeof(decibel_str), "%f", (double) decibel);
dbgwrite("SIGNAL: ");
_dbgwrite(decibel_str);
Note on the usage of snprintf() instead of sprintf(): The former version of this "conversion" function does take care of not overflowing the target buffer, that is where the alphanumerical representation of the arguments passed are stored. This can easely happend and would provoke undefined behaviour.

Looks like you're sending a bad data type (signal). Perhaps this should be a float or unsigned int instead of a character array? "char" denotes a string of text, and you can't operate on it as a number.

Related

typecast structure member in C during assignment

Is there a way to type cast structure member during its initiation, for instance:
struct abc {
char k;
};
int main()
{
struct abc data[] = {.k= 'TI'};
}
Above wouldn't work since k is of type char, is there way to type caste this member k (to int) during its assignment to 'TI' ?
You don't need a cast here.
struct abc {
char k;
};
int main()
{
struct abc data[] = {.k= 'TI'};
}
Your object data is an array of struct abc. The initializer is for a single object of type struct abc.
If you want data to be a 1-element array, you can do this:
struct abc data[] = {{.k= 'TI'}};
or, if you want to be more explicit:
struct abc data[] = {[0] = {.k = 'TI'}};
That's valid code, but it's likely to trigger a warning. 'TI' is a multi-character constant, an odd feature of C that in my experience is used by accident more often than it's used deliberately. Its value is implementation-defined, and it's of type int.
Using gcc on my system, its value is 21577, or 0x5449, which happens to be ('T' << 8) + 'I'. Since data[0].k is a single byte, it can't hold that value. There's an implicit conversion from int to char that determines the value that will be stored (in this case, on my system, 73, which happens to be 'I').
A cast (not a "type cast") converts a value from one type to another. It doesn't change the type of an object. k is of type char, and that's not going to change unless you modify its declaration. Maybe you want to have struct abc { int k; };?
I can't help more without knowing what you're trying to do. Why are you using a multi-character constant? Why is k of type char?
No matter what you do to the value, it doesn't change the fact that the field cannot store that much information. You will need to change the type of k.
'TI' is wrong you probably mean string "TI"
If typecast mean see the sting "TI" as integer you need to use union - it is called type punning.
typedef union
{
char k[2]; //I do not want to store null terminating character
short int x;
}union_t;
int main(void)
{
union_t u = {.k = "TI"};
printf("u.k[0]=%c (0x%x), u.k[1]=%c (0x%x) u.x = %hd (0x%hx)\n", u.k[0], u.k[0], u.k[1], u.k[1], u.x, u.x);
}
https://godbolt.org/z/EhbKG5qnW
"...I was thinking if member K which of type char can be type caste to int ..."
As mentioned in comments, struct members are static and cannot be cast.
But given your willingness to cast (even though that will not work) why not start with a type that naturally accommodates multi-byte characters, i.e. wchar_t ?
If this is acceptable for your work, then when working with multi-byte char in C, you can do the following:
#include <wchar.h>
struct abc {
wchar_t k[2];//or k[3] depending on k will be used as a C string.
};
...
//inside function somewhere:
//assignment can be done as follows:
struct abc buf = {.k[0] = L'T', .k[1] = L'I'};
// Or:
struct abc buf = {.k = L"TI"};//Note, no null terminator, so not C string
Note: regarding 2nd method, by definition, L"TI" contains three characters, T, I and \0. If k is to be used as a string, k must be defined with space for the null terminator: wchar_t k[3];.
(See examples here.)
This results in the following:
(where 84 and 73 are the ASCII values for T and I respectively.)
Note: compiled using GNU GCC, set to follow C99 rules

Convert a double to a char type variable without using sprintf

I'm working on a code to create my own printf. The use of printf, sprintf, and the like are prohibited. I need to convert a double type variable to a char type variable in order to use it in a puts() function with prefixes and other things added. How do I turn a double into a string?
I found this earlier, but it only converts the memory of the variable to a string:
#include <string.h>
double a=2.132;
char arr[sizeof(a)];
memcpy(arr,&a,sizeof(a));
What can I do to make this a variable? So far, the snippet of my code where I integrated that looks like this:
double num = 10.99;
char arr[sizeof(num)];
memcpy(arr, &num, sizeof(num));
puts(arr);
//Expected output: 10.99
//Actual output:
doesn't work and will return nothing to the console. If anyone could point me in the right direction, that would be much appreciated!

How do I return a character given the function has integer return data type?

I was given a skeleton code to build an AddressBook program in C language. The code gives me a helper function get_option() to obtain user input that returns an integer. The driver code, however, requires me to return a character from using get_option(). Please help
get_option() function and the function that calls get_option()
Here are the global variables declared in a header file(not important)
global variable declared in header file
To use an integer value as char, you can just make a cast from int to char, like the example:
int main() {
//int cast to char
int a = 78; //'N' code in ascii table
printf("%c\n", (char)a); //will print "N"
//char cast to int
char c = 't';
printf("%d\n", (int)c); //will print 116, that is the 't'code in ascii table
}
by doing this, your int will be treated as a char. But, you must be careful, because not all integer values have the char representation. For more details, you can search the ascii table. That is a table that codify the characters into integers.
So, because of that, you can treat an integer(not all) as a char and a char as an integer.

I have a issue with passing by reference using string

This is the question i am working on.
"A simple encryption scheme named "rotate13" for encrypting text is to convert each letter (a…z or A...Z) to another letter by counting forward 13 letters, looping around from 'z' to 'a' or 'Z' back to 'A' if necessary.
Write a function named rotate13 which takes a single null-terminated string as a parameter
and converts it to its rotate13 equivalent. The function should modify the string directly, and it
should not return anything. Remember, only letters should change; all other characters remain
the same. You may assume that ctype.h is correctly included at the top of your program so
that you can use any functions within the library if you wish. "
And this is the error i keep getting
"error C2664: 'rotate13' : cannot convert parameter 1 from 'char (*)[10]' to 'char *[]'"
Thanks for the help. It will help me in my revisions for finals.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int rotate13(char *array[]);
int size=10;
int main()
{
char arr[10];
printf("Please enter the letters you wish to encrypt: ");
scanf("%s",&arr);
printf("%s",arr);
rotate13(&arr);
system ("pause");
return 0;
}
int rotate13(char *array[])
{
int pointer;
while(*array[pointer]!='\0')
{
if(isupper(*array[pointer])!=0)
{
if(*array[pointer]<'N')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
else
{
if(*array[pointer]<'n')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
pointer++;
}
printf("%s", *array);
return 0;
}
Remove & from scanf("%s",&arr);
scanf("%s",arr);
rotate13 is expecting an argument of type char ** but, by passing &arr you are passing it an argument of type int (*)[10]. Passing arr to rotate13 will solve your problem.
rotate13(arr);
You want to pass a string as the parameter of rotate13, so use either
int rotate13(char *array);
or
int rotate13(char array[]);
and pass arr like rotate13(arr). the same for scanf("%s",arr);
And inside the function rotate13, pointer is an int(bad variable name) that isn't initialized. To access the characters, use array[pointer], not *arr[pointer].
The function should look like this:
int rotate13(char array[])
{
int n;
while(array[n]!='\0')
{
Use rotate13(arr); instead of rotate13(&arr); and parameter should be char [] instead of char *[]
rotate13(&arr); sends the address of the array to the function which causes the parameter mismatch
As other answers have said, you're better of with int rotate13(char array[]). To understand the context, you should read this wonderful page: http://c-faq.com/aryptr/
Basically, passing a pointer to an array is redundant here, because in C when you pass an array to a function, what's actually passed is a pointer to its first element. Arrays are inherently passed by reference.
Some things need to be explained. "string" in C is the address of a character buffer.
Since the identifier arr in char arr[10]; degrades to a pointer to the first element of the array, So you don't need to specify a pointer (i.e &) to the string in the argument to scanf.
By passing &arr in your scanf as scanf("%s",&arr); the pointer passed to scanf is now a doubly-indirect pointer (it is a pointer to a pointer to the beginning of the buffer) and will likely cause the program to crash or other bad behaviour.
The strings in c, dont require &array as they implicitly pass address of the first element of the character array
So your two statments scanf("%s",&arr) should be simply scanf("%s",arr) and rotate13(&arr) should be rotate13(arr). notice that address of the first element are implicitly passed in the function calls.
Your function rotate13(char *array[ ]) is completely wrong way of doing it
char arr[10] -> can hold single string ( simply an array )
char *array[] -> can hold multiple strings ( also called array of pointers)
the formal parameter should be rotate13(char array[]) or rotate13(char *array).
After seeing your code I believe your not changing the contents of arr so you require a call by value instead of a call by address
char array[] - > call by value , char *array -> call by address
Your variable int pointer is not initialized before its use, Its dangerous. First initialize is to zero.
Change all the occurences of *array[pointer] to array[pointer]
If your wishing to change the contents of arr use call by address just change rotate13(char array[]) to rotate13(char *array) and Dont forget to initialize pointer variable to zero .

printf and casting float arguments

As a part of my program I use:
int ret = vprintf (format, args);
The args I get on the stack and I can't know what actually was pushed on the stack.
The format is a string, which I can read.
The above approach works until I have to print floats. When I print float I get some strange numbers ...
I checked that if I call float fArg = *(reinterpret_cast<const float*>(args) - and then print fArg the correct value is printed (I tried it when args was consisted only from one actual argument)
So probably I need special behavior for "%...f" sub-format - the corresponding (sub)argument should be cast
to float. (The ... notation means that precision, width etc. could be added before f)
How can I implement it?
Note that with variable-length argument lists, all float values are promoted to (and passed as) double values. You cannot reliably use:
float f = va_arg(args, float); /* BAD! */
because the language never places a float value on the stack. You would have to write:
float f = va_arg(args, double); /* OK */
This may be your entire problem.
If not, it is likely that you will need to scan the format string, and isolate the format specifiers, and implement a significant portion of the core printf() code. For each specifier, you can collect the appropriate value from the args. You then simply call the appropriate printf() function on a copy of the initial segment of the format string (because you can't modify the original) with the correct value. For your special case, you do whatever it is you need to do differently.
It would be nice to be able to pass the args parameter to vprintf() so it deals with collecting the type, etc, but I don't think that's portable (which is undoubtedly a nuisance). After you've passed a va_list value such as args to a function that uses va_arg() on it, you cannot reliably do anything other than va_end() on the value after the function returns.
Earlier this year, I wrote an printf()-style format string analyzer for POSIX-enhanced format strings (which support the n$ notation to specify which argument specifies a particular value). The header I created contains (along with enumerations for PFP_Errno, PFP_Status, FWP_None and FWP_Star):
typedef struct PrintFormat
{
const char *start; /* Pointer to % symbol */
const char *end; /* Pointer to conversion specifier */
PFP_Errno error; /* Conversion error number */
short width; /* Field width (FPW_None for none, FPW_Star for *) */
short precision; /* Field precision (FPW_None for none, FPW_Star for *) */
short conv_num; /* n of %n$ (0 for none) */
short width_num; /* n of *n$ for width (0 for none) */
short prec_num; /* n of *n$ for precision (0 for none) */
char flags[6]; /* [+-0# ] */
char modifier[3]; /* hh|h|l|ll|j|z|t|L */
char convspec; /* [diouxXfFeEgGAascp] */
} PrintFormat;
/*
** print_format_parse() - isolate and parse next printf() conversion specification
**
** PrintFormat pf;
** PFP_Status rc;
** const char *format = "...%3$+-*2$.*1$llX...";
** const char *start = format;
** while ((rc = print_format_parse(start, &pf)) == PFP_Found)
** {
** ...use filled in pf to identify format...
** start = pf.end + 1;
** }
** if (rc == PFP_Error)
** ...report error, possibly using print_format_error(pf.error)...
*/
extern PFP_Status print_format_parse(const char *src, PrintFormat *pf);
extern const char *print_format_error(PFP_Errno err);
extern PFP_Status print_format_create(PrintFormat *pf, char *buffer, size_t buflen);
The parse function analyzes the source and sets the appropriate information in the structure. The create function takes a structure and creates the corresponding format string. Note that the conversion specifier in the example (%3$+-*2$.*1$llX) is valid (but a little dubious); it converts an unsigned long long integer passed as argument number 3 with a width specified by argument 2 and a precision specified by argument 1. You probably could have a longer format, but only by a couple of characters without repetition, even if you used tens or hundreds of arguments in total.
There's no easy, portable way to do this; to inspect a va_list, you must know what types of values it holds and the only way to know is by parsing the format string. Effectively, you'll have to reimplement part of vprintf. (Part, because you can still send off the individual format specifier + cast value pairs to printf and not worry about how to pick apart a float.)

Resources