I am writing some codes that deals with string with double quote in Swift. Here is what I've done so far:
func someMethod {
let string = "String with \"Double Quotes\""
dealWithString(string)
}
func dealWithString(input: String) {
// I placed a breakpoint here.
}
When I run the codes the breakpoint stopped there as usual but when I input the following into the debugger:
print input
This is what I get:
(String) $R0 = "String with \"Double Quotes\""
I got this string with the backslashes. But if I tried to remove the backslashes from the source, it will give me compile error. Is there a workaround for this?
You are doing everything right. Backslash is used as an escape character to insert double quotes into Swift string precisely in the way that you use it.
The issue is the debugger. Rather than printing the actual value of the string, it prints the value as a string literal, i.e. enclosed in double quotes, with all special characters properly escaped escaped.
If you use print(input) in your code, you would see the string that you expect, i.e. with escape characters expanded and no double quotes around them.
Newer versions of Swift support an alternate delimiter syntax that lets you embed special characters without escaping. Add one or more # symbols before and after the opening and closing quotes, like so:
#"String with "Double Quotes""#
Be careful, though, because other common escapes require those extra # symbols, too.
#"This is not a newline: \n"#
#"This is a newline: \#n"#
You can read more about this at Extended String Delimiters at swift.org.
extension CustomStringConvertible {
var inspect: String {
if self is String {
return "\"\(self)\""
} else {
return self.description
}
}
}
let word = "Swift"
let s = "This is \(word.inspect)"
Related
I know that single and double quotes have at least some level of equivelence in Dart. For example,
var myString = "Hello world"; // double quotes
and
var myString = 'Hello world'; // single quotes
have no programmatic difference to my knowledge.
I keep seeing them used seemingly interchangeably in various examples and in some documentation. I'm wondering if there is a subtle difference that I am missing or if there is a recommended style to follow, especially in Flutter.
This is a Q&A self answer after reading the Flutter and Dart style guides.
Single and double quotes both work in Dart
final myString = 'hello';
is the same as
final myString = "hello";
Delimiters need to be escaped
Use a \ backslash to escape single quotes in a single quote string.
final myString = 'Bob\'s dog'; // Bob's dog
Same thing to escape double quotes in a double quote string.
final myString = "a \"quoted\" word"; // a "quoted" word
But no need to escape anything if the delimiter is different.
final myString = "Bob's dog"; // Bob's dog
final myString = 'a "quoted" word'; // a "quoted" word
Also no need to worry about the value passed into an interpolated string.
final value = '"quoted"'; // "quoted"
final myString = "a $value word"; // a "quoted" word
Prefer single quotes in Flutter
The Flutter style guide recommends using single quotes for everything
final myString = 'hello';
except for nested strings
print('Hello ${name.split(" ")[0]}');
or strings containing single quotes (optional)
final myString = "Bob's dog";
final myString = 'Bob\'s dog'; // ok
The Dart style guide appears to be silent on the issue.
I am constructing json code syntax in a string. The format needs to be {"field":"somedata"} and so on. The problem is that I need to use a string and the code that I wrote is:
astring=astring + "{\"field\":\"somedata\"}"
The problem is that when I save the string as a textfile the backslashes is also saved and disqualifies this as json.
The I tried to use a diff char (a dog) as a replacement for \" and tried to replace the dog using:
res_str=res_str.stringByReplacingOccurrencesOfString("🐶", withString: "\"")
But the backslash was included. And finally I tried to
res_str=res_str.stringByReplacingOccurrencesOfString("🐶", withString: String(UnicodeScalar(34)))
But the backslash is included. In PHP for example I could have used single quote as outer string separator but that isn't allowed in Swift.
Any ideas?
I am trying to escape string for new line i.e \n.
For example lets say string is:-
First Line Of String
second Line of String
Third Line of String
Now if i use String extension and say
func escapeString() -> String{
newString = self.stringByRemovingPercentEncoding
return newString
}
This extension does not give me newString as
First Line Of String\nSecond Line Of String\nThird Line Of String
I need above string as a jsonString to pass to server.i.e. i have to String encode it
Swift 5
You can use JSONEncoder to escape \n, \, \t, \r, ', " and etc. characters instead of manually replacing them in your string e.g.:
extension String {
var escaped: String {
if let data = try? JSONEncoder().encode(self) {
let escaped = String(data: data, encoding: .utf8)!
// Remove leading and trailing quotes
let set = CharacterSet(charactersIn: "\"")
return escaped.trimmingCharacters(in: set)
}
return self
}
}
let str = "new line - \n, quote - \", url - https://google.com"
print("Original: \(str)")
print("Escaped: \(str.escaped)")
Outputs:
Original: new line -
, quote - ", url - https://google.com
Escaped: new line - \n, quote - \", url - https:\/\/google.com
stringByRemovingPercentEncoding is for percent encoding as used in URLs, as you might expect from the name. (If not from that, maybe from reading the docs, the pertinent part of which even shows up in Xcode code completion.) That is, it takes a string like "some%20text%20with%20spaces" and turns it into "some text with spaces".
If you want to do a different kind of character substitution, you'll need to do it yourself. But that can still be a one-liner:
extension String {
var withEscapedNewlines: String {
return self.stringByReplacingOccurrencesOfString("\n", withString: "\\n")
}
}
Note the first argument to self.stringByReplacingOccurrencesOfString is an escape code passed to the Swift compiler, so the actual value of the argument is the newline character (ASCII/UTF8 0x0A). The second argument escapes the backslash (in the text passed to the Swift compiler), so the actual value of the argument is the text \n.
I saw the operator r#"" in Rust but I can't find what it does. It came in handy for creating JSON:
let var1 = "test1";
let json = r#"{"type": "type1", "type2": var1}"#;
println!("{}", json) // => {"type2": "type1", "type2": var1}
What's the name of the operator r#""? How do I make var1 evaluate?
I can't find what it does
It has to do with string literals and raw strings. I think it is explained pretty well in this part of the documentation, in the code block that is posted there you can see what it does:
"foo"; r"foo"; // foo
"\"foo\""; r#""foo""#; // "foo"
"foo #\"# bar";
r##"foo #"# bar"##; // foo #"# bar
"\x52"; "R"; r"R"; // R
"\\x52"; r"\x52"; // \x52
It negates the need to escape special characters inside the string.
The r character at the start of a string literal denotes a raw string literal. It's not an operator, but rather a prefix.
In a normal string literal, there are some characters that you need to escape to make them part of the string, such as " and \. The " character needs to be escaped because it would otherwise terminate the string, and the \ needs to be escaped because it is the escape character.
In raw string literals, you can put an arbitrary number of # symbols between the r and the opening ". To close the raw string literal, you must have a closing ", followed by the same number of # characters as there are at the start. With zero or more # characters, you can put literal \ characters in the string (\ characters do not have any special meaning). With one or more # characters, you can put literal " characters in the string. If you need a " followed by a sequence of # characters in the string, just use the same number of # characters plus one to delimit the string. For example: r##"foo #"# bar"## represents the string foo #"# bar. The literal doesn't stop at the quote in the middle, because it's only followed by one #, whereas the literal was started with two #.
To answer the last part of your question, there's no way to have a string literal that evaluates variables in the current scope. Some languages, such as PHP, support that, but not Rust. You should consider using the format! macro instead. Note that for JSON, you'll still need to double the braces, even in a raw string literal, because the string is interpreted by the macro.
fn main() {
let var1 = "test1";
let json = format!(r#"{{"type": "type1", "type2": {}}}"#, var1);
println!("{}", json) // => {"type2": "type1", "type2": test1}
}
If you need to generate a lot of JSON, there are many crates that will make it easier for you. In particular, with serde_json, you can define regular Rust structs or enums and have them serialized automatically to JSON.
The first time I saw this weird notation is in glium tutorials (old crate for graphics management) and is used to "encapsulate" and pass GLSL code (GL Shading language) to shaders of the GPU
https://github.com/glium/glium/blob/master/book/tuto-02-triangle.md
As far as I understand, it looks like the content of r#...# is left untouched, it is not interpreted in any way. Hence raw string.
This question already has answers here:
What is the syntax for a multiline string literal?
(5 answers)
Closed 1 year ago.
Is it possible to write something like:
fn main() {
let my_string: &str = "Testing for new lines \
might work like this?";
}
If I'm reading the language reference correctly, then it looks like that should work. The language ref states that \n etc. are supported (as common escapes, for inserting line breaks into your string), along with "additional escapes" including LF, CR, and HT.
Another way to do this is to use a raw string literal:
Raw string literals do not process any escapes. They start with the
character U+0072 (r), followed by zero or more of the character U+0023
(#) and a U+0022 (double-quote) character. The raw string body can
contain any sequence of Unicode characters and is terminated only by
another U+0022 (double-quote) character, followed by the same number
of U+0023 (#) characters that preceded the opening U+0022
(double-quote) character.
All Unicode characters contained in the raw string body represent
themselves, the characters U+0022 (double-quote) (except when followed
by at least as many U+0023 (#) characters as were used to start the
raw string literal) or U+005C (\) do not have any special meaning.
Examples for string literals:
"foo"; r"foo"; // foo
"\"foo\""; r#""foo""#; // "foo"
"foo #\"# bar";
r##"foo #"# bar"##; // foo #"# bar
"\x52"; "R"; r"R"; // R
"\\x52"; r"\x52"; // \x52
If you'd like to avoid having newline characters and extra spaces, you can use the concat! macro. It concatenates string literals at compile time.
let my_string = concat!(
"Testing for new lines ",
"might work like this?",
);
assert_eq!(my_string, "Testing for new lines might work like this?");
The accepted answer with the backslash also removes the extra spaces.
Every string is a multiline string in Rust.
But if you have indents in your text like:
fn my_func() {
const MY_CONST: &str = "\
Hi!
This is a multiline text!
";
}
you will get unnecessary spaces. To remove them you can use indoc! macros from indoc crate to remove all indents: https://github.com/dtolnay/indoc
There are two ways of writing multi-line strings in Rust that have different results. You should choose between them with care depending on what you are trying to accomplish.
Method 1: Dangling whitespace
If a string starting with " contains a literal line break, the Rust compiler will "gobble up" all whitespace between the last non-whitespace character of the line and the first non-whitespace character of the next line, and replace them with a single .
Example:
fn test() {
println!("{}", "hello
world");
}
No matter how many literal (blank space) characters (zero or a hundred) appear after hello, the output of the above will always be hello world.
Method 2: Backslash line break
This is the exact opposite. In this mode, all the whitespace before a literal \ on the first line is preserved, and all the subsequent whitespace on the next line is also preserved.
Example:
fn test() {
println!("{}", "hello \
world");
}
In this example, the output is hello world.
Additionally, as mentioned in another answer, Rust has "raw literal" strings, but they do not enter into this discussion as in Rust (unlike some other languages that need to resort to raw strings for this) supports literal line breaks in quoted content without restrictions, as we can see above.