C++. Examples of working with text files. Modification of files. Sort data in files. Convert file data to list

Examples of working with text files. Modification of files. Sort data in files. Convert file data to list

This topic provides examples of solutions to known problems that arise when processing text files in C++. Having worked out solutions to these problems, you will learn how to process arrays of string data, manage memory allocation, and use C++ tools to work with text files.


Contents


Search other websites:




1. How to determine if the data in a text file has run out?

To determine the end of the file, use the eof() function. The function returns a result of type bool. The prototype of the function is as follows

bool std::eof();

here std – namespace in which the eof() function is declared.

If, when calling the function, the current read pointer points to the end of the file, then the function returns true. Otherwise, the function returns false.

Example 1. Below is a snippet of code that uses the eof() function to determine whether the end of the file is reached, which corresponds to the instance named inputFile

if (inputFile.eof() == false)
{
  cout << "End of file not reached.";
}
else
{
  cout << "End of file is reached.";
}

 

Example 2. Most often, the eof() function is used in a while loop when reading lines in a file.

while (!inputFile.eof()) // until the end of the file
{
  // Reading lines from a file
  // ...
}

As soon as the end of the inputFile is reached, the loop will exit.

 

2. Function CountLinesInFile(). Count the number of lines in a text file

The CountLinesInFile() function returns the number of lines in a text file.

#include <iostream>
using namespace std;

// <fstream> module is necessary for working with files
#include <fstream>

// A function that determines the number of lines in a file.
// The file name is set by the input parameter
int CountLinesInFile(char* filename)
{
  // 1. Declare an instance of F that is associated with the file filename.
  // The file is opened for reading in text format.
  ifstream F(filename, ios::in);

  // 2. Checking if a file exists
  if (!F)
  {
    return -1;
  }

  // 3. Calculate the number of lines in a file
  // 3.1. Declare additional variables
  int count = 0;
  char buffer[1000]; // buffer for saving one line

  // 3.2. The lines reading cycle.
  // Each line of the file is read by the getline () function.
  // Checking the end of the file is done by the eof () function.
  while (!F.eof())
  {
    // Increase row counter
    count++;

    // Read one line to the buffer
    F.getline(buffer, 1000);
  }

  // 4. Close the file F
  F.close();

  // 5. Return the result
  return count;
}

void main()
{
  // Determining the number of lines in the file "TextFile1.txt"
  int nLines = CountLinesInFile((char*)"TextFile1.txt");

  // Display the result
  if (nLines == -1)
    cout << "Error opening file";
  else
    cout << "nLines = " << nLines << endl;
}

 

3. The GetStringsFromFileC() function. Get an array (list) of char* strings from a text file

The list of lines can be returned in one of two ways in which one line is perceived differently:

  • as a char* type. In this case, the list of strings is of type char**;
  • as a type string – a list of strings is of type string*.

To determine the number of lines in a file, the function calls the CountLinesInFile() function, which is described in step 2.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that returns lines of a file as a list of type char**.
// Parameters:
// - filename - the name of file;
// - _lines - list of lines of a file of type (char**).
// The function returns the total number of lines read in the file,
// if the reading failed, the function returns -1.
int GetStringsFromFileC(string filename, char*** _lines = nullptr)
{
  // 1. Additional variables
  char** lines;
  int n = CountLinesInFile(filename); // get the number of lines in a file

  // 2. Check if row count is known
  if (n == -1) return -1;

  // 3. Declare a file variable
  ifstream F(filename); // open file for reading

  // 4. Checking if a file opened
  if (!F) return -1;

  // 5. An attempt to allocate memory for n lines
  try
  {
    lines = new char* [n];
  }
  catch (bad_alloc e)
  {
    // if memory cannot be allocated, then exit
    cout << e.what() << endl; // display error message
    F.close(); // close the file
    return -1;
  }

  // 6. The cycle of reading strings and allocating memory for them
  int len; // single line length
  char buffer[1000]; // memory where one line from the file is written

  for (int i = 0; i < n; i++)
  {
    // 6.1. Read line from file
    F.getline(buffer, 1000);

    // 6.2. Determine the length of the read line
    for (len = 0; buffer[len] != '\0'; len++);

    // 6.3. Allocate memory for len+1 characters
    lines[i] = new char[len + 1];

    // 6.4. Copy data from buffer to lines[i]
    for (int j = 0; j < len; j++)
      lines[i][j] = buffer[j];
    lines[i][len] = '\0'; // add a newline character
  }

  // 7. Close the file
  F.close();

  // 8. Write the result
  *_lines = lines;
  return n;
}

Using the GetStringsFromFileC() function can be, for example, the following:

void main()
{
  // Output the lines of the file on the screen
  // 1. Declare an internal variables
  int count; // number of lines
  char** lines = nullptr; // a list of strings of type char*

  // 2. Get a list of strings of type char**
  count = GetStringsFromFileC("TextFile1.txt", &lines);

  // 3. Check if the list is received
  if (count < 0)
  {
    cout << "Error" << endl;
    return;
  }

  // 3. Display a list of string on the screen.
  for (int i = 0; i < count; i++)
  {
    cout << lines[i] << endl;
  }

  // 4. Release the memory allocated for each string
  if (lines!=nullptr)
    for (int i = 0; i < count; i++)
      delete lines[i];

  // 5. Release the memory allocated for lines
  if (lines != nullptr)
    delete[] lines;
}

 

4. The GetStringsFromFileS() function. Get an array of strings of type string from a text file

Working with the string type is more convenient than with the char* type. The following code fragment implements the GetStringsFromFileS() function, which reads lines from a text file and writes them to an array (list) of type string. This function uses the CountLinesInFile() function, which is described in paragraph 2 of this topic.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that receives a file string as an array of type string *
// Parameters:
// - filename - the name of file;
// - _lines - array of lines of a file of type string *.
// The function returns the total number of lines read.
int GetStringsFromFileS(string filename, string** _lines)
{
  // 1. Additional variables
  string* lines; // temporary array of strings
  int n = CountLinesInFile(filename); // Get a number of lines in file

  // 2. Checking if lines from file are read correctly
  if (n == -1) return -1;

  // 3. Declare a file variable and open the filename for reading
  ifstream F(filename);

  // 4. Checking if a file is open
  if (!F) return -1;

  // 5. Attempting to allocate memory for n strings of type string
  try
  {
    lines = new string[n];
  }
  catch (bad_alloc e)
  {
    cout << e.what() << endl; // display error message
    F.close();
    return -2; // return with code -2
  }

  // 6. Reading lines from a file and writing lines to the lines list
  char buffer[1000]; // buffer for reading a line

  for (int i = 0; i < n; i++)
  {
    // 6.1. Read a line from a file into the buffer
    F.getline(buffer, 1000);

    // 6.2. Calculate read string length
    int len;
    for (len = 0; buffer[len] != '\0'; len++);

    // 6.3. Copy buffer => lines[i], use the assign() method.
    // Copy len bytes from buffer to lines[i].
    lines[i].assign(buffer, len);
  }

  // 7. Close the file
  F.close();

  // 8. Return the result
  *_lines = lines;
  return n;
}

Using GetStringsFromFileS() function can be, for example, as follows

void main()
{
  // Displaying an array of file lines on the screen
  // 1. Declare internal variables
  int count; // the number of lines
  string* lines = nullptr; // array of strings

  // 2. Get a list of strings of type string*
  count = GetStringsFromFileS("TextFile1.txt", &lines);

  // 3. Check if the array is received
  if (count < 0)
  {
    cout << "Error" << endl;
    return;
  }

  // 3. Display a list of lines on the screen.
  for (int i = 0; i < count; i++)
  {
    cout << lines[i] << endl;
  }

  // 4. Free memory allocated for lines array
  if (lines != nullptr)
    delete[] lines;
}

The result of the program (the contents of the TextFile1.txt file):

#include <iostream>

using namespace std;

void main()
{
  cout << "Hello world!";
}

 

5. Function SetStringsToFileS(). Write an array (list) of strings of type string to a text file

When working with text files, the SaveStringsToFileS() function is useful, which writes an array of strings to a file. In the following examples, this function will be used to write the modified list to a file.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that writes an array of strings of type string to a text file.
// Parameters:
// - filename - the name of file;
// - lines - an array of strings that are written to the file;
// - count - number of strings.
// The function returns true if the strings were saved successful.
bool SetStringsToFileS(string filename, string* lines, int count)
{
  // 1. Declare an additional variables
  ofstream F(filename); // Open file for writing

  // 2. Check whether the file was opened successfully
  if (!F) return false;

  // 3. Writing lines to a file except the last line
  for (int i = 0; i < count - 1; i++)
    F << lines[i] << endl;

  // 4. Write the last line as is (without the character '\n')
  F << lines[count - 1];

  // 5. Close the file
  F.close();

  // 6. Return the result
  return true;
}

The following is an example of using the SetStringsToFileS() function.

void main()
{
  // Writing an array of strings to a file
  // 1. Declare the internal variables
  int count; // number of strings
  string* lines = nullptr; // array of strings

  // 2. Form the strings
  try
  {
    // attempt to allocate memory for 5 strings
    lines = new string[5];
  }
  catch (bad_alloc e)
  {
    cout << e.what() << endl;
    return;
  }

  // write some text to the lines array
  lines[0] = "#include <stdio.h>";
  lines[1] = "using namespace std";
  lines[2] = "void main()";
  lines[3] = "{";
  lines[4] = "}";

  // 3. Write strings to the TextFile2.txt
  if (SetStringsToFileS("TextFile2.txt", lines, 5))
    cout << "OK!" << endl;
  else
    cout << "Error." << endl;

  // 4. Release memory allocated for lines array
  if (lines != nullptr)
    delete[] lines;
}

 

6. Function ChangeStringInFileC(). Replacing a string in a text file

The example shows a function that replaces a line in a file at a given position. This function uses the following functions:

  • CountLinesInFile() – determines the number of lines in the file (implemented in paragraph 3);
  • GetStringsFromFileC() – returns the lines of the file as an array (implemented in step 4). Strings are represented by type char*.

This function does not use an additional file for copying. The function receives the lines of the file as an array of lines, which serve as a copy of the file. Then these lines are written to the same file, except for the line that needs to be replaced in the file. At the replacement position, the input replacement string is written. Thus, the line in the text file is replaced.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that replaces a line in a file.
// Parameters:
// - filename - the name of file;
// - position - the position of the line in the file to be replaced;
// - str - line replacing the line in the file.
// The function returns true if the string replacement operation was successful.
bool ChangeStringInFileC(string filename, int position, string str)
{
  // 1. Get file lines as an array
  char** lines; // array of file lines
  int count; // the number of lines in the file
  count = GetStringsFromFileC(filename, &lines); // get the array lines

  // 2. Checking if the file is read correctly
  if (count < 0) return false;

  // 3. Check if position 0 <= position < count is correct
  if ((position < 0) || (position >= count)) return false;

  // 4. Writing lines to a file
  ofstream F(filename); // open file for writing

  // 5. Checking if a file opened correctly - is_open() function
  if (!F.is_open()) return false;

  for (int i = 0; i < position; i++)
    F << lines[i] << endl; // output a string to a file

  // 6. Writing a line from position
  F << str.c_str() << endl; // the string str is written here

  // 7. Writing lines after position
  for (int i = position + 1; i < count - 1; i++)
    F << lines[i] << endl;

  // 8. Write the last line without the character '\n'
  F << lines[count - 1];

  // 9. Close the file
  F.close();

  // 10. Release the memory allocated for the strings
  for (int i = 0; i < count; i++)
    delete lines[i];

  // 11. Release the pointer to the strings
  delete[] lines;
}

Using this function can be, for example, the following:

void main()
{
  // Replacing the input line in a file
  string filename = "TextFile1.txt"; // source file
  int pos = 5; // the original string position
  string str = "Hello world!"; // the original replacement string

  if (ChangeStringInFileC(filename, pos, str))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

Optionally, you can change the input of the input data (file name, position, replacing the string).

 

7. Function RemoveStringFromFileByIndex(). Delete a line from a file by its number

Deleting a line from a file by its number can be performed according to the example of p. 6 (replacing a line in a text file).

The general algorithm is as follows:

  • read all lines of the file into an array (list);
  • remove string from the array;
  • write the modified array back to the file.

To create a list of strings, you can use the GetStringsFromFileC() and GetStringsFromFileS() functions, which are described in paragraphs 3 and 4.

The text of the line delete function by its number is as follows.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that deletes a line in a file at a given number,
// line number starts at 0.
// Function parameters:
// - filename - name of the file from which the line is deleted;
// - position - line number in the file to be deleted.
// If the operation is successful, the function returns true;
// if the row is not deleted, the function returns false.
bool RemoveStringFromFileByIndex(string filename, int position)
{
  // 1. Checking if string is specified correctly
  if (position < 0) return false;

  // 2. Additional variables
  string* lines; // array of strings
  int n; // number of lines into the file

  // 3. Read the number of lines in a file
  n = CountLinesInFile(filename); // invoke the function from paragraph 2

  // 4. Checking if filename was read
  if (n == -1) return false;

  // 5. Checking if position is correct
  if (position >= n) return false;

  // 6. Get a list of lines of type string *
  n = GetStringsFromFileS(filename, &lines); // function from paragraph 4

  // 7. Delete line at position
  for (int i = position; i < n - 1; i++)
    lines[i] = lines[i + 1];

  // 8. Reduce the total number of strings
  n--;

  // 9. Write a list to a file - use the SetStringsToFileS() function
  bool res = SetStringsToFileS(filename, lines, n);

  // 10. Release array lines
  if (n > 0) delete[] lines;

  // 11. Return the result
  return res;
}

Using a function can be, for example, as follows

void main()
{
  // Removing the source line in the file
  string filename = "TextFile1.txt"; // source file
  int pos = 7; // specified position of the string

  if (RemoveStringFromFileByIndex(filename,pos))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

 

8. Function InsertStringToFile(). Insert a line at a given position in a file

The approach is the same as in the previous paragraphs. You need to get the lines of the file as an array (type string or char*). Then you need to insert the string into the array and write the modified array of strings back to the file.

If the value of the insertion position is equal to the number of elements in the file, then the line is added to the end of the file.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that inserts the specified string at the specified file position.
// Function parameters:
// - filename - the name of file;
// - str - string to be inserted;
// - position - position of string str. It is numbered from 0 to the number of lines in the file.
// If the insert was successful, the function returns true.
bool InsertStringToFile(string filename, string str, int position)
{
  // 1. Additional variables
  int count;
  string* lines = nullptr; // list of file lines

  // 2. Get a list of lines from a file - a call to the function described in paragraph 4
  count = GetStringsFromFileS(filename, &lines);

  // 3. Checking if the lines reading process is normal
  if ((count < 0)) return false;

  // 4. Check if position value is correct.
  // If positon == count, then the line is added to the end of the file.
  if ((position < 0) || (position > count)) return false;

  // 5. Create a new list of lines2, in which there is 1 more element
  string* lines2 = nullptr;
  try
  {
    // attempt to allocate memory for array lines2
    lines2 = new string[count + 1];
  }
  catch (bad_alloc e)
  {
    // if the attempt to allocate memory is unsuccessful, then exit the program
    cout << e.what() << endl;
    if (lines != nullptr) // release memory
      delete[] lines;
    return false;
  }

  // 6. Copy lines=>lines2
  // 6.1. First copy to the position
  for (int i = 0; i < position; i++)
    lines2[i] = lines[i];

  // 6.2. Add to lines2[position] string str
  lines2[position] = str;

  // 6.3. Copy the following strings
  for (int i = position; i < count; i++)
    lines2[i + 1] = lines[i];

  // 7. Increase the total number of lines by 1
  count++;

  // 8. Write lines to the file
  bool res = SetStringsToFileS(filename, lines2, count);

  // 9. Release memory, allocated for lines, lines2
  if (lines != nullptr) delete[] lines;
  if (lines2 != nullptr) delete[] lines2;

  // 10. Return the result
  return res;
}

The call to the InsertStringToFile() function in the main() function can be as follows.

void main()
{
  // Paste the specified line at the specified file position
  string filename = "TextFile1.txt"; // source file
  int pos = 8; // specified position of the string
  string s = "Hello"; // insertion string

  if (InsertStringToFile(filename, s, pos))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

 

9. Function SwapStringsInFile(). Swap two lines in a file

The algorithm of the SwapStringsInFiles() function is as follows:

  1. Read the lines of the file to the array.
  2. Change the lines in the array.
  3. Write the modified array back to the file.

The text of the string exchange function is as follows.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that swaps two lines at specified positions.
// Parameters:
// - filename - the name of the file;
// - pos1 - line position 1 (numbered from 0);
// - pos2 - line position 2 (numbered from 0);
// If the swapping was successful, then the function returns true. Otherwise false.
bool SwapStringsInFile(string filename, int pos1, int pos2)
{
  // 1. Check if pos1, pos2 are correct
  if ((pos1 < 0) || (pos2 < 0)) return false;

  // 2. Additional variables
  int count;
  string* lines = nullptr; // array of file lines
  string s;

  // 3. Get array of file lines
  count = GetStringsFromFileS(filename, &lines); // function from paragraph 4

  // 4. Checking whether reading from a file has been successful
  if (count < 0) return false;

  // 5. Check if pos1, pos2 are within count
  if (pos1 >= count) return false;
  if (pos2 >= count) return false;

  // 6. Swap lines[pos1] and lines[pos2]
  s = lines[pos1];
  lines[pos1] = lines[pos2];
  lines[pos2] = s;

  // 7. Write an array of lines back to the file
  bool res = SetStringsToFileS(filename, lines, count);

  // 8. Release memory allocated for the array lines
  if (lines != nullptr)
    delete[] lines;

  // 9. Return the result
  return res;
}

The call to the SwapStringsInFile() function from the main() function can be as follows

void main()
{
  // Swap two lines in a file
  string filename = "TextFile1.txt"; // source file
  int pos1 = 2; // position 1 of line
  int pos2 = 7; // position 2 of line

  if (SwapStringsInFile(filename,pos1, pos2))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

 

10. Function ReverseStringsInFile(). Reversing file lines (rearranging file lines in reverse order)

The algorithm of the method is as follows:

  • read lines from a file and write them to an array;
  • swap the elements of the array so that the rows of the array are placed in the reverse order;
  • write modified array back to file

The text of ReverseStringsInFile() function is as follows.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// A function that reverses file lines in reverse order.
// Parameters:
// - filename - the name of the file.
// If the operation is successful, the function returns true.
bool ReverseStringsInFile(string filename)
{
  // 1. Additional variables
  int count;
  string* lines = nullptr;
  string s;

  // 2. Read lines from the file
  count = GetStringsFromFileS(filename, &lines);

  // 3. Checking if rows were read correctly
  if (count <= 0) return false;

  // 4. Reversing the array lines
  for (int i = 0; i < count / 2; i++)
  {
    s = lines[i];
    lines[i] = lines[count - i - 1];
    lines[count - i - 1] = s;
  }

  // 5. Write array lines to the file
  bool res = SetStringsToFileS(filename, lines, count);

  // 6. Release memory, allocated for array lines
  if (lines != nullptr) delete[] lines;

  // 7. Return the result
  return res;
}

Using ReverseStringsInFile() could be, for example, the following

void main()
{
  // Reversing the lines of a file
  string filename = "TextFile3.txt"; // source file

  if (ReverseStringsInFile(filename))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

 

11. Function SortStringsInFile(). Sort lines in a file

The example demonstrates sorting file lines using the insert method. Previously, the lines are copied to the array and sorted there. Then, the sorted array of strings is written back to the file.

#include <iostream>
using namespace std;

// the <fstream> module is necessary for working with files
#include <fstream>

// The function of sorting lines in a file by the insert method.
// Parameters:
// - filename - the name of a file.
// If the sorting occurred correctly, then the function returns true.
bool SortStringsInFile(string filename)
{
  // 1. Additional variables
  int count;
  string* lines = nullptr;
  string s;

  // 2. Read lines from file to array lines
  count = GetStringsFromFileS(filename, &lines); // function from p.4

  // 3. Checking if lines were read correctly
  if (count < 0) return false;

  // 4. Sort lines in file ascending by insertion
  for (int i = 0; i < count - 1; i++)
    for (int j = i; j >= 0; j--)
      if (lines[j] > lines[j + 1])
      {
        s = lines[j];
        lines[j] = lines[j + 1];
        lines[j + 1] = s;
      }

  // 5. Write sorted array of lines to file
  bool res = SetStringsToFileS(filename, lines, count);

  // 6. Release memory allocated for array lines
  if (lines != nullptr) delete[] lines;

  // 7. Return the result
  return res;
}

Using a file in the main() function

void main()
{
  // Sort lines in a file
  string filename = "TextFile4.txt"; // source file

  if (SortStringsInFile(filename))
  {
    cout << "OK!!!";
  }
  else
  {
    cout << "Error";
  }
}

 


Related topics