Struct function accessing struct identifiers

I am a newbie in zig trying to read command line arguments, handling and checking them.
getting : error struct has no member named …

const std = @import("std");

//  TEST  [/L=<filename> or empty=screen] [/DL]");
const Arguments = struct {
	log 		: [] u8   ,
	logging		: bool    ,
	debugtolog 	: bool    ,

     //pub fn setLogging ( setlog: bool ) void { 
     //  std.debug.print("true", .{});
        
    //	logging = setlog; 
    //}
};


fn checkMinimumArguments() !void { 
    const minargs: u8 = 1; 
    const maxargs: u8 = 2;
    var   rc: bool    = false;
           
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();

    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);

    std.debug.print("There are {d} args:\n", .{args.len});

    if (args.len < minargs or args.len > maxargs) {
        std.debug.print("Usage:\n", .{});
	std.debug.print("  TEST  [/L=<filename> or empty=screen] [/DL]", .{});
    }

    for(args) |arg| {
        std.debug.print("  {s}\n", .{arg});
    }
    
    rc = checklogging(args);		

    // .. other commandline arguments	
}


fn checklogging(args: [][:0] u8) bool {
    const	logparmtext	 = "/L=";
   // const	debuglogparmtext = "/DL";
    var		str_found: bool  = false;

    for (args) |value| {
        if ( std.mem.startsWith(u8, value, logparmtext) ) {
	    std.debug.print("true", .{});
	    str_found = true;
	}
	else {
	   std.debug.print("false", .{});
	   str_found = false;
        }
    }
    //Arguments.setLogging ( str_found );
    Arguments.logging = str_found;

    return str_found;
}

pub fn main() !void { 
    try checkMinimumArguments();
}
1 Like

Welcome to Ziggit @haheide!

Arguments is a struct type, it isn’t an instance of that type.

You could create an Arguments instance in your main function and then pass a pointer to it to your checkMinimumArguments function:

fn checkMinimumArguments(arguments:*Arguments) !void {
    ...
    rc = checklogging(args, arguments);
    ...
}
fn checklogging(args: [][:0] u8, arguments:*Arguments) bool {
    ...
    arguments.logging = str_found;
    ...
}

pub fn main() !void {
    var arguments: Arguments = undefined;
    try checkMinimumArguments(&arguments);
}

Then further you could turn your checking functions into methods of the Arguments type by swapping the *Arguments to be the first parameter and putting the functions within the struct:

const Arguments = struct {
    log: [] u8,
    logging: bool,
    debugtolog: bool,

    fn checkMinimumArguments(arguments:*Arguments) !void {
        ...
        rc = arguments.checklogging(args);
        ...
    }
    fn checklogging(arguments:*Arguments, args: [][:0] u8) bool {
        ...
        arguments.logging = str_found;
        ...
    }
};

pub fn main() !void {
    var arguments: Arguments = undefined;
    try arguments.checkMinimumArguments();
}

Then another thing after that would be to put the GeneralPurposeAllocator in the main function and pass the allocator as a parameter.


Just a side note, but instead of doing your own hand rolled source code formatting, I think it is better and easier to use zig fmt and auto-format the code.

I was doing these kinds of column based vertical alignments of things in other languages previously too sometimes, but I have found when you stop doing these manual vertical spacing of code for a little while, your brain adapts to no longer wanting or expecting to get that kind of layout and it allows you to modify and write code more quickly.

You also don’t have spacing layout changes mixed with your actual code changes in your commits, making clearer what actually changed.

Also I found it helpful when looking at other peoples code that there is a common way to format things.

3 Likes

Thanks for answer!

1 Like