【问题标题】:How do I use sscanf to get names and print them out the way i want them to如何使用 sscanf 获取名称并按照我想要的方式打印出来
【发布时间】:2011-06-23 03:43:52
【问题描述】:

我正在制作一个程序,该程序使用逗号分隔的用户名。该程序允许用户在逗号之间放置任意数量的空格。比如:

如果我要输入类似的东西

Smith, John

Smith,John

我想打印出来

John, Smith

问题是虽然我的程序没有正确处理上面的以下示例;如果输入类似于

Smith , John

Smith ,John.

这是我的代码:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LINESIZE 128

int get_last_first(FILE *fp);

int main (void)
{
    get_last_first(stdin);
}

/*takes names in the format [LASTNAME],[FIRSTNAME]*/
int get_last_first(FILE *fp)
{
    char first[LINESIZE];
    char last[LINESIZE];
    char line[LINESIZE];
    size_t i;

    while(1)
    {
        printf("Enter your last name followed by a comma and your first name\n");

        /*if we cant read a line from stdin*/
        if(!fgets(line, LINESIZE, fp)) 
        {
            clearerr(stdin);
            break;   /*stop the loop*/
        }

        /*goes through the line array and checks for non-alphabetic characters*/        
        for(i = 0; i < strlen(line); i++)
        {
            if(!isalpha(line[i]))
            {
                /*if it sees a space hyphen or comma, it continues the program*/
                if((isspace(line[i]) || line[i] == ',') || line[i] == '-' )
                {
                    continue;
                }
                else
                {
                    return -1;
                }
            }

        }

        if(sscanf(line, "%s , %s", last, first))
        {
            printf("%s, %s", first, last);
            return 1;
        }

        return 0;   

    }
}

是因为我没有正确使用 sscanf 吗?

【问题讨论】:

    标签: c ansi main scanf fgetc


    【解决方案1】:

    sscanf() 不进行模式匹配;逗号是一个完全有效的非空白字符串组件,因此会被%s 规范所吞噬。您可以使用 %[^ \t,] 之类的内容来匹配最多为空格或逗号的字符。

    【讨论】:

    • 如果你不介意可以告诉我如何正确使用它来处理这种情况,我有一段时间没有使用Regex,所以我有点生疏
    • 这不是正则表达式,是问题所在。 :) %s 读取非空白序列; %[xyz] 读取字符序列xyz,而%[^xyz] 读取字符序列除了 xy 或@ 987654332@。否则,它就是字面意思:除了% 之外没有任何魔术字符,并且除%[...]%c 之外的任何说明符都在空格处停止。
    【解决方案2】:

    geekosauranswer 中概述了基本问题 - 是的,您误用了sscanf()

    您的代码中还有其他问题。

    • 不要在循环测试中使用strlen();它每次都会被调用并产生相同的答案(除非你正在破解字符串)。在循环之前调用一次并使用保存的值。
    • 从风格上讲,条件中有不必要的括号和空格(并遗漏了必要的空格):

      if((isspace(line[i]) || line[i] == ',') || line[i] == '-' )
      
      if (isspace(line[i]) || line[i] == ',' || line[i] == '-')
      

      关键字后面应该有一个空格(见标准)。没有必要用额外的括号破坏三向条件的对称性;最后的右括号之前不需要空格。 (或者,如果你坚持的话,那么你需要在条件的左括号之后有一个平衡的开放空间。但请不要坚持。)

    • 您需要测试sscanf() 是否成功转换了两个值;您只需检查它是否没有转换 0 值。它可能返回 1;它可能会返回 EOF(以及 0 或 2)。

    • 您的“无限循环”被break 打破,但随后该函数没有返回值。
    • 您的 main() 程序会忽略函数的返回值 - 因此您根本不需要返回值。
    • 在风格上,虽然 C99 标准允许您在 main() 的末尾省略 return,但我更喜欢在那里看到它。 (你没有犯下让main()返回void的罪过;谢谢。)
    • 您可能已经注意到,我在格式化问题时删除了一些嵌入在 cmets 中的杂散代码。不要保留死代码 - 也不要在 SO 上炫耀它。
    • 在风格上,我在#include&lt;stdio.h&gt; 之间放置了空格。再次查看 C 标准并注意他们是如何编写的:#include &lt;stdio.h&gt;,你也这样做。

    标记为“风格”的 cmets 是建议 - 编译器在很大程度上忽略了空格或缺少空格。尽管如此,C 标准显示了所有在 #include 行中带有空格的示例,以及在 forif 等关键字之后的空格,并且 Kernighan 和 Ritchie 对 C 的原始描述也是如此,因此有可靠的先例你跟随。通常,如果您遵循标准约定,其他人会发现您的代码更易于阅读。大括号的定位更具争议性——但如果你在那里遵循 K&R 就不会出错(尽管我更喜欢 Allman 风格)。

    【讨论】:

    • 严格来说,在关键字之后或#include 和 之间不需要使用空格。我的意思是,我知道你的意思很好,教授代码和东西的良好实践......我认为它是有效的,但我认为你应该明确表示标准不会强制执行它,即使人们应该这样做。
    猜你喜欢
    • 2022-11-24
    • 1970-01-01
    • 2019-02-15
    • 2021-09-11
    • 2019-06-17
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多