Search code examples
c++sortingfile-read

sort a file based on user input


I am trying to sort a file based on the users choice of 2 files. I'm using a string variable and passing it into the instream() but it keeps going into the if statement that says the file is corrupt or does not exist. I know it exists because when I hardcode the file name in then it works perfectly fine! I'm sure its something simple but I just can't figure it out. I'm very new to c++ so please be thorough with your answers so that I can understand and learn. Thanks in advance!

#include <iterator>
#include <algorithm>
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

std::string file = "";
std::ofstream out("outputfile.txt");
std::vector<int> numbers;
std::string sortType = "";

void sort(std::vector<int>);
void MergeSort(vector<int> &numbers);


int main()
{
  std::cout << "Which type of sort would you like to perform(sort or mergesort)?\n";
  std::cin >> sortType;

  std::cout << "Which file would you like to sort?\n";
  std::cin >> file;

  std::ifstream in(file);
  //Check if file exists
  if(!in)
  {
    std::cout << std::endl << "The File is corrupt or does not exist! ";
    return 1;
  }

  // Read all the ints from in:
  std::copy(std::istream_iterator<int>(in), std::istream_iterator<int>(),
            std::back_inserter(numbers));

  //check if the file has values
  if(numbers.empty())
  {
      std::cout << std::endl << "The file provided is empty!";
      return 1;
  } else
  {
      if(sortType == "sort")
      {
          sort(numbers);
      }else
      {
          MergeSort(numbers);
      }

      // Print the vector with tab separators:
      std::copy(numbers.begin(), numbers.end(),
                std::ostream_iterator<int>(std::cout, "\t"));
      std::cout << std::endl;

        // Write the vector to a text file
      std::copy(numbers.begin(), numbers.end(),
                std::ostream_iterator<int>(out, "\t"));
        std::cout << std::endl;
  }
  return 0;
}

void sort(std::vector<int>)
{
  // Sort the vector:
  std::sort(numbers.begin(), numbers.end());
  std::unique(numbers.begin(), numbers.end());

  return;
}

vector<int> Merge(vector<int> &left, vector<int> &right)
{
    std::vector<int> result;

    while (left.size() > 0 && right.size() > 0)
    {
        if (left[0] <= right[0])
        {
            result.push_back(left[0]);
            left.erase(left.begin());
        } else
        {
            result.push_back(right[0]);
            right.erase(right.begin());
        }
    }

    if (left.size() > 0)
    {
        result.insert(result.end(), left.begin(), left.end());
    } else
    {
        result.insert(result.end(), right.begin(), right.end());
    }
    return result;
}

void MergeSort(vector<int> &numbers)
{
    if (numbers.size() <= 1)
    {
        return;
    }

    // split vector into two peices
    vector<int> left, right;
    unsigned int Middle = numbers.size() / 2;

    for (unsigned int i = 0; i < Middle; i++)
    {
        left.push_back(numbers[i]);
    }

    for (unsigned int i = Middle; i < numbers.size(); i++) {
        right.push_back(numbers[i]);
    }

    MergeSort(left);
    MergeSort(right);
    numbers = Merge(left, right);
    return;
}

Solution

  • You're still checking the file given by the name "". When you put the line

    std::ifstream in(file);
    

    it opens the stream to the file specified by the name "" (the value of file at that point). Later, you say

    if (!in)
    

    without actually updating the file used.

    Try this:

    std::ifstream in; //no file specified
    
    //the following comes before if (!in)
    in.open (file);
    

    This will open the stream to the inputted value of file.

    A better way to do this would be to just declare and open the file in place of the second line and lose the first:

    std::ifstream in (file); //after they input the filename
    

    Using global variables is a generally bad idea if you don't have any reason to. It's better to pass them around in functions, or contain it all in a class.

    Also, I notice you've declared using namespace std;, but still use std::vector etc. I would definitely opt for the latter and remove the former. Take care to add the resolution to the couple of things there missing it then though.