## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

# 4.15. Converting Between Tabs and Spaces in a Text File

## Problem

You have a text file that contains tabs or spaces, and you want to convert from one to the other. For example, you may want to replace all tabs with three spaces, or you may want to do just the opposite and replace occurrences of some number of spaces with a single tab.

## Solution

Regardless of whether you are replacing tabs with spaces or spaces with tabs, use the `ifstream` and `ofstream` classes in `<fstream>`. In the first (simpler) case, read data in with an input stream, one character at a time, examine it, and if it’s a tab, write some number of spaces to the output stream. Example 4-23 demonstrates how to do this.

Example 4-23. Replacing tabs with spaces

```#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

int main(int argc, char** argv) {

if (argc < 3)
return(EXIT_FAILURE);

ifstream in(argv[1]);
ofstream out(argv[2]);

if (!in || !out)
return(EXIT_FAILURE);

char c;
while (in.get(c)) {
if (c == '\t')
out << "   "; // 3 spaces
else
out << c;
}

out.close();

if (out)
return(EXIT_SUCCESS);
else
return(EXIT_FAILURE);
}```

If, instead, you need to replace spaces with tabs, see Example 4-24. It contains the function `spacesToTabs` that reads from an input stream, one character at a time, looking for three consecutive spaces. When it finds three in a row, it writes a tab to the output stream. For all other characters, or for fewer than three spaces, whatever is read from the input stream is written to the output stream.

Example 4-24. Replacing spaces with tabs

```#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <cstdlib>

using namespace std;

void spacesToTabs(istream& in, ostream& out, int spaceLimit) {

int consecSpaces = 0;
char c;

while (in.get(c)) {
if (c != ' ') {
if (consecSpaces > 0) {
for (int i = 0; i < consecSpaces; i++) {
out.put(' ');
}
consecSpaces = 0;
}
out.put(c);
} else {
if (++consecSpaces == spaceLimit) {
out.put('\t');
consecSpaces = 0;
}
}
}
}

int main(int argc, char** argv) {

if (argc < 3)
return(EXIT_FAILURE);

ifstream in(argv[1]);
ofstream out(argv[2]);

if (!in || !out)
return(EXIT_FAILURE);

spacesToTabs(in, out, 3);

out.close();

if (out)
return(EXIT_SUCCESS);
else
return(EXIT_FAILURE);
}```

## Discussion

The mechanism for both of these solutions is the same; only the algorithms differ. Read characters from an input stream using `get`, and put them to an output stream with `put`. Put your logic for doing the translation between calls to these two functions.

You probably noticed in Example 4-24 that in `main` I declared `in` and `out` to be of types `ifstream` and `ofstream`, respectively, and that the parameters to `spacesToTabs` are actually `istream` and `ostream`. I did this to allow `spacesToTabs` to work on any kind of input or output streams (well, not any kind of stream—ones that inherit from `basic_istream` or `basic_ostream`), and not just file streams. For example, you may have the text you want to reformat in a string stream (`istringstream` and `ostringstream` in `<sstream>`). In that case, do something like this:

```istringstream istr;
ostringstream ostr;

// fill up istr with text...

spacesToTabs(istr, ostr);```

As with strings, streams are actually class templates that are parameterized on the type of character the stream operates on. For example, an `ifstream` is a `typedef` for `basic_ifstream<char>`, and a `wifstream` is a `typedef` for `basic_ifstream<wchar_t>`. Thus, if you need `spacesToTabs` from Examples Example 4-23 or Example 4-24 to work on a stream of any kind of character, you can use the class templates instead of the `typedefs`:

```template<typename T>
void spacesToTabs(std::basic_istream<T>&

in,
std::basic_ostream<T>& out,
int spaceLimit) { //...```

## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

No credit card required