I need to use define inside another define to make code simple by replacing only at one place.
Problem (Objective C code)
#define URL #"www.example.com/"
#define UserLogin #"<Login xmlns=\"http://www.example.com/\"><Email>%#</Email><Password>%#</Password></Login>"
.
.
.
#define UserRegistration #"<Reg xmlns=\"http://www.example.com/\"><Email>%#</Email></Reg>"
I am having a list of statements like this can I use URL at the place of xmlns=\".../\"
can I use the above defined URL like xmlns=\"URL/\"
so I can replace url at only at one place.
You can in the following way --
#define URL #"www.example.com/"
#define UrlWithUrl [NSString stringWithFormat:#"<Login xmlns=\"http://%#/\">",URL]
A #define token will be expanded in a subsequent #define provided it is not in a string – in your case you wish to use URL in a string so just writing in the string will not result in it being expanded.
However in (Objective-)C adjacent string literals are automatically concatenated by the compiler to become a single string literal, e.g.:
#"one " #"two"
is transformed by the compiler into:
#"one two"
Knowing that you can rewrite your definition of UserLogin as three strings which will be joined by the compiler into one:
#define UserLogin #"<Login xmlns=\"" URL #"\"><Email>%#</Email><Password>%#</Password></Login>"
and a use of UserLogin in your code will be replaced by the three strings which are then joined by the compiler, e.g.
NSLog("%#", UserLogin);
becomes after preprocessing:
NSLog("%#", #"<Login xmlns=\"" #"www.example.com/" #"\"><Email>%#</Email><Password>%#</Password></Login>");
and then the adjacent string literals are joined:
NSLog("%#", #"<Login xmlns=\"www.example.com/\"><Email>%#</Email><Password>%#</Password></Login>");
For more complex cases you will need to read up on the preprocessor, in particular stringification
In Xcode you can see the results of your macros by selecting the menu item Product:Perform Action:Preprocess "...", this opens a window showing your source file after all the macros have been expanded, i.e. the resultant source code the compiler will compile.
HTH
Related
I have the following Objective-C code:
[#"http://www.google.com" stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
// http%3A//www.google.com
And yet, in Swift:
"http://www.google.com".addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
// http://www.google.com
To what can I attribute this discrepancy?
..and for extra credit, can I rely on this code to encode for url path reserved characters while passing a full url like this?
The issue actually rests in the difference between NSString method stringByAddingPercentEncodingWithAllowedCharacters and String method addingPercentEncoding(withAllowedCharacters:). And this behavior has been changing from version to version. (It looks like the latest beta of iOS 11 now restores this behavior we used to see.)
I believe the root of the issue rests in the particulars of how paths are percent encoded. Section 3.3 of RFC 3986 says that colons are permitted in paths except in the first segment of a relative path.
The NSString method captures this notion, e.g. imagine a path whose first directory was foo: (with a colon) and a subdirectory of bar: (also with a colon):
NSString *string = #"foo:/bar:";
NSCharacterSet *cs = [NSCharacterSet URLPathAllowedCharacterSet];
NSLog(#"%#", [string stringByAddingPercentEncodingWithAllowedCharacters:cs]);
That results in:
foo%3A/bar:
The : in the first segment of the page is percent encoded, but the : in subsequent segments are not. This captures the logic of how to handle colons in relative paths per RFC 3986.
The String method addingPercentEncoding(withAllowedCharacters:), however, does not do this:
let string = "foo:/bar:"
os_log("%#", string.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
Yields:
foo:/bar:
Clearly, the String method does not attempt that position-sensitive logic. This implementation is more in keeping with the name of the method (it considers solely what characters are "allowed" with no special logic that tries to guess, based upon where the allowed character appears, whether it's truly allowed or not.)
I gather that you are saddled with the code supplied in the question, but we should note that this behavior of percent escaping colons in relative paths, while interesting to explain what you experienced, is not really relevant to your immediate problem. The code you have been provided is simply incorrect. It is attempting to percent encode a URL as if it was just a path. But, it’s not a path; it’s a URL, which is a different thing with its own rules.
The deeper insight in percent encoding URLs is to acknowledge that different components of a URL allow different sets of characters, i.e. they require different percent encoding. That’s why NSCharacterSet has so many different URL-related character sets.
You really should percent encode the individual components, percent encoding each with the character set allowed for that type of component. Only when the individual components are percent encoded should they then be concatenated together to form the whole the URL.
Alternatively, NSURLComponents is designed precisely for this purpose, getting you out of the weeds of percent-encoding the individual components yourself. For example:
var components = URLComponents(string: "http://httpbin.org/post")!
let foo = URLQueryItem(name: "foo", value: "bar & baz")
let qux = URLQueryItem(name: "qux", value: "42")
components.queryItems = [foo, qux]
let url = components.url!
That yields the following, with the & and the two spaces properly percent escaped within the foo value, but it correctly left the & in-between foo and qux:
http://httpbin.org/post?foo=bar%20%26%20baz&qux=42
It’s worth noting, though, that NSURLComponents has a small, yet fairly fundamental flaw: Specifically, if you have query values, NSURLQueryItem, that could have + characters, most web services need that percent escaped, but NSURLComponents won’t. If your URL has query components and if those query values might include + characters, I’d advise against NSURLComponents and would instead advise percent encoding the individual components of a URL yourself.
I am working in an ABAP program and I have a question.
For example in C# when we have a String variable: string name; , and we want this to be filled with some data from a textbox but also add some ohter text.
For example:
string name = "Hello: " + textBox1.text;,
And I want to ask you how can I do this in ABAP ??? How to add text plus the text written from a Parameter type C?
CONCATENATE and the concatenate operator && will do it as answered by Jagger and vwegert. To do it with string expressions, you use the below where name is the screen field or whatever that has the name in it (it doesn't need to be a field-symbol):
greeting = |Hello: { <name> }|.
String expressions are extremely useful as they can be used to build up complex values without declaring extra variables - e.g. they can passed as directly as function module or method parameters without first assigning to a local variable.
You can either use the CONCATENATE keyword or -- in newer releases -- string expressions. Be sure to check the online documentation and sample programs available using the transaction ABAPDOCU, it will save you a ton of seemingly basic questions.
The equivalent operator is &&.
So in your case it would be:
name = 'Hello: ' && textBox1->text.
I want to make a scientific calculator in which the user enters something like 3+4*(3-5)/23 and then the calculator can return the value.
Now I'm trying to find a way to parse a string of mathematical expression. I know that there are some built parsers and algorithms but I want to know whether it's possible by using #define method.
Basically, I want to use the #define to literally remove the # and " " in a string and make it look like an expression that can be evaluated. At this stage, I won't use unknown variables like x or 3*k or a*b/c. All will be numbers and operators like 3+4 and 32 that can be directly evaluated by the compiler. Here is what I want to write in #define:
#define eval#"(x)" x
In the above code, eval is just a signal of parsing and the #"x" is the actual string that need to parse and x is a mathematical expression. After the translation, only x will remain. For example, if I write
double result = eval#"(3+4)";
the compiler will read
double result = 3+4;
(according to my understanding of #define). However, the code does not work. I suspect that the quotation marks confuse the compiler and cause the code to break. So my question is: can anyone come up with a solution using #define?
This is not possible with the preprocessor, no string manipulation besides concatenation supported.
Why would you need the #"x" syntax anyways? You can just put the expression right there in the code.
People are right, you cannot do it in direct way, however if you very want macro:
#define eval(x) [[[NSExpression expressionWithFormat:x] expressionValueWithObject:nil context:nil] doubleValue]
double result = eval(#"3+4");
#define is an invocation of the C preprocessor, which is not capable of this kind of manipulation. It almost sounds like you're trying to define an Objective-C macro that would do the same kind of thing as a LISP macro, but that's not possible. Why don't you tell us what the original problem is that you're trying to solve... I think we can probably come up with an easier way to do what you're trying to do.
I'm trying to simplify my code by using #define statements. This is because it contains a lot of repetitive "chunks" of code that cannot be repeated using the obvious alternative, functions, because in these chunks, variables need to be declared like you'd do in a #define statement, e.g. #define dostuff(name) int name##Variable;.
Code
#define createBody(name,type,xpos,ypos,userData,width,height) b2BodyDef name##BodyDef;\
name##BodyDef.type = type==#"dynamic"?b2_dynamicBody:b2_staticBody;\
name##BodyDef.position.Set(xpos,ypos);\
name##BodyDef.userData = userData;\
name=world->CreateBody(&name##BodyDef);\
b2PolygonShape name##shape;\
name##shape.SetAsBox(width/ptm_ratio/2,height/ptm_ratio/2);
... and applying that in the following:
createBody(block, #"dynamic", winSize.width*5/6/ptm_ratio, winSize.height*1/6/ptm_ratio, ((__bridge void*)blockspr), blockspr.contentSize.width, blockspr.contentSize.height)
// error appears there: ^
Now my point is that everything's working great, no errors, except a single one that's freaking me out:
Expected unqualified-id
which points at the first bracket in ((__bridge ..., as indicated. (That argument gets passed via the userData argument to createBody.)
I know this code is nowhere near simple, but since everything else is working, I believe that an answer must exist.
This is my first question on SO, so if there's anything unclear or insufficient, please let me know!
I'm trying to simplify my code by using #define statements.
This sounds an alarm in my mind.
Break this down into functions. You said you can't. I say you can.
Notice that your macro here:
createBody(name,type,xpos,ypos,userData,width,height);
It has exactly the same syntax as a C function. So you've already created a function, you only declared it as a macro. There's no reason why you couldn't rewrite it as a function (C or Objective-C doesn't matter). You do not need to give each body its own name, instead you could store them in a dictionary (careful though because Box2D takes ownership of the bodies).
Task:
I am planning to parse a formula string in NSPredicate and to replace variables in the string by their numeric values. The variables are names for properties of existing object instances in my data model, for instance I have a class "company" with an instance "Apple Corp."
Set-up:
My formula would like look like this: "Profitability_2011_in% = [Profit 2011] / [Revenue 2011]"
The instance "Apple Corp" would have the following properties:
Revenue 2009 = 10, Revenue 2010 = 20, Revenue 2011 = 30,
Profit 2009 = 5, Profit 2010 = 10, Profit 2011 = 20.
Hence, the formula would yield 20 / 30 = 67%.
Variables are usually two-dimensional, for instance defined by "profit" as the financial statement item and "year" (for instance 2011).
The variables are enclosed in [ ] and the dimensions are separated by " " (whitespace).
How I would do it
My implementation would begin with NSRegularExpression's matchesInString:options:range: to get an array of all variables in the formula (Profit 2011, Revenue 2011) and then construct an NSDictionary (key = variable name) out of this array by querying my data model.
What do you think?
Is there a better way to do it in your view?
In the formula, how would you replace the variables by their values?
How would you parse the formula?
Thank you!!
Yes, you can do this. This falls under the category of "Using NSPredicate for things for which it was not intended", but will work just fine.
You'll need to replace your variables with a single word that start with a $, since that's how NSPredicate denotes variables:
NSPredicate *p = [NSPredicate predicateWithFormat:#"foo = $bar"];
However you want to do that, great. NSRegularExpression is a fine way to do that.
Once you do that, you'll have something like this:
#"$profitability2011 = $profit2011 / $revenue2011"
You can then pop this through +predicateWithFormat:. You'll get back an NSComparisonPredicate. The -leftExpression will be of type NSVariableExpressionType, and the -rightExpression will be of type NSFunctionExpressionType.
This is where things start to get hairy. If you were to -evaluteWithObject:substitutionVariables:, you'd simply get back a YES or NO value, since a predicate is simply a statement that evaluates to true or false. I haven't explored how you could just evaluate one side (in this case, the -rightExpression), but it's possible that -[NSExpression expressionValueWithObject:context:] might help you. I don't know, because I'm not sure what that "context" parameter is for. It doesn't seem like it's a substitution dictionary, but I could be wrong.
So if that doesn't work (and I have no idea if it will or not), you could use my parser: DDMathParser. It has a parser, similar to NSPredicate's parser, but is specifically tuned for parsing and evaluating mathematical expressions. In your case, you'd do:
#import "DDMathParser.h"
NSString *s = #"$profit2011 / $revenue2011";
NSDictionary *values = ...; // the values of the variables
NSNumber *profitability = [s numberByEvaluatingStringWithSubstitutions:values];
The documentation for DDMathParser is quite extensive, and it can do quite a bit.
edit Dynamic variable resolution
I just pushed a change that allows DDMathParser to resolve functions dynamically. It's important to understand that a function is different from a variable. A function is evaluated, whereas a variable is simply substituted. However, the change only does dynamic resolution for functions, not variables. That's ok, because DDMathParser has this neat thing called argumentless functions.
An argumentless function is a function name that's not followed by an opening parenthesis. For convenience, it's inserted for you. This means that #"pi" is correctly parsed as #"pi()" (since the constant for π is implemented as a function).
In your case, you can do this:
Instead of regexing your string to make variables, simply use the names of the terms:
#"profit_2011 / revenue_2011";
This will be parsed as if you had entered:
#"divide(profit_2011(), revenue_2011())"
You can the set up your DDMathEvaluator object with a function resolver. There are two examples of this in the DDMathParser repository:
This example shows how to use the resolver function to look up the "missing" function in a substitution dictionary (this would be most like what you want)
This example shows you to interpret any missing function as if it evaluated to 42.
Once you implement a resolver function, you can forego having to package all your variables up into a dictionary.
Is there a better way to do it in your view?
Yes - using Flex & Bison.
Possibly you could achieve what you want with a regex - but for many expression grammars, a regex isn't powerful enough to parse the grammar. Also, regex things like this get large, unreadable, and unyieldy.
You can use Flex (a lexer) and Bison (a parser) to create a grammar definition for your expressions, and generate C code (which, as I'm sure you know, works perfectly with Objective-C since Objective-C is C) which you can use to parse your expressions.
In the formula, how would you replace the variables by their values?
As you parse through it with Bison you should have a hash table with variable names and their current values. When you generate the syntax tree, add references to the variables to your syntax tree nodes.
How would you parse the formula?
Again - Flex & Bison are specifically meant to do this kind of thing - and they excel at it.