【问题标题】:How does concatenation work in C?连接在 C 中是如何工作的?
【发布时间】:2014-10-08 13:35:09
【问题描述】:

我目前正在学校学习 C 课程,在习惯了 Java 之后,我似乎不明白 C 中的连接是如何完成的。在 Google 中搜索并没有帮助,因为大多数代码我看到的是如何连接像"Hello" + "World" 这样的实际字符串。

在 Java 中,假设我想在一行中连接一个算术表达式,我可以轻松地使用 + 运算符,但在 C 中,我看到熟悉的东西的唯一地方是这样的:

int grade;
scanf("%d", &grade);

我可以理解 grade 变量被作为输入,但如果我想使用 +& 运算符对该变量执行算术运算,我会出错。这是我尝试做的一个例子:

printf("The average score is "& grade / 2 & "");

即使我使用 + 运算符也会返回错误,但在 Java 中可以正常工作:

System.out.println("The average score is " + grade / 2 + "");

我可以理解它们是不同的语言,但 +& 运算符不应该在 C 中用于连接吗?

【问题讨论】:

  • 阅读 C 格式字符串的概念,看起来这就是让您感到困惑的地方?
  • 在 C 中,没有“字符串”类型,只有被解释为字符的字节数组。 “字符串”的结尾由零字节指定。因此,每当您想要“连接字符串”时,您都可以“连接”两个字节数组。这可以通过显式分配足够容量的新内存块并将源数组的内容移动到那里来完成。如果需要,还可以显式释放()源数组。

标签: java c string concatenation


【解决方案1】:

没有。 + 和 & 不适用于 C 中的连接。无论如何,在 C 中,您通常会使用 strncat 连接 char *(s),但您的问题似乎是关于打印的。为此,您应该执行类似的操作

printf("The average score is %d\n", grade / 2);

【讨论】:

  • 谢谢 Elliott,如果我有字符串的其他部分要添加到输出中,我仍然使用 , 符号吗?喜欢printf("The average score is %d\n", grade / 2 , " ..Good grade!" );
  • 您还需要使用正确的format string,第二个是printf("The average score is %d %s\n", grade / 2 , " ..Good grade!"); 注意格式字符串中的“%s”。
  • @geek.x 格式字符串后 printf 的参数数量应与格式字符串中格式说明符的数量相匹配(无论如何在最简单的情况下)。所以如果你想添加一个额外的字符串参数,你需要在你的格式字符串中添加一个%s。但是,您可以直接将字符串添加到格式字符串 (printf("... is %d.\n ... good grade!\n", grade / 2);),这样会更有意义。
【解决方案2】:

在 java 中,+ 符号用于连接字符串,例如:

System.out.println("hello"+","+" "+"World");
这只是显示字符串连接的一种粗略方式。这在 java 中是可能的,因为 + 运算符用于算术运算,并且 + 被重载以连接字符串。

但是在 C 中,+ 符号应该只执行算术运算,而不是重载连接。

因此,在 C 语言中,打印输出的最佳方式是使用格式化的打印语句:printf

printf("String <format specifier>",arg1,arg2,...);
有关打印声明的更多详细信息。 Click Here

【讨论】:

    【解决方案3】:

    所以,你有两个问题伪装成一个问题。

    C 的格式化 I/O 例程(printffprintf)根本不像 Java 的 I/O 例程那样工作。您可以使用具有变量数据占位符的 格式字符串,而不是将项目连接到字符串,然后将变量数据作为附加参数传递:

    printf( "The average score is %d\n", grade/2 );
    

    %d 是一个转换说明符;它告诉printf,还有一个类型为int 的附加参数,并且它应该被格式化为数字序列。请注意,printf 依赖于格式字符串中的转换说明符来告诉它需要多少和哪些类型的附加参数;如果您传递的参数对于给定的转换说明符类型错误,或者没有传递足够的参数,那么您将得到从乱码输出到彻底崩溃的任何东西。如果您传递的参数多于格式字符串要求的参数,则评估附加参数,否则将被忽略。

    请参阅方便的 C 参考手册,了解所有不同转换说明符及其使用方式的说明。

    至于字符串连接,C 没有字符串类型本身,也没有字符串连接运算符1。在 C 中,“字符串”是由 0 值字节终止的字符值序列。字符串存储char的数组,如:

    char h[] = "hello";
    char w[] = "world";
    

    数组h 包含值{'h', 'e', 'l', 'l', 'o', 0}w 包含{'w', 'o', 'r', 'l', 'd', 0}。要将字符串连接在一起,您需要留出足够大的目标缓冲区以容纳两个字符串。如果你有一个支持变长数组的编译器,你可以这样做:

    char result[ strlen(h) + strlen(w) + 2 ]; 
    

    否则你将不得不动态分配内存:

    char *result = malloc( sizeof *result * (strlen(h) + strlen(w) + 2) );
    

    + 2 是“hello”和“world”之间的空格以及终止 0 字节所必需的。

    一旦有了目标缓冲区,就可以使用strcpystrcat 的组合来写入:

    strcpy( result, h );
    strcat( result, " " ); // note " " instead of ' '; the second argument *must* be a string
    strcat( result, w );
    

    或者您可以使用sprintf(其工作方式类似于printf,但将结果写入char 的数组而不是流):

    sprintf( result, "%s %s", h, w );
    

    要使strcat 工作,目标缓冲区中必须已经有一个有效的以0 结尾的字符串,这就是我们以strcpy 开头的原因,它将在复制的字符串的末尾附加一个0 字节。一个空字符串包含一个 0 值字节,所以我们也可以这样做:

    result[0] = 0;       // or memset( result, 0, sizeof result ), which sets the whole buffer to 0
    strcat( result, h );
    strcat( result, " " );
    strcat( result, w );
    

    strcat 查找终止的 0 字节,并用下一个字符串的开头覆盖它,然后在结果的末尾附加一个 0 字节。


    1。彼此相邻的字符串 literals 在编译的预处理阶段被连接起来,所以你可以写类似printf( "start of string " A_STRING_MACRO " end of string\n"); 的东西,在预处理之后它看起来像 `printf("start of string 不管是在 string\n" 的宏末尾),但没有运行时连接运算符。

    【讨论】:

      【解决方案4】:

      在你的例子中

      printf("The average score is "& grade / 2 & "");
      

      & 运算符用于获取任何变量的内存地址,因此当您尝试仅打印普通 int 变量时,不需要 &

      你可以这样做

      printf("The average score is %d", ( grade/2 ));
      

      printf 中使用的%d 用于匹配您提供的变量

      【讨论】:

      • & 在这里用在中缀位置,所以它不需要任何地址 - 它是位和运算符。
      • @sepp2k:顺便说一句,他问这个问题的方式,我以为他对scanfscanfprintf 中的& 感到困惑
      • 您的 printf 有错字;)
      • @NicolasCharvozKurzawa: 在哪里... :p ;)
      【解决方案5】:

      你有java的概念,但是所有语言的语法都不一样,所以我给你的建议是先读C语言输入输出操作,在C语言中&是用来获取变量的内存地址的,所以你不能用它来连接两个字符串类型的工作,在java中'+'可以用来连接两个字符串它是高级语言,所以你可以这样做,但在c中这是不可能的,%d在 c 中用于从内存中获取变量。 所以你的输出代码将是:

      `printf("平均分是%d",(grade)/2);

      【讨论】:

        猜你喜欢
        • 2016-01-28
        • 2010-10-01
        • 2023-03-30
        • 1970-01-01
        • 2014-01-28
        • 2011-01-05
        • 2011-07-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多