Computer Science Canada

decrypting ROT13 (vectors)

Author:  Geminias [ Thu Jan 05, 2006 1:21 pm ]
Post subject:  decrypting ROT13 (vectors)

hi, i need some help with this code... this vector class is giving me a really rough time.

in case you don't know ROT13 just means rotate 13, so any letter you pick in the alphabet you just count upward 13 letters. this code should take a text file encrypted with ROT13 and decrypt it to console.

code:


#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>
#define countof( array ) ( (sizeof( array )/sizeof( array[0] )) - 1 )

using namespace std;

void decrypt (vector<int>::iterator iWords_beg,
              vector<int>::iterator iWords_end,
              int size)
{


 
         for (int i = 0 ; i <= size ; i++)
       {
         char word [] = *iWords_beg [i];
       
        for (int s = 0 ; int < (countof ( word )) ; s++)
        {
             if ((int) word [s]) <= 75 || 97 <= (int) word [s]) <= 122  )
             {  word [s] = char (((int) word [s]) + 13 ));         }
             else if ((int) word [s]) < 97)
             {  word [s] =  char ((((int) word [s]) % 77) + 64);   }
             else if ((int) word [s]) >= 97)
             {  word [s] =  char ((((int) word [s]) % 109) + 96);  }
         }

             *iWords_beg[i] = word;
       }
}



int main ()
{
      ifstream file("file.txt");
      vector<string> words =
                 vector<string> (istream_iterator<string>(file),
                                 istream_iterator<string>());
       decrypt (words.begin(), words.end(), words.size() );
       
       copy (words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
     
      return 0;
}
     

Author:  Geminias [ Thu Jan 05, 2006 1:23 pm ]
Post subject: 

c++:


#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>
#define countof( array ) ( (sizeof( array )/sizeof( array[0] )) - 1 )

using namespace std;

void decrypt (vector<int>::iterator iWords_beg,
              vector<int>::iterator iWords_end,
              int size)
{


 
         for (int i = 0 ; i <= size ; i++)
       {
         char word [] = *iWords_beg [i];   //switch vector data to array
       
        for (int s = 0 ; int < (countof ( word )) ; s++)
        {
             if ((int) word [s]) <= 75 || 97 <= (int) word [s]) <= 122  )
             {  word [s] = char (((int) word [s]) + 13 ));         }
             else if ((int) word [s]) < 97)
             {  word [s]char ((((int) word [s]) % 77) + 64);   }
             else if ((int) word [s]) >= 97)
             {  word [s]char ((((int) word [s]) % 109) + 96)}
         }

             *iWords_beg[i] = word;
       }
}



int main ()
{
      ifstream file("file.txt");
      vector<string> words =
                 vector<string> (istream_iterator<string>(file),
                                 istream_iterator<string>());
       decrypt (words.begin(), words.end(), words.size() );
       
       copy (words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
     
      return 0;
}
     


note: i couldn't find anything on accessing individual characters in a vector<string> so i decided to transfer it to an array as a quick fix. also the "countof" constant is yet another quick fix.

Author:  wtd [ Thu Jan 05, 2006 1:30 pm ]
Post subject: 

Why should you expect this to work?

Your decrypt function takes arguments of type:

code:
vector<int>::iterator


Yet you pass it iterators of type:

code:
vector<string>::iterator


You might use templates to make your life easier.

code:
template <typename Iter>
void decrypt(Iter start, Iter end, ...)
{
   ...
}


The compiler will infer the types provided, so you can call decrypt the same way you do now.

Author:  Geminias [ Thu Jan 05, 2006 1:37 pm ]
Post subject: 

i haven't gotten to the template part in my sams teach yourself c++ in 21 days lol. (more like teach me in 5 months)

does the template automatically change a type to the type of variable? cause i see you named it Iter, but no where did you tell it Iter = vector<string>::iterator

Author:  wtd [ Thu Jan 05, 2006 1:46 pm ]
Post subject: 

Let's try some decent formatting.

code:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>

#define countof( array ) ( (sizeof( array )/sizeof( array[0] )) - 1 )

using namespace std;

void decrypt (vector<int>::iterator iWords_beg,
              vector<int>::iterator iWords_end,
              int size)
{
   for (int i = 0; i <= size; i++)
   {
      // Switch vector data to array.
      char word[] = *iWords_beg[i];   
       
      for (int s = 0; int < countof(word); s++)
      {
         if ((int)word[s]) <= 75 || 97 <= (int)word[s]) <= 122)
         { 
            word[s] = char(((int)word[s]) + 13 ));         
         }
         else if ((int)word[s]) < 97)
         { 
            word[s] = char((((int)word[s]) % 77) + 64);   
         }
         else if ((int)word[s]) >= 97)
         {
            word[s] =  char((((int)word[s]) % 109) + 96);
         }
      }

      *iWords_beg[i] = word;
   }
}



int main ()
{
   ifstream file("file.txt");
   vector<string> words =
      vector<string> (istream_iterator<string>(file),
                      istream_iterator<string>());
   decrypt(words.begin(), words.end(), words.size());
       
   copy (words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
     
   return 0;
}


Now that we can read this code, we can find the errors and just plain mistakes.

code:
else if ((int)word[s]) < 97)


Let's count parentheses! I see two open parentheses, but three closing parentheses. Welcome to the wonderful world of syntax errors.

I also see this with things like:

code:
word[s] = char(((int)word[s]) + 13));


Now, with respect to other errors...

You do realize that characters are integral types?

code:
static_cast<int>(some_char_var) > 97


Can be rewritten as:

code:
some_char_var > 'a'


It is now much simpler and easier to understand.

If you are going to use casts, though, do not use C-style casts. Use things like "static_cast".

Author:  Geminias [ Thu Jan 05, 2006 1:51 pm ]
Post subject: 

no i didnt know you could do that in c++, i thought that was another turing thing. (the chars being integers)

well thanks, your like a portable debugger lol. i'll hopefully be able to fix up this code in no time and post a ROT13 decrypter! yay!

Author:  Geminias [ Thu Jan 05, 2006 1:54 pm ]
Post subject: 

by the way, what is your stance on how i grabbed each individual character. did i miss something in the vector class that could have made life easier? or is the vector class just not optomized for things like this?

Author:  wtd [ Thu Jan 05, 2006 1:57 pm ]
Post subject: 

Well, if you have the beginning and end of a vector, then looping over it...

code:
for (; beginning_of_vector != end_of_vector; beginning_of_vector++)
{
   cout << *beginning_of_vector << endl;
}

Author:  Geminias [ Thu Jan 05, 2006 2:03 pm ]
Post subject: 

Quote:
fuck.cpp:11: error: expected `,' or `...' before '>' token
fuck.cpp: In function `void decrypt(Iter, Iter)':
fuck.cpp:17: error: `size' undeclared (first use this function)
fuck.cpp:17: error: (Each undeclared identifier is reported only once for each f
unction it appears in.)
fuck.cpp:19: error: initializer fails to determine size of `word'
fuck.cpp:21: error: `int' is not a template
fuck.cpp:21: error: missing `>' to terminate the template argument list
fuck.cpp:21: error: expected primary-expression before "int"
fuck.cpp:21: error: expected `;' before "int"
fuck.cpp:21: error: expected primary-expression before "int"
fuck.cpp:21: error: expected `)' before "int"
fuck.cpp:21: error: declaration does not declare anything
fuck.cpp:21: error: name lookup of `s' changed for new ISO `for' scoping
fuck.cpp:21: error: using obsolete binding at `s'
fuck.cpp:21: error: expected `;' before ')' token
fuck.cpp: In function `int main()':
fuck.cpp:43: error: no matching function for call to `decrypt(__gnu_cxx::__norma
l_iterator<std::string*, std::vector<std::string, std::allocator<std::string> >
>, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allo
cator<std::string> > >, size_t)'



i'm worried about this "int is not a template" thing... i can't have an "int size" as an argument?

Author:  wtd [ Thu Jan 05, 2006 2:03 pm ]
Post subject: 

C++ is not Turing. People actually use it. Wink

Thus if you find yourself thinking, "there has to be a better way to do this", there probably is.

Author:  wtd [ Thu Jan 05, 2006 4:38 pm ]
Post subject: 

So, you're trying to ROT13 a string?

This is pretty simple, and it's easier if you break it down.

Write a function which performs a ROT13 transformation on a character. Then to ROT13 an entire file, just use the STL functions to apply that function to every character in the file.

Author:  Geminias [ Fri Jan 06, 2006 12:46 am ]
Post subject: 

i narrowed down my largest problem to the fact that this:

code:

char word [] = *iWords_beg; 

is an illegal initializer.
code:

char word [25];

word = *iWords_beg; 


*iWords_beg is an incompatible type. However.. i do not understand this being that if i just ask for a:

cout << *iWords_beg

it displays a lovely little string, (the right string and everything)

heres my code so far, and i didn't use templates because dont you have to make a struct or a class to implement them?

c++:


#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>
#define countof( array ) ( (sizeof( array )/sizeof( array[0] )) - 1 )

using namespace std;

void decrypt (vector<string>::iterator iWords_beg,
              vector<string>::iterator iWords_end)
{

        while ( iWords_beg != iWords_end )
        {
            char word [25] = *iWords_beg++;
       
        for (int s = 0 ; int < ((countof ( word )) ; s++)
        {
             if ( word [s] <= 75 || 97 <= word [s] <= 122  )
               word [s] = char ((((int) word [s]) + 13 ));
             else if ( word [s] < 97 )
               word [s]char ((((int) word [s]) % 77) + 64);
             else if ( word [s] >= 97 )
               word [s]char ((((int) word [s]) % 109) + 96);
         }

             *iWords_beg = word;
       }
}



int main ()
{
      ifstream file("file.txt");

      vector<string> words =
                 vector<string> (istream_iterator<string>(file),
                                 istream_iterator<string>() );

      decrypt (words.begin(), words.end() );
       
      copy (words.begin(), words.end(), ostream_iterator<string>(cout, "\n"));
     
      return 0;
}
     
     


Author:  Geminias [ Fri Jan 06, 2006 12:49 am ]
Post subject: 

so basically i need to know how to get a string into an array, so that i could manipulate it character by character.

Author:  Geminias [ Fri Jan 06, 2006 12:50 am ]
Post subject: 

EDIT: A string into a char [] array. i always thought you could. i guess not.

Author:  wtd [ Fri Jan 06, 2006 12:51 am ]
Post subject: 

Why don't you take my advice and create a "char rot13(char input)" function first, then work from there.

Author:  wtd [ Fri Jan 06, 2006 12:53 am ]
Post subject: 

You can't turn a std::string into a character array? Someobody should tell the C++ standards committee.

code:
std::string foo = "hello";
char *bar = foo.c_str();


But you don't need this to deal with this problem.

Author:  Geminias [ Fri Jan 06, 2006 12:55 am ]
Post subject: 

i dont know how. i intend to learn c++ inside and out, but there are just other things in my life so its taking a lot longer than i'd have wanted. plus i'm new to the whole concept of programming... i first understood what a string was just 2 weeks into september of last year.

So go easy on me... and i think the only other way i would have known how to do this would be to read all the information into an array, a big array, and then deal with it from there, but i wanted to try out vectors so i could learn them. and this experience has taught me a lot about vectors, which i wouldn't trade for anything. So to complete this experience it would be nice to be able to do this using the structure i already have. I will do it, with or without your help.

Author:  Geminias [ Fri Jan 06, 2006 1:02 am ]
Post subject: 

code:

std::string foo = "hello";
char *bar = foo.c_str();


this code will not compile. Invalid conversion from a constant char to a char.[/code]

Author:  wtd [ Fri Jan 06, 2006 1:10 am ]
Post subject: 

Once you have that function, you can use std::transform to rot13 every character in the file.

Author:  Geminias [ Fri Jan 06, 2006 1:12 am ]
Post subject: 

i dont know what your talking about
Embarassed

Author:  wtd [ Fri Jan 06, 2006 1:12 am ]
Post subject: 

Contemplate.

code:
#include <iostream>
#include <vector>
#include <fstream>
#include <iterator>

using namespace std;

char rot13(char input);

int main()
{
   ifstream file("file.txt");

   vector<char> transformed_chars;

   transform(istream_iterator<char>(file),
             istream_iterator<char>(),
             back_inserter(transformed_chars),
             rot13);

   copy(transformed_chars.begin(),
        transformed_chars.end(),
        ostream_iterator<char>(cout, "\n"));

   return 0;
}

char rot13(char input)
{
   if (input >= 'a' && input <= 'z')
   {
      return input + 32;
   }
   else if (input >= 'A' && input <= 'Z')
   {
      return input - 32;
   }
   else
   {
      return input;
   }
}

Author:  wtd [ Fri Jan 06, 2006 1:35 am ]
Post subject: 

Geminias wrote:
i narrowed down my largest problem to the fact that this:

code:

char word [] = *iWords_beg; 

is an illegal initializer.


iWords_beg is not only a really bad variable name, but it's also an iterator. When you "dereference" is with *, you get a string. Not a pointer to a string. Further, this is a std::string, rather than a char array.

This examplains a lot of your other misconceptions.

Geminias wrote:
heres my code so far, and i didn't use templates because dont you have to make a struct or a class to implement them?


No, you do not. A function can be a template.

Author:  Geminias [ Fri Jan 06, 2006 1:44 am ]
Post subject: 

c++:

#include <iostream>
#include <vector>
#include <fstream>
#include <iterator>

using namespace std;

char rot13(char input);

int main()
{
   ifstream file("fuck2.txt");

   vector<char> transformed_chars;

   transform(istream_iterator<char>(file),
             istream_iterator<char>(),
             back_inserter(transformed_chars),
             rot13);

   copy(transformed_chars.begin(),
        transformed_chars.end(),
        ostream_iterator<char>(cout, "\n"));

   return 0;
}

char rot13(char input)
{
   if (input <= 'm' || A <= input && M >= input )
   {
      return input + 13;
   }
   else if (input >= 'm' && input <= 'z')
   {
      return ((input % 77) + 64);
   }
   else if (input >= 'M' && input <= 'Z')
   {
      return ((input % 109) + 96);
   else
   {
      return input;
   }
}


code:

fuck.cpp:16: error: invalid initializer
fuck.cpp:18: error: `int' is not a template
fuck.cpp:18: error: missing `>' to terminate the template argument list
fuck.cpp:18: error: expected primary-expression before "int"
fuck.cpp:18: error: expected `;' before "int"
fuck.cpp:18: error: expected primary-expression before "int"
fuck.cpp:18: error: expected `)' before "int"
fuck.cpp:18: error: declaration does not declare anything
fuck.cpp:18: error: name lookup of `s' changed for new ISO `for' scoping
fuck.cpp:18: error:   using obsolete binding at `s'
fuck.cpp:18: error: expected `;' before ')' token


is my compiler not fully equipped with the stl? keep in mind i'm not using gcc right now.

Author:  Geminias [ Fri Jan 06, 2006 1:47 am ]
Post subject: 

never mind i found the errors, it compiles now it just doesn't work lol.

Author:  wtd [ Fri Jan 06, 2006 1:56 am ]
Post subject: 

Are you using VC++ 6?

Author:  Geminias [ Fri Jan 06, 2006 2:05 am ]
Post subject: 

no, mingw. it works now, all is well... now i'll have to research those functions you gave me.

part, well actually, the biggest problem i have is i can't find the source of "stl::copy ()" or "stl::sort ()" and without it i found it difficult to pass the iterators into my decrypt function and manipulate the vector. partly because as you saw i had to guess what type they were, (the iterators) .

one question: how do i keep spaces? i found that this program eliminates the spaces in its output... how would i keep them?

Author:  wtd [ Fri Jan 06, 2006 2:24 am ]
Post subject: 

Yes, that has to do with the default way istreams work. I had failed to take this into account.

As for figuring out how functions like copy and transorm work:

http://www.sgi.com/tech/stl/

It's all there. The place to start would be the table of contents.

Author:  wtd [ Fri Jan 06, 2006 2:25 am ]
Post subject: 

Oh, and with MinGW you are using G++. Minimalist GNU for Windows.

Author:  Geminias [ Fri Jan 06, 2006 2:38 am ]
Post subject: 

oh, lol. yeah it wasn't the compiler after all.

Author:  wtd [ Fri Jan 06, 2006 2:47 am ]
Post subject: 

My rot13 function's body was also all wrong. My brain is apparently having some issues. Still, my advice about the general stuff... dead on.

Author:  Geminias [ Fri Jan 06, 2006 3:06 am ]
Post subject: 

i didn't realize you're rot13 function was intended to be a rot13 function. i thought you just dug something up as an example.

yes, it was entirely flawed here's a working source:

c++:

#include <iostream>
#include <vector>
#include <fstream>
#include <iterator>

using namespace std;

char rot13(char input);

int main()
{
   ifstream file("decrypt.txt");

   vector<char> transformed_chars;

   transform(istream_iterator<char>(file),
             istream_iterator<char>(),
             back_inserter(transformed_chars),
             rot13);

   copy(transformed_chars.begin(),
        transformed_chars.end(),
        ostream_iterator<char>(cout));

   return 0;
}

char rot13(char input)
{
   if (input <= 'm' || 'A' <= input && 'M' >= input )
   {
      return input + 13;
   }
   else if (input >= 'm' && input <= 'z')
   {
      return ((input % 77) + 64);
   }
   else if (input >= 'M' && input <= 'Z')
   {
      return ((input % 109) + 96);
   }
   else
   {
      return input;
   }
}



: