字符串类istream问题

时间:2018-02-25 14:34:46

标签: c++ string data-structures

我无法让我的字符串课程正常工作。我的istream函数似乎读取了数据,并且我确认+ =正在添加字符,但是在第一个字符之后,添加的是垃圾。我已经尝试了一切我能想到的工作。有人可以提供一些有关出错的见解。谢谢。

istream& operator >>(istream& ins, string& target)
{
    char newInput; 
    while (ins && isspace(ins.peek()))
        ins.ignore(); 
    target = ("");
    //int count = 0; 
    while (ins && !isspace(ins.peek())) //(ins.peek())))
    {
        ins >> newInput;
        target.operator+=(newInput); 


    }
    return ins; 
}

 void string::operator +=(char addend)

{
    if (this->current_length + 1 > this->allocated)
    {
        reserve(allocated + 1);
    }

    sequence[current_length] = addend;

    current_length += 1;
}

void string::reserve(size_t n)
{
    assert(n > current_length);
    char *newSequence = new char[n]; 

    if (n == allocated)
    {
        return;
    }



    for (size_t i = 0; i < n; i++)
    {
        newSequence[i] = sequence[i]; 
    }

    //destroy old array

    delete[] sequence; 

    //update capacity

    allocated = n; 

    //point data at new array


    sequence = newSequence; 


}

完整代码:**

#pragma warning(disable : 4996)
#ifndef MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#define MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#include <cstdlib>  // Provides size_t
#include <cassert>
#include <string.h>
#include <iostream>
#include <ctype.h>
#include <algorithm>


using namespace std;

namespace main_savitch_4

{
    class string
    {
    public:
        // CONSTRUCTORS and DESTRUCTOR
        string(const char str[] = "");
        string(const string& source);
        ~string() { delete[] sequence; }
        // MODIFICATION MEMBER FUNCTIONS
        void operator +=(const string& addend);
        void operator +=(const char addend[]);
        void operator +=(char addend);
        void reserve(size_t n);
        void operator =(const string& source);
        // CONSTANT MEMBER FUNCTIONS
        size_t length() const { return current_length; }
        char operator [ ](size_t position) const;
        // FRIEND FUNCTIONS
        friend ostream& operator <<(ostream& outs, const string& source);
        friend bool operator ==(const string& s1, const string& s2);
        friend bool operator !=(const string& s1, const string& s2);
        friend bool operator >=(const string& s1, const string& s2);
        friend bool operator <=(const string& s1, const string& s2);
        friend bool operator > (const string& s1, const string& s2);
        friend bool operator < (const string& s1, const string& s2);
    private:
        char *sequence;
        size_t allocated;
        size_t current_length;
    };

    // CONSTRUCTOR for the string class:
    //   string(const char str[ ] = "") -- default argument is the empty string.
    //     Precondition: str is an ordinary null-terminated string.
    //     Postcondition: The string contains the sequence of chars from str.

    string::string(const char str[])
    {
        current_length = strlen(str);
        allocated = current_length + 1;
        sequence = new char[allocated];
        for (size_t i = 0; i < allocated; i++)
        {
            sequence[i] = str[i];
        }
    }


    string::string(const string& source)
        //copy constructor 
    {
        current_length = source.current_length;
        allocated = current_length + 1;
        sequence = new char[allocated];

        for (size_t i = 0; i < allocated; i++) {
            sequence[i] = source.sequence[i];
        }

    }




    //~string();

    // CONSTANT MEMBER FUNCTIONS for the string class:
    //   size_t length( ) const
    //     Postcondition: The return value is the number of characters in the
    //     string.

    //
    //   char operator [ ](size_t position) const
    //     Precondition: position < length( ).
    //     Postcondition: The value returned is the character at the specified
    //     position of the string. A string's positions start from 0 at the start
    //     of the sequence and go up to length( )-1 at the right end.

    char string::operator [ ](size_t position) const
    {
        assert(position < length());
        return (sequence[position]);

    }


    // MODIFICATION MEMBER FUNCTIONS for the string class:
    //   void operator +=(const string& addend)
    //     Postcondition: addend has been catenated to the end of the string.
    //

    void string::operator =(const string& source)
    {
        //string assigned to self 
        if (sequence == source.sequence)
        {
            return;
        }

        if (source.current_length > this->allocated)
            reserve(source.current_length);

        delete[] sequence;


        current_length = source.current_length;
        allocated = current_length + 1;
        for (size_t i = 0; i < allocated; i++) {
            sequence[i] = source.sequence[i];

        }
    }

    void string::operator +=(const string& addend)
    {

        if (this->current_length + addend.current_length > this->allocated)
        {
            reserve(current_length + addend.allocated);
        }

        //copy addend to sequence 

        for (size_t i = 0; i < addend.current_length; i++)
        {
            sequence[i + current_length] = addend.sequence[i];
        }
        current_length = current_length + addend.current_length;

    }


    //   void operator +=(const char addend[ ])

    //     Precondition: addend is an ordinary null-terminated string.
    //     Postcondition: addend has been catenated to the end of the string.

    void string::operator +=(const char addend[])
    {

        if (this->current_length + strlen(addend) > this->allocated)
            reserve(current_length + strlen(addend));

        //copy addend to sequence 

        for (size_t i = 0; i < strlen(addend); i++)
        {
            sequence[i + current_length] = addend[i];
        }
        current_length += strlen(addend);

    }




    //   void operator +=(char addend)
    //     Postcondition: The single character addend has been catenated to the
    //     end of the string.
    //

    void string::operator +=(char addend)

    {
        if ((this->current_length + 1) > (this->allocated))
        {
            reserve(allocated + 1);
        }

        //copy addend to sequence 
        sequence[current_length] = addend;



        current_length += 1;
    }


    //   void reserve(size_t n)
    //     Postcondition: All functions will now work efficiently (without
    //     allocating new memory) until n characters are in the string.

    void string::reserve(size_t n)
    {
        assert(n > current_length);

        //create new array
        char *newSequence = new char[n];

        if (n == allocated)
        {
            return;
        }

        if (n < current_length + 1)
        {
            n = current_length + 1;
        }


        for (size_t i = 0; i < current_length; i++)
        {
            newSequence[i] = sequence[i];

        }



        delete[] sequence;

        //update capacity

        allocated = n;

        //point data at new array


        sequence = newSequence;


    }

    //Friend Functions

    bool operator ==(const string& s1, const string& s2)
    {
        return (s1 == s2);
    }
    bool operator !=(const string& s1, const string& s2)
    {

        return !(s1 == s2); //(strcmp(s1.sequence, s2.sequence) == 0);
    }
    bool operator >=(const string& s1, const string& s2)
    {

        return (s1 >= s2); //(strcmp(s1.sequence, s2.sequence) >= 0);
    }
    bool operator <=(const string& s1, const string& s2)
    {

        return (s1 <= s2); //(strcmp(s1.sequence, s2.sequence) <= 0);
    }
    bool operator > (const string& s1, const string& s2)
    {

        return (s1 > s2); //(strcmp(s1.sequence, s2.sequence) > 0);
    }
    bool operator < (const string& s1, const string& s2)
    {

        return (s1 < s2); // (strcmp(s1.sequence, s2.sequence) < 0);
    }



    // NON-MEMBER FUNCTIONS for the string class

    //   string operator +(const string& s1, const string& s2)
    //     Postcondition: The string returned is the catenation of s1 and s2.
    //

    string operator +(const string& s1, const string& s2)
    {
        string temp = s1;
        temp = s1 + s2;
        return temp;
    }





    //   istream& operator >>(istream& ins, string& target)
    //     Postcondition: A string has been read from the istream ins, and the
    //     istream ins is then returned by the function. The reading operation
    //     skips white space (i.e., blanks, newlines, tabs) at the start of ins.
    //     Then the string is read up to the next white space or the end of the
    //     file. The white space character that terminates the string has not
    //     been read.
    //

    istream& operator >>(istream& ins, string& target)
    {
        char newInput;
        while (ins && isspace(ins.peek()))
            ins.ignore();
        target = ("");
        while (ins && !isspace(ins.peek())) //(ins.peek())))
        {
            ins >> newInput;
            cout << newInput;
            target.operator+=(newInput);

        }
        return ins;
    }



    //   ostream& operator <<(ostream& outs, const string& source)
    //     Postcondition: The sequence of characters in source has been written
    //     to outs. The return value is the ostream outs.

    ostream& operator <<(ostream& outs, const string& source)
    {
        outs << source.sequence;
        return outs;
    }



    //
    //   void getline(istream& ins, string& target, char delimiter)

    void getline(istream& ins, string& target, char delimiter)
    {
        {
            int count = 0;
            char newLine;
            while (ins)
            {
                ins.get(newLine);

                target.operator+=(newLine);

            }
        }
    }

}

#endif
#pragma once

2 个答案:

答案 0 :(得分:0)

必须平衡new[]delete[]

string::operator=(const string&)例程是delete[]序列数组,稍后在保留例程中再次获得delete[]

答案 1 :(得分:0)

while (ins && !isspace(ins.peek())) //(ins.peek())))
{
    ins >> newInput;
    target.operator+=(newInput); 


}

在这里:

  • 检查流是否有任何错误或尝试读取结束
  • 提取下一个字符,假设此成功,然后查看它是否为空格
  • 读取所述字符,并再次假设此成功 - 如果成功,则将其分配给newInput
  • newInput的内容插入target(出于某种原因直接调用函数)

如果下一次阅读失败,您就没有检查,newInput并不是您认为的。

您只是在之前检查了之前的错误。

也许这样的事情会更适合:

while (true) {
   const auto next = ins.peek();
   if (!ins) break;
   if (isspace(next)) break;

   ins >> newInput;
   target += newInput;
}

我假设如果peek成功,那么>>也会成功,但实际上我可能会在!ins之前再次检查target += 1}}行,除非我关注速度。特别是,您应该仔细检查peek()是否设置 eofbit ,因为我无法记住,如果不记得,您肯定需要另一个if