Ошибка сегментации с классом Dynami c (домашнее задание) - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь преобразовать рабочий класс c String в динамический c String класс, используя указатели, но когда я реализую указатель, он выдает ошибку ошибки сегментации. Код ниже:

mystring1.h:

//File: mystring1.h
// Declaration file for user-defined String class.


#ifndef _MYSTRING_H
#define _MYSTRING_H
#include<iostream>
#include <cstring>
using namespace std;

#define MAX_STR_LENGTH  200


class String {
public:
  String();
  String(const char *s);  // a conversion constructor   
  void append(const String &str);

  //deconstructor
  ~String();

  //copy constructor
  String (const String & origString);

  //assignment operator overload
  String operator =(const String &origString);

  // Relational operators
  bool operator >(const String &str) const;
  bool operator <(const String &str) const;    

  String operator +=(const String &str);      

  void print(ostream &out) const;    
  int length() const;

  char operator [](int i) const;  // subscript operator 



private:
    char *contents;
    int len;
    //int capacity;
};

ostream & operator<<(ostream &out, const String & r); // overload ostream operator "<<" - External!  


#endif /* not defined _MYSTRING_H */

mystring1. cpp:

//File: mystring1.h
// Implementation file for user-defined String class.

#include "mystring1.h"


String::String()
{
  contents[0] = '\0';
  len = 0;
}

String::String(const char s[])
{
  len = strlen(s);
  contents = new char[len + 1];
  strcpy(contents, s);
}



void String::append(const String &str)
{
  strcat(contents, str.contents);
  len += str.len;
}

//deconstructor
String::~String()
{
  delete [] contents;
}

//copy constructor
String::String(const String &origString)
{
  len = origString.len;
  contents = new char[len + 1];

  for (int i = 0; i < len; i++)
  {
    contents[i] = origString.contents[i];
  }
}

//assignment operator overload
String String::operator =(const String &origString)
{
  if (this != &origString)
  {
    len = origString.len;
    delete [] contents;
    contents = new char[len + 1];

    for (int i = 0; i < len; i++)
    {
      contents[i] = origString.contents[i];
    }
  }

  return *this;
}


bool String::operator >(const String &str) const
{
  return strcmp(contents, str.contents) > 0;
}

bool String::operator <(const String &str) const
{
  return strcmp(contents, str.contents) < 0;
}


String String::operator +=(const String &str)
{
    append(str);
    return *this;
}

void String::print(ostream &out) const
{
  out << contents;
}

int String::length() const
{
  return len;
}

char String::operator [](int i) const
{
  if (i < 0 || i >= len) {
    cerr << "can't access location " << i
         << " of string \"" << contents << "\"" << endl;
    return '\0';
  }
  return contents[i];
}

ostream & operator<<(ostream &out, const String & s) // overload ostream operator "<<" - External!
{ 
    s.print(out);
    return out;
}

Назначение 5 Драйвер:

/**
 * cmpsc122 Assignment 5 test file
 * File Name: Assign5driver.cpp
 *
 * Description: This program demonstrates a basic String class that implements
 * dynamic allocation and operator overloading.
 *
 */

#include <iostream>
#include "mystring1.h"
using namespace std;


/*************************** Main Program **************************/

int main()
{
  String str1, str2("dog");  // Using constructor for initial strings
  char s1[100], s2[100];              // Some C strings.

  // Print out initial strings

  cout << "Initial values:" << endl;
  cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;

  // Inputs some new strings in them

  cout << "\nEnter a value for str1 (no spaces): ";
  cin >> s1;
  str1 = s1;

  cout << "\nEnter a value for str2 (no spaces): ";
  cin >> s2;
  str2 = s2;


  cout << "\nAfter assignments..." << endl;
  cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;

  // Get some elements...

  int i;

  cout << "\nEnter which element of str1 to display: ";
  cin >> i;
  cout << "Element #" << i << " of str1 is '" << str1[i] << "'" << endl;

  cout << "\nEnter which element of str2 to display: ";
  cin >> i;
  cout << "Element #" << i << " of str2 is '" << str2[i] << "'" << endl;

  // Concate some strings

  cout << "\nEnter a value to append to str1 (no spaces): ";
  cin >> s1;
 // str1.append(s1); // Actually, the cstring is converted to String object here by the constructor
  str1 += s1;   // same as above

  cout << "\nEnter a value to append to str2 (no spaces): ";
  cin >> s2;
  str2 += s2;



  cout << "\nAfter appending..." << endl;
  cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;

  // Compare strings...

  cout << "\nComparing str1 and str2..." << endl;

  cout << "\"";

  cout<< str1;   // test the overloading of ostream operator <<

  cout << "\" is ";

  if (str1 < str2) {      // test the overloading of comparison operator <
    cout << "less than";
  } else if (str1 > str2) {
    cout << "greater than";
  } else {
    cout << "equal to";
  }

  cout << " \"";
  cout << str2;
  cout << "\"" << endl;

  cout << "\ntest the = operator, after str1 = str2; "<< endl;

  str1 = str2;

 cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;

  str1 += s1;

  cout << "\nAfter str1 = str1 + s1: "<< endl;

  cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;

  String str3(str2);
  cout << "\ntest the copy constructor, after str4(str3);"<< endl;

  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
  cout << "str3 holds \"" << str3 << "\" (length = " << str3.length() << ")" << endl;

  cout << "\nafter appending str2 by str1" << endl;
  str2 += str1;
  cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
  cout << "str3 holds \"" << str3 << "\" (length = " << str3.length() << ")" << endl;

  cout<< "\nstr3 are not changed. Type any letter to quit." << endl;

  char q;

  cin >> q;

  return 0;
}

Буду признателен за любую помощь, я перепробовал все, что мог, и мое исследование причин ошибок сегментации не очень помогло.

1 Ответ

1 голос
/ 17 февраля 2020

В вашей реализации есть несколько очевидных ошибок:

  1. Конструктор по умолчанию использует неинициализированный указатель contents.
  2. Метод ::append() не гарантирует наличие достаточного места в буфере назначения перед выполнением strcat.
  3. Конструктор копирования и метод ::operator=() не NUL не определяют буфер contents.

Вероятно, что подробнее.

Вы должны собрать свою тестовую программу с помощью g++ -fsanitize=address ... и исправить все найденные ошибки.

Вы также должны собрать свою программу с -Wall -Wextra флажками и исправить все предупреждение, которое он выдает.

...