【问题标题】:C - printf doesn't display full stringC - printf 不显示完整的字符串
【发布时间】:2015-01-11 20:11:17
【问题描述】:

我正在尝试使用指针而不是 strcat 连接两个字符串,由空格分隔。我已经让串联工作了,但是当我尝试打印串联的字符串时,它只打印第一个字符串。

代码:

#include <stdio.h>

int main(void){
    char string1[10];
    char string2[10];
    char fullString[21];

    char *string1Ptr = string1;
    char *string2Ptr = string2;
    char *fullStringPtr = fullString;

    printf("Enter first string: ");
    scanf_s("%s", &string1, 10);
    fflush(stdin);

    printf("Enter second string: ");
    scanf_s("%s", &string2, 10);
    fflush(stdin);

    for (int i = 0; i < 21; ++i){
        if (i < 10){
            fullStringPtr[i] = string1Ptr[i];
        }
        else if (i == 10){
            fullStringPtr[i] = ' ';
        }
        else if (i > 10){
            fullStringPtr[i] = string2Ptr[i - 11];
        }
    }

    printf("%s\n", fullString);
    //printf("%c", fullString[11]);

    getchar();
    return (0);
}

如果我输入 Hello 作为第一个字符串,World 作为第二个字符串,打印输出只是显示“Hello”。但是,如果我尝试在第二个字符串中的特定位置打印字符,例如fullString[11],我得到了应该在那个位置的字符,在这种情况下是 W。

第二个字符串显然在那里,printf 只是不打印它。我缺少关于 printf 的一些东西吗?

【问题讨论】:

  • fullString 存储为 "Hello\0\0\0\0\0 World\0\0\0\0\0\0",但由于 C 字符串以空值结尾,printf 在第一个 \0 处停止
  • 所以...在循环中检查 \0 并用空格替换,同时处理第一个字符串。
  • @EricJ。那是行不通的,因为这样可能会复制未初始化的值,从而导致未定义的行为。
  • 哦,对了......所以@frxstrem 的陈述也不一定正确,因为第一个字符串中第一个 \0 之后的值是未定义的。因此,无论源字节是什么,我猜想设置从第一个字符串复制的第一个 \0 及之后的内容。

标签: c string pointers printf


【解决方案1】:

在c中,字符串被定义为带有终止'\0'字节的字节序列,因此"A\0"将表示字符串A"A\0ABCDEF"也将表示字符串"A"scanf附加此'\0' 将字符串分隔到数组的特殊值,因此复制每个字符也复制此字节。

不仅如此,如果你在第一个scanf处输入例如ABC,那么数组的内容就是

[A|B|C|\0|?|?|?|?|?|?]
 0 1 2  3 4 5 6 7 8 9

其中? 表示UNINITIALIZED 它们是来自这些位置内存先前内容的随机垃圾值,因此尝试读取这些值是未定义的行为。

你将'\0'从第一个字符串复制到结果字符串的中间,我建议2个循环

int j = 0;

for (i = 0 ; string1Ptr[i] != '\0' ; ++i)
    fullStringPtr[j++] = string1Ptr[i];

fullStringPtr[j++] = ' ';

for (i = 0 ; string2Ptr[i] != '\0' ; ++i)
    fullStringPtr[j++] = string2Ptr[i];
fullStringPtr[j++] = '\0';

printf 打印在找到 '\0' 之前遇到的每个字符,并且由于您将该值从第一个字符串复制到第二个字符串,它应该只打印第一个字符串,'\0' 之后的字符被省略.

如果可以包含string.h 标头,则只需使用strcat

fullStringPtr[0] = '\0';

strcat(fullStringPtr, string1Ptr);
strcat(fullStringPtr, " ");
strcat(fullStringPtr, string2Ptr);

【讨论】:

  • 啊,我实际上是要摆脱未初始化的位置,但我想确保首先正确复制字符串,然后我遇到了这个。我从来没有想过这是导致问题的原因。谢谢!
【解决方案2】:

当您从firstStringsecondString 复制时,fullString 存储为"Hello\0\0\0\0\0 World\0\0\0\0\0\0",但由于 C 字符串以空值结尾,printf 在找到的第一个 \0 处停止打印字符串。

其他人已经发布了其他解决方案,但我想补充一点,最简单的可能是使用strcpystrcat

strcpy(fullStringPtr, string1Ptr); // copy to fullString
strcat(fullStringPtr, " ");        // add to end of fullString
strcat(fullStringPtr, string2Ptr); // add to end of fullString

printf("%s\n", fullString); // works as expected

【讨论】:

  • 通常我会使用 strcpy 和 strcat 但我想练习使用指针。
【解决方案3】:

问题出在字符串连接码上。

您碰巧在fullString 目标缓冲区中嵌入了一些'\0's,并且由于C 字符串是'\0' 终止的,所以printf() 在目标缓冲区中找到第一个'\0' 时会停止打印。

要解决这个问题,您可以更改字符串连接代码,如下所示:

  1. 将字符从第一个字符串复制到目标缓冲区(相应地更新字符串指针)
  2. 在目标缓冲区中写入空格(并相应地更新目标字符串指针)
  3. 将第二个字符串中的字符复制到目标缓冲区(相应地更新字符串指针)

这可以用 C 代码写成这样:

#include <stdio.h>

int main(void) 
{
    char string1[10];
    char string2[10];
    char fullString[21];

    char *string1Ptr = string1;
    char *string2Ptr = string2;
    char *fullStringPtr = fullString;

    printf("Enter first string: ");
    scanf_s("%s", string1, 10);
    fflush(stdin);

    printf("Enter second string: ");
    scanf_s("%s", string2, 10);
    fflush(stdin);

    /* Reality-check: print read strings */
    printf("First string:  %s\n", string1);
    printf("Second string: %s\n", string2);

    /* Copy string1 to dest buffer */
    while (*string1Ptr != '\0')
    {
        *fullStringPtr = *string1Ptr;
        ++fullStringPtr;
        ++string1Ptr;
    }

    /* Add space */
    *fullStringPtr = ' ';
    ++fullStringPtr;

    /* Concat string2 to dest buffer */
    while (*string2Ptr != '\0')
    {
        *fullStringPtr = *string2Ptr;
        ++fullStringPtr;
        ++string2Ptr;
    }

    /* Terminate full string */
    *fullStringPtr = '\0';

    /* Print result */
    printf("%s\n", fullString);

    return 0;
}

输出:

Enter first string: Hello
Enter second string: World
First string:  Hello
Second string: World
Hello World

注意

除非您将这段代码作为学习经验来理解指针等,否则请考虑使用内置的字符串复制和连接函数,例如 strcpy()/strcat(),或者更好的更安全的版本,例如 strcpy_s()strcat_s() .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-02
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多