如何在c中使用scanf读取空白?

时间:2010-09-21 22:39:28

标签: c whitespace scanf fgets

问题:我需要能够识别连续出现两个空格的时间。

我已阅读以下问题:

how to read a string from a \n delimited file

how to read scanf with spaces

我知道scanf问题:http://c-faq.com/stdio/scanfprobs.html

输入将采用以下格式:

1 5 3 2  4 6 2  1 9  0

两个空格表示需要处理下一组数据并与其自身进行比较。线的长度未知,每组中的数字或整数是未知的。两个空格是分隔下一个数据集的最多空格。

虽然我可以使用fgets和各种内置函数来解决这个问题,但我现在处理scanf问题可能会更容易。但是,如果不是这样,使用fgets,strtok和atoi将完成大部分工作,但我仍需要连续识别两个空格。

以下将采用整数,直到输入非整数。

while ( scanf ( "%d", &x ) == 1 )

我需要做的是读取空格,如果有两个连续的空格,我会让程序对下一组数据做一些不同的事情。

一旦我得到一个白色空间,我不知道该怎么说:

if ((input == "whitespace") && (previousInput == "whitespace"))
  ya da ya da
else (input == "whitespace")
  ya da ya da
else 
  ya da ya da

感谢您的时间,感谢您的帮助。

获得的经验教训: 虽然下面由Jonathan Leffler发布了scanf的解决方案,但解决方案对于getc来说更简单一些(通过对内部scanf,正则表达式和char的更少了解)。回想起正则表达式的更好的知识,scanf和char会使问题变得更容易,当然知道哪些函数是可用的,哪一个是从一开始就使用的最好的函数。

5 个答案:

答案 0 :(得分:5)

getcungetc是您的朋友

#include <stdio.h>

int main(void) {
  int ch, spaces, x;
  while (1) {
    spaces = 0;
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++;
    if (ch == EOF) break;
    ungetc(ch, stdin);
    if (scanf("%d", &x) != 1) break;
    printf("%d was preceded by %d spaces\n", x, spaces);
  }
  return 0;
}

http://ideone.com/xipm1

演示

编辑 Rahhhhhhhhh ......我将其上传为C ++。这是完全相同的事情,但现在C99 stricthttp://ideone.com/mGeVk

答案 1 :(得分:1)

while ( scanf ( "%c", &x ) == 1 )

使用%c可以读取空格字符,只能读取所有数据并存储在数组中。然后分配char* cptr并将cptr设置为数组的开头,然后分析数组,如果要读取十进制数,则可以在sscanf上使用cptr想要读取小数,但你必须在数组上有一个好位置的指针(数字你想读的数字)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' '))
  ya da ya da
else ((*cptr)== ' '))
  ya da ya da
  sscanf(++cptr, "%d", &x);
else 
  ya da ya da

答案 2 :(得分:0)

您对“空白区域”的定义是什么?

坦率地说,我认为我不想尝试使用scanf()来识别双白空格;几乎所有其他方法都会容易得多。

但是,如果你坚持做的不是非常敏感,那么你可能想要使用以下代码:

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

int main(void)
{
    int d;
    char sp[3] = "";
    int n;

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0)
    {
        printf("n = %d; d = %d; sp = <<%s>>", n, d, sp);
        if (n == 2 && strlen(sp) == 2)
            printf(" end of group");
        putchar('\n');
    }
    return 0;
}

方括号括起一个字符类,在它坚持最多2个字符之前的2。您可能不得不担心它读取换行符并尝试获取更多数据来满足字符类 - 可以通过从字符类中删除换行符来解决。但是它取决于你对空白区域的定义,以及组是否自动以换行符结束。在循环结束时重置sp[0] = '\0';并没有什么坏处。

或许,你可以更好地逆转字段,在数字之前检测两个空格。但是在普通情况下会失败,所以你会回到简单的"%d"格式来读取数字(如果失败,你知道你既没有空格也没有数字 - 错误)。请注意,%d会占用前导空格(由标准定义) - 所有这些空间。

我看得越多,我就越不喜欢'scanf()。提醒我不要在你的大学上课。

答案 3 :(得分:0)

如果您真的需要scanf类型功能,可以使用fgetssscanf,并使用%n说明符获取scanf,为您的程序提供偏移量每个空白跨越的开始和结束,同时完成其余的工作。

否则,抛弃整个scanf家庭。在我看来,它很可能是标准库中最无用的部分。

答案 4 :(得分:0)

这是一个仅使用scanf()函数的解决方案。我在这个示例中使用了sscanf()来获得相同的功能。

#include <stdio.h>


int p_1_cnt = 0, p_2_cnt = 0;

void process_1(int x)
{
    p_1_cnt++;
}


void process_2(int x)
{
    p_2_cnt++;
}


char * input_line = "1 5 3 2  4 6 2  1 9  0";

int main(void)
{
    char * ip = input_line;

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2;

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0)
    {
        ip += ws_0;

        if ((preceding_spaces) == 1)
            process_1(x);
        else
            process_2(x);

        preceding_spaces = ws_1 - ws_0;
    }

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt);
    _fgetchar();

    return 0;
}