-3

I want shift char array from read file and write output. but i got 2 errors. i dont know with this error.

  1. no suitable conversion function from "std::valarray" to "const char *" exists

  2. 'std::basic_ostream> &std::basic_ostream>::write(const _Elem *,std::streamsize)': cannot convert argument 1 from 'std::valarray' to 'const _Elem *'

void CaesarCipher(std::wstring i_inputFilePath, std::wstring o_outputFilePath, int shift)
{
    ifstream file(i_inputFilePath, ios::binary);
    if (file.is_open())
    {
        ofstream output(o_outputFilePath, ios::binary);
        std::array<char, 1024> buffer;
        while (!file.eof()) {
            file.read(buffer.data(), buffer.size());
            std::rotate(buffer.begin(), std::next(buffer.begin(), shift), buffer.end());
            output.write(buffer, buffer.size());
        }
        output.close();
        file.close();
    }
    else
    {
        cout << "File is not exist";
    }

}

int main()
{

    CaesarCipher(L"D:/input.exe", L"D:/output.exe", 1);
}
  • 1
    Worth reading regarding `while(!file.eof())`: https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – Galik Nov 20 '18 at 16:01
  • @Galik i don't problem with the read in chunk file. i already test it in my project. the problem how to shift data from file read and write it. –  Nov 20 '18 at 16:06
  • I wasn't trying to answer your question. I was just pointing out a bug in your code. – Galik Nov 20 '18 at 16:18
  • You've changed the code so now the problem description and error messages no longer make sense. – Blastfurnace Nov 20 '18 at 16:35
  • Unrelated note about the tag [tag:visual-studio]. If you read the description, it says *DO NOT use this tag on questions regarding code which merely happened to be written in Visual Studio.*, so it should not be used in this question. Similar applies to the Linux and Windows tags. – Richardissimo Nov 21 '18 at 21:19

2 Answers2

1

Your problem is with

output.write(dataShiftLeft, sizeof(data));

std::ostream::write takes a const char* and you provide a valarray<char>, that's why the compiler complains.

You need to iterate over the valarray and write the elements one by one:

for (auto c : dataShiftLeft) output << c;

But I'm confident that you would be better off with a std::array and the std::rotate algorithm, along those lines:

std::array<char, 1024> buffer;
// ...
file.read(buffer.data(), buffer.size());
auto trailing_zeros = std::rotate(buffer.begin(), std::next(buffer.begin(), 1), buffer.end()); // or 
std::fill(trailing_zeros, buffer.end(), 0);
papagaga
  • 868
  • 5
  • 13
  • Showing the example reworked with `std::array` and `std::rotate` would be helpful. – Peter Ruderman Nov 20 '18 at 16:07
  • shift diferent with rotate. shift involve element in bit. not element position. –  Nov 20 '18 at 16:16
  • 1
    @edwardjoe: https://en.cppreference.com/w/cpp/numeric/valarray/shift: "Returns a new valarray of the same size with elements whose positions are shifted by count **elements**" – papagaga Nov 20 '18 at 16:18
  • how to revert it back after rotate? i want to make simple encryption and decryption file. –  Nov 20 '18 at 16:19
  • @papagaga thank, i don't read the description. i think rotate ways same. how to revert it back says i rotate it 1. is it just put -1 for revert back? –  Nov 20 '18 at 16:22
  • by the way. why i get error incomplete type is not allowed? –  Nov 20 '18 at 16:29
  • Sorry, there was a mistake in my answer, `std::rotate` takes iterators as arguments. See https://en.cppreference.com/w/cpp/algorithm/rotate for the full reference. To revert use the return value of the first call to rotate as the second argument for the next call: `auto bkp = std::rotate(first, first+offset, end); /* ... */ std::rotate(buffer.begin(), bkp, buffer.end());` – papagaga Nov 20 '18 at 16:31
  • Look my new edit. i follow your code. i get incomplete type is not allowed in compiler. –  Nov 20 '18 at 16:32
  • did you include ``? – papagaga Nov 20 '18 at 16:32
  • @papagaga i already include it. i get same error as my question. with can't convert argument array. its like ofstream.write only accept constat char. –  Nov 20 '18 at 16:36
  • don't pass the array as argument but the pointer to its data (`out.write(array.data(), array.size())` – papagaga Nov 20 '18 at 16:51
0

With follow body of your CaesarCipher function should do the trick.

ifstream file(i_inputFilePath, ios::binary);
if (!file) {
    cout << "file is no exist\n";
    return;
}
std::array<char, 1024> buffer;
if (shift < 0) {
    shift = -shift;
    shift %= buffer.size();
    shift = buffer.size() - shift;
} else {
    shift %= buffer.size();
}
ofstream output(o_outputFilePath, std::ios_base::binary);
while (file.read(buffer.data(), buffer.size()) {
    std::rotate(begin(buffer), std::next(begin(buffer), shift), end(buffer));
    output.write(buffer.data(), buffer.size());
}

But I'd like to add that this does not look like a Caesar cipher function since you are to shift the individual characters within the defined alaphbet.

Bo R
  • 1,899
  • 1
  • 5
  • 15