-1

I want to keep this code but now I am just wondering if there is a way when i read in the file in my while loop if i can remove the blanks within that loop

I am having a ton of problems with removing blanks I do not have a large understanding on reading in files to my program so this has been very difficult for me, can anybody tell me where I am making my mistakes?

#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;
 }
Falco
  • 7
  • 4
  • To start with, you should probably use [`std::isblank`](http://en.cppreference.com/w/cpp/string/byte/isblank) instead of your own function. Also remember that the C++ standard library have a very nice set of [algorithms](http://en.cppreference.com/w/cpp/algorithm), like for example [`std::remove_if`](http://en.cppreference.com/w/cpp/algorithm/remove). – Some programmer dude Oct 11 '13 at 14:20
  • 2
    I would say that the main problem is that you aren't reading the file a line at a time. Surely that's essential if you want to remove leading blanks (and blank lines). Instead you are reading a character at a time. – john Oct 11 '13 at 14:24
  • 1
    @user2748096 Are you trying to remove the trailing and leading blanks from each line? – Ali Oct 11 '13 at 14:25
  • 2
    Another mistake is your read-loop. As structured it will insert EOF into your string on the last iteration before it terminates. Using `f.eof()` as a while-loop condition is almost always wrong. – WhozCraig Oct 11 '13 at 14:28
  • 1
    @Wurz: Programming by guessing does not work. You are going to have to _read the documentation_. – Lightness Races in Orbit Oct 11 '13 at 15:25

2 Answers2

1

There are a number of things that I would do differently. Without going into details, here is what I propose; it requires C++11 (pass the -std=c++11 also to the compiler if you are using gcc or 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;
}

Now the title says you want to remove only the leading spaces but to my question you answered that you want to remove the trailing spaces as well from the end of the lines. If it is like that, use trim() instead of ltrim(). The necessary functions are:

// 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));
}

There are other, most likely faster trim implementations. See, for example: What's the best way to trim std::string?

Community
  • 1
  • 1
Ali
  • 56,466
  • 29
  • 168
  • 265
0

The standard library already has most of the functionality you want, so I'd do my best to rely on that to do most of the job.

Copying some data with a specified subset removed is what std::remove_copy_if is supposed to do, so I'd use it for the main loop:

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(); });

So, given an appropriate definition of a line, that will copy lines with any empty ones removed.

Our next step is to define a line class that removes leading white-space when we extract one from a stream, and can be converted to a string. For that, I'd "cheat" a little. When we extract a character from a stream like mystream >> mychar;, it automatically skips any leading white-space. I'd use that by reading a char, then putting it back into the stream1, so I had the stream starting from the first non-whitespace character. Then I'd use getline to read the rest of the line.


1. Reading a character, then immediately putting it back into the stream is probably unusual enough to merit either a comment, or being put into a function with a descriptive name like skip_leading_blanks:

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

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111