0

for a very long time I can not figure out how to solve this condition, I ask for your help

Condition of the problem: Create a class for working with lines. The maximum sequence length is 254. The first byte must contain information about the actual number of array elements. Perform an overload of operations:

  • "=" – assignment,
  • "+" – concatenation (connection) of strings,
  • "<=" – relation "less than or equal",
  • " >= " – relation "greater than or equal",
  • "==" – relation "is equal",
  • "!=" – relation "is not equal".

Provide an initialization constructor, copy constructor, destructor in the class.*

Here is my code Main.cpp file

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


using namespace std;

int main(){
    setlocale(LC_ALL , "Ukrainian");
    int change;
    String input1, input2;
    cout << "Enter the first line: ";
    cin >> input1;
    cout << "Enter the second line: ";
    cin >> input2;
    cout << "\t\tActions" << endl;
    cout << "1.Assign strings;" << endl;
    cout << "2.Concatenation (connection) of strings;" << endl;
    cout << "3.Ratio (greater than or equal to);" << endl;
    cout << "4.Ratio (less than or equal to);" << endl;
    cout << "5.Ratio (equal to);" << endl;
    cout << "6.Ratio (not equal)." << endl;
    cout << "Your choice: ";  

    cin >> change;  
    switch(change){
        case 1:{
            input2 = input1;
            cout << "Result: " << input2 << endl;;
            break;
        }
        case 2:{
            String result = input1 + input2;
            cout << "Result of concatenation: " << result << endl;
            break;
        }
        case 3:{                  
            bool result = input1 >= input2;
            if(result == true){
                cout << "The first line is greater than or equal to the second
" << endl;
            }
            else{
                cout << "The first line is smaller than the second" << endl;
            }
            break;  
        }
        case 4:{
            bool result = input1 <= input2;
            if(result == true){
                cout << "The first line is less than or equal to the second" << endl;
            }
            else{
                cout << "The first line is bigger than the second" << endl;
            }
            break;  
        }
        case 5:{
            if((input1 == input2)){
                cout << "Equals"    << endl;
            }
            else{
                cout << "Not Equals" << endl; 
            }                  
            break;
        }
        case 6:{
            bool result = input1 != input2;
            if(result == true){
                cout << "The first line is not equal to the second" << endl;
            }
            else{
                cout << "The first line is equal to the second" << endl;
            }
            break;
        }
        
        default:{
            cout << "Invalid value ..." << endl;
            return 1;
            break;
        }
    } 
    return 0;

}

Line.h file (String class)

#include <iostream>
#include <cstdlib>

using namespace std;

class String{ 
private:
    char *str;
public:
    String();
    ~String();
    String(const String &other);
    
    
    friend String operator + (String &line, String &line2);
    String operator = (String &line);
    bool operator <= (String &line);
    bool operator >= (String &line);
    friend bool operator == (String &line, String &line2);
    bool operator != (String &line);
    
    friend ostream &operator<<(ostream &stream, String& obj);
    friend istream &operator>>(istream &stream, String& obj);
    
    void strcopy(char *str1,char *str2);
    char mystrcat(char *str1,const char *str2);
    int strlenght(const char *str);
                        
};


String::String(){
    str = new char[256];    
}
    
String::~String(){
    delete[] str;
}

String::String(const String &other){
    str = new char[256];
    strcopy(str,other.str);
}  

String String::operator = (String &line){
    strcopy(str,line.str);
    return *this;
}

String operator + (String &line,String &line2){
    String output = line;
    line.mystrcat(output.str,line2.str);
    return output;
}

bool String::operator >= (String &line){
    if(strlenght(str) >= strlenght(line.str)){
        return true;
    }
    else{
        return false;
    }
}

bool String::operator <= (String &line){
    if(strlenght(str) <= strlenght(line.str)){
        return true;
    }
    else{
        return false;
    }
}

bool String::operator != (String &line){
    if(strlenght(str) != strlenght(line.str)){
        return true;
    }   
    else{
        return false;
    }
}  

bool operator == (String &line1, String &line2){
    return line1.strlenght(line1.str) == line2.strlenght(line2.str);
}


ostream &operator<<(ostream &stream, String &obj){
    stream<<obj.str;
    return stream;
}

istream &operator>>(istream &stream, String &obj){
    stream>>obj.str;
    return stream;
}


void String::strcopy(char *str1,char *str2){
    while(*str1++ = *str2++);   
}

char String::mystrcat(char *str1,const char *str2){
    char *begin = str1;
    
    while(*str1){
        str1++;
    }
    while(*str1++ = *str2++);
    
    
    *str1 = '\0';
    return *begin;
}


int String::strlenght(const char *str){
    int counter = 0;
    while(*str != '\0'){
        counter++;
        str++;
    }
    
    return counter;
}

I understand that I could have done something wrong as I am just learning.

Let's move on to the problem. This part of the condition caused me a problem: The maximum sequence length is 254. The first byte must contain information about the actual number of array elements. Please tell me how this can be implemented. I will be very grateful

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
T1mple
  • 1
  • 1
  • why do you not use `std::string` ? As an exercise? Then you urgently need to read https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three/4172724#4172724 – 463035818_is_not_an_ai Apr 05 '22 at 13:55
  • We were told not to use ready-made functions but to describe them ourselves – T1mple Apr 05 '22 at 13:56
  • 1
    thats an unclear requirement. You are using functions from the standard library all over the place. For example when you write `cout << "\t\tActions" << endl;` – 463035818_is_not_an_ai Apr 05 '22 at 13:57
  • Oh sorry, I got it wrong. I thought you were a library for working with strings – T1mple Apr 05 '22 at 14:05
  • fwiw, `if (some_condition) {return true; } else { return false; }` is usually written as `return some_condition;` – 463035818_is_not_an_ai Apr 05 '22 at 14:10
  • 2
    I think author of this problem used to work with old Pascal where strings were working more or less like this. Limit `254` comes from: buffer size is 256, first byte is used for counting number of characters and terminating zero to maintain compatibility with C-string. I think dynamic allocation is not expected here. Anyway question abut this task should be directed to problem author, we can only guess what he meant. – Marek R Apr 05 '22 at 14:16
  • The first byte (so long as char is unsigned) can hold integer values from 0..255. Right? So that's big enough for your string length. Now you just need to actually store your length in the first char in the array, and use it instead of calling `mystrlen` everywhere. Oh, and don't print it or concatenate it like a regular character. – Useless Apr 05 '22 at 14:17
  • I've never dealt with Pascal :) I understand that maybe it's easy, but I really have no options how to implement it – T1mple Apr 05 '22 at 14:18
  • Has your instructor told you that a `char` is one byte big? (except on *really esoteric* hardware) – Caleth Apr 05 '22 at 14:28

2 Answers2

3

There is no need for new or delete in your code. Using an array of maximum size also for smaller sizes is wasting a bit of memory, but that is definitely worth the decrease in complexity.

The maximum sequence length is 254. The first byte must contain information about the actual number of array elements.

They ask you to allocate enough space for 254 characters and store the information on the number of characters in the first element. Assuming you should also store a terminating \0 you can do it along the line of this:

 char data[255];             // 254 + 1 for the size
 data[0] = 0;                // initial size is 0
 data[ data[0] + 1] = '\0';  // terminating null character

 // add a character:
 data[data[0] + 1] = 'a';        // add character at the end
 data[data[0] + 2] = '\0';       // new terminator
 ++data[0];                      // increment size stored in the first byte

 // "remove" a character
 data[ data[0] ] = '\0';         // overwrite last character with \0
 --data[0];                      // update size

The initial arary is

0  \0  ....

After adding a character it is

1  a  \0 ....

After removing the character it is

0  \0 \0 ...

Depending on details of the assignment the terminating \0 may not be needed. Note that currently your code is assuming that the strings are null-terminated, while the assignment asks you to store the size together with the data, which tells you the size more directly (provided you do the bookkeeping whenever the size changes).


PS: The String class you wrote is broken due to ignoring the rule of 3/5. If you write a class that manages a resource, like a manually allocated array you need to consider the rule. What is The Rule of Three?.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

The first byte must contain information about the actual number of array elements.

The assignment is asking you to implement strings differently to how C strings normally are. You have written a wrapper around C strings.

Your class's data members could look something like:

class String{ 
private:
    unsigned char size = 0;
    char text[255] = {};
public:
    friend String operator + (const String &line, const String &line2);
    friend bool operator == (const String &line, const String &line2);
    friend bool operator <= (const String &line, const String &line2);
    friend bool operator >= (const String &line, const String &line2);
    friend bool operator != (const String &line, const String &line2);

    friend ostream &operator<<(ostream &stream, String& obj);
    friend istream &operator>>(istream &stream, String& obj);
};

ostream &operator<<(ostream &stream, String& obj) {
    return (stream << obj.size).write(obj.text, obj.size);
}

istream &operator>>(istream &stream, String& obj) {
    return (stream >> obj.size).read(obj.text, obj.size);
}

You no longer need strlenght, because a String knows it's length, nor do you need strcopy, and the default special members work correctly. mystrcat can probably be rolled into +.

I leave it as an excersise to fill in the implementation of the remaining operators using size and text.

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • How then to use the copy constructor, the destructor? – T1mple Apr 05 '22 at 14:27
  • 2
    `size` should be `unsigned` to avoid strange errors. – Marek R Apr 05 '22 at 14:32
  • @T1mple they are generated, and they do the correct thing. That's called following the [Rule of Zero](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-zero) – Caleth Apr 05 '22 at 14:32
  • Implementing a copy constructor and destructor is a must for this task, but how do I use them if I don't use dynamic memory? – T1mple Apr 05 '22 at 14:51
  • 1
    If you really have to provide them: `~String() = default; String(const String &) = default; String& operator=(const String &) = default;` – Caleth Apr 05 '22 at 14:58