Results 1 to 13 of 13

Thread: Basic C++ Array Question.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19

    Basic C++ Array Question.

    Hi,

    I am a first year uni student. I am practising for an exam, so I decided to try to write some C++ code that takes an input as a string, and creates a new array with all the duplicate entries removed.

    So for example, if I took an input into an array, and it was {f,a,n,t,a,s,t,i,c} it would create a new array {f,a,n,t,s,i,c}

    The code that I tried using compiles, but doesn't work.

    string keynodupes;

    // Place first letter from keyword into new array.
    keynodupes[0] = keyword[0];

    for(i=1;i<keyword.length();i++){

    for(j=(i-1);j>=0;j--){
    if(keyword[i] = keyword[j]){
    flag=1;
    }
    }

    if(flag == 0){
    keynodupes[counter] = keynodupes[i];
    counter++;
    flag=0;
    }
    }
    I delcated keynodupes and keyword as strings. i.e.

    string keyword;
    sting keynodupes;

    i'm not sure if maybe i should have done char[] keyword, or if there is a logic problem or what. i wasn't sure what length to make the keynodupes array if i did that...

    I included the <string.h> library.

    Any help would be greatly appreicated. Thanks!

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    If you want to use the STL heavily and don't care if the order of the letters is changed (fantastic becomes acfinst)
    Code:
    #include <string>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int main()
    {
      string str;
      cin >> str; // read a word
      // sort, so unique works
      sort(str.begin(), str.end());
      // now filter multiple letters and output
      unique_copy(str.begin(), str.end(), ostream_iterator<char>(cout, "");
      // note: str is now sorted but still contains multiple letters
      // if you don't want that, do
      // unique(str.begin(), str.end());
      // which alters str, but doesn't ouput automatically
      return 0;
    }
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  3. #3
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Some info:
    <string.h> is the old style header file. This notation is deprecated and shouldn't be used in new code anymore.
    Use <string>. (None of the C++ standard headers have the .h ending anymore)
    Because the new headers all declare their elements in the namespace std, you must either import the things you need one by one:
    using std::string;
    using std::cout;
    using std::endl;
    ...
    or get the whole namespace at once:
    using namespace std;

    Use the first notation if you just use very few things from the namespace or if you include a lot of headers, else your global namespace gets too cluttered. No independent header should use the second notation as any programmer (not only you) could include the header and may not want to have this statement.

    A string, as any other STL-container, is usually not accessed by index anymore if you want to do more than just access one element. Usually you use iterators. An iterator is a class that behaves like a pointer to an element of a container. An iterator knows how to jump from element to element, this means it knows how to increment/decrement itself.

    To give an example, here's your code cleaned up in modern style:
    Code:
    #include <string>
    using std::string;
    
    // This is your way of doing it, I will show you a faster version later
    void remove_all_dupes_stable(const string &in, string &out)
    {
      // I'd like to have a copy_if algorithm, but there seems to be none
      // Clear the out string
      out.empty();
      // You need to allocate enough space in the out string
      // size(): I could use length() instead, but size() works for all
      // containers, while length() is string-specific. For string, those
      // two are synonyms.
      out.reserve(in.size());
      // Get the various iterators. Note: itEnd does not point to a
      // valid element! It is the first invalid position after in.
      string::iterator itIn = in.begin(), itEnd = in.end(), itOut = out.begin();
      // Now loop through the string
      for(;itIn != itEnd; itIn++)
      {
      // if the out string doesn't contain the current letter yet
        if(npos == out.find(*itIn))
        {
      // then copy it there
          *itOut++ = *itIn;
        }
      }
      // done
    }
    The "stable" is what makes the difference to my last solution. It means that the order of the elements is preserved.
    This is not exactly what you did. You made one decisive error: = is the assignement operator, not the comparison operator. To speed things up you could break the loop when you find a dupe (you don't need to search further, it makes no difference if 200 elements are the same or 2).
    But I added another acceleration. I don't search a substring of in, I search out. This makes it faster in this special case:
    "adddddbdddddcddddddedddfdddgdddckloi"
    When your algorithm encounters the second 'c' it will search this substring
    "adddddbdddddcddddddedddfdddgddd" backwards, while my system searches only the out string, which in this case is
    "adbcefg"
    It doesn't matter whether I search forward or backwards, I'm faster in nearly every case. And I don't need to calculate a substring (but that advantage is virtually nil in terms of speed).
    For containers other than string you can't use the find method, you must use a member of the <algorithm> header.

    But I promised you a faster version:
    Code:
    #include <string>
    #include <bitset>
    using std::string;
    using std::bitset;
    
    remove_all_dupes_large_strings_stable(const string &in, string &out)
    {
      bitset<256> ut; // all bits initially 0
      out.empty();
      out.reserve(in.size());
      string::iterator itIn = in.begin(), itEnd = in.end(), itOut = out.begin();
      
      for(;itIn != itEnd; itIn++)
      {
       if(!ut[*itIn])
        {
          *itOut++ = *itIn;
          ut[*itIn] = 1;
        }
      }
    }
    This code has an especially large speed advantage if the input string is very long (say 150+ characters, less if they are evenly distributed). For short strings it might even be slower because of the time it takes to initialize the bitset. It doesn't search any string for other occurences of a character but rather uses a boolean lookup table to see if a character has already been encountered. When it first encounters a character, it sets a mark in the table. (The ASCII code of a character is it's index into the table).
    It would actually be possible to refine this function as a template so that it can handle both unicode and ascii strings but I'll leave that to you as a future exercise.
    Hints are written backwards to avoid accidental spoiling
    Try writing a string reverse function using only iterators and use this hints as test string.
    Hint1:
    noitazilaiceps etalpmet a si gnirts
    Hint2:
    tesrahc eht ni sretcarahc fo rebmun eht ot gnidrocca )retemarap etalpmet eht( testib eht fo ezis eht tsujda trum uoy

    Good Luck!
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19
    Thank you so much! The information you posted here was very helpful. Thanks for taking the time to help me out, I really appreciate it!

    Cheers,

    Michael Bray

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19
    Hi,

    I managed to get it working your way. I am trying to do it differently now, and I cannot find where I have gone wrong. The logic I am using this time is to create a new array. From the "keyword", I loop through, and insert the characters from it into a new array. Then I have a loop that goes through the new array, and should print the characters from that array if it isn't empty. Anyway, it is sort of working, but it's not. I think the logic in it should be right. Any advice would be great. I want to try to use simple programming techniques if possible. Thanks in advance.

    #include <iostream>
    #include <string>
    using namespace std;

    // Prototypes.
    string getline(void);

    // Variables.
    char normal_alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y' ,'z'};
    char cipher_alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y' ,'z'};
    char remove_dupes[26];
    string keyword;
    string message;

    void main()
    // -------------------------------------------------------------------
    // Accept the user input, and then call the functions to process the data.
    //
    {
    int i,j,k;

    cout<<"Please enter the keyword\n";
    keyword = getline();

    cout<<"\nPlease enter a small message.\n";
    message = getline();

    cout<<"\n\n\n";

    for(j=0;j<keyword.length();j++){

    switch (keyword[j])
    {
    case 'a': remove_dupes[0] = 'a'; break;
    case 'b': remove_dupes[1] = 'b'; break;
    case 'c': remove_dupes[2] = 'c'; break;
    case 'd': remove_dupes[3] = 'd'; break;
    case 'e': remove_dupes[4] = 'e'; break;
    case 'f': remove_dupes[5] = 'f'; break;
    case 'g': remove_dupes[6] = 'g'; break;
    case 'h': remove_dupes[7] = 'h'; break;
    case 'i': remove_dupes[8] = 'i'; break;
    case 'j': remove_dupes[9] = 'j'; break;
    case 'k': remove_dupes[10] = 'k'; break;
    case 'l': remove_dupes[11] = 'l'; break;
    case 'm': remove_dupes[12] = 'm'; break;
    case 'n': remove_dupes[13] = 'n'; break;
    case 'o': remove_dupes[14] = 'o'; break;
    case 'p': remove_dupes[15] = 'p'; break;
    case 'q': remove_dupes[16] = 'q'; break;
    case 'r': remove_dupes[17] = 'r'; break;
    case 's': remove_dupes[18] = 's'; break;
    case 't': remove_dupes[19] = 't'; break;
    case 'u': remove_dupes[20] = 'u'; break;
    case 'v': remove_dupes[21] = 'v'; break;
    case 'w': remove_dupes[22] = 'w'; break;
    case 'x': remove_dupes[23] = 'x'; break;
    case 'y': remove_dupes[24] = 'y'; break;
    case 'z': remove_dupes[25] = 'z'; break;
    default: /*do nothing*/;
    }

    remove_dupes[j] = keyword[j];
    //cout<<keyword[j];
    }

    cout<<"\n";

    for(i=0;i<message.length();i++){
    //cout<<message[i];
    }

    cout<<"\n\n\n";

    for(k=0;k<26;k++){
    if(remove_dupes[k] != ' '){
    cout<<remove_dupes[k];
    }
    }

    }

    string getline(void)
    // -------------------------------------------------------------------
    // Function used to get the users input.
    //
    {

    char input;
    string stringtoreturn;

    while (1){
    cin.get(input);
    if(input == '\n')
    return stringtoreturn;
    stringtoreturn += input;
    }
    }

  6. #6
    Fanatic Member Mushroom Realm's Avatar
    Join Date
    Mar 2002
    Location
    Murrieta, California
    Posts
    650
    to get it just the way u want it make ur own class of string and add a function to it for scanning, that way u can manipulate the data easily

    [code]

    #ifndef STRING_H
    #define STRING_H
    #include <iostream.h>

    class string
    {
    friend ostream& operator << (ostream& s, const string& Str);
    friend istream& operator >> (istream& s, string& Str);

    public:
    string();
    string(const string& Str);
    string& operator = (const string& Str);
    ~string();

    string(char* p);
    short GetLength();
    bool operator < (const string& Str);
    bool operator == (const string& Str);
    bool operator > (const string& Str);
    bool operator >= (const string& Str);
    bool operator <= (const string& Str);
    bool operator != (const string& Str);

    private:
    short m_Length;
    char* m_Data;
    };
    #endif


    #include <iostream.h>
    #include <string.h>
    #include "string10.h"

    string::string()
    : m_Rep(new StringRep)
    {
    m_Rep->m_Length = 1;
    m_Rep->m_Data = new char [m_Rep->m_Length];
    memcpy(m_Rep->m_Data,"",m_Rep->m_Length);
    m_Rep->m_Count = 1;
    }

    string::string(const string& Str)
    : m_Rep(Str.m_Rep)
    {
    m_Rep->m_Count ++;
    }

    string& string:perator = (const string& Str)
    {
    if (&Str != this)
    {
    m_Rep->m_Count --;
    if (m_Rep->m_Count <= 0)
    {
    delete [ ] m_Rep->m_Data;
    delete m_Rep;
    }
    m_Rep = Str.m_Rep;
    m_Rep->m_Count ++;
    }
    return *this;
    }

    string::~string()
    {
    m_Rep->m_Count --;
    if (m_Rep->m_Count <= 0)
    {
    delete [ ] m_Rep->m_Data;
    delete m_Rep;
    }
    }

    string::string(char *p)
    : m_Rep(new StringRep)
    {
    m_Rep->m_Length = strlen(p) + 1;
    m_Rep->m_Data = new char [m_Rep->m_Length];
    memcpy(m_Rep->m_Data,p,m_Rep->m_Length);
    m_Rep->m_Count = 1;
    }

    short string::GetLength()
    {
    return m_Rep->m_Length - 1;
    }

    bool string:perator < (const string& Str)
    {
    short Result;
    short CompareLength;

    if (Str.m_Rep->m_Length < m_Rep->m_Length)
    CompareLength = Str.m_Rep->m_Length;
    else
    CompareLength = m_Rep->m_Length;

    Result = memcmp(m_Rep->m_Data,Str.m_Rep->m_Data,CompareLength);

    if (Result < 0)
    return true;

    if (Result > 0)
    return false;

    if (m_Rep->m_Length < Str.m_Rep->m_Length)
    return true;

    return false;
    }

    bool string:perator == (const string& Str)
    {
    short Result;

    if (m_Rep->m_Length != Str.m_Rep->m_Length)
    return false;

    Result = strncmp(m_Rep->m_Data,Str.m_Rep->m_Data,m_Rep->m_Length);

    if (Result == 0)
    return true;

    return false;
    }

    bool string:perator > (const string& Str)
    {
    short Result;
    short CompareLength;

    if (Str.m_Rep->m_Length < m_Rep->m_Length)
    CompareLength = Str.m_Rep->m_Length;
    else
    CompareLength = m_Rep->m_Length;

    Result = memcmp(m_Rep->m_Data,Str.m_Rep->m_Data,CompareLength);

    if (Result > 0)
    return true;

    if (Result < 0)
    return false;

    if (m_Rep->m_Length > Str.m_Rep->m_Length)
    return true;

    return false;
    }

    bool string:perator >= (const string& Str)
    {
    short Result;
    short CompareLength;

    if (Str.m_Rep->m_Length < m_Rep->m_Length)
    CompareLength = Str.m_Rep->m_Length;
    else
    CompareLength = m_Rep->m_Length;

    Result = memcmp(m_Rep->m_Data,Str.m_Rep->m_Data,CompareLength);

    if (Result > 0)
    return true;

    if (Result < 0)
    return false;

    if (m_Rep->m_Length >= Str.m_Rep->m_Length)
    return true;

    return false;
    }

    bool string:perator <= (const string& Str)
    {
    short Result;
    short CompareLength;

    if (Str.m_Rep->m_Length < m_Rep->m_Length)
    CompareLength = Str.m_Rep->m_Length;
    else
    CompareLength = m_Rep->m_Length;

    Result = memcmp(m_Rep->m_Data,Str.m_Rep->m_Data,CompareLength);

    if (Result < 0)
    return true;

    if (Result > 0)
    return false;

    if (m_Rep->m_Length <= Str.m_Rep->m_Length)
    return true;

    return false;
    }

    bool string:perator != (const string& Str)
    {
    short Result;

    if (m_Rep->m_Length != Str.m_Rep->m_Length)
    return true;

    Result = memcmp(m_Rep->m_Data,Str.m_Rep->m_Data,m_Rep->m_Length);

    if (Result == 0)
    return false;

    return true;
    }

    ostream& operator << (ostream& s, const string& Str)
    {
    for (short i=0; i < Str.m_Rep->m_Length-1; i ++)
    s << Str.m_Rep->m_Data[i];

    return s;
    }

    istream& operator >> (istream& s, string& Str)
    {
    const short BUFLEN = 256;

    char Buf[BUFLEN];
    memset(Buf,0,BUFLEN);

    if (s.peek() == '\n')
    s.ignore();
    s.getline(Buf,BUFLEN,'\n');
    Str = Buf;

    return s;

    }

    [\code]

    im assuming u can use vectors

  7. #7
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Why go through all that trouble mush? What can this class do what the STL cannot?

    Michael: a) Please use code /code instead of quote /quote tags. It makes the code easier to read.

    b)
    Code:
    for(j=0;j<keyword.length();j++){
    
    switch (keyword[j])
    {
    case 'a': remove_dupes[0] = 'a'; break;
    case 'b': remove_dupes[1] = 'b'; break;
    case 'c': remove_dupes[2] = 'c'; break;
    case 'd': remove_dupes[3] = 'd'; break;
    case 'e': remove_dupes[4] = 'e'; break;
    case 'f': remove_dupes[5] = 'f'; break;
    case 'g': remove_dupes[6] = 'g'; break;
    case 'h': remove_dupes[7] = 'h'; break;
    case 'i': remove_dupes[8] = 'i'; break;
    case 'j': remove_dupes[9] = 'j'; break;
    case 'k': remove_dupes[10] = 'k'; break;
    case 'l': remove_dupes[11] = 'l'; break;
    case 'm': remove_dupes[12] = 'm'; break;
    case 'n': remove_dupes[13] = 'n'; break;
    case 'o': remove_dupes[14] = 'o'; break;
    case 'p': remove_dupes[15] = 'p'; break; 
    case 'q': remove_dupes[16] = 'q'; break; 
    case 'r': remove_dupes[17] = 'r'; break;
    case 's': remove_dupes[18] = 's'; break;
    case 't': remove_dupes[19] = 't'; break;
    case 'u': remove_dupes[20] = 'u'; break;
    case 'v': remove_dupes[21] = 'v'; break;
    case 'w': remove_dupes[22] = 'w'; break;
    case 'x': remove_dupes[23] = 'x'; break;
    case 'y': remove_dupes[24] = 'y'; break;
    case 'z': remove_dupes[25] = 'z'; break;
    default: /*do nothing*/;
    }
    
    remove_dupes[j] = keyword[j];
    //cout<<keyword[j];
    }
    What do you want to do with that code? I don't really get it.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19
    Sorry. I altered was I was doing slightly. What I am trying to do now is take the keyword, remove the duplicate letters in it, then place the remaining letters of the alphabet onto the end of it in order, without repeating letters.

    Basically to make a tacky encryption program.

    i.e. if keyword = dgdhil

    then i would create an array[26] of...

    d,g,h,i,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a,b,c,e,f,j,k

    then you just replace all a's in a message with d, all b's with g etc. Just having a few problems with it. It's almost done. The code I'll post here will give you an error cause I just made a few changes to it before, however it does remove the duplicate things from the keyword.

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    // Prototypes.
    string getline(void);
    
    // Variables.
    char normal_alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    char cipher_alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    char remove_dupes[26] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
    int remove_dupes_position[26] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 
    string keyword;
    string message;
    
    void main()
    // -------------------------------------------------------------------
    // Accept the user input, and then call the functions to process the data.
    //
    {
    	int i,j,k,l,m,count,position,p,b,a,found,counter;
    	
    	position = 1;
    
    	cout<<"Please enter the keyword\n";
    	keyword = getline();
    
    	cout<<"\nPlease enter a small message.\n";
    	message = getline();
    
    	cout<<"\n\n\n";
    
    
    	cout<<"\nRemove Dupes Position original:";
    
    for(p=0;p<26;p++)
    	cout<<remove_dupes_position[p]<<" ";
    
    cout<<"\n\n\n";
    
    
    	// I want to do a frequency check on the characters in the keyword here.
    	for(j=0;j<keyword.length();j++){
    		
    		switch (keyword[j])
    		{
    		case 'a': ++remove_dupes[0]; if(remove_dupes_position[0] == '0'){remove_dupes_position[0] = position; position++;} break;
    		case 'b': remove_dupes[1]++; if(remove_dupes_position[1] == '0'){remove_dupes_position[1] = position; position++;} break;
    		case 'c': remove_dupes[2]++; if(remove_dupes_position[2] == '0'){remove_dupes_position[2] = position; position++;} break;
    		case 'd': remove_dupes[3]++; if(remove_dupes_position[3] == '0'){remove_dupes_position[3] = position; position++;} break;
    		case 'e': remove_dupes[4]++; if(remove_dupes_position[4] == '0'){remove_dupes_position[4] = position; position++;} break;
    		case 'f': remove_dupes[5]++; if(remove_dupes_position[5] == '0'){remove_dupes_position[5] = position; position++;} break;
    		case 'g': remove_dupes[6]++; if(remove_dupes_position[6] == '0'){remove_dupes_position[6] = position; position++;} break;
    		case 'h': remove_dupes[7]++; if(remove_dupes_position[7] == '0'){remove_dupes_position[7] = position; position++;} break;
    		case 'i': remove_dupes[8]++; if(remove_dupes_position[8] == '0'){remove_dupes_position[8] = position; position++;} break;
    		case 'j': remove_dupes[9]++; if(remove_dupes_position[9] == '0'){remove_dupes_position[9] = position; position++;} break;
    		case 'k': remove_dupes[10]++; if(remove_dupes_position[10] == '0'){remove_dupes_position[10] = position; position++;} break;;
    		case 'l': remove_dupes[11]++; if(remove_dupes_position[11] == '0'){remove_dupes_position[11] = position; position++;} break;
    		case 'm': remove_dupes[12]++; if(remove_dupes_position[12] == '0'){remove_dupes_position[12] = position; position++;} break;
    		case 'n': remove_dupes[13]++; if(remove_dupes_position[13] == '0'){remove_dupes_position[13] = position; position++;} break;
    		case 'o': remove_dupes[14]++; if(remove_dupes_position[14] == '0'){remove_dupes_position[14] = position; position++;} break;
    		case 'p': remove_dupes[15]++; if(remove_dupes_position[15] == '0'){remove_dupes_position[15] = position; position++;} break;		
    		case 'q': remove_dupes[16]++; if(remove_dupes_position[16] == '0'){remove_dupes_position[16] = position; position++;} break; 
    		case 'r': remove_dupes[17]++; if(remove_dupes_position[17] == '0'){remove_dupes_position[17] = position; position++;} break;
    		case 's': remove_dupes[18]++; if(remove_dupes_position[18] == '0'){remove_dupes_position[18] = position; position++;} break;
    		case 't': remove_dupes[19]++; if(remove_dupes_position[19] == '0'){remove_dupes_position[19] = position; position++;} break;
    		case 'u': remove_dupes[20]++; if(remove_dupes_position[20] == '0'){remove_dupes_position[20] = position; position++;} break;
    		case 'v': remove_dupes[21]++; if(remove_dupes_position[21] == '0'){remove_dupes_position[21] = position; position++;} break;
    		case 'w': remove_dupes[22]++; if(remove_dupes_position[22] == '0'){remove_dupes_position[22] = position; position++;} break;
    		case 'x': remove_dupes[23]++; if(remove_dupes_position[23] == '0'){remove_dupes_position[23] = position; position++;} break;
    		case 'y': remove_dupes[24]++; if(remove_dupes_position[24] == '0'){remove_dupes_position[24] = position; position++;} break;
    		case 'z': remove_dupes[25]++; if(remove_dupes_position[25] == '0'){remove_dupes_position[25] = position; position++;} break;
    		default: cout<<"Keyword should only contain lower case characters.";
    		}
    
    	}
    
    count = 0;
    
    // Woohoo!!! remove_dupes now contains the frequency count of the characters in keyword.
    
    
    for(l=1;l<27;l++){
    	
    	for(b=0;b<26;b++){
    		if(remove_dupes_position[b] == l){
    			cipher_alphabet[count] = normal_alphabet[b];
    			count++;
    			cout<<normal_alphabet[l]<<"\t"<<remove_dupes[l]<<"\tPosition:\t"<<remove_dupes_position[l]<<"\n";
    		}
    	}
    }
    
    
    counter = m;
    
    for(m=count;m<26;m++){
    
    	for(a=m-1;a>=0;a--){
    	
    		found = 0;
    
    	    if(cipher_alphabet[m-1]+1 == cipher_alphabet[a])
    			found = 1;
    	}
    	
    	if(found == 0){
    		cipher_alphabet[counter] = (cipher_alphabet[m-1]+1);
    			
    		if(cipher_alphabet[m] > 'z'){
    			cipher_alphabet[counter] = cipher_alphabet[m]-26;
    		}
    	counter++;
    	}
    
    
    }
    
    
    cout<<"Cipher Alphabet\n";
    for(k=0;k<26;k++){
    	cout<<cipher_alphabet[k]<<" ";
    }
    
    
    cout<<"\nRemove Dupes Position after:";
    
    for(p=0;p<26;p++)
    	cout<<remove_dupes_position[p]<<" ";
    
    cout<<"\n\nCount:\t"<<count;
    cout<<"\n\nPosition:\t"<<position;
    
    	cout<<"\n\n\n";
    
    
    
    
    	cout<<"\n";
    
    	cout<<"Message:\t";
    	for(i=0;i<message.length();i++){
    		cout<<message[i];
    	}
    
    	cout<<"\nEncrypted message:\t";
    
    
    }
    
    string getline(void)
    // -------------------------------------------------------------------
    // Function used to get the users input.
    // Sample usage: variable = getline();
    //
    {
      
    	char input;
    	string stringtoreturn;
    
    	while (1){
    		cin.get(input);
    		if(input == '\n')
    			return stringtoreturn;
    		stringtoreturn += input;
        }
    }

  9. #9
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I'm even more confused...


    What errors?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  10. #10

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19
    OK,

    I'll explain the logic in my code. Will probably help.

    First off, the big switch statement lot of code is my method of removing the tacky code. It loops through the characters in the keyword, and adds the frequency of the occurences of each character into an array, remove_dupes[]

    so if remove_dupes was {2,3,0,0,0,0,0,0} you would know that there was 2 a's and 3 b's in the keyword. Then it also updates another array called position, which registers the position of the characters. So if the first character was a c, and the 2nd character was an e, the remove_dupes_position would be {0,0,1,0,2}.

    The following code simply places the keyword, with no repeating characters, in order, into the new array, cipher_alphabet[]

    Code:
    for(l=1;l<27;l++){
    	
    	for(b=0;b<26;b++){
    		if(remove_dupes_position[b] == l){
    			cipher_alphabet[count] = normal_alphabet[b];
    			count++;
    					}
    	}
    }
    Then after I have done that, I need to continue on with the alphabet continuing on from the last letter in the keyword... I wrote code that did that...

    Code:
    for(m=count;m<26;m++){
    		cipher_alphabet[m] = (cipher_alphabet[m-1]+1);
    		if(cipher_alphabet[m] > 'z'){
    			cipher_alphabet[m] = cipher_alphabet[m]-26;
    	}
    }
    however there is a problem. if i used keyword, "harry" for example, it produces the cipher_array[] of

    {h,a,r,y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}

    as you can see - a,h and r are in there twice, and v, w and x are not in there. I need it to leave out the a, h and r, and continue on in order so that all the letters of the alphabet are used...

    Hope that clears up what I was trying to do

  11. #11
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Yep, I understand now...

    Let's see.

    First, you should simplify the switch thing. Take advantage of the fact that the characters are in order in the ASCII table.

    Code:
    #include <cctype>
    #include <string>
    #include <iostream>
    using namespace std;
    // access the old ctype functions and macros
    // in C++ you should use the locale class
    // but that's more work
    
    void main()
    {
      // again, you should use iterators for this
      // simplify the large switch block:
      int position = 0;
      for(string::iterator it=keyword.begin(); it != keyword.end(); it++) {
        if(isalpha(*it)) {
          remove_dupes[tolower(*it)-'a']++;
          if(remove_dupes[tolower(*it)-'a'] == 1)
            cipher_alphabet[position++] = tolower(*it);
        }
      }
      // this has accomplished exactly the same, except one thing
      // read ahead
    This tests whether the character is a letter. If it is, it converts it to lower case, substracts the ASCII value of 'a' (I think 97) and receives a 0-based index usable for array indexing.

    Let's see the next part.

    There's a small optimization possible: we know that the unduped keyword only contains position values.
    And a large one: remove_dupes_position is redundant! You create it, and then just search it to create cipher_alphabet which at this time is just index and value exchanged! If you create cipher_alphabet like I did, you save a lot of time (and don't confuse me that much).

    So let's check the faulty part.
    The problem is that you don't check whether a character already exists. But this would be very easy: you already have the wonderful lookup table remove_dupes.
    Code:
    char off = position;
    char last_char = cipher_alphabet[position-1]+1;
    for(l=position; l < 26; l++) {
      if(remove_dupes[((l-off+last_char-'a')%26)] == 0) {
        // did not yet appear, add it with "wrap-around" effect
        cipher_alphabet[l] = (((((l-off)+last_char)-'a')%26)+'a');
      } else {
        // repeat this position but skip this character
        l--;
        off--;
      }
    }
    This requires some explanation.
    last_char is the character after the last character of the keyword (so if the last char of the keyword was 's', last_char would be 't').
    off is not a character but rather an offset, but all vars that occur in the calculations are char, so it makes sense if this is a char too.
    off is the difference between l and a simultaneous count starting from 0. I could have used another variable for this, but I think this solution is cooler
    I'll best explain with an example. I assume 'a' == 97
    Entered keyword: "thisisme"
    remove_dupes:
    0,0,0,0,1,0,0,1,2,0,0,0,1,0,0,0,0,0,2,1,0,0,0,0,0,0
    cipher_alphabet after the first block
    t,h,i,s,m,e,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    position is now 6
    last_char = 'e'+1 = 'f' = 102
    off = 6
    second block, it1:
    l=6
    l - off = 0, therefore l-off+last_char = 102 = 'f', which is the letter we want to insert
    substract 'a' to get the index into remove_dupes = 5
    remove_dupes[5] = 0 (there was no 'f'), so go on
    This is now a very confusing line. The left side is easy:
    set the character at position l (6) to ...
    Here's the right side:
    (((((l-off)+last_char)-'a')%26)+'a')
    l-off = 0
    +last_char = 102 ('f')
    -'a' = 5
    % (modulo) 26 = 5
    + 'a' = 102 = 'f', which is what we want to insert at the current pos.
    Why that complicated? You'll see! I promise.
    Next iteration:
    l = 7
    l-off = 1, therefore l-off+last_char = 103 = 'g'
    remove_dupes[6] = 0 (no 'g')
    (((((l-off)+last_char)-'a')%26)+'a') = 'g'
    Next iteration:
    l = 8
    l-off = 2+last_char = 104 ('h')
    remove_dupes[7] = 1 -> there was a 'h' already!
    Now decrement both l and off
    l = 7
    off = 5
    Next iteration:
    l = 8 (same as last, as we still want to insert at the same pos)
    l-off = 3 (because off is less than last iteration)
    +last_char = 105 ('i')
    'i' was used too, so l and off are decremented again
    Next iteration:
    l = 8 (still)
    l-off = 4+last_char = 106 ('j')
    remove_dupes[9] = 0, so we found a character
    (((((l-off)+last_char)-'a')%26)+'a') = 'j'
    and so on...

    It gets interesting again in this iteration (the one after 'z' was added):
    l=22
    off = 1
    l-off = 21+last_char = 123, which is too much! This is not a lowercase letter anymore, but some sign.
    This is why we need the %26:
    123-'a' = 26, which is too large as an index for the tables.
    Then we do
    26 % 26 = 0
    which is ok, 0+'a' = 'a', which is exactly what we want.

    I attached a .cpp file that contains this example. Just compile and make sure you can scroll the result (or do "exename | more").
    Attached Files Attached Files
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Sep 2002
    Posts
    19
    Thanks mate,

    I really appreciate you taking the time to help me with this. I'll compile the code you gave me and play around with it. So many different ways to do things with programming, as a beginner it's hard to find the best way to do something.

  13. #13
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    You know, I find this quite amusing.
    Don't tell anyone, I'm at work and I don't have anything better to do...
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width