Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1) implement a text file formatting program. It takes a text file data.txt as an

ID: 3665976 • Letter: 1

Question

1) implement a text file formatting program. It takes a text file data.txt as an input file. The file has a few lines of text but the length(column) of the line is arbitrary. One line could have anywhere between 1 to 200 characters before a new line (carriage return). Your program should ask the number of column to the user and format the text file accordingly. For example, if a user types 65, every line should be aligned 65 long. You may have to combine two linesto one to eliminate the white spaces and blank lines, or split one to two.

2) in cases you need to change line in the middle of a word, you need to use a hyphen (- ) to connect a word between two lines.

3) There should be no more than one white space between two words. Multiple spaces, newlines or tabs must be replaced with a space.

You can assume that a hyphen can be added after the maximum column. So if you're formatting a text to 60 columns and a word is starting at the 60th column, you can add hyphen at 61st. Only the hyphen can come at 61st.

For the output, display the formatted text on screen and save it to data.out.

Hint: read Appendix F for the file I/O and string handling. You may find eat_white( ) function useful for removing white spaces. Read Standard C String & Character  (Links to an external site.)and use appropriate functions like strcpy, strcat, memcmp etc.

Here is the code for mystring.h

Here is the code for mystring.cpp

Explanation / Answer

main.cpp


//
// FILE: main.cpp
//
// This file contains a program utilizing the class my_string
// It takes an input text file of any number of lines and any number of columns from
// either a command line parameter or using the default file name data.txt.
// The program then takes from the user a specified column width and then formats that input
// text into a vector that is exactly that many columns wide. If a word spans the line a hyphen
// is added to the end of the line just past the specified width.
//
// For documentation of program functions please see functions.h

#include <iostream>
#include <fstream>
#include <vector>
#include "mystring.h"
#include "functions.h"

using namespace hw4;
using namespace std;

int main(int argc, char** argv){
   my_string test;
   int number_of_columns;
   vector<my_string> formatted_text; // vector to hold formated text.

   ifstream InFile("data.txt"); // open the input file
   if (!InFile.is_open())
       return 0;

   number_of_columns = Get_Width(); // get number of columns for output //

   Format_Input(InFile, number_of_columns, formatted_text); // do the work....
  
   InFile.close(); // close input file
  
   Display_Output(formatted_text); // Print the output to the screen
  
   Save_Output(formatted_text); // output data to file
}

mystring.cpp
// CLASS IMPLEMENTED: my_string (see mystring.h for documentation)
// INVARIANT for the my_string class:
// 1. The string is stored as a null-terminated string in the dynamic array
//    that characters points to.
// 2. The total length of the dynamic array is stored in the member variable
//    allocated.
// 3. The total number of characters prior to the null character is stored in
//    current_length, which is always less than allocated.

#include <ctype.h>       // Provides stream tools
#include <assert.h>       // Provides assert()
#include <string.h>       // Provides strcpy(), strcat(), strlen(), strcmp()
#include <stdlib.h>       // Provides size_t, NULL
#include <iostream>       // Provides stream types
#include "mystring.h"
using namespace std;

namespace hw4
{

// CONSTRUCTORS and DESTRUCTOR
my_string::my_string(const char str[ ])
// Library facilities used: string.h
{
    current_length = strlen(str);
    allocated = current_length + 1;
    sequence = new char[allocated];
    strcpy(sequence, str);
}

my_string::my_string(const my_string& source)
// Library facilities used: string.h
{
    sequence = new char[source.allocated];
    current_length = source.current_length;
    allocated = source.allocated;
    strcpy(sequence, source.sequence);
}

my_string::~my_string( )
{
    delete [ ] sequence;
}

// MODIFICATION MEMBER FUNCTIONS
// CONSTANT MEMBER FUNCTIONS
// In-lined: size_t length( ) const;
char my_string::operator [ ](size_t position) const
// Library facilities used: assert.h
{
    assert(position < current_length);
    return sequence[position];
}
// += Operator overloading.
void my_string::operator +=(const my_string& addend)
// Library facilities used: string.h
{
    size_t totalLength;
  
    totalLength = (current_length+1+addend.current_length);
    if (allocated < totalLength)
        reserve(totalLength);
    strcat(sequence, addend.sequence);
    current_length = totalLength - 1;
}
// += Operator overloading.
void my_string::operator +=(const char addend[ ])
// Library facilities used: string.h
{
    size_t totalLength;
  
    totalLength = current_length+1+strlen(addend);
    if (allocated < totalLength)
        reserve(totalLength);
    strcat(sequence, addend);
    current_length = totalLength - 1;
}
// += Operator overloading.
void my_string::operator +=(char addend)
// Library facilities used: string.h
{
    char addstring[2];
    addstring[0]=addend;
    addstring[1]='';
    size_t totalLength;

    totalLength = (current_length+2);
    if (allocated < totalLength)
        reserve(totalLength);
    strcat(sequence, addstring);
    current_length = totalLength - 1;
}
void my_string::reserve(size_t n)
{
    size_t i;
    char *larger_string;

    if (n == allocated)
        return; // The allocated memory is already the right size
    if (n < current_length+1)
        n = current_length+1; // Can't allocate less than is being used

    larger_string = new char[n];
    for(i=0; i < current_length+1; i++)
        larger_string[i] = sequence[i];
    delete [ ] sequence;
    sequence = larger_string;
    allocated = n;
}
void my_string::insert(size_t n)
// Function to insert a hyphen between words in a string
{
   size_t totalLength;
   totalLength = current_length+2;
   reserve(totalLength);
   current_length = totalLength-1;
   // Insert necessary hyphen at appropriate position
   if ((sequence[n-1] == ' ') && (sequence[n+1] != ' '))
   // Insert hyphen at column + 1 position
   {
       for (int i=current_length; i>n+1; --i)
           sequence[i] = sequence[i-1];
       sequence[n+1] = '-';
   }
   else
   // Insert hyphen at column position
   {
       for (int i=current_length; i>n; --i)
           sequence[i] = sequence[i-1];
       sequence[n] = '-';
   }
}
// = Operator overloading.
void my_string::operator =(const my_string& source)
{
    size_t i;
    char *new_string;

    if (allocated != source.allocated)
    {
        new_string = new char[source.allocated];
        delete [ ] sequence;
        sequence = new_string;
        allocated = source.allocated;
    }
    current_length = source.current_length;
    for (i=0; i < current_length+1; i++)
        sequence[i] = source.sequence[i];
}
// FRIEND FUNCTIONS
// << Operator overloading.
ostream& operator <<(ostream& outs, const my_string& source)
{
    size_t i;

    for (i=0; i < source.current_length; i++)
        outs << source.sequence[i];
    return outs;
}
// == Operator overloading.
bool operator ==(const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return (comp==0);
}
// != Operator overloading.
bool operator !=(const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return (comp!=0);
}
// >= Operator overloading.
bool operator >=(const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return ((comp>0)||(comp==0));
}
// <= Operator overloading.
bool operator <=(const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return ((comp<0)||(comp==0));
}
// > Operator overloading.
bool operator > (const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return (comp>0);
}
// < Operator overloading.
bool operator < (const my_string& s1, const my_string& s2)
// Library facilities used: string.h
{
    int comp = strcmp(s1.sequence, s2.sequence);

    return (comp<0);
}
// + Operator overloading.
// NON-MEMBER FUNCTIONS for the String class
my_string operator +(const my_string& s1, const my_string& s2)
{
    my_string combinedString;

    combinedString += s1;
    combinedString += s2;

    return combinedString;
}
// >> Operator overloading.
istream& operator >>(istream& ins, my_string& target)
{
    char c;

    while (ins && isspace(ins.peek()))
        ins.ignore();
    target=""; // Set the target to the empty string.
    while (ins && !isspace(ins.peek()))
    {
        ins >> c;
        target += c; // Call the operator += with a char argument.
    }

    return ins;
}
void getline(istream& ins, my_string& target)
{
    char c;

    eat_white(ins, target);   // Removes initial whitespace
    target="";
    ins.get(c);
    while (ins && (c!=' '))
    {
        target += c;
       if (ins && isspace(ins.peek()) && ins.peek()!=' ')
       {
           eat_white(ins, target); // Removes additional
                                                // whitespace between words
           target += ' ';
       }
       ins.get(c);
    }
}
void eat_white(istream& ins, my_string& target)
{
   while (ins && isspace(ins.peek()))
       ins.ignore();
}

}

functions.h

//
// FILE: functions.h
//
// This file contains the functions for HW4, text formattting excercise.
// The functions used are as follows:
//
//   ifstream Open_Input(int& exist_test, char** filename)
//     Precondition: argv and arc functions must be parameters of the main function
//     Postcondition: an input filestream object of either a file specified at the command line
//                      or the default data.txt file or an unopened stream. Error displays are handled
//                      by the function, but the use need to check the stream completed.
//
//   void Get_Width()
//       post condition: returns an int value, after asking how many columns.
//
//   void Format_Input(ifstream& InFile, const int& text_width, vector<my_string>& lines)
//       precondition: Input file stream must exist. User inputs the width of the format and a vector for the format output
//       post condition: a vector filled with properly formatted text, specified by the input width from the user.
//
//   void Display_Output(vector<my_string>& text)
//       post condition: text displayed to the screen of a line by line output of the vector file served as input.
//
//   void Save_Output(vector<my_string>& text)
//       post condition: a file called data.out is created containing a line by line output of the vector served as input.

#ifndef FUNCKES_HW4
#define FUNCKES_HW4

#include <vector>
#include "mystring.h"
using namespace std;
namespace hw4{
   ifstream Open_Input(int& exist_test, char** filename);
   int Get_Width();
   void Format_Input(ifstream& InFile, const int& text_width, vector<my_string>& lines);
   void Display_Output(vector<my_string>& text);
   void Save_Output(vector<my_string>& text);
}
#endif

functions.cpp

//
// FILE: functions.cpp
//
// Implementation of functions.h
// Please see functions.h for documentation

#include <iostream>
#include <vector>
#include <cassert>
#include <fstream>
#include "functions.h"
#include "mystring.h"
using namespace std;

namespace hw4{

/*   ifstream Open_Input(int& exist_test, char** filename){
       /// PRE-TEST FOR COMMAND ARGUMENT//// Test if a file name was specified before any operations occur.
       if (exist_test < 2){
           cout << "There was no file specified at run time, the default file 'data.txt will be used' ";
           ifstream InFile("data.txt");
           if (!InFile.is_open()){ // Error check if data.txt can not open
               cout << "The file data.txt or specified file was not found. Please put data.txt "
                   << "in the default directory or specify a file at run time EX: hw4 thisfile.txt ";
               return InFile;
           }
       } // end error checking

       ifstream InFile(filename[1]);
       if (!InFile.is_open()){
           cout << "The file " << filename[1] << " was not found. "
               << "Please check the filename and try again. ";
           return InFile;
       }
       return InFile;
   }
*/
   int Get_Width(){
       int text_width;
       char input[25] = "a"; // intermediate input to check number value is entered
       while (!isdigit(input[0]) || atoi(input) < 1){ // loop until a digit is inupt for the width
           cout << "How many columns wide should the output be? ";
           cin >> input;
           if (isdigit(input[0]) && atoi(input) > 0){
               text_width = atoi(input); // convert to a int value
               return text_width;
           } // return back the width for formatting.
           cout << "Please enter a width as a number greater than 0 EX: 50 ";
       }
       return 0; // will never hit this return, it just clears compiler warning.
   }
   void Format_Input(ifstream& InFile, const int& text_width, vector<my_string>& lines){
       assert(InFile.is_open()); // check a valid open input file.
       my_string incomming; // used for read in and out going text
       my_string housing; // houses intermediate my_string
       unsigned place = 0; // Keeps track of the charictor number
       int width = text_width; // width is a modifiable text_width, to increase the char read loop by one if the first is a space
       bool first = true; // Keeps track if the charictor is the first on the line (to eliminate a first char space)
       housing.reserve(1000); // reserves space to prevent re-sizing
       incomming.reserve(1000); // reserves space to prevent resizing
       /* -------------------------
       Loop gets all lines of input from the file, overloaded getline from the class
       my_string already eliminates white space. Assemble lines in a single
       my_string called housing.
       ---------------------------- */
       for (int i = 0; !InFile.eof(); i++){
           getline(InFile, incomming);
           housing += incomming + " ";
       }
       incomming = "";
       /* ------------------------
       Place Keeps track of read in charactors and compared them with the total size of the text.
       Inside loop, reads in charictors until the proper size is reached.
       When the proper length is reached, pushes the correctly sized line out a vector
       and resets the read in my_string.
       --------------------------- */
       while (place < housing.length() - 1){
           for (int loop = 0; loop < width && place < housing.length() - 1; loop++){ //for loop control lines written to vector.
               if (first == true && housing[place] == ' '){ width++; } // determines if the charictor is first on a line and also a space, if so increase the width and skip the write.
               else{ incomming += housing[place]; } // if it is not the first and not a space, then apend the char to the string for output
               first = false;// set first = false, as we are through the loop once
               ++place; // increment the place in the original string regardless of space status.
           }
           if (housing[place - 1] != ' ' && housing[place - 1] != '.'){ // if the word is running over the line then add a -
               incomming += '-';
           }
           lines.push_back(incomming); // push into the vector the completely formatted line
           incomming = ""; // clear the incomming my_string
           width = text_width; // ensure width = proper length regardless of first char space status
           first = true; // set first back to true, to start the loop back on first char.
       }
   }
   void Display_Output(vector<my_string>& text){
       cout << "The formated text is: ";
       for (unsigned i = 0; i < text.size(); i++){
           cout << text[i] << endl;
       }
   }
   void Save_Output(vector<my_string>& text){
       ofstream OutFile("data.out"); // open file for output, erases and data.out that exists
       if (!OutFile.is_open()){
           cout << "output.dat did not open ";
           return;
       }
       for (unsigned i = 0; i < text.size(); i++){ // send output to file
           OutFile << text[i];
           OutFile << endl;
       }
       OutFile.close(); // close file
   }
}


mystring.h
// FILE: mystring.h
// CLASS PROVIDED: my_string
//   This is a simple version of the Standard Library string.
//   It is part of the namespace main_savitch_4, from the textbook
//   "Data Structures and Other Objects Using C++"
//   by Michal Main and Walter Savitch
//
// CONSTRUCTOR for the my_string class:
//   string(const char str[ ] = "") -- default argument is the empty string.
//     Precondition: str is an ordinary null-terminated string.
//     Postcondition: The string contains the sequence of chars from str.
//
// CONSTANT MEMBER FUNCTIONS for the my_string class:
//   size_t length( ) const
//     Postcondition: The return value is the number of characters in the
//     string.
//
//   char operator [ ](size_t position) const
//     Precondition: position < length( ).
//     Postcondition: The value returned is the character at the specified
//     position of the string. A string's positions start from 0 at the start
//     of the sequence and go up to length( )-1 at the right end.
//
// MODIFICATION MEMBER FUNCTIONS for the my_string class:
//   void operator +=(const string& addend)
//     Postcondition: addend has been catenated to the end of the string.
//
//   void operator +=(const char addend[ ])
//     Precondition: addend is an ordinary null-terminated string.
//     Postcondition: addend has been catenated to the end of the string.
//
//   void operator +=(char addend)
//     Postcondition: The single character addend has been catenated to the
//     end of the string.
//
//   void reserve(size_t n)
//     Postcondition: All functions will now work efficiently (without
//     allocating new memory) until n characters are in the string.
//
//   void insert(size_t n)
//     Postcondition: A hyphen is added to a string at position n or n+1
//     depending on where n is in a string.
//
//   void operator =(const my_string& source)
//     Postcondition: The string has been set to be equal to source.
//
// NON-MEMBER FUNCTIONS for the my_string class:
//   string operator +(const string& s1, const string& s2)
//     Postcondition: The string returned is the catenation of s1 and s2.
//
//   istream& operator >>(istream& ins, string& target)
//     Postcondition: A string has been read from the istream ins, and the
//     istream ins is then returned by the function. The reading operation
//     skips white space (i.e., blanks, newlines, tabs) at the start of ins.
//     Then the string is read up to the next white space or the end of the
//     file. The white space character that terminates the string has not
//     been read.
//
//   ostream& operator <<(ostream& outs, const string& source)
//     Postcondition: The sequence of characters in source has been written
//     to outs. The return value is the ostream outs.
//
//   void getline(istream& ins, string& target)
//     Postcondition: A string has been read from the istream ins. The reading
//     operation starts by skipping any white space, then reading all characters
//     (skipping any additional whitespace, leaves only one space between
//     words) until the newline character is read and discarded (but not
//     added to the end of the string). The return value is ins.
//
// VALUE SEMANTICS for the my_string class:
//    Assignments and the copy constructor may be used with string objects.
//
// TOTAL ORDER SEMANTICS for the string class:
//    The six comparison operators (==, !=, >=, <=, >, and <) are implemented
//    for the string class, forming a total order semantics, using the usual
//    lexicographic order on strings.
//
// DYNAMIC MEMORY usage by the string class:
//   If there is insufficient dynamic memory then the following functions call
//   new_handler: The constructors, resize, operator +=, operator +, and the
//   assignment operator.

#ifndef MYSTRING_H
#define MYSTRING_H
#include <cstdlib> // Provides size_t

namespace hw4
{

class my_string
{
public:
// CONSTRUCTORS and DESTRUCTOR
my_string(const char str[ ] = "");
my_string(const my_string& source);
~my_string( );
// MODIFICATION MEMBER FUNCTIONS
void operator +=(const my_string& addend);
void operator +=(const char addend[ ]);
void operator +=(char addend);
void reserve(size_t n);
void operator =(const my_string& source);
void insert(size_t n);
// CONSTANT MEMBER FUNCTIONS
size_t length( ) const { return current_length; }
char operator [ ](size_t position) const;
// FRIEND FUNCTIONS
friend std::ostream& operator <<(std::ostream& outs, const my_string& source);
friend bool operator ==(const my_string& s1, const my_string& s2);
friend bool operator !=(const my_string& s1, const my_string& s2);
friend bool operator >=(const my_string& s1, const my_string& s2);
friend bool operator <=(const my_string& s1, const my_string& s2);
friend bool operator > (const my_string& s1, const my_string& s2);
friend bool operator < (const my_string& s1, const my_string& s2);
private:
char *sequence;
size_t allocated;
size_t current_length;
};

// NON-MEMBER FUNCTIONS for the string class
my_string operator +(const my_string& s1, const my_string& s2);
std::istream& operator >>(std::istream& ins, my_string& target);
void getline(std::istream& ins, my_string& target);
void eat_white(std::istream& ins, my_string& target);

}

#endif

data.txt

This   is a test.       file for interpretation.
it is a very special file cause is has a bunch of BS

implement a text file           formatting program.

sample output

                                                                                                                                              
How many columns wide should the output be?                                                                                                                 
60                                                                                                                                                          
The formated text is:                                                                                                                                       
This is a test. file for interpretation. it is a very specia-                                                                                               
l file cause is has a bunch of BS implement a text file form-                                                                                               
atting program.