-1

我想保留这段代码,但现在我想知道是否有办法在我的 while 循环中读取文件时是否可以删除该循环中的空白

我在删除空白方面遇到了很多问题我对将文件读入我的程序没有很大的了解,所以这对我来说非常困难,谁能告诉我我在哪里犯了错误?

#include <iostream>
#include <cassert>
#include <string>
#include <fstream>
#include <cstdio>

using namespace std;

int main (void)
 {
 int i=0;
 int current=0;
 int len;
 int ch;
 string s1;
 string s2;
 ifstream fileIn;
  cout << "Enter name of file: ";
  cin >> s1;
  fileIn.open(s1.data() );
   assert(fileIn.is_open() );

 while (!(fileIn.eof() ) )
  { ch=fileIn.get();
  s1.insert(i,1,ch);
  s1.end(); 
  i++;}



cout << s1;
len=s1.length();
cout << len;

 while (current < len-1)
    {
        if (!(s1[current] == ' ' && s1[current + 1] == ' ') &&
            !(s1[current] == '\n' && s1[current + 1] == '\n')
            )
        {
            s2.append(s1[current]);
        }

        current++;

    }

 return 0;
 }
4

2 回答 2

1

有很多事情我会做不同的事情。无需赘述,这就是我的建议;它需要 C++11(-std=c++11如果您使用 gcc 或 clang,也将其传递给编译器):

#include <algorithm> 
#include <cctype>
#include <fstream>
#include <functional> 
#include <iostream>
#include <locale>

using namespace std;

// trim from left
static string ltrim(string s) {
        s.erase(s.begin(), find_if(s.begin(), s.end(), [](char c) { return !isblank(c); } ));
        return s;
}

int main() {

  string file_name;

  cout << "Please enter the file name: " << flush;
  cin >> file_name;

  ifstream in(file_name);

  if (!in.good()) {

    cout << "Failed to open file \"" << file_name << "\"" << endl;

    return 1;
  }

  string buffer;

  while (getline(in, buffer)) {

    buffer = ltrim(buffer);

    if (!buffer.empty()) {

      cout << buffer << '\n'; // <-- or write into a file as you need
    }
  }

  return 0;
}

现在标题说您只想删除前导空格,但对于我的问题,您回答说您也想从行尾删除尾随空格。如果是这样,请使用trim()代替ltrim(). 必要的功能是:

// trim from left
static string ltrim(string s) {
        s.erase(s.begin(), find_if(s.begin(), s.end(), [](char c) { return !isblank(c); } ));
        return s;
}

// trim from right
static string rtrim(string s) {
        s.erase(find_if(s.rbegin(), s.rend(), [](char c) { return !isblank(c); }).base(), s.end());
        return s;
}

// trim from both left and right
static string trim(string s) {
        return ltrim(rtrim(s));
}

还有其他最有可能更快的修剪实现。例如,请参阅:修剪 std::string 的最佳方法是什么

于 2013-10-11T14:52:12.040 回答
0

标准库已经拥有你想要的大部分功能,所以我会尽力依靠它来完成大部分工作。

复制一些删除了指定子集的数据std::remove_copy_if是应该做的,所以我将它用于主循环:

std::remove_copy_if(std::istream_iterator<line>(std::cin), 
        std::istream_iterator<line>(),
        std::ostream_iterator<std::string>(std::cout, "\n"),
        [](std::string const &s){return s.empty(); });

因此,给定 a 的适当定义line,它将复制删除任何空行的行。

我们的下一步是定义一个line类,当我们从流中提取一个空格时,它会删除前导空格,并且可以转换为string. 为此,我会“作弊”一点。当我们从类似的流中提取字符时mystream >> mychar;,它会自动跳过任何前导空格。我会通过读取一个字符来使用它,然后将它放回流1,所以我的流从第一个非空白字符开始。然后我会getline用来阅读该行的其余部分。


1. 读取一个字符,然后立即将其放回流中可能是不寻常的,足以值得评论,或者被放入具有描述性名称的函数中,例如skip_leading_blanks

void skip_leading_blanks(std::istream &is){
    char ch;
    is >> ch;
    is.putback(ch);
}

于 2013-10-11T14:46:00.350 回答