为什么scanf无法使用正则表达式和动态分配

时间:2016-07-02 10:45:52

标签: c scanf dynamic-allocation

我正在尝试使用带有char指针的scanf来存储字符串。如果是ENTER键击,我希望它被捕获。我知道我可以使用fgets,但我很想知道是否可能,所以我设法编写以下代码:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *string = NULL;

    printf("Type anything : ");

    scanf("%*[^\n]%10[^\n]ms", string);

    printf("Your input : %s\n", string);

    free(string);

    return EXIT_SUCCESS;
}

但似乎效果不佳。这是输出:

Type anything : 123
Your input : (null)
Type anything : 
Your input : (null)

如何让我的程序正确显示字符串?

2 个答案:

答案 0 :(得分:1)

在我解释您的问题之前,您首先需要知道的是,如果要读取的第一个字符是%[^\n] \n将会失败。

现在让我们分析scanf("%*[^\n]%10[^\n]ms", string);的含义:

  1. %*[^\n]扫描所有内容,直到换行符,但不会扫描到最终\n
  2. %10[^\n]ms并没有真正按照您的想法行事:

    • 记住! %s%[是两个不同的格式说明符!尾随s 不是 %[说明符的一部分。
    • 你的m位置错误。


    更正这些内容时,应该%10m[^\n]扫描所有内容,直到换行符或最多10个字符(以先发生者为准),并分配足够的内存来保存此字符串。

  3. 另一个错误是,m期望char**,而不是char*,因此,您应该提供&string,而不仅仅是string

    现在,让我们执行你的scanf(纠正上述错误后)!

    1. 执行到达scanfscanf等待输入。
    2. 您输入123\n
    3. %*[^\n]扫描并丢弃123,看到\n,然后停止扫描,而不是使用\n
    4. %10m[^\n]看到\n失败,原因在于我的回答第一句中给出的原因。
    5. scanf返回0(因为没有扫描并成功分配)并且scanf完成执行。
    6. printf打印(null),因为string仍为NULL
    7. 好的,我们现在看到出了什么问题。真正的问题是,为什么这个小程序在%*[^\n]开头有scanf?删除它,一切都会按预期工作!

      建议:

      1. scanf("%*[^\n]"); getchar();之后添加scanf,以便输入的其余部分(如果有的话)以及最终的\nstdin中弹出,以后将读取没问题。
      2. 检查scanf的返回值,看它是否成功。 RTFM知道它返回的内容。
      3. 固定代码 (未经测试)

        #include <stdio.h>
        #include <stdlib.h>
        
        int main(void)
        {
            char *string = NULL;
        
            printf("Type anything : ");
        
            if(scanf("%10m[^\n]", &string) != 1)
            {
                fputs("Uh, oh! `scanf` failed! Exiting...\n", stderr);
                return EXIT_FAILURE;
            }
            scanf("%*[^\n]");
            getchar();
        
            printf("Your input : %s\n", string);
        
            free(string);
        
            return EXIT_SUCCESS;
        }
        

        此答案假设您的实现支持m格式说明符

答案 1 :(得分:0)

[的{​​{1}}格式说明符(真的转换)指定了接受的字符范围(或者,如果它以scanf()开头,则被拒绝)字符。这不是一个正则表达式。

您需要将[^声明为固定长度数组,或使用string为其分配内存。

以下修改版本使用99个字符的固定长度字符串以及终止malloc()的字符串(即100 \0长):

char

以下代码变体使用动态数组执行相同的操作:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
        char string[100];

        printf("Type anything : ");

        scanf("%99s", string);

        printf("Your input : %s\n", string);

        return EXIT_SUCCESS;
}

要在C un un Unix系统中使用正则表达式,请查找#include <stdio.h> #include <stdlib.h> int main(void) { char *string; string = malloc(100); if (string == NULL) { puts("Something went wrong"); abort(); } printf("Type anything : "); scanf("%99s", string); printf("Your input : %s\n", string); free(string); return EXIT_SUCCESS; } 标题中声明的regcomp()函数。