Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么scanf不使用正则表达式和动态分配_C_Scanf_Dynamic Allocation - Fatal编程技术网

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

为什么scanf不使用正则表达式和动态分配,c,scanf,dynamic-allocation,C,Scanf,Dynamic Allocation,我正在尝试使用scanf和char指针来存储字符串。在输入键笔划的情况下,我希望它被捕捉。我知道我可以使用FGET,但我很想知道这是否可能,所以我设法编写了以下代码: #include <stdio.h> #include <stdlib.h> int main(void) { char *string = NULL; printf("Type anything : "); scanf("%*[^\n]%10[^\n]ms", string)

我正在尝试使用scanf和char指针来存储字符串。在输入键笔划的情况下,我希望它被捕捉。我知道我可以使用FGET,但我很想知道这是否可能,所以我设法编写了以下代码:

#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;
}

如何使程序正确显示字符串?

用于
scanf()
[
格式说明符(转换,真的)指定接受(或拒绝)字符的字符范围。它不是正则表达式

您需要将
string
声明为固定长度数组,或者使用
malloc()
为其分配内存

以下修改版本使用99个字符的固定长度字符串加上以
\0
结尾的字符串(即100
char
长):

#包括
#包括
内部主(空)
{
字符串[100];
printf(“键入任何内容:”);
scanf(“%99s”,字符串);
printf(“您的输入:%s\n”,字符串);
返回退出成功;
}
以下代码变体使用动态数组执行相同的操作:

#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;
}
#包括
#包括
内部主(空)
{
字符*字符串;
字符串=malloc(100);
if(字符串==NULL){
看跌期权(“出了问题”);
中止();
}
printf(“键入任何内容:”);
scanf(“%99s”,字符串);
printf(“您的输入:%s\n”,字符串);
自由(弦);
返回退出成功;
}

要在Unix系统中使用正则表达式,请查找
regex.h
标题中声明的函数。

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

现在让我们分析一下什么是
scanf(“%*[^\n]%10[^\n]ms”,字符串);
意味着:

  • %*[^\n]
    扫描所有内容直到换行符,但不扫描最后的
    \n
  • %10[^\n]ms
    并没有真正做到您认为它能做到的事情:

    • 记住!
      %s
      %[
      是两个不同的格式说明符!后面的
      s
      不是
      %[
      说明符的一部分
    • 您的
      m
      位于错误的位置

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

  • 另一个错误是
    m
    需要一个
    char**
    ,而不是
    char*
    ,因此,您应该提供
    &string
    ,而不仅仅是
    string

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

  • 执行到达
    scanf
    并且
    scanf
    等待输入
  • 您可以键入
    123\n
  • %*[^\n]
    扫描并丢弃
    123
    ,查看
    \n
    ,然后停止扫描,而不使用
    \n
  • %10m[^\n]
    看到
    \n
    并且失败,原因在我的答案的第一句中给出
  • scanf
    返回0(因为未成功扫描和分配任何内容),并且
    scanf
    完成执行
  • printf
    打印
    (null)
    ,因为
    string
    仍然是
    null
  • 好的,现在我们看到了哪里出了问题。真正的问题是,为什么在这个小程序的
    scanf
    开头有
    %*[^\n]
    ?删除它,一切都会正常工作


    建议:

  • scanf
    之后添加
    scanf(“%*[^\n]”);getchar();
    ,这样剩余的输入(如果有的话)以及最后的
    \n
    将从
    stdin
    中弹出,以后的读取将不会有问题
  • 检查
    scanf
    的返回值以查看它是否成功。RTFM以了解它返回的内容

  • 固定代码(未测试)
    #包括
    #包括
    内部主(空)
    {
    char*string=NULL;
    printf(“键入任何内容:”);
    if(scanf(“%10m[^\n]”,&字符串)!=1)
    {
    fputs(“呃,哦!`scanf`失败了!正在退出…\n”,stderr);
    返回退出失败;
    }
    scanf(“%*[^\n]”);
    getchar();
    printf(“您的输入:%s\n”,字符串);
    自由(弦);
    返回退出成功;
    }
    


    这个答案假设您的实现支持
    m
    格式说明符1)您的代码中没有正则表达式。
    scanf
    不支持它们。2)请了解C语言中内存分配是如何工作的。您的代码显示了严重的错误概念。3)您的代码调用了未定义的行为(serach!)
    scanf(%*[^\n]%10[^\n]ms“,string);
    -->
    scanf(%m[^\n]]*c“,&string);
    与glibc一起使用。空字符串保持为空。您需要自己预先分配字符串。@kusalanda-see。glibc支持
    m
    。OP知道
    m
    但用法错误。
    %*c
    :它将使用换行符。(因为
    [\n]
    不接受换行符)
    %s.99”
    -->
    %99[^\n]“
    (或
    %99s”
    )@BLUEPIXY谢谢,
    %s.99
    应该是
    %.99s
    (固定)。
    %99s
    将允许分配的缓冲区溢出,而
    %.99s
    将输入截断为99个字符。
    %99[^\n]
    可能会出现缓冲区溢出的问题,并且在任何情况下都不会在字符串中读取换行符。感谢您的回答,尽管这不是我想要的。但是这里有很多有用的信息。我确实知道静态和动态分配的数组。句点(
    )不需要。RTFM。没有UB。
    免费(空)
    是完全有效的,是一个不可操作的选项。谢谢,它起作用了。什么是
    #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;
    }
    
    #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;
    }
    
    #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;
    }