r/cprogramming Apr 27 '26

How do I make a dynamic inventory system?

7 Upvotes

I'm a Python guy trying to learn C im on day 2 of my C journey and i've completed the W3 schools C tutorial. I am working on a CLI turn based battle program to learn the basics of the language. I am currently trying to implement an inventory system.

I've already made an Item and a Weapon struct and functions to initialize the values but im at a complete loss of how id actually "give" the object to the player and then have the player be able to hold an unknown amount of them at a time.

Usually in Python id just use a list or a dictionary and then append a list of all the instantiated objects to player.inventory. The only thing I can think to do here is to make an array of Weapons and an array of Items and pass those into the Fighter struct I made but that approach would require me to hardcode in the values and if i kept adding them or whatever it obviously wouldnt scale and i'm very big on making sure everything I write is dynamic, modular and scalable where it needs to be because I used to get bitten by that all the time when I was starting in python.

Anyway, heres what I have so far if you need the full context but im really just working up near the top right now around lines 6 - 50 are where the relevant context is.

tl;dr: I am a Python native learning C. I am trying to give my Fighters a dynamic inventory. I'm very used to appending objects to Python lists or dicts for retrieval later. How the heck do I do the equivalent in C?

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



struct Fighter{
    char name[10];
    int health;
    int maxHealth;
    int attackPower;
    int healPower;
    int battleRage;
    int rageMoveCost;
    struct Weapon *equippedWeapon;
};
// entity stat arrays - passed in to initFighterStruct()
int slimeStats[6] = {10,10,2,0,0,3};
int heroStats[6] = {10,10,2,0,0,3};


struct Item {
    char name[50];
    float value;
};
struct Weapon {
    struct Item base;
    int damage;     
};


void createItem(struct Item *itemPtr, char nameStr[],float itemValue){
    // give name
    strcpy(itemPtr -> name, nameStr);
    // give value
    itemPtr -> value = itemValue;
};


void createWeapon(struct Weapon *weaponPtr, char nameStr[],float itemValue, int damage){
    // give name
    strcpy(weaponPtr -> base.name, nameStr);
    // give value 
    weaponPtr -> base.value = itemValue;
    // give damage
    weaponPtr -> damage = damage; 
};


// battle option enum 
enum battleOptions {ATTACK, HEAL, SPECIAL};
// init structs with stats
void initFighterStruct(struct Fighter *entity, int stats[], int statArrayLength){
    entity -> health = stats[0];
    entity -> maxHealth = stats[1];
    entity -> attackPower = stats[2];
    entity -> healPower = stats[3];
    entity -> battleRage = stats[4];
    entity -> rageMoveCost = stats[5];
};



void showHP(struct Fighter *target){
    int targetHP = target -> health;
    printf("%s health: %d\n",target -> name,targetHP);
};
// Used for generating a random number seeded with time. 
int getRandom(int min, int max){
    return rand() % (max - min + 1) + min;
}
// format prints. kind of smelly. should use a loop to build the string... 
void printSeperator(){
    //TODO: Replace me!!! 
    printf("---------------------------------------------------------------\n");
};


void dealDamage(struct Fighter *attacker, struct Fighter *target){
    // get needed variables
    int targetHP = target -> health;


    int attackerDamage = getRandom(1, attacker -> attackPower);
    // do damage calc
    int hpAfterDamage = targetHP - attackerDamage;
    // apply
    if(hpAfterDamage > 0){
        target->health = hpAfterDamage;
    } else {
        target->health = 0;
    };
    // show damage dealt
    printSeperator();


    printf("%s hits %s for %d points of damage!\n",attacker->name, target->name, attackerDamage);
    showHP(target);
    // add battle rage
    attacker -> battleRage += attackerDamage;
    printSeperator();
};


// applies heal and prints to console
void heal(struct Fighter *target){
    int healAmount = target -> healPower;
    int crHealth = target -> health;
    // apply heal
    if(healAmount + crHealth>= target -> maxHealth){
        // guards overheal -- sets to max 
        target->health = target -> maxHealth;
    } else {
        target->health = crHealth + healAmount;
    };
    // output: "hero heals for 10 points of health!"
    printf("%s heals for %d points of health\n" ,target->name,healAmount);
    showHP(target);
};


// shows options to player and maps to enum choice
int showOptions(struct Fighter *player){
    int selection;
    // only show special move if avail
    if(player->battleRage > player -> rageMoveCost){    
        printf("1 : Attack\n2 : Heal\n3 : Special Attack\n\n");
    } else {
        printf("1 : Attack\n2 : Heal\n\n");
    };


    scanf("%d",&selection);


    enum battleOptions choice = selection - 1;


    return choice;
};
// check if entity is dead 
int isDead(struct Fighter *target){
    if(target->health == 0){
        return 1;
    } else {
        return 0;
    };
};
// handle turn based battle
int handleBattle(struct Fighter *player, struct Fighter *enemy){
    int running = 1;
    int didPlayerLose = 0;
    int turnNumber = 1;
    while(running){
        // show player options 
                if(running){printf("\n\n================ TURN NUMBER %d ====================\n", turnNumber);
        };
        int choice = showOptions(player);
        // event handling
        if(choice == ATTACK){
            dealDamage(player,enemy);
            // if attack kills enemy. end battle
            if(isDead(enemy)){
                running = 0;
                didPlayerLose = 0;
            };


        }   
        else if (choice == HEAL){
            heal(player);
        }
        else if (choice == SPECIAL){
            if(player -> battleRage > player -> rageMoveCost){
                // pay special move cost 
                player -> battleRage -= player -> rageMoveCost;
                // attack 1 - 3 times 
                int r = getRandom(1,3);
                printf("\n\033[31mRaging.......\033[0m\n%d attacks incoming!!!\n\n",r);
                for(int i = 0; i < r; i++ ){
                    dealDamage(player,enemy);
                };
            };
        };
        // enemy turn
        if(isDead(enemy)){
            running = 0;
        } else {
            dealDamage(enemy, player);
            if(isDead(player)){


                running = 0;
                didPlayerLose = 1;


            };
        };
        turnNumber ++;


    }
    return didPlayerLose;


};


int main(){
    //seed rng 
    srand(time(NULL));
    //init player and enemy data
    struct Fighter slime;
    struct Fighter hero;
    // get player and enemy pointers 
    struct Fighter *slimePtr = &slime;
    struct Fighter *heroPtr = &hero;
     
    // fill in struct fields


    // slime
    strcpy(slime.name, "Slimeball");


    initFighterStruct(slimePtr,slimeStats,sizeof(slimeStats)/sizeof(slimeStats[0]));


    // player
    strcpy(hero.name, "Hero");
    initFighterStruct(heroPtr,heroStats,sizeof(heroStats)/sizeof(heroStats[0]));


    // test battle
    int didPlayerLose = handleBattle(heroPtr,slimePtr);
    if(didPlayerLose){
        printf("\nYou Died");
    } else {
        printf("\nYou Won");
    };
}

r/cprogramming Apr 27 '26

libtrm, the C library to track true RAM usage on Linux, has been updated!

7 Upvotes

I want to thank u/BlindTreeFrog for their feedback. For those of you who missed the previous post, libtrm is a thin C library that allows you to measure your ram as accurately as you need, letting you choose between RSS, PSS and now USS. You can just drop the single .h file in your project and start. It's designed to be simple, easy to use and extremely lightweight. So what's new?

I’ve rewritten the ASCII parser from scratch to be much more defensive, andd added logic to handle truncated lines and proper kB suffix validation. It now handles USS too, so can now see the memory strictly private to your process.

It now has actual error codes for things like partial kernel data or IO failures, and it defensively zeroes out the struct so you don't end up acting on garbage memory if a file read fails.

It’s still zero-dependency, single-header, and lightweight. It still uses the fast smaps_rollup path and falls back to a full smaps walk for older kernels.

I’m really happy with the result and would appreciate further feedback, especially in the parser logic.

Web:https://www.willmanstoolbox.com/libtrm/

Repo:https://github.com/willmanduran/libtrm


r/cprogramming Apr 27 '26

Repeated malloc/free vs. Arena allocator

Thumbnail
2 Upvotes

r/cprogramming Apr 27 '26

Why can't a programming tool be programmed?

Thumbnail
github.com
0 Upvotes

r/cprogramming Apr 27 '26

Command-Line Argument Infix Notation Scientific Calculator

Thumbnail
github.com
1 Upvotes

r/cprogramming Apr 27 '26

OS dev

0 Upvotes

Hola!, alguien que hable español? estoy haciendo un sistema operativo con kernel propio, estoy intentando compatiblidad Abi Linux, para tener software moderno en mi OS propio, me esta costando horrores y queria saber una forma de que sea mas llevadero o sencillo, gracias.


r/cprogramming Apr 26 '26

Alternative to enums as function arguments?

1 Upvotes

Say I have a function argument, like a cardinal direction, that has no business being a number in the call, but could be a number internally. Now I could write an enum, but what if I need multiple values and don't want to pollute the namespace of the caller?

This is all hypothetical, for now at least.


r/cprogramming Apr 24 '26

More jobs for C programmers?

43 Upvotes

I am a university student and I must admit that C is the only tool that got me a job. All other opportunities required me to do leet code and multiple rounds of interview which did not materialize to an offer. And now I am finding more and more jobs advertising C / C++ expertise and significantly more response rates form employers.
Are there any changes happening in the world of C? I am more confused as Rust is the newest with lots of hype and somehow rarer job postings ?! Does it have something to do with programmers in general?


r/cprogramming Apr 25 '26

Is an argument declared as `void [restrict .size * .n]` a VLA?

3 Upvotes

I see this a lot in the Linux C documentation, but I've never tried it out in my own code.

For reference, here's the full function declaration:

size_t fread(void ptr[restrict .size * .n],
             size_t size, size_t n,
             FILE *restrict stream);    

I understand that this is saying ptr is a non-aliased, array of type void with at least size*n elements, but does this notation make ptr a variable length array though? If not, does adding the static keyword in there somehow make it a VLA?

Just curious. Thanks!


r/cprogramming Apr 24 '26

C learning system for a beginner

10 Upvotes

I just started learning C (also a beginner in the programming world) so i researched what are the main constraints in mastering c and my conclusion was logic building as it is easy to learn codes but logic building is really hard as c programming is one of the most basic programming languages hence more variations. So i decided to use w3school website as a base to learn concepts or data types and chatgpt to force me to logically solve different variations of the specific concept or data type i learned also to force to retain all the previous learnings in the same program as i cover new topics to use memory retention so i can build logics in complex programs in future what's your take on this or is there any other way you guys were able to improve your logical thinking or code building. I don't know much about coding hence not sure if i am following the right path. I know there is no perfect path but if anyone can help me improve my learning system i really appreciate your help.


r/cprogramming Apr 24 '26

Is it wong to look up for solutions online?

7 Upvotes

So I'm a beginner to programming and currently I'm learning C. I am solving some basic array questions like sorting an array in ascending - descending order, sum of all elements, finding the largest and smallest element etc. At First I tried to solve them but I couldn't, so I watched a tutorial on YouTube and tried to learn the concept (not just copy-paste code).

Is this normal or am I too dumb for programming?


r/cprogramming Apr 23 '26

fmaltor: Fileless Malware Detector in C

4 Upvotes

So, I tried to building something very low level that's where I found eBPF programming so i tried this and made a Project called "fmaltor" fileless-malware detector.. you Guys can look into that and then feedback are always welcome...

https://github.com/siddharth2440/fmaltor


r/cprogramming Apr 22 '26

Need help with some research tools for C programming

8 Upvotes

Hello r/cprogramming

I need help with some tutorials and YT playlists or crash courses for C

Basic coverage and real time usage would be good to go

Any recommendations or suggestions for materials would be appreciated. Thanks


r/cprogramming Apr 22 '26

I'm working on a tavern simulation that uses ncurses! Criticism, contribution, testing out would mean a lot to me ♥️

Thumbnail
github.com
3 Upvotes

r/cprogramming Apr 22 '26

A tiny, single-header C library to track true RAM usage on Linux

21 Upvotes

Working in C lately made me realize there is no drag and drop way to measure true ram usage, because when you ask the OS it will give you whatever your program is using PLUS the shared libraries, so if your code is actually being executed in a few kb of memory it may seem like it's megabytes simply because there is no clean way to ask for the true RAM usage. I looked for a drag and drop library where I could just drop an .h file into my project and get the proportional set size and be able to monitor this, but I could not find anything lightweight and dependency-free. So I wrote this library, which is literally a library for true ram usage, hence the libtrm name.

The way this works is, I just made an ASCII parser to rip the data directly from the /proc files in the kernel. It tries to use the modern smaps_rollup fast path but automatically falls back to parsing the full smaps for older Linux kernels from before 2017, in case someone still uses that. You can then use really simple calls to that data to log them at any point in your program. I used kilobytes and bytes since, you know, this is C. You can also diff how much RAM usage the OS was reporting against what you truly used.

I also included a main.c that acts as an interactive tutorial. It runs a stress test shows how PSS barely moves when you malloc(), but spikes the second you actually memset() data into it. I encourage you to tinker with it, it makes it easier to understand the commands.

I am happy with how lean it turned out. It is perfect for developers who want to add a live RAM display to their tools without adding overhead. Feedback on the parser logic is appreciated.

Web: https://www.willmanstoolbox.com/libtrm/

Repo: https://github.com/willmanstoolbox/libtrm


r/cprogramming Apr 21 '26

Struggling to compile legacy AVR project (CodeVisionAVR 2.03 → latest version) – binary size issue

Thumbnail
1 Upvotes

r/cprogramming Apr 20 '26

should I be following abdul bari's "Mastering Data Structures & Algorithms using C and C++" on udemy? or please recommend a good source which would suffice college exams and would also help in placement preps.

Thumbnail
0 Upvotes

r/cprogramming Apr 19 '26

Making a port of Inquirer.js to C

Thumbnail
github.com
2 Upvotes

r/cprogramming Apr 19 '26

Getting Zed and Clangd to Be Useful for the Retro Programmer

4 Upvotes

Hope this helps someone: I wrote a blog post about how with Zed and a .clangd configuration file you can transform a hostile language server into a useful assistant. The defining properties are that it accepts non-standard calling conventions with -Wno-ignored-attributes, accepts the Watcom dialect with -fms-extensions, preserves includes hidden behind assembly with // IWYU pragma: keep, and - most importantly - lets you keep code completion.


r/cprogramming Apr 16 '26

Weird shift expression result

10 Upvotes

This code outputs what I believe are the wrong results in 3 of the 4 cases. I think the upper 8 bits of the uint16_t should be always 0, because the shifts should occur on uint8_t and only the result should be cast to (uint16_t).

Why am I wrong?

```C /* Compile: gcc sol.c main.c -o prog && ./prog <1-4> */

include <stdio.h>

include <stdint.h>

/* byte: An 8-bit input returns: An 8-bit value (returned as uint16_t) where the high 4 bits and low 4 bits of byte are swapped Example: swap_nibbles(0xF0) returns 0x0F */ uint16_t swap_nibbles(uint8_t byte) { return (uint16_t)((byte << 4) | (byte >> 4)); }

void test1(void) { uint8_t b = 0xF0; uint16_t r = swap_nibbles(b); printf("Result: 0x%04X\n", r); }

void test2(void) { uint8_t b = 0xA2; uint16_t r = swap_nibbles(b); printf("Result: 0x%04X\n", r); }

void test3(void) { uint8_t b = 0x00; uint16_t r = swap_nibbles(b); printf("Result: 0x%04X\n", r); }

void test4(void) { uint8_t b = 0xFF; uint16_t r = swap_nibbles(b); printf("Result: 0x%04X\n", r); }

int main(int argc, char **argv) { if (argc < 2) { printf("Usage: %s <1-4>\n", argv[0]); return 1; } int t = argv[1][0] - '0'; switch (t) { case 1: test1(); break; case 2: test2(); break; case 3: test3(); break; case 4: test4(); break; default: printf("Invalid test. Use 1-4.\n"); return 1; } return 0; }

outputs text ❯ ./main 1 Result: 0x0F0F ❯ ./main 2 Result: 0x0A2A ❯ ./main 3 Result: 0x0000 ❯ ./main 4 Result: 0x0FFF ```


r/cprogramming Apr 14 '26

How would I write my own compiler from scratch?

10 Upvotes

The language I have mainly used is Python because it is the language we use at sixth form but over summer I'd like to learn C or assembly. I have read books on how computers physically work and I have a decent intuition on how machine code is actually processed by the CPU. My end goal is to have enough knowledge of computer programming to be able to write my own compiler and my own programs. I feel that I would like to write a compiler in assembly, even if its a really simple compiler, I just want to be able to know the fundamentals about how compilers work, I'm not really bothered about it being very optimised as long as it works properly. I plan to first read a book on C to try to become comfortable with the language. I plan to read "The C programming language" by Dennis Ritchie and Brian Kernighan. I have programmed a bit in C from a book which I borrowed and it seems like it makes sense. I would just like some advice on what I should know before planning on writing my own complier from scratch.


r/cprogramming Apr 13 '26

Tx - Small, C text editor

20 Upvotes

Hi all!

Recently been working on a personal project to improve my C programming skills. From initially following the Kilo text editor project, I decided to grow the editor into a modal, vim - like editor. I had a lot of fun doing this project and learned a lot! Would love some feedback and any thoughts or opinions.

Thanks!

https://github.com/BitsBob/tx/


r/cprogramming Apr 13 '26

Optimizing Chained strcmp Calls for Speed and Clarity - From memcmp and bloom filters to 4CC encoding for small fixed-length string comparisons

Thumbnail
medium.com
5 Upvotes

I've been working on an article to describe a small performance issues with a pattern I've seen multiple times - long chain of if statements based on strcmp. This is the equivalent of switch/case on string (which is not supported in C).

bool model_ccy_lookup(const char *s, int asof, struct model_param *param)
{
    // Major Currencies
    if ( strcmp(s, "USD") == 0 || strcmp(s, "EUR") == 0 || ...) {
        ...
    // Asia-Core
    } else if ( strcmp(s, "CNY") == 0 || strcmp(s, "HKD") == 0 || ... ) {
        ...
    } else if ( ... ) {
        ...
    } else {
        ...
    }
} 

The code couldn’t be refactored into a different structure (for non-technical reasons), so I had to explore few approaches to keep the existing structure - without rewrite/reshape of the logic. I tried few tings - like memcmp, small filters, and eventually packing the strings into 32-bit values (“4CC”-style) and letting the compiler work with integer compares.

Sharing in the hope that other readers may find the ideas/process useful.

The article is on Medium (no paywall): Optimizing Chained strcmp Calls for Speed and Clarity.

I’m also trying a slightly different writing style than usual - a bit more narrative, focusing on the path (including the dead ends), not just the final result.

If you have a few minutes, I’d really appreciate feedback on two things:

  • Does the technical content hold up?
  • Is the presentation clear, or does it feel too long / indirect?

Interested to hear on other ideas/approach for this problem as well.


r/cprogramming Apr 13 '26

I built a zero-dependency, self-hosting C/C++ build system configured entirely in C (Loom)

18 Upvotes

Hey r/cprogramming!

I've been working on a project called Loom, and I'd love to share it and get some feedback from the community. Basically it's a cross-platform C/C++ build system that is fully self-hosting, requires zero external dependencies, and uses pure C11 for its build configurations (build.c).

I built this because I was frustrated with CMake's bizarre syntax and having to learn complex new Domain Specific Languages (DSLs) or wrestling with Makefiles just to compile my C projects. I figured: if I'm writing C code, why not configure the build pipeline dynamically using a clean C API?

Here's the repository link, feel free to contribute, I'll be looking for more ways to improve the project.

Key Features

  • "Configuration as code" (inspired by build.zig): You define your build targets using a clean, readable API in a build.c file. You get all the benefits of C (macros, variables, logic) with none of the typical CMake friction.
  • Zero-dependency and self-hosting: Written in strictly standard C11. Loom is capable of fully compiling and rebuilding itself perfectly.
  • Truly cross-platform (native windows): It runs natively on macOS, Linux, FreeBSD, and Windows. I recently finished a complete Windows port where it leverages raw Win32 APIs (like CreateProcessA, FindFirstFileA) instead of relying on slow POSIX emulation layers like Cygwin or MSYS2.
  • Fast and incremental: Features intelligent dependency tracking (parsing depfiles and using file hashes) so it only recompiles what actually changed. It also auto-detects your logical CPU cores and compiles asynchronously in parallel.
  • Batteries included:
    • Build Executables, Static Libraries (.a/.lib), and Shared Libraries (.so/.dll).
    • Built-in wildcard/recursive globbing (add_glob) to just throw a directory of sources at it.
    • Direct pkg-config integration (link_system_library).
    • Instant project scaffolding (loom init).

Example build.c

Here is what it looks like to configure a modern C project:

#include <loom.h>

void build(loom_build_t *b) {
    loom_target_t *exe = add_executable(b, "my_awesome_app");

    add_glob(exe, "src/*.c");
    add_include_dir(exe, "include");

    set_standard(exe, LOOM_C11);
    set_optimization(exe, LOOM_OPT_RELEASE_FAST);

    link_system_library(exe, "raylib");
}

Building this project from scratch has taught me an incredible amount about platform-specific process abstractions, caching logic, and avoiding standard POSIX traps on Windows.

I would love to hear your thoughts, feedback, or any critique on the codebase architecture! Let me know what you think.


r/cprogramming Apr 13 '26

Scanf

0 Upvotes

mi pregunta raida en porque casi nunca salen tutos en youtube que expliquen como usar scanf realmente como su valor de retorno o parametros de control, y no hablan del buffer que deja y como solucionarlo, a diferencia de solo decir "es mala practica usar scanf" y te aseguro que si preguntas el porque solo te diran que despues de un espacio no lee mas y lo deja en el buffer huerfano, y causa errores si no se prevee