gpt4 book ai didi

c - 如何在 C 中解析输入?

转载 作者:太空宇宙 更新时间:2023-11-04 03:54:36 24 4
gpt4 key购买 nike

完整、调整后的代码在文章末尾

如果我要求用户输入并使用 scanf() 获取输入,这个过程是如何工作的(关于缓冲区等的细节)?

人们提到“刷新”缓冲区是什么意思?我还听说刷新输入(或者更确切地说,未定义?)是不好的做法,但是刷新输出流是创建 fflush() 等函数的目的。-- 上面上下文中的“流”是什么意思?

所以,在程序上,如果我要像这样要求输入:

printf("Enter a string: ");
scanf("%s", string);

输入发生了什么;字符串在哪里被 scanf 函数“抓取”?

输入缓冲区中的“空白”是什么? (空格字符、NULL 等?)


在我看来,虽然我读过的文献从未专门解决过这些问题,但我想像来自用户或来自 FILE 的输入将存储在一些临时字符数组中,这些数组可以被访问、打印/存储使用适当的指针。

我之所以提出这个问题是因为我有一个与以下代码相关的问题:

int main(){
char string[20];
char string2[20];

//strlen test
printf("Enter a string: ");
scanf("%s", string);
printf("\t length: %d\n", strlen(string));

//strcat test
printf("Enter two strings to concatentate: ");
scanf("%s %s", string, string2);
strcat(string2, string);
printf("\nConcatenated: %s\n\n\n", string);

return 0;

顺便说一句:上面的 strlen() 和 strcat() 函数是在本地定义的,因此参数可能与您从 C 库中熟悉的不匹配。

产生以下输出:

img

我假设,一旦 scanf 函数遇到空格,它就会假设字符串结束。虽然,剩余的输入仍然存在于缓冲区中。然后,当我要求更多输入时,输入的数据被放在缓冲区的末尾。因此,当这次调用 scanf() 时,'andothernonsensehere' 被视为下一个输入,因为它早先存在于缓冲区中。

虽然,如果我上面所说的是真的,第二个“andothernonsensehere”字符串和在第二次调用“sherrell”时输入的第一个字符串不应该连接起来吗?


tl;verison 博士如何刷新缓冲区以确保下一个输入事件将被 scanf() 捕获?


完整、已编辑、代码:

#include <stdio.h>

int main(){
char string[20];
char string2[20];

//strlen test
printf("Enter a string: ");
scanf("%s", string);
printf("\t length: %d\n", strlen(string));
clear(); //make sure buffer is empty

//strcat test
printf("Enter two strings to concatentate: ");
scanf("%s %s", string, string2);

strcat(string2, string);
printf("\nConcatenated: %s\n\n\n", string);

return 0;
}

void strcat(char *toCopy, char *org){
while(*org != NULL) org++; //find end of characters
while( (*org++ = *toCopy++) != NULL); //copy
}

int strlen(char *a){
char *b = a;
while(*b++ != NULL);
return b-a;
}


void clear(){
while(getchar() != '\n');
}

最佳答案

您基本上做对了,尽管缓冲可能不是您认为的那样。

scanf不维护缓冲区。从概念上讲,它一次读取一个字符,直到格式或输入耗尽。

但是,终端输入通常由终端驱动程序缓冲。或者,更准确地说,如果没有等待读取的字符,终端输入请求在按下 Enter 键之前不会返回任何内容,即使程序只读取一个字符也是如此。未读字符保留在内核中,将按要求提供给用户程序。 (终端驱动程序还处理在键入字符时回显字符、处理退格键和许多其他事情。)不过,所有这些行为都可以更改。参见 man sttyman termios (可能还有 man tty_ioctl )了解很多细节。很多。

所以 scanf完全不知道接下来会发生什么。它只会消耗字符,直到满足为止,如果有必要,调用 ungetc返回它读取但不需要的最后一个字符。

现在,你的问题:

shouldn't the second 'andothernonsensehere' string and the first string entered at the second call, 'sherrell,' be concatenated?

回答:是的,他们应该。他们将与标准库函数strcat ,前提是您按正确的顺序放置它的参数并确保 string有足够的空间来容纳连接加上终止 NUL性格。

如您所说,我无法对您的 strcat 做出任何假设,所以我不知道它接受参数的顺序与标准库版本相同。但是,如果确实如此,那么您看到的行为是意料之中的:strcat将附加 stringstring2 结束(覆盖随机内存,因为 string2 不够大,无法容纳串联),但这不会改变 string (除非 string 是被覆盖的随机内存)。所以当你打印出 string ,你会看到它最初是什么,即一个 20 个字符的字符串,其终止符 NUL字节也被覆盖在其他一些随机内存位置。

随着所有这些未定义的行为发生,您的程序几乎可以产生任何输出,或者它可能会出现段错误或触发 nasal demons .我认为您的 C 编译器可能会在双字边界上对齐字符串,因为我期望 string2立即关注string , 所以尾随 NUL在你将 20 个字符放入 string 之后将是 string2 的第一个字节,然后将在 scanf 时被覆盖填写string2 .附加 string 的后果至 string2那时会,嗯,很有趣。

关于c - 如何在 C 中解析输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17667438/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com