C-忽略scanf()

时间:2018-07-27 11:25:52

标签: c algorithm scanf

我正在尝试进行简单的字符串获取。我需要从输入(stdin)编写一个字符串,该字符串可以包含空格,并不保存保存单词之间的任何空格。

到目前为止,我已经编写了此简单的代码来保存所有内容(还包括空格),但是我不知道如何使scanf()忽略空格。

int main(){
    char str[10];
    scanf("%[^\n]s, str);
    printf("%s", str;
}

例如

如果我的输入是:I love C programming!,我的输出应该是:IloveCprogramming!

我尝试使用%*来忽略字符,但是没有成功。

我还知道一旦保存就可以“重新扫描”字符串并删除所有空格,但是我需要尽可能高效地进行此获取,并且重新扫描每个字符串以删除空格将大大增加计算时间(而不只是扫描和忽略,它的复杂度为O(n))

5 个答案:

答案 0 :(得分:4)

您使用的工具错误。您需要使用getc

然后执行以下操作

int ch;
char str[10];

// Loop until either loop reaches 9 (need one for null character) or EOF is reached
for (int loop = 0; loop < 9 && (ch = getc(stdin)) != EOF; ) {
   if (ch != ' ' ) {
     str[loop] = ch;
     ++loop;
   }
}
str[loop] = 0;

printf("%s", str);

无需重新扫描

答案 1 :(得分:2)

如果有兴趣从输入中除去其他空格(除了''),则还可以合并C库函数 isspace(.) ,该函数将测试以下各项:标准空白字符:

  

''(0x20)空间(SPC)
  '\ t'(0x09)水平制表符(TAB)
  '\ n'(0x0a)换行符(LF)
  '\ v'(0x0b)垂直制表符(VT)
  '\ f'(0x0c)提要(FF)
  '\ r'(0x0d)回车(CR)

此示例使用isspace(.);库函数合并了函数,并提供了一种从C字符串中清除所有标准空白的方法。

int main(void)
{
    char string[] = {"this contain's \n whitespace\t"};
    int len = strlen(string);
    char out[len+1];// +1 for null terminator 
                    //(accommodates when input contains no whitespace)
    int count = clean_whitespace(string, out);

    return 0;
}

int clean_whitespace(const char *in, char *out)
{
    int len, count=0, i;
    if((in) && (out))
    {
        len = strlen(in);
        for(i=0;i<len;i++)
        {
            if(!isspace(in[i]))
            {
                out[count++] = in[i];
            }
        }
        out[count]=0;//add null terminator.
    }
    return count;
}

答案 2 :(得分:2)

scanf()对您的用途没有用,实际上,您甚至不需要缓冲区来从一行输入中去除空格:只需一次读取一个字节,忽略空格,输出其他字节并停在换行符或EOF:

#include <stdio.h>

int main(void) {
    int c;
    while ((c = getchar()) != EOF) {
        if (c != ' ') {
            putchar(c);
        }
        if (c == '\n') {
            break;
        }
    }
    return 0;
}

还请注意,您的代码有问题:

  • scanf()格式的字符串未终止
  • 结尾的s不正确,格式仅为%[^\n]
  • 更安全的是在空终止符之前指定要存储到数组中的最大字节数:scanf("%9[^\n]", str);
  • 您应该测试scanf()的返回值,以避免在转换失败(例如在空行或空文件中)时将未初始化的数组传递给printf

您可以使用scanf()作为一种低效率的方式,使用char c; while (scanf(" %c", &c) == 1) { putchar(c); }也会在忽略空格的同时读取字符,但是您将无法检测到行尾。

答案 3 :(得分:1)

  

到目前为止,我已经编写了这个简单的代码,可以保存所有内容(也   空格),但我不知道如何使scanf()忽略空格。

与大多数新C程序员所做的相反方向相反。问题通常不是使scanf跳过空格,因为对于大多数类型的字段,特别是对于%s字段,默认情况下会这样做。通常将空格识别为字段定界符,因此不仅会跳过前导空格,而且不会在字段内部读取空格。我想这是因为您知道您正在使用%[字段。

但是你不能吃蛋糕也不能吃。字段指令%[^\n]表示要读取的数据由一系列非换行符组成。 scanf将忠实地读取所有这样的字符并将它们转移到您指定的数组。您没有选择指示scanf避免转移您告诉它属于该字段的某些字符。

如果您想继续使用scanf,则有两个选择:

  • 在读取数据后删除空格,或者
  • 将空格分隔的部分读取并传输为单独的字段。

另一个答案已经描述了前者的操作方法。后者的处理方法如下:

int main(void) {
    int field_count;

    do {
        char str[80];
        char tail;

        field_count = scanf("%79[^ \n]%c", str, &tail));
        if (field_count == 0) {
            // No string was scanned this iteration: the first available char
            // was a space or newline.  Consume it, then proceed appropriately.
            field_count = scanf("%c", &tail);
            if (field_count != 1 || tail == '\n') {
                // newline, end-of-file, or error: break out of the loop
                break;
            } // else it's a space -- ignore it
        } else if (field_count > 0) {
            // A string was scanned; print it:
            printf("%s", str);

            if (field_count == 2) {
                // A trailing character was scanned, too; take appropriate action:
                if (tail == '\n') {
                    break;
                } else if (tail != ' ') {
                    putchar(tail);
                } // else it is a space; ignore it
            }
        } // else field_count == EOF
    } while (field_count != EOF);
}

注意事项

  • scanf %79[^ \n]指令中的79个字符(最大)字段宽度。如果没有字段宽度,则存在严重的错误,可能会超出数组边界(必须至少比字段长一个字符才能使用字符串终止符)。
  • [是字段类型,而不是限定符。 s是一个单独的字段类型,它也处理字符串,但是具有不同的行为;这里没有使用s字段。
  • scanf的返回值告诉您成功扫描了多少个字段,如果输入和格式之间或输入的末尾出现不匹配的情况,则可以少于格式字符串中描述的字段达到或发生I / O错误。需要考虑这些可能性。
  • 如果实际上扫描了第二个字段%c,它使您可以确定前面的字符串字段是否由于字段宽度已用尽而没有到达空格或换行符而结束,因为空格是观察到,或者因为观察到换行符。这些情况中的每一个都需要不同的处理方式。
  • 尽管scanf跳过了大多数字段类型的前导空白,但%[%c字段是三个例外中的两个。
  • 此方法专门跳过空格字符(' ');它不会跳过其他空白字符,例如水平和垂直制表符,回车符,换页等。这种方法也可以适用于处理这些字符,但是所提供的内容足以证明这一点。

答案 4 :(得分:0)

我要发布此消息是为了证明使用scanf也可以解决此问题。

 int main() {
   char a[10];
    for(int i = 0; i < 10 ; i++){
        scanf("%c", &a[i]);
        if( a[i] == ' ')
        i--;
    }
}

上面的代码只扫描了10个字符,中间没有空格。

    for(int i = 0; i < 9; i++){
       printf("%c,", a[i]);
     }

    printf("%c", a[9]);

,这是您要用其他内容替换空格的方法,例如:','

如果您希望输入包含更多字符,只需定义一个新变量x并将10更改为x,将9更改为x-1