Как использовать getline() для копирования ввода в выходной файл С++

avatar
Nick Lybarger
8 августа 2021 в 22:52
84
1
0

Мой код запрашивает у пользователя имя входного файла, копирует содержимое файла, используя getline(), а затем выводит содержимое в другой файл, "new.txt". Я пытался использовать input.ignore(), но безрезультатно. Рассматриваемый код можно найти в определении функции addDot. Далее следует мой код (программа не полностью завершена, но именно здесь я сейчас застрял):

#include <iostream>
#include <fstream>
#include <string>
#include <istream>
using namespace std;
const int MAX_SIZE = 200;
ifstream input;
ofstream output;

//function prototypes
void readImageFile(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used);
void displayInfo(int& num_rows_used, int& num_cols_used);
void addDot(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used);
void saveOutputImage(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used);

int main()
{


    int image[MAX_SIZE][MAX_SIZE]; // this is the 2-D array that holds the [row][column] pixel values
    int num_rows_used;
    int num_cols_used;

    readImageFile(image, num_rows_used, num_cols_used); 
    displayInfo(num_rows_used, num_cols_used);
    addDot(image, num_rows_used, num_cols_used);
    saveOutputImage(image, num_rows_used, num_cols_used); 
}

//function definitions
void readImageFile(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used) {

    string fileName;
    cout << "Please enter an image filename: ";
    cin >> fileName;
    input.open(fileName);
    if (input.fail()) {
        cout << "Error opening " << fileName << "\n";
        exit(1);
    }
    input.ignore(100, '\n');
    input >> num_cols_used >> num_rows_used;
    input.ignore(100, '\n');
    input.ignore(100, '\n');

    for (int i = 0; i < num_rows_used; i++) {
        for (int k = 0; k < num_cols_used; k++) {
            input >> image[i][k];
        }

    }

}

void displayInfo(int& num_rows_used, int& num_cols_used) {
    cout << "The size of the image is:\n" << "X: " << num_cols_used << " pixels\n" << "Y: " << num_rows_used << " pixels\n";
}


//CULPRIT CODE FOUND HERE
void addDot(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used)
{
    string line;
    input.open("img1.txt");
    output.open("new.txt");
    for (int j = 0; j < num_rows_used + 2; j++) {
        input.ignore(256, ' ');
        getline(input, line);
        output << line << "\n";
    }


}


void saveOutputImage(int image[MAX_SIZE][MAX_SIZE], int& num_rows_used, int& num_cols_used)
{
    output.close();
    input.close();
}

Входной файл выглядит следующим образом:

P2 
8 4 
255 
  0  255    0  255    0  255    0  255 
255  127  255    0  255  127  255    0 
  0  255  160  255    0  255  160  255 
255   86  255    0  255   86  255    0  
Источник
Remy Lebeau
8 августа 2021 в 22:56
0

Было бы полезно, если бы вы показали фактические данные входного файла и то, на что вы хотите, чтобы выходной файл выглядел, и объяснили, почему вы считаете, что вам вообще нужно использовать ignore(). Тем не менее, я укажу, что вы пытаетесь open() поток input, когда он уже открыт, что, вероятно, приведет поток в состояние ошибки. Это, вероятно, ваша основная проблема. Вам нужно close() поток, прежде чем вы сможете open() его снова. В противном случае оставьте его открытым и просто прочитайте с того места, где он остановился, или seekg(), если вы хотите перечитать прошлые данные.

Shawn
8 августа 2021 в 22:56
0

Почему вы вставляете это ignore()?

Shawn
8 августа 2021 в 22:57
0

Если вы просто хотите сделать прямую копию одного файла в другой, есть С++ 17 std::filesystem::copy_file()...

Nick Lybarger
8 августа 2021 в 23:00
0

Я использую ignore(), потому что где-то читал, что getline() плохо сочетается с пробелами.

Remy Lebeau
8 августа 2021 в 23:01
0

@NickLybarger либо то, что вы прочитали, неверно, либо, что более вероятно, вы неправильно поняли, о чем там говорилось.

Nick Lybarger
8 августа 2021 в 23:09
0

Я попытался удалить второй input.open() и все еще получаю тот же результат. Я пробовал и с ignore(), и без него.

Sam Varshavchik
8 августа 2021 в 23:21
0

Ну, что бы ты "где-то ни читал", ты либо невнимательно прочитал, либо неправильно. getline отлично работает со строками, содержащими пробелы. Вы знакомы с тем, что на самом деле делает ignore?

Nick Lybarger
8 августа 2021 в 23:25
0

Очевидно, я неправильно использовал функцию ignore. После удаления ignore проблема осталась.

Shawn
8 августа 2021 в 23:29
0

Какая у вас проблема?

Nick Lybarger
8 августа 2021 в 23:32
0

Моя проблема в том, что когда я пытаюсь скопировать содержимое из "img1.txt" в "new.txt", копируется только \n. Мой выходной файл показывает только 7 пустых строк.

Pete Becker
9 августа 2021 в 00:25
0

out_file << in_file.rdbuf(); скопирует содержимое входного потока in_file в выходной поток out_file.

Ответы (1)

avatar
Shawn
8 августа 2021 в 23:33
0

Если вы просто пытаетесь скопировать файл A в файл B, есть несколько способов. Первый основан на библиотеке файловой системы C++17, другой работает на более старых версиях C++, используя классы streambuf_iterator для копирования:

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>

#include <filesystem>

// Uses the C++17 filesystem library
void my_copy_file1(const std::string &from, const std::string &to) {
  std::filesystem::copy_file(from, to);
}

void my_copy_file2(const std::string &from, const std::string &to) {
  std::ifstream in{from, std::ios::binary};
  std::ofstream out{to, std::ios::binary};
  std::copy(std::istreambuf_iterator{in}, std::istreambuf_iterator<char>{},
            std::ostreambuf_iterator{out});
}

int main(int argc, char **argv) {
  if (argc != 4) {
    std::cerr << argv[0] << " FROMFILE TOFILE1 TOFILE2\n";
    return 1;
  }

  my_copy_file1(argv[1], argv[2]);
  my_copy_file2(argv[1], argv[3]);
}