Enum/Dictionary-Like Tool in C? - c

I'm reading over a solution to a problem in K&R's chapter 7 posted here. Basically, the program will convert the standard input into lowercase or uppercase depending on the name of the program ("upper" or "lower"). It seems to store the names of the conversion functions in some kind of dictionary, like so:
int (*convcase[2])(int) = {toupper, tolower};
and later access these functions depending on whether the name of the program started with a u or an l:
if(argc > 0)
{
if(toupper((unsigned char)argv[0][0]) == 'U')
{
func = 0;
}
else
{
func = 1;
}
while((ch = getchar()) != EOF)
{
ch = (*convcase[func])((unsigned char)ch);
putchar(ch);
}
}
I understand what that code block is doing, but I've never seen anything like the initial declaration of convcase. It seems like some kind of weird combination of a macro, an enum, and an array. Could anyone explain (1) why convcase is a pointer; (2) what's with the (int) cast after its name; (3) what exactly toupper and tolower are within that declaration, because they're not char *s; and (4) when/why to use this kind of setup. Is it just a quick macro-like tool to save some space when you have multiple possible function calls?

convcase is an array of two function pointers; It's not a pointer. An array expression will be implicitly converted to a pointer when it is used in a place where a pointer is expected.
That's not a cast. It's specifying that the functions accept an int argument, as the toupper and tolower functions do.
convcase is initialised with the function pointers toupper and tolower.
I presume this question is regarding function pointers. Use function pointers when you wish for the abstraction of function pointers. I'd suggest that this example is an unnecessary use of function pointers. The ability to change convcase[0] or convcase[1] to Spanish or Japanese, depending upon user input would more likely warrant the use of function pointers in this case. Additionally, function pointers could be used in arguments to provide additional abstraction. For example, the qsort function is able to sort arrays of any type because of it's usage of function pointers for a comparer of objects. Here's an example that sorts int input using the int_compare function as the comparer.
#define nelem(array) (sizeof (array) / sizeof *(array))
int int_compare(const void *p1, const void *p2) {
int x = *(int *)p1, y = *(int *)p2;
return (x > y) - (y > x);
}
int main(void) {
int value[16];
for (size_t x = 0; x < nelem(value); x++) {
if (scanf("%d", &value[x]) != 1) {
break;
}
}
qsort(value, sizeof *value, x, int_compare);
return 0;
}

Related

How to cast a void pointer at runtime in C, in a way which can be used in rest of the code? [duplicate]

This question already has answers here:
How can mixed data types (int, float, char, etc) be stored in an array?
(6 answers)
Closed 7 years ago.
This is not a 'How can a mixed data type (int, float, char, etc) be stored in an array?' question read carefully please!
Suppose I have the following void pointer, something I don't know it's type until runtime:
void* data;
now I know I can do the following, when I know the type of data(e.g. int):
int typed_data = *(int*)data;
using a switch case statement I could check a variable to determine which cast to perform:
switch(type_id) {
case INT:
int typed_data = *(int*)data;
break;
case FLOAT:
float typed_data = *(float*)data;
break;
// ...
// etc.
}
But, this way I will not be able to access typed_data outside the switch block, consider the below funstion as an example; It takes two void pointers, and according to the value of type_id, it casts the s and x to correct data types, and then does other things with the newly defined typed data:
int sequential_seach(int n, void* s, void* x, type_id) {
int location = 0;
switch(type_id) {
case INT:
int *list = s;
int element = *(int*)x;
break;
case FLOAT:
float *list = s;
float element = *(float*)x;
break;
// ...
// etc.
}
while(location < n && list[location] != element) { // <---This will cause a compile error
location++;
if(location > n - 1) {
location = -1;
}
}
return location;
}
In the above function location and list are not accessible outside the swtich block, even if type_id matched one of the case values and they were defined, they are still out of scope, outside the switch block, therefore when the compiler reaches the line while resides, it complains that location and list are not defined. But these typed variables are needed for the function. So how to solve this? should I copy paste the while block into every case? That doesn't look it's a very good solution. What if I had a longer code which needed these variables in 100 different places?
Sounds like you need generics: the ability to define functions with compile-time type parameters.
Unfortunately, C doesn't natively have generics. Fortunately, you can use macros as pseudo-generics to make the preprocessor automatically generate multiple versions of your code.
Adapted from the linked answer:
// sequential_search.h
/* Provide some helpers that generate a name of the form of sequential_search_T,
unique for each type argument */
#define TOKENPASTE(x, y) x ## y
#define SEQ_SEARCH(T) TOKENPASTE(sequential_search_, T)
/* Provide the generic type definition of your function */
int SEQ_SEARCH(TYPE) (int n, void* s, void* x) {
int location = 0;
TYPE* list = s;
TYPE element = *(TYPE*)x;
while(location < n && list[location] != element) {
location++;
if(location > n - 1) {
location = -1;
}
}
return location;
}
Instantiate it once for each type argument you intend to pass:
// sequential_search.c
#define TYPE int
#include "sequential_search.h"
#undef TYPE
#define TYPE float
#include "sequential_search.h"
#undef TYPE
// etc.
Finally, create a (statically resolvable) call spot that will switch on the type id you have (the runtime information) and then immediately dispatch to one of the generic versions:
int sequential_search(int n, void* s, void* x, type_id) {
switch(type_id) {
case INT: return sequential_search_int(n, s, x);
case FLOAT: return sequential_search_float(n, s, x);
// etc.
}
}
It's not possible to cast a void pointer at runtime in C.
And your code doesn't check if the cast is valid either. Doing this, you will either lose some data or risk a segmentation fault since data types aren't all the same size.

How can I pass an array as a list of args to a function with varying number of parameters in C

I wonder how can I tease out an array in C to several arguments of a function.
After I saw the amazing syntatic sugar from Go (golang) I thinking about it.
The c code:
#include <stdio.h>
#include <stdarg.h>
// assert: all args are valid ints
void printEach(int len, ...) {
// Irrelevant, this function print their arguments
// And I know how to use va_start, va_arg...
}
void handleVet(int* v, int n) {
// **HERE is my the question!!!**
printEach(n, v[0]...[n]) // <----------- NON-C code. I need it.
}
int main(void) {
int v[] = {12,14,15,15};
//I can do that only because the vector is static. I know the len when I'm coding
printEach(4, v[0],v[1],v[2],v[3]);
// But if we imagine an arbitrary vector, we got a problem
handleVet(v, 4);
return 0;
}
By Example, in go it would be:
package main
import "fmt"
func printEach (v ...int64) {
// Irrelevant, this function print their arguments
}
func main() {
var arr []int64 = []int64{1,14,15,}
printEach(arr...)
}
How can I achieve the same effect of "printEach(arr...)" in C?
This is a rudimentary example on how vararg is working in C.
I wasn't able to take refference to your go example as I don't udnerstand what your code does. I hope this minimal example is clear enough. If you have any questions ask me and I will edit it in.
void Foo(size_t sizeParamAmount, char *types, ...);
void Foo(size_t sizeParamAmount, char *types, ...)
{
size_t i;
float fTmp;
int iTmp;
va_list vlArgList;
va_start (vlArgList, sizeParamAmount);
for (i= 0; i< sizeParamAmount; i++)
{
switch (types[i])
{
case 'i':
iTmp = va_arg (vlArgList, int));
break;
case 'f':
fTmp = va_arg (vlArgList, float));
break;
default:
return;//error
}
}
va_end(vlArgList);
}
After reading your edit:
As I already did in my minimal example, you can hand in a pointer before the var_arg's which is explaining which argument is of what type. so you could call Foo this way:
Foo (3, "ifi", 3, 5.973, 92);
And after reading your comment to another answer I got what you are asking about.
In that case you really jsut should hand in a pointer (or array without [] behaves for this case the same) which holds an end content token.
Anyway there is a way. but you had to freak around with preprocessing tokens.
And would be totally over the top for your needs. This answer would anyway give you the requested notation. you had to set for PRED a limit by sizeof(yourarray) and the let OP take the single elements.
https://stackoverflow.com/a/10542793/2003898
But there is sadly not a more minimal example.
You will need to specify the size of the array. Here's what it might look like:
void printEach(int* values, int size)
{
if(size==0)
return;
printf("%d", value[0]);
printEach(values+1, size-1);
}
You are looking for Variadic function, you should look at
stdarg.h and varargs.h

How can I sort an array of strings (2D Array) alphabetically?

I already have a list of strings read in from a text file into a 2D array named word ready to be sorted.
The list looks like:
I
like
cherry
pie
and
chocolate
pie
I want the list to look like this after sorted:
and
cherry
chocolate
I
like
pie
pie
The function prototype is below. int counter is the amount of strings, and MAX_CHAR_LEN = 1024 in case you were wondering.
void alphabetize(char word[][MAX_CHAR_LEN], int counter)
{
return;
}
Notice that sorting by the first character alone is not sufficient, as the list contains two strings that start with "ch"
Can someone provide a function that can do this? Thanks in advance.
You want to use the qsort() function.
qsort(base, num_of_elements, element_size, my_compare);
The comparison function my_compare takes two arguments, each a const void *, and returns a number indicating the relative order of the arguments. A negative number means the first argument is before the second argument. A positive number means the first argument is after the second argument. A zero is returned if the arguments have compared to be equal.
As your string comparison is case insensitive, you will need to create your own comparison function, or find one provided to you by your system that is not part of the C library proper. POSIX provides strcasecmp() for this purpose (Google tells me that _stricmp() is available on Windows).
int my_compare (const void *a, const void *b) {
return strcasecmp(a, b);
}
Defining the comparison function is usually the trickiest part of using qsort(). You have to understand the context of the pointers that are being passed into that function. When an array of TYPE is passed into qsort(), it will pass a pointer to const TYPE to each argument of the comparison function.
In your case, you would be passing in an array of array of MAX_CHAR_LEN chars. So, each argument to the comparison function is a pointer to const array of MAX_CHAR_LEN chars. This means that technically, the my_compare function should be written like this:
int my_compare (const void *a, const void *b) {
typedef char TYPE[MAX_CHAR_LEN];
const TYPE *aa = (const TYPE *)a;
const TYPE *bb = (const TYPE *)b;
return strcasecmp(*aa, *bb);
}
The cast on the arguments would normally not be necessary, except that C doesn't really support the notion of a constant array. It converts such a thing into an array of constants, so the cast is required to reflect that.
However, the address of an array is equal to the address of its first element. That is, for the code above, the following assertions would be true:
assert(aa == (const void *)*aa);
assert(bb == (const void *)*bb);
So, because the dereference of a pointer to an array equals the decayed address value of the same array, the first implementation of my_compare() is sufficient for your 2-D array.
You can use the qsort function to sort. You also need to create a compare function that compares two arrays of chars, and then pass that function pointer as an argument.
Example that sorts ints:
/* qsort example */
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */
int values[] = { 40, 10, 100, 90, 20, 25 };
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int n;
qsort (values, 6, sizeof(int), compare);
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
The above code can easily be adapted to sort arrays of chars instead of ints.
If you want to write your own sort function, something like this is pretty straight forward.
for (int i = 0; i < array.size(); i++)
{
for (int j = i+1; j < array.size(); j++)
{
if (array[i] > array[j])
swap(array[i],array[j]);
}
}
qsort is Good Option. See it's detail here
You can also try Bubble Sort. It's implementation in C is easy - See this Good answer for help

Create a C function that accepts parameters of different data types

I'm relatively new to the C programming language, and I'm trying to figure out how to create a function that can accept different types of data as parameters. The function is supposed to count and return the number of elements in a character or integer array. I already have two separate functions that will do this, but I would really like to be able to use one function for both tasks. Is there a way to do this in C?
Thanks in advance!
There is no standard function overloading in C (nor are there templates), but you could probably look into "printf-like" functions (or variadic functions) and maybe they can do what you need. If anything they allow for a flexible parameter list.
There is an example here of such a function that takes a variable size integer array.
Perhaps you could have a function signature such as void iterate(const char* format, ...); that you use in the following ways:
iterate("char", some_char_array); // for char arrays/strings
Or
iterate("int", some_int_array); // for integer arrays
Aniket makes a good point though, how do you count the elements in an integer array? If you pass an int array as an argument, you would need to pass the size too which defeats the purpose of counting the elements in the array (as you already know that i.e. the size).
I assume you don't know the size but you have a terminator value in the array (such as -1).
I've hacked something quick that kinda does what you need with the above assumption in mind.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int iterate(const char* format, ...)
{
va_list ap;
va_start(ap, format);
if (strcmp(format, "char") == 0)
{
char* array = va_arg(ap, char*);
va_end(ap);
return strlen(array);
}
else if (strcmp(format, "int") == 0)
{
int j = -1;
int* int_array = va_arg(ap, int*);
while (int_array[++j] != -1)
;
va_end(ap);
return j;
}
va_end(ap);
return 0;
}
int main()
{
printf("%d\n", iterate("char", "abcdef"));
int arr[] = {5, 4, 3, 2, 1, 0, -1};
printf("%d\n", iterate("int", arr));
return 0;
}
This prints:
$ ./a.out
6
6
So, let's assume your two functions are called sizeof_char_array and sizeof_int_array.
In C11, there is a new feature called "generic selection" that will let you do what you want with a relatively simple macro:
#define sizeof_array(X) \
_Generic (*(X), \
char: sizeof_char_array, \
default: sizeof_int_array) (X)
(I don't even have a C11 implementation to test this against, so caveat emptor!)
Prior to C11, this was sometimes accomplished with a macro using regularly named functions. You can define a macro that will call one function or the other depending on a macro argument hint:
#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)
int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";
sizeof_array(int, a); /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b); /* macro expands to sizeof_char_array(b) */
If the input argument is truly an array, you can use a macro to compute its size directly:
#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))
In the case of an array, the following expression is true:
(void *)arr == &arr
Because the address of an array has the same location in memory as the address of its first element.
So, the macro computes: sizeof(arr)/sizeof(arr[0]). Since the sizeof operator reports the size in bytes of its argument, the computed expression results in the number of elements in the array. However, if you are using a sentinel to compute the length, the ARRAY_SZ macro will result in a size at least one larger than the length found traversing the array for the sentinel.
In the case that the argument is not an array, then the expression results in a divide by 0 exception.
The answer is quite simple. You do need a function for this task. Just try this piece of code
#define len(array) sizeof(array)/sizeof(*array)
and that's it.
Important note: As pointed out in the comments, this will not work for dynamically allocated arrays.
You should make your function arguments take in a void * type. This way, you can pass in different types of data, and type-cast it to the one you want. However, you do need to watch out because there is no guaranteed way to correctly 'guess' the type that a void* points to.
In either case, you will need some sort of type-inferencing system to tell the C compiler which function to call. Which means, you will need to know, before-hand the type of array you might send in as a parameter to this "super function" of yours.
There is no "auto-type-inferencing" in C that can let you reflect upon the type of data at runtime. Better yet, you might have to write your own runtime environment for this to happen.
A slightly trivial hackish way to do this:
#include <stdio.h>
size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes)
{
return sizeOfTheArrayInBytes/sizeOfOneElementInArray;
}
int main(int argc, char *argv[])
{
char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'};
int iArr[5] = {10,20,30,40,50};
printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)),
GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr)));
return 0;
}
It's not really possible, but you can make a tagged union
typedef struct {
union {
ssize_t i;
double d;
char *s;
} unknown;
char identity;
} Dynamic;
Or you can use a void pointer:
typedef struct {
void *unknown;
char identity;
} Dynamic;

Initializing local pointers by passing the address of a pointer

I see the following way of initializing a local pointer in almost every part of my code. want to understand the reason and intricacies in doing so.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize_p(char **p)
{
char *p_local = NULL;
p_local=malloc(6);
strcpy(p_local,"sandy");
*p = p_local;
}
int main(void)
{
char *p = NULL;
initialize_p(&p);
printf("Name : %s\n",p);
return 0;
}
It is just that, i am showing here with simple string. And in my actual code, it is being done using structures.
I kind of understand the above logic and also I don't. Please clear the concept involved in the above style of implementing. Also, let me know if there is any other better way of doing the same.
Please Enlighten .. :)
I'd probably return the newly allocated string instead of passing a pointer to a pointer as an argument:
char *initialize(void) {
char *init = "sandy";
char *ret = malloc(sizeof(init)+1);
if (ret != NULL)
strcpy(ret, init);
return ret;
}
int main() {
char *p = initialize();
printf("Name: %s\n", p);
free(p);
return 0;
}
In initialize_p a chunk of memory is allocated and some string is copied into the memory. In order for the caller of initializer to get the address of this new chunk of memory the address of the pointer p is passed to initialize_p:
char **p
+---+---+---+---+---+----+
*p -> | s | a | n | d | y | \0 |
+---+---+---+---+---+----+
if only the *p would have been passed then setting the pointer inside the function would be the equivalent of:
void foo(int a)
{
a=3;
...
}
a better way would be to use strdup which does the same thing as you do in your function
char* initialize_p()
{
return strdup("sandy");
}
also make sure you free the string that is returned to avoid memory leak.
I'd suggest you to create allocation and deallocation function pair
char *createP()
{
char *p = NULL;
p=malloc(6);
strcpy(p,"sandy");
return p;
}
void freeP(char *p)
{
if (p) free(p);
}
int main(void)
{
char *p = createP();
printf("Name : %s\n",p);
freeP(p);
return 0;
}
Clearing the concept? Well, in such a simple case I don't see the point in operating with byref output parameters - for me, object-oriented-like structure constructor functions are easier to understand if they work like this:
struct foo *bar = myobj_new(); // uses malloc and returns a pointer
// do something with bar
myobj_destroy(bar); // uses free
Some agree that this design is good because then the return value of the function can be used as an error/success code (have you seen SQLite3?), but I disagree. I think the primary, the most important result of a function should go through the return value, and not some auxiliary stuff. (I tend to write libraries in which failure is indicated by returning NULL and setting a byref-passed error code).
The only valid scenario I can think of is when it's more logical or symmetrical to pass arguments like this. For example, imagining a very strange sort function which is similar to the C stdlib function qsort(), but requires its comparison function itself to make the swapping of two elements when needed. The comparison function obviously needs byref access to its two parameters in order to exchange them, but it may also be useful to return the originally encountered order to the caller sort function in order to optimize the algorithm. So this comparison function could be something like:
int compare(void *a, void *b)
{
int x = *(int *)a;
int y = *(int *)b;
if (x > y)
{
*(int *)a = y;
*(int *)b = x;
return +1;
} else if (x < x) {
return -1;
}
return 0;
}
Well, pretty much that's it about my opinion...
it's an out-parameter. the function produces a result for you, and saves it to the parameter you pass. this is often used when the size of the result may vary, or if the type of the parameter is Opaque.
Personally, I think returning the result is much clearer, and is less error-prone when a dynamic allocation is required (as seen in JerryCoffin's answer +1).
when a dynamic allocation is not required, then pass it by reference (as a non-const parameter) if it is not trivially small:
struct t_struct { int a[100]; };
void InitStruct(struct t_struct* pStruct) {
pStruct->a[0] = 11;
...
}
struct t_struct s;
void InitStruct(&s);
and if it is trivially small, you may consider returning by value.

Resources