Как изменить значение переменной указателя и сохранить изменения вне функции без передачи по ссылке? - PullRequest
0 голосов
/ 06 сентября 2018

Я делаю проект для класса, пишущего функции редактирования C-String. 3/5 функций, которые я должен написать, изменяют размер массивов символов, которые я должен использовать, и они читаются через ввод ifstream. Вот программа:

#include <iostream>
#include <fstream>

using namespace std;

void stringCopy(char *A, char *B);
bool stringCompare(char *A, char *B);
void stringConcatenation(char *A, char *B);    //added const to make sure b is never changed
int stringPosition(char *A, char B);
int stringLength(char *A);
//-------------------MY-FUNCTIONS----------------------
int cStringLen(const char*);  //finds string length, but doesn't account for null char
void reSize(char*&, int len, int newLen);
void input(char*& A, istream& is);
void printMessage(const char* word1, const char* word2, const char* message);

int main()
{
    ifstream ifs{"input.txt"};
    ofstream ofs{"output.txt"};
    char* word1 = "";
    char* word2 = "";

    input(word1, ifs);
    input(word2, ifs);
    printMessage(word1, word2, "stringCopy()");
    stringCopy(word1, word2);
    printMessage(word1, word2, "after stringCopy()");
    cout << endl;

    input(word1, ifs);
    input(word2, ifs);
    printMessage(word1, word2, "stringCompare()");
    if(stringCompare(word1, word2))
    {
        cout << "They match!" << endl;
    }
    else
    {
        cout << "They don't match!" << endl;
    }
    stringCopy(word1, word2);
    printMessage(word1, word2, "comparing after stringCopy()");
    if(stringCompare(word1, word2))
    {
        cout << "They match!" << endl;
    }
    else
    {
        cout << "They don't match!" << endl;
    }
    cout << endl;

    input(word1, ifs);
    input(word2, ifs);
    printMessage(word1, word2, "stringConcatenation()");
    stringConcatenation(word1, word2);
    printMessage(word1, word2, "after stringConcatenation()");
    cout << endl;

    input(word1, ifs);
    input(word2, ifs);
    printMessage(word1, word2, "stringPosition()");
    cout << "Searching for 'm' in word1..." << endl << "position returned is: " << stringPosition(word1, 'm') << endl;
    cout << "Searching for 'n' in word2..." << endl << "position returned is: " << stringPosition(word2, 'n') << endl;
    cout << endl;

    input(word1, ifs);
    cout << "stringLength()" << endl;
    cout << "word1: " << word1 << endl;
    cout << "The length of word1 is: " << stringLength(word1) << endl;
    cout << "after stringLength()" << endl;
    cout << "word1: " << word1 << endl;

    return 0;
}

void stringCopy(char *A, char *B)
{
    ///GETTING THE SIZES OF BOTH ARRAYS
    int counterA = cStringLen(A) + 1;
    int counterB = cStringLen(B) + 1;
    ///MAKES SURE BOTH ARE THE SAME SIZE BEFORE COPYING
    if(counterA < counterB)
    {
        reSize(A, counterA, counterB);
    }
    else
    {
        reSize(A, counterB, counterA);
    }
    ///THE COPY
    for(int i = 0; i < counterB; i++) *(A + i) = *(B + i);  //each character is copied to A from B
}

bool stringCompare(char *A, char *B)
{
    ///getting length of one string
    int counter = cStringLen(A);
    ///will move through string until diff char found
    for(int i = 0; i < counter + 1; i++)
    {
        if(*(A + i) != *(B + i))
        {
            return false;
        }
    }
    return true;
}

void stringConcatenation(char *A, char *B)    //added const to make sure b is never changed
{
    ///getting length of both strings
    int counterA = cStringLen(A)+1;
    int counterB = cStringLen(B)+1;
    ///putting the length of both together for new string
    const int COUNTERS = counterA + counterB - 1;
    ///making A the size of both strings - 1
    reSize(A, counterA, COUNTERS);
    ///copying b to the parts of a past the original
    for(int i = 0; i < counterB; i++)
    {
        *(A + (counterA - 1) + i) = *(B + i);   //will override the '/0' char of A
    }
}

int stringPosition(char *A, char B)
{
    int counter = cStringLen(A) + 1;
    ///searching through string for char
    for(int i = 0; i < counter; i++)
    {
        if(*(A + i) == B)
        {
            return i;   //found!
        }
    }
    ///checking if b == '\0' and a '\0' isn't found somewhere before last spot of A
    if(B == '\0')
    {
        return counter;
    }
    return -1;  //not found
}

int stringLength(char *A)
{
    int counter = cStringLen(A) + 1;
    char* car = new char[counter + 1];
    for(int i = 0; i < counter; i++)
    {
        *(car + 1 + i) = *(A + i);
    }
    *(car + 0) = counter;
    delete[] A;
    A = car;
    /**
    * Will take string as param.

    * Shifts all characters to the right by one and store the length of the string in position 0.
        - Length doesn't include position 0.
    */
    return counter;   //temp
}

//-----------------------------------------MY FUNCTIONS---------------------------------------------------------------------------
int cStringLen(const char* A) //finds string length, but doesn't account for null char
{
    int counter = 0;
    while(*(A + counter) != '\0')
    {
        counter++;
    }
    return counter;
}

void reSize(char*& A, int len, int newLen)
{
    char* car = new char[newLen];
    for(int i = 0; i < newLen; i++)
    {
        if(i < len)
        {
            *(car + i) = *(A + i);
        }
        else if(i >= len && i < newLen)
        {
            *(car + i) = '\0';
        }
    }
    delete[] A;
    A = car;
}

void input(char*& A, istream& is)
{
    int wordSize = 0;
    int arrSize = 1;
    char c = 'o';   //checking char
    char* car = new char[arrSize];
    while((!(is.eof())) && (c != ' ' && c != '\t' && c != '\n'))
    {
        is.unsetf(ios_base::skipws);
        is >> c;

        if(is.eof())
        {
            delete[] A;
            A = car;
            return;
        }
        if(c != ' ' && c != '\t' && c != '\n')
        {
            if(wordSize == arrSize)
            {
                reSize(car, arrSize, arrSize * 2);
            }
            *(car + wordSize) = c;
        }
        wordSize++;
    }
    is.setf(ios_base::skipws);
    delete[] A;
    A = car;
}

void printMessage(const char* word1, const char* word2, const char* message)
{
    cout << message << endl;
    cout << "word1: " << word1 << endl << "word2: " << word2 << endl;
}

Я думал, что все это сделано просто отлично. Имейте в виду, что я добавил оператор «&» после каждого из параметров указателя уже. Вот как они были раньше:

void stringCopy(char *&A, char *B);
bool stringCompare(char *A, char *B);
void stringConcatenation(char *&A, char *B);    //added const to make sure b 
is never changed
int stringPosition(char *A, char B);
int stringLength(char *&A);

Но, когда я добрался до класса, мой учитель сказал, что нам не разрешалось менять заголовки функций. Итак, я застрял, передавая значение для назначения. Проблема в том, что у меня нет способа изменить c-строки вне функций редактирования. Любые изменения, которые я делаю с ними, остаются там.

Все это прекрасно компилируется, и, если я сделаю указатели по ссылке, программа будет работать без сбоев. Мне просто интересно, как я мог изменить значения c-строк вне функций редактирования. Это задание начинает становиться болезненным (так много чертовых ограничений).

1 Ответ

0 голосов
/ 04 октября 2018

Я думаю, что ваш учитель хочет, чтобы вы изменили значение в символьном указателе вместо создания новой строки.

Поэтому вместо попытки переназначить параметр A на новый char* вы меняете значение, на которое A указывает в памяти. Таким образом, метод, который вызвал вашу функцию, все еще указывает на ту же самую память, и когда они обращаются к этому местоположению, вы получаете значение, которое вы изменили из вашей функции.

...