为什么scanf不使用正则表达式和动态分配
我正在尝试使用scanf和char指针来存储字符串。在输入键笔划的情况下,我希望它被捕捉。我知道我可以使用FGET,但我很想知道这是否可能,所以我设法编写了以下代码:为什么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)
#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
结尾的字符串(即100char
长):
#包括
#包括
内部主(空)
{
字符串[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;
}