Отделение пробелов от getline и cin >> string

Вопрос или проблема

Контекст: Это было упражнение для “курса”, где мне был предоставлен файл с ASCII-числами, и мне сказали декодировать эти ASCII-числа в слова. Каждое слово было написано в одной строке, каждую букву ASCII разделяли пробелы.
Пример:

107 97 119 97
112 105 101 115
100 111 109

В терминале действительно возвращались декодированные слова, но мой код был отмечен как неправильный, и один администратор курса сказал мне использовать file >> line вместо (getline(file, line)) в основной функции, после чего другой администратор сказал мне использовать (getline(file, line)), что уже есть в моем коде… Я не смог получить никакой полезной обратной связи, поэтому хотел бы спросить здесь. Является ли использование getline неэффективным для этого, а file >> line идеальным? Как бы вы разделили декодированные слова на отдельные строки, когда file >> line не учитывает пробелы?

#include <iostream>
#include <fstream>
using namespace std;

int stringToInt(string numberSet)
{
    int position = 1;
    int number = 0;

    for (int i = numberSet.length() - 1; i >= 0; i--)
    {
        number = number + (numberSet[i] - 48) * position;
        position = position * 10;
    }
    return number;
}

string convertToWord(string line)
{
    string numberSet = "";
    string word = "";
    int number;

    for (int i = 0; i < line.length(); i++)
    {
        if (line[i] != ' ' && line[i] != '/n')
        {
            numberSet = numberSet + line[i];
        }
        else
        {
            number = stringToInt(numberSet);
            char letter = number;
            word = word + letter;

            numberSet = "";
        }
    }

    number = stringToInt(numberSet);
    char letter = number;
    word = word + letter;

    return word;
}

int main()
{
    ifstream file;
    ofstream result;
    file.open("slowa1.txt");
    result.open("wyniki2.txt");

    string line;
    bool isEmpty = true;

    while (getline(file, line))
    {
        isEmpty = false;
        cout << convertToWord(line) << endl;
        result << convertToWord(line) << endl;
    }

    if (isEmpty)
    {
        cout << "No solutions" << endl;
        result << "No solutions" << endl;
    }

    file.close();
    result.close();
    return 0;
}

Изначально я использовал (getline(file, line)) в основной функции, но мне сказали, что это неправильно, без дальнейшего пояснения. Для примера ввода выше мой код вернул

kawa
pies
dom

Является ли код неправильным, потому что я не использовал file >> line вместо этого? Как можно добавить ‘/n’ или endl после каждого слова, как выше, используя file >> line, чтобы вывод не стал kawapiesdom без пробелов?

Является ли код неправильным, потому что я не использовал file >> line вместо этого?

Мы не можем знать схему оценки, но учитывая, что администраторы курса не согласны, я бы предположил, что это не так. Вы, без сомнения, заметили проблемы, которые file >> line имеет по сравнению с getline(file, line), и в этом случае у него нет преимуществ.

Тем, что могло быть отмечено как неправильное, являются ваши функции stringToInt и convertToWord, которые можно упростить, используя std::stringstream

string convertToWord(stringstream in)
{
    string word;
    int letter;

    while(in >> letter)
    {
        word.push_back(static_cast<char>(letter));
    }

    return word;
}

Еще одна проблема в том, что вы дважды вызываете convertToWord, когда записываете в два выходных потока.

while (getline(file, line))
{
    isEmpty = false;
    string word = convertToWord(line);
    cout << word << endl;
    result << word << endl;
}

Ответ или решение

Конечно, давайте разберем вопрос, касающийся использования getline и cin >> для считывания строк с пробелами.

1. Использование getline vs cin >>

При работе с файлами и вводом в C++, существует два популярных способа считывания данных: getline() и cin >>.

getline(file, line)

  • Преимущества:

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

    • Необходимо вручную разбивать строку на элементы, если данные в строке нужно обработать по частям (например, в вашем случае – преобразовать ASCII к буквам).

cin >> line

  • Преимущества:

    • Простота использования для считывания отдельных слов или токенов. Будет игнорировать пробелы, считывая только непрерывные последовательности символов.
  • Недостатки:

    • Не сможет считать целую строку, содержащую пробелы, целиком, что может привести к тому, что данные будут обрабатываться неправильно, если в строке два или более токенов.

2. Ваша задача

Ваша задача включает декодирование строк, которые содержат коды ASCII, разделенные пробелами. Использование getline() является правильным решением, так как эта функция позволяет вам получать всю строку, содержащую все значения ASCII.

3. Оптимизация существующего кода

Ваш текущий код работает, но он может быть оптимизирован. Предложу усовершенствовать функцию convertToWord, чтобы упростить чтение и преобразование.

#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

string convertToWord(const string& line)
{
    string word;
    stringstream ss(line);
    int letter;

    while (ss >> letter)
    {
        word.push_back(static_cast<char>(letter));
    }

    return word;
}

int main()
{
    ifstream file("slowa1.txt");
    ofstream result("wyniki2.txt");
    string line;

    // Считываем строки из файла
    while (getline(file, line))
    {
        cout << convertToWord(line) << endl;
        result << convertToWord(line) << endl;
    }

    file.close();
    result.close();
    return 0;
}

4. Проблемы, связанные с выводом

Как вы отметили, при использовании cin >> или даже getline важно следить за тем, как вы выводите результаты. В вашем новом подходе к записыванию в файл и выводу в консоль:

cout << convertToWord(line) << endl;
result << convertToWord(line) << endl;

Этот код правильно вставляет символ новой строки (endl) после каждой строки, что гарантирует, что слова будут распечатаны в отдельных строках.

Заключение

Использование getline в вашем случае – правильный и более подходящий способ для обработки данных. Помните, что улучшение вашего кода с использованием потоков позволяет упростить логику и повысить читаемость. Убедитесь, что вы избегаете дублирования вызовов функций (как с convertToWord), для более эффективного использования ресурсов.

Если у вас возникли какие-либо дополнительные вопросы или проблемы, не стесняйтесь задавать!

Оцените материал
Добавить комментарий

Капча загружается...