为什么scanf()不能过滤双引号,尽管将格式设置为[A-Za-z]

时间:2014-12-10 08:58:22

标签: c string scanf standard-library

我试图只提取除了句子中其他字符之外的字母单词。

为此,我使用两个scanf()如下所示。

scanf("%s", word);
sscanf(word, "%[A-Za-z]", word);

问题在于,虽然我将格式设置为%[A-Za-z],但未删除双量化标记 然而,奇怪的是,如果这个标记位于单词的最后一个位置,则将其删除。

有没有人知道原因?

测试案例
- “迪士尼乐园” - 左。“

#include <stdio.h>
#include <string.h>

#define MAX_WORD    128

int main(int argc, char* argv[]) {
    char word[MAX_WORD];

    /* Read all of contents */
    while (EOF != scanf("%s", word)) {
        printf("origin word: %s\n", word);
        sscanf(word, "%[A-Za-z\"]s", word);
        printf("transformed: %s\n", word);

    }   
 }

2 个答案:

答案 0 :(得分:1)

由于期间而不是引用,它剥离了第二行的末尾,因此它剥离了期间报价。

您已要求它扫描由字母A-Za-z^"组成的字符串,因此句点的存在会导致它在此时停止。

我不确定你是否完全理解它的运作方式。它赢了给你字符串中所有与你指定的字符相匹配的字符,丢掉其余的字符。相反,它会接受第一个有效的字符,然后扔掉所有其他字符。如果你输入一些中间无效的完全有效的字符,你可以看到这个:

abcdefg.hijklmnop
origin word: abcdefg.hijklmnop
transformed: abcdefg

由此可见,它在第一个无效字符处停止,而不是仅删除无效字符。

如果您想要一个只有匹配字符的字符串,您可以使用以下内容:

#include <stdio.h>
#include <string.h>

#define MAX_WORD 128

static void strip(char *word, char *allow) {
    char *d = word;
    while (*word != '\0') {
        if (strchr (allow, *word) != NULL)
            *d++ = *word;
        word++;
    }
    *d = '\0';
}

int main (void) {
    char word[MAX_WORD];

    while (EOF != scanf ("%s", word)) {
        printf("origin word: %s\n", word);
        strip (word, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz^\"");
        printf("transformed: %s\n", word);
    }
}

,并且有一组样本:

"Disneyland
origin word: "Disneyland
transformed: "Disneyland

Left."
origin word: Left."
transformed: Left"

dvsdhjshhvsdf6553785365^%%$$@@#*&*&mjdvsdddhvjhdfvb
origin word: dvsdhjshhvsdf6553785365^%%$$@@#*&*&mjdvsdddhvjhdfvb
transformed: dvsdhjshhvsdf^mjdvsdddhvjhdfvb

答案 1 :(得分:0)

        sscanf(word, "%[A-Za-z\"]s", word);

编程语言 - C - sscanf功能 - 说明

  

...如果在重叠的对象之间进行复制,则行为是   未定义。

因此,您对sscanf的使用无效。也就是说,即使正确使用,您的测试用例的结果也是可以预期的; paxdiablo的答案中包含了一个解释。