【问题标题】:C- Save string to array and print a charC-将字符串保存到数组并打印一个字符
【发布时间】:2017-08-25 22:56:00
【问题描述】:

我试图将一个最多 100 个字符的字符串保存到一个数组中,然后通过索引打印数组的指定字符,但我得到分段错误 11,这是代码:`

#include<stdio.h>
#include<stdlib.h>
int main()
{
   char str1[100];
   int index;
   printf("Enter text of max 100 characters: \n");
   scanf("%s", str1);

   printf("Enter the index to search\n");
   scanf("%d", &index);

   printf("your char is: %c\n", str1[index]);

   return(0);
}

` 有什么建议吗?

【问题讨论】:

  • char str1[100]; --> char str1[100+1];(和scanf("%s", str1); --> scanf("%100s", str1);
  • 对于合理的输入,没问题。请在问题中发布您所做的输入、您的预期以及发生了什么。最好在调试时使用char str1[10]; 等。
  • 一般来说,避免使用scanf。它很容易溢出你的数组。之后使用 fgets 和 sscanf。
  • scanf如果你正确指定字段宽度,就不容易溢出。
  • 在调用任何scanf() 系列函数时:1) 始终检查返回值(而不是参数值)以确保操作成功。 2) 当使用 '%s' 输入格式说明符时,始终包含一个比输入缓冲区长度小 1 的 MAX CHARACTERS 修饰符。这避免了缓冲区溢出的任何可能性。这种溢出是未定义的行为,可能导致段错误事件。

标签: c arrays string segmentation-fault character


【解决方案1】:

虽然用户输入通常可以通过使用fgets 读取输入,然后使用sscanf 从结果缓冲区中解析您需要的内容来更好地处理,但只需使用一对指针和“英寸蠕虫向下”(a/k/ a "walking") 测试每个字符并根据需要进行处理的字符串——总是值得一看 scanf 以详细说明成功将其用于用户输入所需的操作。

虽然fgets 并非没有必要的验证,但scanf 所需验证的数量和类型以及在输入失败 或匹配失败为新的(不是那么新的)C 程序员创造了许多额外的陷阱。

scanf 的两个主要问题是 (1) 读取到任何缓冲区的字符数没有默认限制(可能会溢出您的数组); (2) 它不会从输入缓冲区中删除尾随'\n'(或输入匹配失败后的任何字符) (例如stdin)。 由您自己决定考虑输入缓冲区中的所有字符并根据需要清空缓冲区。

更复杂的是不同的scanf 格式说明符处理前导空白的方式(数字转换通常会跳过前导空白,而字符转换不会) 另一个问题是处理 included 空格。 "%s" 格式说明符只会读取遇到的第一个空格,因此无法使用单个 %s 说明符读取 "My dog has fleas"。 (您可以使用字符类来读取包含的空格——如下例所示)

scanf 还有许多其他微妙之处,因此值得花时间阅读和理解man scanf

从 cmets 中,您现在知道,如果您请求一串 100 字符,则至少需要 101 字符的存储空间——我们假设这是学会的。

当使用scanf 进行任何输入时,您必须始终验证返回以确保预期的转换次数确实发生了。例如,如果您使用转换说明符"%d %s" 读取"5 dogs",则返回2 表示成功转换为整数和字符串。但是,您也知道,至少有一个 '\n' 保留在输入缓冲区中(并且可能还有更多字符,如果输入了 "5 dogs and cats"。您可以删除 '\n' 和任何其他剩余的字符, 在尝试使用 scanf 读取更多输入之前。

以下示例捕获了您的示例中的大部分缺陷,并提供了一些您可以在处理用户输入时使用的工具。底线是学会使用fgets,但也要知道如何使用scanf。您的目标是提供尽可能健壮和防弹的输入例程。想想用户在提示输入时可能会做的所有愚蠢的事情(或者天堂禁止,一只猫从键盘上走过)总是有更多的验证可以添加。查看每个包含的验证,如果您有任何问题,请告诉我:

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

#define MAXC 100    /* if you need a constant, declare one  */

/* helper function to remove any chars left in input buffer */
void empty_stdin()
{
    int c = getchar();
    while (c != '\n' && c != EOF)
        c = getchar();
}

int main (void) {

    char str1[MAXC+1] = ""; /* initialize to all zero */
    int index, rtn, len;    /* index, return, length  */

    for (;;) {  /* loop until valid input obtained */
        printf ("Enter text of max 100 characters: ");
        rtn = scanf ("%100[^\n]", str1);    /* read at most MAXC char */

        if (rtn != 1) {         /* validate scanf return */
            if (rtn == EOF) {   /* check if EOF, ctrl+d, ctrl+z (windoze) */
                printf ("input canceled.\n");
                return 0;
            }
            if (!str1[0])       /* was a character entered? */
                fprintf (stderr, "error: string is empty.\n");
            /* remove '\n' and any chars that remain in stdin */
            empty_stdin();
        }
        else {  /* all conditions met, good entry, empty stdin and break */
            empty_stdin();
            break;
        }
    }

    len = (int)strlen (str1);   /* get string length */

    for (;;) {  /* now do the same thing for integer */
        printf ("Enter the index to search (0-%d): ", len - 1);
        if ((rtn = scanf ("%d", &index)) != 1) {
            if (rtn == EOF) {
                printf ("input canceled.\n");
                return 0;
            }
            fprintf (stderr, "error: invalid input - not integer.\n");
            /* only need to strip if non-integer entered, because %d
             * will skip leading whitespace, including '\n'.
             */
            empty_stdin();
        }
        else if (index < 0 || len < index + 1)  /* validate index value */
            fprintf (stderr, "error: invalid index - out of range.\n");
        else
            break;
    }

    printf ("your char is: %c\n", str1[index]);

    return 0;
}

使用/输出示例

$ ./bin/scanfstr1
Enter text of max 100 characters: 12345678901234567890
Enter the index to search (0-19): -1
error: invalid index - out of range.
Enter the index to search (0-19): 0
your char is: 1

$ ./bin/scanfstr1
Enter text of max 100 characters: 12345678901234567890
Enter the index to search (0-19): foo
error: invalid input - not integer.
Enter the index to search (0-19): 6
your char is: 7

$ ./bin/scanfstr1
Enter text of max 100 characters: My dog has fleas.
Enter the index to search (0-16): d
error: invalid input - not integer.
Enter the index to search (0-16): 3
your char is: d

$ ./bin/scanfstr1
Enter text of max 100 characters:
error: string is empty.
Enter text of max 100 characters: My cats are fine.
Enter the index to search (0-16): meow
error: invalid input - not integer.
Enter the index to search (0-16): input canceled.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多