【问题标题】:Fixed string with spacebars and EOF check修复了带空格键和 EOF 检查的字符串
【发布时间】:2014-03-26 17:30:07
【问题描述】:

好的,这里我有这个sn-p的代码:

struct Computer
{
    char name[20];
    float hdd;
    int price;
    int ram;
};

struct Computer list[7];
int n = 0;

for(n; n < 7; n++)
{

    printf("\nEnter PC name, 20 characters:");
    /* here should be name entry for list[n].name */
}

很多方法都行不通。我尝试了fgets()getch()scanf() 和许多其他方法,但要么不起作用,要么没有足够的功能。

fgets(list[n].name, 20, stdin) 无法识别条目中的 EOF,这是必需的。

list[n].name[counterChar] = getch() 只是有一些奇怪的行为,并且有很多回声的例程。

scanf("%c", &amp;list[n].name[counterChar]) 让用户在每个符号后按回车键。

我需要的是:名称限制为 20 个字符,包括空格,如果是 EOF,则跳出循环。

【问题讨论】:

  • 对于完整的name 条目,您希望如何终止每个输入?例如,假设您想将其命名为 "Ha Ha!",您想为此做什么?

标签: c string pointers struct char


【解决方案1】:

这样的事情会起作用:

int ret; 
...
{
    ret = scanf(" %19[^\n]", list[n].name);
    if(ret == EOF)
        break;

澄清这段代码在做什么:

  • 这将读取 19 个字符(为空终止符留出 1 个空格)。如果您将完整的 20 读入 name[20],您将填充数组并且不会为 scanf() 留出空间来附加空终止符 ('\0')。如果你真的想要 20 个字符,那么你需要将你的数组增加到 name[21]

  • 格式字符串利用negated scanset 并告诉scanf() 在换行符处停止,而不是在“所有空白”字符处停止。这意味着它将读取空格,但也会读取其他空白字符(例如制表符、换行符等)。

    如果这不是您可以通过在其中添加更多“停止”字符来调整扫描集。例如,如果您希望它在换行符或制表符处停止,您可以这样做:" %19[^\n\t]"

  • 格式字符串在初始"%之间也有一个空格,这是故意的。它告诉scanf() 忽略stdin 缓冲区上留下的任何空白。在循环中使用scanf() 会将前一个换行符('\n')留在缓冲区中。

  • 最后,检查scanf() 的返回值,打破你得到EOF 的循环。如果遇到 EOF 而不是来自 man page 的字符串,您可以看到这是您将得到的结果:

如果在第一次成功转换或匹配失败发生之前到达输入结尾,则返回值 EOF。

【讨论】:

  • @ajay - 是的......和? "读取过去的空格(只在换行处停止)" == "它也读取空格"
  • 这实际上是有效的,除了对于纯 20 个符号,而不是 19 应该是 20,并且字段应该是 21 大小。非常感谢!
【解决方案2】:

您应该使用scanf格式字符串中的最大字段宽度来防止缓冲区溢出,并检查1scanf的返回值以确定调用是否成功。

struct Computer list[7];
int n = 0;
int retval;
char ch;

for(; n < 7; n++) {
    printf("Enter PC name, 20 characters:\n");

    // save one char space for the null byte 
    // appended by scanf at the end
    retval = scanf("%19[^\n]", list[i].name);  
    if(retval == EOF)
        break;

    if(retval == 1) {
        // if the input was longer than 20 chars
        // then discard the extra input if this is
        // what you want so that it doesn't mess with
        // the next scanf call

        if(strlen(list[i].name) == 19) {
             // read and discard extra input 
             // up till and including the newline 
             while((ch = getchar()) != '\n')  
                 ; // the null statement
        }    
    }
}    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 2023-02-05
    • 2021-12-07
    • 2020-08-30
    • 2018-11-28
    • 1970-01-01
    • 2015-05-29
    • 2021-08-17
    相关资源
    最近更新 更多