So I'm calling a whole lot of functions what kind of have a similar pattern
(disclaimer:I did not write these)
They go like so:
Write_thing0<x>_object00<y>(somedata);
where <x> takes values from 0 to 6 and <y> takes values from 1 to 20.
Is there a sane way to do this, perhaps in a loop? The token-pasting operator was suggested but that doesn't work or I can't find a way to use it.
Edit:
Okay so I'll go into more depth:
Write_thing000_object001_A(uint8);
Write_thing000_object001_B(uint8);
Write_thing000_object001_C(uint16);
.................................
Write_thing000_object001_Z(uint8);
Write_thing000_object002_A(uint8);
.................................
Write_thing000_object002_Z(uint8);
/* all the way up to object 20, then thing changes to 001 and object count resets */
the pattern of parameters stays the same in each A-Z block.
I hope that makes more sense.
It can be done with x-macros:
#define CALL_ONE(i,j) call_func_##i##_##j(); // Put your function name here.
#define LIST_A(m,d) m(0,d) m(1,d) m(2,d) // Replace 0,1,2 with actual values.
#define LIST_B(m,d) m(X,d) m(Y,d) m(Z,d) // Replace X,Y,Z with actual values.
#define CALL_A(x,unused) LIST_A(CALL_ONE,x)
#define CALL_B() LIST_B(CALL_A,)
Now, CALL_B() expands to:
call_func_0_X(); call_func_1_X(); call_func_2_X();
call_func_0_Y(); call_func_1_Y(); call_func_2_Y();
call_func_0_Z(); call_func_1_Z(); call_func_2_Z();
It should be easy to adapt this for your purposes.
From your example you seem to suggest that the code looks like this:
Write_thing000_object001(somedata);
Write_thing000_object002(somedata);
Write_thing000_object003(somedata);
Write_thing000_object004(somedata);
Write_thing000_object005(somedata);
/// lots of lines
Write_thing006_object0020(somedata);
If this is exactly what your code looks like fine. But it raises a lot of questions to me
1) Does some data stay the same for each function call (or set of calls)
2) Is every function name used or is a subset of names
3) What do all these functions do? It seems likely give the name that they could be all be rewritten like this:
Write_thing_object(somedata,x,y);
then you just have one function and you can put the whole thing in a loop -- why can't you do that?
Also as a side note, this is often called a 'dispatch pattern', if you simple make this function and have it call the correct other function. You could do this efficiently by creating a 2 dimension array of function pointers. If this is what you need to do I could show you how to do that.
Related
I've been following the guide on Exceljet for how to create a recursive LAMBDA function that removes all numbers from a string. For example, A1B2C3D4E5 becomes ABCDE.
The only thing I wanted differently was to have the string containing the character omissions stored inside the function rather than the cell. So, I took away the chars parameter from the opening line and used the LET function to store the string.
The problem is I keep getting a #VALUE! error and can't work out why.
=LAMBDA(str,sub,
LET(chars,"0123456789",
IF(chars="",str,
ReplaceChars(
SUBSTITUTE(str,LEFT(chars),sub),
MID(chars,2,LEN(chars)-1),
sub
)
)
))
A nested LET() in a recursive LAMBDA() is going to be troublesome since every time you'd use the variable in the recursion you'd start from scratch. Replacing characters will therefor never stop (if my interpretation of this is correct). But in your case you don't even need to make a recursive LAMBDA() to replace numbers, for example:
=LAMBDA(str,LET(X,MID(str,SEQUENCE(LEN(str)),1),CONCAT(IF(ISNUMBER(X*1),"",X))))
Core of this function is now:
=LET(X,MID(A1,SEQUENCE(LEN(A1)),1),CONCAT(IF(ISNUMBER(X*1),"",X)))
which can be used outside of LAMBDA() just fine. We can even replace this with
=LET(X,MID(A1,SEQUENCE(LEN(A1)),1),CONCAT(IF(ISNUMBER(FIND(X,"0123456789")),"",X)))
to do the same thing with any character you want to replace.
Now you can call =REPLACECHARS(A1). However, IMHO the beauty of the use of variables is now lost and the original approach (for example here would have my personal preference.
So, I have tried to do the same in a case of array of structures where 'char name[100]' is the only data member.
1st part of the code
2nd part of the code
The problem that I have encountered here is that once I provide a no. of names during program runtime, the output screen either does not print anything afterwards, or, prints the data without sorting it.
output screen
I did not get any compile time errors so I believe that there is a flaw in the logic.
There's this another method I tried hoping to get positive results. I type-casted characters to integers hoping that ASCII values could be used to compare. But, the results are exactly the same (undesired results).
updated logic of the 2nd part of the code
I hope somebody helps me find a way to correct this logic or provide another logic that is efficient.
the sorting logic you used is good , but from what is see the use of function's in C need's to be provided by pointers. other wise all the data inside the function will born and die inside the function , and the all the variables in the Main will stay the same as given, that explains why the output is the same as the input
try to print inside the sorting function's to see if this is the problem.
I want to compare c and XML files with Beyond Compare. But I want to detect if there are differences within a Block to the corrosponding on the other file and if there is a difference in a block I dont want Beyond Compare to Show the difference in the block, but handle it like this block is not in the other file. I Need this because in my files are certain Code blocks which are nearly the same but do have different Signalnames in it.
So for example i got a c file that Looks like this:
//1
functioncall(
Singalname1,
Singalname2,
Singalname3,
Singalname4,
Singalname5,
Singalname6);
//2
functioncall(
Singalname31,
Singalname32,
Singalname33,
Singalname34,
Singalname53,
Singalname36);
And a second file which Looks like this:
//1
functioncall(
Singalname1,
Singalname2,
Singalname3,
Singalname4,
Singalname5,
Singalname6);
//2
functioncall(
Singalname371,
Singalname372,
Singalname373,
Singalname374,
Singalname573,
Singalname376);
If I compare those two files with BeyondCompare it determines the difference within the second function call because the signalnames all contain a 7. But i want Beondcompare compare the whol functioncall an if there are differences in the functionCall to Show the functioncall beside empty space so i can add it eaily to the second file.
So not like this:
I want it like this:
I tried to add some comments with a begin comment and an end comment with a incrementing number in it something like this:
//begin1
functioncall(
Singalname1,
Singalname2,
Singalname3,
Singalname4,
Singalname5,
Singalname6);
//end1
And then adding a specific rule in beyond compare. Unfortnatly i did not manage to add this rule to beyond compare.
Furthermore Ithink the Code is not good with this comments in it.
Beyond Compare doesn't provide a method to do this. The best workaround is to use the right click Align With command to shift the function alignment.
Did you try the "Never align differences" checkbox in the Alignment tab of the session settings?
I have the following nested struct:
hole 1x200 struct, diam 1x12 struct, which has the following fields: pos, freq1, fre12
That is:
hole(1 to 200).diam(1 to 12).pos
.freq1
.freq2
From a value (freq1 and freq2), I would like to obtain the field name of the struct. So I will need to find the value that matches with freq1 and freq2 and show the fieldname.
I tried to use structfun in order to apply a function to each field.
[struct.field]=structfun(#(x) find(x.freq1==27.059783995484867 & freq2==76.468355874897000))
But I guess I am writing something wrong on the code.
Also I create an anonymous fuction but I have the following error:
'Error using structfun / Inputs to STRUCTFUN must be scalar
structures'
. How ever when I verified if an specific value of the struct is scalar, I have a positive answerd: isscalar(hole(130).diam(10))
I belive I more near the solution using this script:
myfun=#(yourarray,desiredvalue) yourarray==desiredvalue;
%//Apply function to each field of scalar structure, it SCALAR??
desiredfieldindex=myfun(structfun(#(x) x,hole),26.697046257785030)
desiredFieldName=fNames(desiredFieldIndex)
I don´t know if I am in the rigth path, or I should utilize the function find. ALso I that case I don´t know how to implement it.
Couple of things.
FLOATING POINT VALUES! Careful!! Never compare a floating point value as val==0.3! do abs(val-0.3)<10^-8 or something similar. Read more here.
You are using structfun wrong. The function needs 2 arguments, and you are just passing 1! However, structfun will apply a function to each field so you are not using it rigth either in that sense. Lets see an example
example:
a.hithere=5;
a.notthis=3;
fun=#(x)x==5;
[isfive]=structfun(fun,a)
isfive =
1
0
As you can see, it applies the function to each of them. If you try to change the function to fun=#(x)x.hithere==5 you will get an error! As the function is applied to each field, and x.hithere.hithere or x.notthis.hithere do not exist.
If you want to check both values, you will need to check them independently making two separated calls to structfun or avoiding structfun and just making a for loop.
An Example
Suppose we have a text to write and could be converted to "uppercase or lowercase", and can be printed "at left, center or right".
Specific case implementation (too many functions)
writeInUpperCaseAndCentered(char *str){//..}
writeInLowerCaseAndCentered(char *str){//..}
writeInUpperCaseAndLeft(char *str){//..}
and so on...
vs
Many Argument function (bad readability and even hard to code without a nice autocompletion IDE)
write( char *str , int toUpper, int centered ){//..}
vs
Context dependent (hard to reuse, hard to code, use of ugly globals, and sometimes even impossible to "detect" a context)
writeComplex (char *str)
{
// analize str and perhaps some global variables and
// (under who knows what rules) put it center/left/right and upper/lowercase
}
And perhaps there are others options..(and are welcome)
The question is:
Is there is any good practice or experience/academic advice for this (recurrent) trilemma ?
EDIT:
What I usually do is to combine "specific case" implementation, with an internal (I mean not in header) general common many-argument function, implementing only used cases, and hiding the ugly code, but I don't know if there is a better way that I don't know. This kind of things make me realize of why OOP was invented.
I'd avoid your first option because as you say the number of function you end up having to implement (though possibly only as macros) can grow out of control. The count doubles when you decide to add italic support, and doubles again for underline.
I'd probably avoid the second option as well. Againg consider what happens when you find it necessary to add support for italics or underlines. Now you need to add another parameter to the function, find all of the cases where you called the function and updated those calls. In short, anoying, though once again you could probably simplify the process with appropriate use of macros.
That leaves the third option. You can actually get some of the benefits of the other alternatives with this using bitflags. For example
#define WRITE_FORMAT_LEFT 1
#define WRITE_FORMAT_RIGHT 2
#define WRITE_FORMAT_CENTER 4
#define WRITE_FORMAT_BOLD 8
#define WRITE_FORMAT_ITALIC 16
....
write(char *string, unsigned int format)
{
if (format & WRITE_FORMAT_LEFT)
{
// write left
}
...
}
EDIT: To answer Greg S.
I think that the biggest improvement is that it means that if I decide, at this point, to add support for underlined text I it takes two steps
Add #define WRITE_FORMAT_UNDERLINE 32 to the header
Add the support for underlines in write().
At this point it can call write(..., ... | WRITE_FORMAT_UNLDERINE) where ever I like. More to the point I don't need to modify pre-existing calls to write, which I would have to do if I added a parameter to its signature.
Another potential benefit is that it allows you do something like the following:
#define WRITE_ALERT_FORMAT (WRITE_FORMAT_CENTER | \
WRITE_FORMAT_BOLD | \
WRITE_FORMAT_ITALIC)
I prefer the argument way.
Because there's going to be some code that all the different scenarios need to use. Making a function out of each scenario will produce code duplication, which is bad.
Instead of using an argument for each different case (toUpper, centered etc..), use a struct. If you need to add more cases then you only need to alter the struct:
typedef struct {
int toUpper;
int centered;
// etc...
} cases;
write( char *str , cases c ){//..}
I'd go for a combination of methods 1 and 2.
Code a method (A) that has all the arguments you need/can think of right now and a "bare" version (B) with no extra arguments. This version can call the first method with the default values. If your language supports it add default arguments. I'd also recommend that you use meaningful names for your arguments and, where possible, enumerations rather than magic numbers or a series of true/false flags. This will make it far easier to read your code and what values are actually being passed without having to look up the method definition.
This gives you a limited set of methods to maintain and 90% of your usages will be the basic method.
If you need to extend the functionality later add a new method with the new arguments and modify (A) to call this. You might want to modify (B) to call this as well, but it's not necessary.
I've run into exactly this situation a number of times -- my preference is none of the above, but instead to use a single formatter object. I can supply it with the number of arguments necessary to specify a particular format.
One major advantage of this is that I can create objects that specify logical formats instead of physical formats. This allows, for example, something like:
Format title = {upper_case, centered, bold};
Format body = {lower_case, left, normal};
write(title, "This is the title");
write(body, "This is some plain text");
Decoupling the logical format from the physical format gives you roughly the same kind of capabilities as a style sheet. If you want to change all your titles from italic to bold-face, change your body style from left justified to fully justified, etc., it becomes relatively easy to do that. With your current code, you're likely to end up searching through all your code and examining "by hand" to figure out whether a particular lower-case, left-justified item is body-text that you want to re-format, or a foot-note that you want to leave alone...
As you already mentioned, one striking point is readability: writeInUpperCaseAndCentered("Foobar!") is much easier to understand than write("Foobar!", true, true), although you could eliminate that problem by using enumerations. On the other hand, having arguments avoids awkward constructions like:
if(foo)
writeInUpperCaseAndCentered("Foobar!");
else if(bar)
writeInLowerCaseAndCentered("Foobar!");
else
...
In my humble opinion, this is a very strong argument (no pun intended) for the argument way.
I suggest more cohesive functions as opposed to superfunctions that can do all kinds of things unless a superfunction is really called for (printf would have been quite awkward if it only printed one type at a time). Signature redundancy should generally not be considered redundant code. Technically speaking it is more code, but you should focus more on eliminating logical redundancies in your code. The result is code that's much easier to maintain with very concise, well-defined behavior. Think of this as the ideal when it seems redundant to write/use multiple functions.