Ввод файлов в C ++ - PullRequest
       51

Ввод файлов в C ++

0 голосов
/ 12 февраля 2012

Я некоторое время искал в Интернете, но все, что я могу найти для ввода файла в C ++, это когда вы знаете имя файла.

Я пытаюсь написать программу, которая добавит в файл 2 числа, которые больше 0, но без использования scanf или cin. Я хочу загрузить файл в память, но весь код, который я могу найти в этой ситуации, требует знания имени файла. Файл форматируется двумя целыми числами в одной строке, разделенными пробелом, и есть несколько строк целых чисел. Программа выведет сумму двух чисел. Я легко могу сделать это с помощью scanf, но если бы мне дали массивный файл, я бы захотел загрузить его в память (сохранить отображение на потом).

Загрузка файла в память доставляет мне неприятности, потому что я не знаю ни имени файла, ни того, как его найти, если только пользователь не введет имя файла (не произойдет). Я хочу, чтобы программа выполнялась так, но с использованием самых простых и базовых форм C ++ IO:

./myprog < boatloadofnumbers

Как мне запустить мою программу, чтобы взять все "номера загрузки" в виде файла, чтобы я мог использовать более простые функции, такие как read ()? (также, как называется вышеупомянутый метод? передача ввода?)

int main(){
    int a,b;
    while (scanf("%i,%i",&a,&b)>-1){
        printf("%i\n",(a+b));
    } //endwhile
    return 0;
} //endmain

Ответы [ 3 ]

1 голос
/ 12 февраля 2012

Когда программа вызывается, как вы указали, содержимое boatloadofnumbers может быть прочитано из std :: cin.

Этот метод называется перенаправление ввода и выполняется оболочкой, а не вашей программой.

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

0 голосов
/ 12 февраля 2012

Не совсем понятно, как вы собираетесь читать файл, когда вы не знаете имя файла. Предположительно, вы не знаете имя файла в время компиляции . Это нормально, вы можете получить это из командной строки в runtime , например:

./myprog boatloadofnumbers

Тогда ваше имя файла в argv[1], и вы можете получить к нему доступ, используя std::ifstream.

Если вы получаете ввод непосредственно на stdin через перенаправление (например, ./myprog < boatloadofnumbers), вам вообще не нужно имя файла, вы можете просто используйте std::cin.

Следующее main() будет иметь дело с обеими этими ситуациями:

int main(int argc, char* argv[])
{
    if (argc == 2)
    {
        std::cerr << "Reading from file" << argv[1] << std::endl;
        std::ifstream ifs(argv[1]);
        if (ifs)
        {
            sum_lines(ifs);
        }
        else
        {
            std::cerr << "Could not read from " << argv[1] << std::endl;
        }
    }
    else
    {
        std::cerr << "Reading from stdin" << std::endl;
        sum_lines(std::cin);
    }
}

Пример sum_lines() может выглядеть примерно так:

void sum_lines(std::istream& is)
{ 
    int first = 0, second = 0;
    std::string line = "";
    while (std::getline(is, line))
    {
        std::istringstream iss(line);
        if (is >> first >> second)
        {
            std::cout << first << " + " << second << " = " << first + second << std::endl;
        }
        else
        {
            std::cerr << "Could not parse [" << line << "]" << std::endl;
        }
    }
}

Это не имеет значения, откуда поступает ввод, так что вы можете легко ввести std::istringstream для модульного тестирования. Кроме того, это не считывает весь файл в память, только одну строку за раз, поэтому он должен иметь дело с averybigboatloadofnumbers.

0 голосов
/ 12 февраля 2012

С перенаправлением оболочки ваша программа может читать со стандартного ввода, что может быть желательным. Тем не менее, также может быть желательно читать из файла. Легко поддерживать оба:

cat data > ./prog
./prog < data

./prog -f data

Первые два схожи, и содержимое файла data доступно из стандартного ввода программы; третья строка просто передает аргумент командной строки. Вот как мы это поддерживаем:

#include <cstdio>
#include <cstring>

void process_input(std::FILE * fp)
{
    char buf[4];
    std::fread(buf, 4, 1, fp);
    // ...
}

int main(int argc, char * argv[])
{
    std::FILE * fp = stdin; // already open!

    if (argc >= 3 && 0 == std::strcmp(argv[1]. "-f"))
    {
        fp = std::fopen(argv[2], "rb");

        if (!fp)
        {
            std::fprintf(stderr, "Could not open file %s.\n", argv[2]);
            return 1;
        }
    }

    process_input(fp);

    if (fp != stdin) { std::fclose(fp); }
}

Эквивалентно, вы можете достичь чего-то похожего с iostreams, хотя и немного более круто иметь хорошую универсальную ссылку:

#include <fstream>

int main()
{
    std::ifstream ifp;

    if ( /* as before */ )
    {
        ifp.open(argv[2], std::ios::binary);
        if (!ifp) { /* error and die */ }
    }

    std::ifstream & infile = ifp ? ifp : std::cin;

    process_input(infile);
}
...