1

我的代码中有以下行:

char y[] = "a";
scanf("Letter: %s", y);
printf("%s\n", y);

第二行根本不影响第三行的输出。我已经包括在内<stdio.h>,我想不出有什么问题......

4

4 回答 4

9

最大的错误之一是在scanf函数中包含除格式规范(如%s%d)之外的引号之间的任何字符串。代码应该是scanf("%s",y)。如果您使用任何其他字符,那么您将不得不挠头寻找出问题。

(即使您包含任何字符,那么您也必须输入该字符,例如,如果您scanf("letter: %s",y);在输入时写入,则必须像C:\>letter: “您将输入的字母”一样写)这显然不是一个明智的主意。而且该scanf功能不存在打印出来,它只是从终端读取输入。要打印出来,你应该使用printf("letter");它。

假设您必须使用一个从两个 int 变量中获取输入,scanf()然后您将使用 like scanf("%d%d",&a,&b);,因为您可以看到除了引号中的格式规范外,我什么也没放。

于 2013-06-19T04:26:23.497 回答
3

我假设您想要一个提示,而不是格式字符串:

printf("Letter: ");
fflush(stdout);
scanf("%s", y);

请注意,您的字符串只能包含一个字符。如果输入更长的字符串,则会出现缓冲区溢出。

您还应该养成测试返回值的习惯scanf。它返回成功读取的项目数。因此,在您的示例中,如果它读取一个字符串,它应该返回1. 因为您没有对其进行测试,所以您花了很长时间试图找出问题所在,而实际上它会告诉您没有读取任何项目。

于 2013-06-19T03:52:46.107 回答
1

其他答案已正确诊断为scanf()不输出任何数据(特别是不生成任何提示),而问题似乎期望scanf("Letter: %s", y)输出提示Letter:然后读取响应。scanf()如果键入多个字符,还会出现诸如不检查返回值和缓冲区溢出等问题。

其中一个答案表明,格式字符串中不应出现转换规范以外的字符。这个答案主要是一个反例,展示了其他角色如何至关重要。您可以获取此示例代码并对其进行修改,以提高您对scanf()函数族如何工作的理解。请注意,它不是交互式程序;它正在使用 转换数据sscanf(),几乎就像数据已被 读取一样fgets()练习:为什么它只是“几乎好像”而不是简单的“好像”?

语境

假设您正在处理一个格式为以下行的文件:

centre (23, 41) size (19, 42)

假设您要读取这四个数字,您的格式字符串可能是以下内容的变体:

"centre (%d,%d) size (%d,%d)"

这几乎是健全的。但是,该格式无法发现缺少第二个右括号。为了确保最后的括号存在,您需要一个格式字符串,如:

"centre (%d ,%d ) size (%d ,%d %1[)]"

其中空格允许输入间距的许多变化,并且扫描集 ( %1[)]) 需要一个右括号。您将测试scanf()返回的 5 个字段。请注意,如果您使用扫描集 ( %*1[)]) 禁止分配,则如果括号丢失,您将不会收到错误指示。这是一个判断,您希望在您接受的有效输入方面有多灵活。

代码

#include <stdio.h>

int main(void)
{
    int x1, y1, x2, y2;
    char str[10];
    const char *data[] =
    {
        "centre ( 19, 43 ) size ( 21, 37 )",
        "centre (19, 43) size (21, 37)",
        "centre (19, 43) size (21, 37",
        "centre(19,43) size(21,37)",
        "centre(19,43) size(21,37",
        "centre ( 19 , 43 ) size ( 21 , 37 )",
    };
    enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };

    const char *format5[] =
    {
        "centre (%d ,%d ) size (%d ,%d %[)]",
        "centre (%d,%d) size (%d,%d%[)]",
    };
    enum { NUM_FORMAT5 = sizeof(format5) / sizeof(format5[0]) };

    const char *format4[] =
    {
        "centre (%d ,%d ) size (%d ,%d )",
        "centre (%d,%d) size (%d,%d)",
    };
    enum { NUM_FORMAT4 = sizeof(format4) / sizeof(format4[0]) };

    printf("Format 5\n");
    for (int i = 0; i < NUM_FORMAT5; i++)
    {
        printf("Format:    <<%s>>\n", format5[i]);
        for (int j = 0; j < NUM_DATA; j++)
        {
            int rc;
            printf("   Data:   <<%s>>\n", data[j]);
            if ((rc = sscanf(data[j], format5[i], &x1, &y1, &x2, &y2, str)) != 5)
                printf("!! Failed: scanf() returned %d\n", rc);
            else
                printf("== Passed: centre(%d,%d) size(%d,%d)\n", x1, y1, x2, y2);
        }
    }

    printf("\nFormat 4\n");
    for (int i = 0; i < NUM_FORMAT4; i++)
    {
        printf("Format:    <<%s>>\n", format4[i]);
        for (int j = 0; j < NUM_DATA; j++)
        {
            int rc;
            printf("   Data:   <<%s>>\n", data[j]);
            if ((rc = sscanf(data[j], format4[i], &x1, &y1, &x2, &y2)) != 4)
                printf("!! Failed: scanf() returned %d\n", rc);
            else
                printf("== Passed: centre(%d,%d) size(%d,%d)\n", x1, y1, x2, y2);
        }
    }

    return 0;
}

输出

Format 5
Format:    <<centre (%d ,%d ) size (%d ,%d %[)]>>
   Data:   <<centre ( 19, 43 ) size ( 21, 37 )>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37>>
!! Failed: scanf() returned 4
   Data:   <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37>>
!! Failed: scanf() returned 4
   Data:   <<centre ( 19 , 43 ) size ( 21 , 37 )>>
== Passed: centre(19,43) size(21,37)
Format:    <<centre (%d,%d) size (%d,%d%[)]>>
   Data:   <<centre ( 19, 43 ) size ( 21, 37 )>>
!! Failed: scanf() returned 2
   Data:   <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37>>
!! Failed: scanf() returned 4
   Data:   <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37>>
!! Failed: scanf() returned 4
   Data:   <<centre ( 19 , 43 ) size ( 21 , 37 )>>
!! Failed: scanf() returned 1

Format 4
Format:    <<centre (%d ,%d ) size (%d ,%d )>>
   Data:   <<centre ( 19, 43 ) size ( 21, 37 )>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre ( 19 , 43 ) size ( 21 , 37 )>>
== Passed: centre(19,43) size(21,37)
Format:    <<centre (%d,%d) size (%d,%d)>>
   Data:   <<centre ( 19, 43 ) size ( 21, 37 )>>
!! Failed: scanf() returned 2
   Data:   <<centre (19, 43) size (21, 37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre (19, 43) size (21, 37>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37)>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre(19,43) size(21,37>>
== Passed: centre(19,43) size(21,37)
   Data:   <<centre ( 19 , 43 ) size ( 21 , 37 )>>
!! Failed: scanf() returned 1

请注意,当缺少第二个右括号时,“格式 4”下的格式字符串如何接受数据。即使缺少字符,也满足 4 个转换规范。“格式 5”格式拒绝这些数据行。

示例代码和数据没有演示它,但代码也很乐意读取多个右括号(因为它使用%[)])。可以通过使用%1[)]来避免这种情况,规定最后只有一个右括号。您还可以使用%n转换规范和第六个参数(另一个int *)来获取处理的字符数。这将允许您检测扫描停止的位置,从而在所需的输入之后是否有未处理的字符。请注意,%n转换规范不计入scanf()等人的返回值中。这个片段可以粘贴在main()代码中函数的末尾:

printf("\nFormat 6\n");
int len, rc;
const char data6[] = "centre ( 19 , 43 ) size ( 21 , 37 )))";
const char format6[] = "centre (%d ,%d ) size (%d ,%d %1[)]%n";
printf("Format:    <<%s>>\n", format6);
printf("   Data:   <<%s>>\n", data[5]);
if (sscanf(data6, format6, &x1, &y1, &x2, &y2, str, &len) != 5)
    printf("!! Failed: scanf() returned %d\n", rc);
else
    printf("== Passed: centre(%d,%d) size(%d,%d) len=%d <<%s>>\n",
           x1, y1, x2, y2, len, &data6[len]);

它生成输出:

Format 6
Format:    <<centre (%d ,%d ) size (%d ,%d %1[)]%n>>
   Data:   <<centre ( 19 , 43 ) size ( 21 , 37 )))>>
== Passed: centre(19,43) size(21,37) len=35 <<))>>

概括

如果您了解为什么会获得每个结果,那么您对scanf()​​. 如果您不确定为什么,请尝试并阅读规范(例如 POSIX sscanf()),直到您确定您理解它为止。

于 2013-06-19T13:16:08.433 回答
-2

在你的情况下

char y[] = "a";
scanf("Letter: %s", y);
printf("%s\n", y);

你应该像这样提供输入。

字母:abcd

它将正常工作

例如,如果 scanf 是这样写的

int y;
scanf("y=%d", &y);

那么你应该输入像

y=10

不是 10

我想你得到了你想要的...... :) 现在享受

于 2013-06-19T04:47:15.510 回答