C ++, строка в массив символов с ограничениями моего профессора - PullRequest
0 голосов
/ 03 июля 2018

Я изучаю C ++, и я понятия не имею, как я должен делать следующее.

В присваивании нам нужно написать функцию, которая проверяет, совпадают ли первые два символа строки с двумя последними.

Это ограничения:

Вы не можете использовать std::string класс или строковую функцию, такую ​​как strlen. Вы должны использовать массив или указатель для этой функции.

Я пробовал это:

bool haveTheSameTwoChars(string str) {
    char arr[] = str;
    if (sizeof(arr) < 3) {
        return false;
    }
    else if (arr[0] == arr[sizeof(arr) - 3] && arr[1] == arr[sizeof(arr) - 2]) {
        return true;
    }
    else {
        return false;
    }
}

Но он не примет str в массив.

Однако, если бы я поместил что-то в кавычки вместо str, он бы это прекрасно воспринял, несмотря на то, что они оба были строками.

Что я делаю не так?

Ответы [ 5 ]

0 голосов
/ 03 июля 2018

Другой подход использует цикл и один указатель для итерации по каждой строке, сохраняя первый и второй символы для сравнения со следующим последним (предпоследним) и последним (последним) символами в строке.

Используя простую итерацию над массивом символов, пока он завершается нулем , вам не нужно беспокоиться об отдельном цикле для определения длины, вы просто захватываете / сохраняете первый два символа, а затем итерации до конца вашей строки, сохраняя предыдущие / последние символы на ходу. Когда вы нажимаете на конец своей строки, все, что вам нужно сделать, это сравнить первое с последним, а второе с последним с последним, например,

/* function iterates pointer through chars in 'line' saving
 * the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
 * ultimate characters in 'prev' & 'last' and compares. returns 1 if
 * 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
 */
int begmatchend (const char *line)
{
    const char *p  = line;  /* pointer to line */
    char beg  = *p++,       /* save for 1st char */
        next = *p++,        /* save for 2nd char */
        prev = *p++,        /* save for next to last char */
        last = *p++;        /* save for last char */

    while (*p) {        /* iterate over line setting prev/last as you go */
        prev = last;
        last = *p++;
    }
    if (beg == last && next == prev)    /* test whether equal */
        return 1;

    return 0;
}

Затем для простого теста вы можете просто подать строки своих программ из файла, вызывающего begmatchend в каждой строке, и затем вывести индикацию совпадения строк. Нечто простое, подобное следующему, является одним из способов:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstddef>

#define MAXC 1024

/* function iterates pointer through chars in 'line' saving
 * the 1st & 2nd chara in 'beg` and 'next' and the penultimate and
 * ultimate characters in 'prev' & 'last' and compares. returns 1 if
 * 1st matches ultimate AND 2nd matches penultimate, 0 otherwise.
 */
int begmatchend (const char *line)
{
    const char *p  = line;  /* pointer to line */
    char beg  = *p++,       /* save for 1st char */
        next = *p++,        /* save for 2nd char */
        prev = *p++,        /* save for next to last char */
        last = *p++;        /* save for last char */

    while (*p) {        /* iterate over line setting prev/last as you go */
        prev = last;
        last = *p++;
    }
    if (beg == last && next == prev)    /* test whether equal */
        return 1;

    return 0;
}

int main (int argc, char **argv) {

    char line[MAXC] = "";
    size_t n = 0;
    std::ifstream f (argc > 1 ? argv[1] : "/dev/stdin");

    if (!f.is_open()) {
        std::cerr << "error: file open failed.\n";
        return 1;
    }

    while (f.getline (line, MAXC, '\n')) {
        if (begmatchend ((const char *)line))
            std::cout << "line[" << std::setw(3) << n << 
                    "] 1st/ultimate matched, 2nd/penultimate matched.\n";
        n++;
    }

    return 0;
}

Пример ввода

$ cat dat/linesbegend.txt
all good vikings go to valhalla
be a tide that will flow and eb
a quick brown fox jumps over the lazy dog
we can find the begin and end - eew

Пример использования / Вывод

$ ./bin/beg_end_match dat/linesbegend.txt
line[  0] 1st/ultimate matched, 2nd/penultimate matched.
line[  1] 1st/ultimate matched, 2nd/penultimate matched.
line[  3] 1st/ultimate matched, 2nd/penultimate matched.

Посмотрите вещи и дайте мне знать, если у вас есть какие-либо вопросы.

0 голосов
/ 03 июля 2018

Вот пример кода для вашей цели

bool haveTheSameTwoChars(const char* p) {

    if(!p || !*p)
        return false;

    int len = -1;

    while(p[++len]);

    if(p[0] == p[len-2] &&
       p[1] == p[len-1])
       return true;

    return false;
}

Это вернет true, если строка «ABxxxAB» и false, если «ABxxxBA». Отдых можно настроить по своему желанию. Спасибо

0 голосов
/ 03 июля 2018

Ваш профессор хочет, чтобы вы использовали const char* в качестве параметра функции, то есть смоделируйте строку как указатель на первый символ в строке, где строка заканчивается на 0. (Мы называем это NUL-терминации ).

Итак, ваша функция

bool haveTheSameTwoChars(const char* s)

Затем вам нужно свернуть свою собственную версию strlen 1 , чтобы вычислить количество символов в строке до NUL:

, не включая
#include <cstddef> // for std::size_t
std::size_t strlen(const char *s) {
    const char *p = s;
    while (*s) ++s;
    return s - p;
}

После этого это простой случай, учитывая, скажем, длину l, который имеет дело с парой крайних случаев и общим случаем:

  1. Если l равно 0 или 1, вернуть false.
  2. Если l равно 2, вернуть true.
  3. Если l больше 2, то будет достаточно чего-то похожего на то, что у вас есть в вопросе, помня, что мой l на единицу меньше вашего.

Обратите внимание, что C ++ не поддерживает массивы переменной длины , поэтому char arr[] = str; не является допустимым C ++, а sizeof является оператором времени компиляции , поэтому вы получите только размер фактического типа массива, а не массива, который распался на тип указателя.


1 Ни один профессиональный программист не мечтал бы об этом. Компилятор может оптимизировать strlen до алгоритма на основе машинного слова, то есть учитывать несколько байтов одновременно.

0 голосов
/ 03 июля 2018

Когда вам не разрешено strlen, это сильный намек на то, что проблему можно решить, не заботясь о длине строки.

Давайте сделаем это:

Во-первых, у вас должен быть прототип (не разрешено string с, верно?)

bool haveTheSameTwoChars(const char* str)

Затем убедитесь, что строка содержит не менее двух символов

if (!str || !str[0] || !str[1])
    return false;

Тогда вы найдете конец строки:

const char* end = str;
while (*end)
    end++;

Затем вернитесь на два символа назад, поэтому end указывает на первый из двух последних символов:

end -= 2;

(Это безопасно, так как мы сначала проверили, что есть по крайней мере два символа.)

Тогда сравните

return str[0] == end[0] && str[1] == end[1];
0 голосов
/ 03 июля 2018

Ну, вот разбивка вашей проблемы:

Вы должны принять ввод как массив или указатель. Например:

bool isMatched( const char* str )
{
    // ...
}

Теперь вам нужно самостоятельно рассчитать длину вашей строки. Пересмотрите циклы и придумайте что-нибудь, что даст вам длину строки с нулевым окончанием. C-строки заканчиваются нулем, то есть '\0', поэтому вы можете завершить свой цикл, когда встретите нулевой символ. Например:

int len = 0;
while ( str[len] != '\0' ) len++;

Это просто идея. Проведите собственное исследование и правильно рассчитайте длину строки.

Остальное - просто сравнение первых и последних двух символов с использованием if. :)

Я уверен, что вы можете собрать все вместе и немного пересмотреть учебный материал, чтобы решить эту проблему

Удачи!
Удачного кодирования!

...