loading...

A newb tries to make map in C

yujiri8 profile image Ryan Westlund ・3 min read

I'm somewhat of a noob at C, and thought I would see if I could figure out a way to take advantage of C's type system to create generics, map, and/or filter. I ended up trying to tackle map first.

Once I did some reading about function pointers, it wasn't too difficult to come up with:

void map(int list[], int len, int (*func)(int)) {
  for (int i = 0; i < len; i++) {
    list[i] = (*func)(list[i]);
  }
}

Somewhat ironically, this alters the list in-place, so it might not really count as "map", but I was happy. It was still limited to int though. And then I remembered what I learned about macros last time I toyed with C. Behold:

#define LOOP(list, len, func) {\
    for (int i = 0; i < len; i++) {\
        func(list[i]);\
    }\
}\
#define MAP(list, len, func) {\
    for (int i = 0; i < len; i++) {\
        list[i] = func(list[i]);\
    }\
}\

Eventually, I was able to apply these badasses to strings. Here's my current file:

#include <stdio.h>
#include <string.h>

#define LOOP(list, len, func) {\
  for (int i = 0; i < len; i++) {\
    func(list[i]);\
  }\
}

#define MAP(list, len, func) {\
  for (int i = 0; i < len; i++) {\
    list[i] = func(list[i]);\
  }\
}

void printn(int x) { printf("%d\n", x); }

int doub(int x) { return x * 2; }

void map(int list[], int len, int (*func)(int)) {
  for (int i = 0; i < len; i++) {
    list[i] = (*func)(list[i]);
  }
}

void oldmap(int list[], int len, void (*func)(int)) {
  for (int i = 0; i < len; i++) {
    (*func)(list[i]);
  }
}

void truncstr(char str[]) { memset(strchr(str, 'f'), 0, 1); }

int main(int argc, char *argv[]) {
  // map ints
  int nums[] = {4, 2, 5};
  map(nums, 3, doub);
  oldmap(nums, 3, printn);
  MAP(nums, 3, doub);
  LOOP(nums, 3, printn);
  // map chars
  char ls[] = "LSE A";
  LOOP(ls, 5, printn);
  MAP(ls, 5, doub);
  LOOP(ls, 5, printn);
  // map strings
  char strs[][6] = {"taf", "tfe", "nurefu", "fo", "if"};
  LOOP(strs, 5, printf);
  putchar('\n');
  LOOP(strs, 5, truncstr);
  LOOP(strs, 5, printf);
}

Aha! The two-dimensional string thing took me forever to solve because I initially declared it as char * strs[] (because char strs[][] wasn't accepted), but that made the strings read-only, which I spent about 30 min debugging. On the bright side, I learned that that's what causes it - apparently char *'s are read-only but char []'s are mutable. Good to know.

The reason the intendation is 2-space is because this was the first time I used clang-format. I didn't end up running it again at the end because it wanted to do some vomit-inducing stuff to my macros:

#define LOOP(list, len, func)                                                  \
  {                                                                            \
    for (int i = 0; i < len; i++) {                                            \
      func(list[i]);                                                           \
    }                                                                          \
  }

#define MAP(list, len, func)                                                   \
  {                                                                            \
    for (int i = 0; i < len; i++) {                                            \
      list[i] = func(list[i]);                                                 \
    }                                                                          \
  }

I'm disappointed in you, clang-format. I tried out a lot of different Python linters and ended up leaving them all behind cause they would insist on crazy things in certain situations. I've never seen a good linter besides the Go ones, but clang-format, you gave me a false hope.

Anyway, I gotta go for now. Let me know if I missed better ways to do this! Next time I've time to play with C, maybe I'll see if I can create something equivalent to filter or generic list operations :)

Posted on by:

yujiri8 profile

Ryan Westlund

@yujiri8

I'm a programmer, writer, and philosopher. My Github account is yujiri8; all my content besides code is at yujiri.xyz.

Discussion

pic
Editor guide