我如何只从C ++中的stdin / cin读取一个空格?

时间:2012-02-28 15:48:12

标签: c++

我无法将以下Java代码转换为其C ++等价物,这是一个解析输入流的简单例程:

   String word = br.readLine();

给定一个示例输入文件,通过管道od -bc以十六进制显示内容,获得以下内容:

   ...
   0000020   040 012 ...
                 \n  
   ...

表示我已正确输入文件,方法是在这一行上提供一个空格字符,跟在换行符后面。

Java能够在整个字符串中读取'<space>\n',但C ++函数(如fgets(),sscanf(),getchar()......及其等效的函数系列)都无法检测到这个空间而不是忽略它,所以我返回了一个零长度的字符串。

这样做的惯用方法是什么?

我的g ++编译器详情:

  

目标:i686-apple-darwin11

     

线程模型:posix

     

gcc 4.2.1版(基于Apple Inc. build 5658)(LLVM build 2336.1.00)

代码+示例输入(镜像@ https://gist.github.com/1933400

#include <tr1/unordered_map>
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string.h>
#include <ctime>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <locale>
#include <sys/time.h>
#include <iterator>

using namespace std;

#define REP(i, a, b)    for(int i=int(a); i<int(b); ++i)

const int MAX_WORD_LENGTH = 22;
char word[MAX_WORD_LENGTH];
string sz_word;
int N, M;

int main()
{
    scanf("%d %d\n", &N, &M);
    REP(i,0,N)
    {
        memset(word, 0, MAX_WORD_LENGTH);
        scanf("%s\n", word);
        //if (i == N-1)
        //  cout << word << endl;
    }

    REP(i,0,M)
    {
        std::getline(std::cin, sz_word);
        cout << "word: '"  << sz_word << "'" << endl;
    }

    return 0;
}

示例输入:

1 1
1
<space>

4 个答案:

答案 0 :(得分:4)

C ++等价物是(假设br是某种std::istream):

std::string word;
std::getline(br, word);

如果您正在阅读标准输入:

std::getline(std::cin, word);

您列出的功能都是C功能;如果你真的想要它们,它们可以用C ++获得,但C ++库通常更方便。

更新:看过你的真实代码,问题在于你是混合了C和C ++风格的输入;这通常是一个坏主意,如果你真的需要,需要一些照顾才能做到正确。问题是:

    \n字符串末尾的
  • scanf将匹配任意数量的空格;它将继续匹配任何换行符,直到您输入除空格之外的其他内容。只需删除\n
  • 即可
  • 在最后一次scanf之后,输入流中仍然存在无法匹配的\n,因此第一个getline会给出一个空行。您可以致电std::cin.ignore()跳过该换行符。

最好的解决方案是对所有输入使用std::cin,而不是尝试使用<cstdio>函数。您可以使用格式化的提取运算符读取数字:std::cin >> N >> M;

答案 1 :(得分:3)

如果我可以简化你的程序并重申你的问题:

#include <cstdio>
#include <iostream>
#include <string>

char word[22];
std::string sz_word;

int main()
{
    std::scanf("%s\n", word);
    std::cout << "'" << word << "'" << std::endl;

    std::getline(std::cin, sz_word);
    std::cout << "word: '"  << sz_word << "'" << std::endl;

    return 0;
}

适当的输入是:

11
 22

注意第二行开头的空格。预期的输出是:

'11'
word: ' 22'

观察到的输出是:

'11'
word: '22'

现在,为什么期望的输出与观察到的输出不同?

答案:因为你致电scanf。从Linux手册页:

  

格式字符串由一系列指令组成......指令是以下之一...
  一系列空格字符(空格,制表符,换行符等;请参阅isspace(3))。该指令在输入中匹配任意数量的空格,包括无空格。

因此,\n格式字符串中的scanfany amount of white space匹配,包括后续行的初始空格。

答案 2 :(得分:1)

fgets()确实应该有用,它不是documented“吃”空格,它甚至包括返回字符串中的换行符。

答案 3 :(得分:1)

通过空白阅读可以帮助解决问题。

char space[1];
// then set the character to either a NULL or to a basic ' ' <space>

SO。例如,使用您的代码而不是调用scanf()我会改为使用构造函数或setSpace()类型函数。字符串可能非常混乱,所以如果可能的话我也会摆脱它们。

希望这至少可以激发某些想法...