【问题标题】:Character Array User Input Scanf字符数组用户输入扫描
【发布时间】:2018-12-12 02:08:44
【问题描述】:

我刚开始自学编程,在尝试使用 scanf 从用户输入创建字符数组时遇到了困难;代码如下:

#include <stdio.h>
#define I 5

int main (void) {

    char a[I+1] = {a[I+1] = '\0'}, q;
    int i;

    for(i = 0; i < I; i++) {
        printf("Enter an alphabet:\t");
        //scanf("%c", &q);
        //scanf("%c*\n", &q);
        //scanf("%[^\n]", &q);
        //scanf("%[a-z, A-Z]", &q);
        scanf("%127[^\n]", &q);
        a[i] = q;
    }

    printf("\n");

    for(i = 0; i < I; i++)  {
        printf("Element a[%d] of a[I]:\t%c\n", i, a[i]);
    }

    printf("And the a[I] string:\t%s\n", a);

    return 0;
}

上述代码中的 scanf 组合都不起作用:程序要么在第一个提示之后跳过输入提示,要么不存储响应。

如何用 scanf 解决这个问题?

【问题讨论】:

  • char a[I+1] = {a[I+1] = '\0'}, q; 是一个错误,如果您没有看到错误消息,请调整您的编译器设置,因为您错过了重要信息
  • 您能否解释一下您如何想象将 127 个输入字符存储在单个字符 q 中?

标签: c


【解决方案1】:

char a[I+1] = {a[I+1] = '\0'} 无效。即使它编译,它在分配'\0' 字符时也会超出范围。常用的约定看起来更像这样:

char a[I+1] = {0};

或者简单地说:

char a[I+1] = {};

也就是说,q 的大小只有 1 个 char,但您的 scanf() 正在尝试将最多 127 个chars 的字符串读入q。所以你会浪费内存。要一次读取一个char,请改用%c

#include <stdio.h>
#include <string.h>

#define MAX_INPUT 5

int main (void) {

    char a[MAX_INPUT+1];
    int i, len;

    for(i = 0; i < MAX_INPUT; i++) {
        printf("Enter an alphabet:\t");
        scanf("%c", &a[i]);
    }
    a[MAX_INPUT] = '\0';

    printf("\n");

    len = strlen(a);
    for(i = 0; i < len; i++)  {
        printf("Element a[%d]:\t%c\n", i, a[i]);
    }

    printf("And the a string:\t%s\n", a);

    return 0;
}

或者,您可以删除循环,并使用"%5[^\n]" 作为格式字符串对scanf() 进行一次调用:

#include <stdio.h>
#include <string.h>

#define MAX_INPUT 5

int main (void) {

    char a[MAX_INPUT+1];
    char fmt[20];
    int i, len;

    sprintf(fmt, "%%%d[^\n]", MAX_INPUT);

    printf("Enter an alphabet:\t");
    scanf(fmt, a);

    printf("\n");

    len = strlen(a);
    for(i = 0; i < len; i++)  {
        printf("Element a[%d]:\t%c\n", i, a[i]);
    }

    printf("And the a string:\t%s\n", a);

    return 0;
}

【讨论】:

  • @Caan 我已经修复了它们
  • @Caan 第一个解决方案不会丢弃在每个字符之后键入的换行符,因此它会进入下一次读取。关于第二种解决方案,您想指出什么?屏幕截图不是描述性的。要一次性阅读一行文本,请使用 fgets()getline() 而不是 scanf()
  • 第二个解决方案只是在第一个响应之后挂起,如屏幕截图所示。
  • @Caan "%5[^\\n]" 应该是 "%5[^\n]"。但也见Why won't this scanf format-string work?
【解决方案2】:

这在带有 Wall 标志的 Cygwin gcc v7.3 上没有任何警告或错误:

#include <stdio.h>
#define I 5

int main (void) {
    char a[I+1] = {a[I+1] = '\0'},q;
    int i;

    for(i = 0; i < I; i++) {
        printf("Enter an alphabet:\t");
        scanf("%c%*c", &q);
        a[i] = q;
    }

    printf("\n");

    for(i = 0; i < I; i++)  {
        printf("Element a[%d] of a[I]:\t%c\n", i, a[i]);
    }

    printf("And the string a[I]:\t%s\n", a);

    return 0;
}

【讨论】:

  • 这很好奇。我将上面的代码保存到文件ok59.c 中。在带有 GCC 7.3.0 的 Mac 上编译它(/opt/gcc/v7.3.0/bin/gcc -O3 -g -std=c11 -Wall -Werror ok59.c -o ok59,我收到消息:ok59.c: In function ‘main’: ok59.c:5:21: error: array subscript is above array bounds [-Werror=array-bounds] 指向 char a[I+1] = {a[I+1] = '\0'},q;。当然,这不是 Cygwin,但是……我也收到带有 -std=c90 的消息。(不是我的 DV。)
  • @JonathanLeffler,我尝试了与您的评论中相同的标志,并且编译时没有任何警告或错误。知道为什么代码和标志相同时响应不同吗?
  • 坦率地说,不——我很惊讶。
猜你喜欢
  • 2016-07-02
  • 2011-08-23
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 2012-12-06
相关资源
最近更新 更多