代码之家  ›  专栏  ›  技术社区  ›  Chet

C中的多行字符串文字#

  •  824
  • Chet  · 技术社区  · 15 年前

    有没有一种简单的方法可以用C创建多行字符串?

    我现在有:

    string query = "SELECT foo, bar"
    + " FROM table"
    + " WHERE id = 42";
    

    我知道PHP有

    <<<BLOCK
    
    BLOCK;
    

    C有类似的东西吗?

    11 回复  |  直到 6 年前
        1
  •  1290
  •   John Rasch    15 年前

    你可以使用 @ 符号位于 string 形成一个 verbatim string literal :

    string query = @"SELECT foo, bar
    FROM table
    WHERE id = 42";
    

    你也 do not have to escape special characters 当你使用这个方法时,除了乔恩·斯基特的答案中所示的双引号。

        2
  •  471
  •   Jon Skeet    7 年前

    它叫做 verbatim string literal 在C中,这只是把@放在字面前面的问题。这不仅允许多行,而且还关闭了转义。例如,您可以:

    string query = @"SELECT foo, bar
    FROM table
    WHERE name = 'a\b'";
    

    唯一的转义是,如果您想要双引号,则必须添加一个额外的双引号符号:

    string quote = @"Jon said, ""This will work,"" - and it did!";
    
        3
  •  92
  •   Martin Clarke    15 年前

    另一个需要注意的是使用string.format中的字符串文本。在这种情况下,您需要转义大括号/方括号“”和“”。

    // this would give a format exception
    string.Format(@"<script> function test(x) 
          { return x * {0} } </script>", aMagicValue)
    // this contrived example would work
    string.Format(@"<script> function test(x) 
          {{ return x * {0} }} </script>", aMagicValue)
    
        4
  •  84
  •   dav_i    9 年前

    我发现使用字符串文字的问题是它可以使代码看起来有点像。” 奇怪的 “因为为了不在字符串本身中获得空格,必须完全左对齐:

        var someString = @"The
    quick
    brown
    fox...";
    

    讨厌。

    所以我喜欢使用的解决方案是:

    var someString = String.Join(
        Environment.NewLine,
        "The",
        "quick",
        "brown",
        "fox...");
    

    当然,如果您只想像现在这样逻辑地拆分SQL语句的行,而实际上不需要新行,那么您可以用 Environment.NewLine 对于 " " .

        5
  •  79
  •   Riegardt Steyn AdrianD    8 年前

    作为补充说明,使用C 6.0,现在可以将插入字符串与逐字字符串文字组合在一起:

    string camlCondition = $@"
    <Where>
        <Contains>
            <FieldRef Name='Resource'/>
            <Value Type='Text'>{(string)parameter}</Value>
        </Contains>
    </Where>";
    
        6
  •  34
  •   Carvo Loco    8 年前

    为什么人们总是混淆字符串和字符串文字?接受的答案是对另一个问题的一个很好的答案,而不是对这个问题。

    我知道这是一个古老的话题,但我来到这里的时候,可能有一个和《行动纲领》相同的问题,看到人们总是误读它,真令人沮丧。或者是我读错了,我不知道。

    大致来说,字符串是计算机内存中的一个区域,在程序执行期间,它包含一系列可以映射到文本字符的字节。另一方面,字符串文字是一段尚未编译的源代码,它表示在随后的程序执行过程中用于初始化字符串的值。

    在C中,语句…

     string query = "SELECT foo, bar"
     + " FROM table"
     + " WHERE id = 42";
    

    生成一个三行字符串,但只生成一行字符串;三个字符串(每个字符串都由不同的文本初始化)的串联不包含新的行修饰符。

    OP似乎在问的不是如何在编译后的字符串中引入类似于源代码中的换行符,而是如何在源代码中分解一行长的文本,以使其清晰明了。 没有 在已编译的字符串中引入分隔符。在不需要延长执行时间的情况下,将来自源代码的多个子字符串连接起来。就像JavaScript或C++中的多行字符串文本中的尾随反斜杠。

    建议使用逐字字符串 StringBuilder S String.Join 甚至是带有字符串反转的嵌套函数,什么都没有,让我觉得人们并没有真正理解这个问题。或者我不明白。

    据我所知,C没有(至少在我仍在使用的旧石器时代版本中,从前十年起)干净地生成多行字符串的功能。 字面量 可以在编译期间而不是执行期间解决。

    也许当前的版本确实支持它,但我想我会分享我在字符串和字符串文本之间所感知到的差异。

        7
  •  11
  •   RobertHana    10 年前

    我没有看到这个,所以我会把它贴在这里(如果你有兴趣传递一个字符串,你也可以这样做。)你的想法是,你可以把字符串分解成多行,并以任何方式添加你自己的内容(也可以是多行)。这里“tablename”可以传递到字符串中。

        private string createTableQuery = "";
    
        void createTable(string tableName)
        {
    
             createTableQuery = @"CREATE TABLE IF NOT EXISTS
                    ["+ tableName  + @"] (
                   [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
                   [Key] NVARCHAR(2048)  NULL, 
                   [Value] VARCHAR(2048)  NULL
                                    )";
        }
    
        8
  •  3
  •   vovkas    6 年前

    你可以使用 @ .

            string sourse = @"{
            ""items"":[
            {
                ""itemId"":0,
                ""name"":""item0""
            },
            {
                ""itemId"":1,
                ""name"":""item1""
            }
            ]
        }";
    
        9
  •  1
  •   rattray    9 年前

    如果不需要空格/换行符,则添加字符串似乎有效:

    var myString = String.Format(
      "hello " + 
      "world" +
      " i am {0}" +
      " and I like {1}.",
      animalType,
      animalPreferenceType
    );
    // hello world i am a pony and I like other ponies.
    

    你可以运行上面的 here 如果你喜欢的话。

        10
  •  1
  •   TamaMcGlinn    6 年前

    是的,您可以将一个字符串拆分为多行,而不必在实际字符串中引入换行符,但它并不漂亮:

    string s = $@"This string{
    string.Empty} contains no newlines{
    string.Empty} even though it is spread onto{
    string.Empty} multiple lines.";
    

    技巧是引入计算结果为空的代码,并且该代码可能包含换行符,而不会影响输出。我从 this answer 类似的问题。

    对于问题是什么,显然有一些混淆,但有两个提示,我们在这里想要的是一个不包含任何换行符的字符串文字,它的定义跨越多行。(在评论中,他这样说,“这是我所拥有的”,显示了不创建包含换行符的字符串的代码)

    此单元测试显示的目的是:

        [TestMethod]
        public void StringLiteralDoesNotContainSpaces()
        {
            string query = "hi"
                         + "there";
            Assert.AreEqual("hithere", query);
        }
    

    更改上面的查询定义,使其为一个字符串文本,而不是由编译器将两个字符串文本串联成一个字符串文本。

    C++方法是用反斜杠结束每行,使换行符被释放,而不会出现在输出中。不幸的是,仍然存在这样一个问题:第一行之后的每一行必须保持对齐,以便不向结果添加额外的空白。

    只有一个选项不依赖可能不会发生的编译器优化,那就是将定义放在一行上。如果你想依靠编译器的优化,你已经拥有的+是很好的;你不需要左对齐字符串,你不会得到换行结果,它只是一个操作,没有函数调用,期望优化。

        11
  •  -7
  •   nassimlouchani    8 年前

    您可以使用这两种方法:

        private static String ReverseString(String str)
        {
            int word_length = 0;
            String result = "";
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == ' ')
                {
                    result = " " + result;
                    word_length = 0;
                }
                else
                {
                    result = result.Insert(word_length, str[i].ToString());
                    word_length++;
                }
            }
            return result;
        }
    //NASSIM LOUCHANI
        public static string SplitLineToMultiline(string input, int rowLength)
        {
            StringBuilder result = new StringBuilder();
            StringBuilder line = new StringBuilder();
    
            Stack<string> stack = new Stack<string>(ReverseString(input).Split(' '));
    
            while (stack.Count > 0)
            {
                var word = stack.Pop();
                if (word.Length > rowLength)
                {
                    string head = word.Substring(0, rowLength);
                    string tail = word.Substring(rowLength);
    
                    word = head;
                    stack.Push(tail);
                }
    
                if (line.Length + word.Length > rowLength)
                {
                    result.AppendLine(line.ToString());
                    line.Clear();
                }
    
                line.Append(word + " ");
            }
    
            result.Append(line);
            return result.ToString();
        }
    

    在splitlinetomultiline()中,需要定义要使用的字符串和行长度,这非常简单。 谢谢您。