0

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;
}
1
  • I am now getting error: no matching function for call to 'std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(std::string&)' Commented May 28, 2012 at 4:06

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

That makes sense. Now im getting an error on that line where I open the file using both ways you suggested. error: no matching function for call to 'std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(std::string&)' I only made the changes you suggested. Besides that its exactly the same as above.
@Fourthmeal70, could you update your code to reflect the changes? That seems odd.
Code is updated. Nothing changed besides moving the std::ifstream in(file) to right before the if(!in) statement.
@Fourthmeal70, I keep forgetting this, but the parameter is of type const char *, not std::string. Use file.c_str() to get that. I'm not exactly sure how it was accepting the empty string before though.
@Fourthmeal70, c_str() retrieves the internal char * that std::string has and appends a '\0' to it so that it is the C-style string representation. The ifstream parameter's type is the C-string type const char *, so you can pass it in. When you put a direct literal in, it's of type const char[], which decays into const char *. These semantics were all present in C (minus the whole ifstream and std::string). In C++, we just have to deal with the compatibility. The tools are there to use if we need an std::string from a char * and vice-versa.
|
0

You need to open() the file before you check the status.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.