Цикл по строкам в с ++ - PullRequest
       3

Цикл по строкам в с ++

0 голосов
/ 18 октября 2019

У меня есть текстовый файл, в котором есть n слов. Я пытаюсь прочитать и распечатать с помощью C ++. Но я могу печатать только последнюю строку. Пожалуйста, помогите мне

int main()
{
    ifstream inFile;
    inFile.open("test.txt");

    if (inFile.fail()) {

        cerr << "Error opening file" << endl;

        exit(1);
    }

    string x;
    string a[100];
    int count = 0, i = 0;

    while (!inFile.eof()) {
        inFile >> x;
        a[i] = x;
        count++;
    }

    for (i = 0; i < 100; i++) {
        cout << a[i];
    }

    return 0;
}

Ответы [ 6 ]

3 голосов
/ 18 октября 2019

Вы не увеличивали переменную i в цикле while, поэтому присваиваете и перезаписываете всегда первый элемент:

int main() {

    ifstream inFile;
    inFile.open("test.txt");


    if(inFile.fail()) {

        cerr << "Error opening file"<< endl ;

        exit(1);
    }

    string x;
    string a[100];
    int count=0,i=0;

    while( !inFile.eof()) {
        inFile >> x;
        a[i]=x;
        i++; // i think you meant i++ not count++
    }

    for (i=0;i<100;i++){
        cout<< a[i];
    }

    return 0;
}
1 голос
/ 18 октября 2019

Ваша ошибка в том, что вы забыли увеличить i в цикле:

while (!inFile.eof()) {
    inFile >> x;
    a[i] = x;

    // You don't increment the `i`
    // That is why you only see the last word.

    count++;
}

Но этого недостаточно, есть еще одна ошибка, которая ранее была скрыта.

while (!inFile.eof()) {  // The last read read up to but not past the eof
                         // So the eof() is still false but there are no
                         // words left in the file.

    inFile >> x;         // So this read will fail

    a[i++] = x;          // Even though your read failed you still
                         // Add it to the array.

    count++;
}

Давайте исправим эту ошибку, проверив, работает ли чтение.

while (!inFile.eof()) {
    if (inFile >> x) {
        a[i++] = x;

        count++;
    }
}

Здесь вы можете увидеть, как мы проверяем состояние потока после чтения. Но это помещает весь значимый код в ветвь if. Почему бы просто не выдвинуть это на один уровень.

while (inFile >> x) {
    a[i++] = x;
    count++;
}

Здесь мы читаем слово из файла. Если это работает, войдите в цикл, в противном случае - нет.

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

// You don't show your headers.
// You should include them.
// Also through the code you don't use `std::` objects with the prefix. This means
// your code contains a `using namespace std;` I know all the books use this
// but it is considered exceedingly bad practice in real code. You should
// avoid it (even for small programs as the habit may cause you to use it
// large programs).
int main()
{
    // Not sure why you want to take two lines here?
    // There is a constructor that takes a file name.
    ifstream inFile;
    inFile.open("test.txt");


    // The stream object when used by itself in a boolean context
    // (i.e. when used in an if expression like here. Will convert itself
    // to bool checking the current state. So you don't need to explicitly
    // call the `fail()` method.
    if (inFile.fail()) {

        // It's not going to make much difference here.
        // But in general you should prefer to use '\n' unless you 
        // absolutely must force a flush of the stream (which generally is no
        // as the stream will flush itself at the most appropriate time). In
        // this case it is also useless as `cerr` is unbuffered and `exit()`
        // would force a flush of any other buffers.
        cerr << "Error opening file" << endl;

        exit(1);
    }

    string x;
    // You only ever have 100 words in the input file?
    // Arrays are not resizable and force the initialization of all members.
    // So this will either be too little space and you will overflow (or need
    // to add specific code to check for overflow and prevent it) or it is
    // way too much space and you have needlessly constructed all those objects.
    //
    // For dynamic array like storage prefer std::vector
    string a[100];

    // Come on. Every coding standard in the world says one variable per line.
    // A lot of people are fine with short variables like `i` but I prefer
    // to use meaningful names for all variables. Especially if the code
    // may grow in the future.
    int count = 0, i = 0;

    // This `while (!inFile.eof())` is WRONG and an anti-pattern.
    //
    // Testing for `eof` here will find the EOF after the you
    // have read the last word from the file. Remember the last
    // read will read up to but not past the eof. So when your read
    // in the loop reads the last word `eof()` is still false.
    // So now you will re-enter the loop and try and read past the
    // end and the read will fail. Since the read fails `x` is
    // unchanged and the last word will be added to `a` twice.
    //
    // The correct way to do this is to read in the while condition.
    //     while(inFile >> x) {
    //
    // This will read a word from the file and return the stream to
    // be used in a bool context (which will be true if you read a
    // word correctly from the stream). So what this does is try
    // and read a word if it works enter the loop if it fails (i.e.
    // you reach the end of the file) the loop will not be entered
    // as the stream object returned is in a bad state with eof set
    while (!inFile.eof()) {
        inFile >> x;   // read a string
        a[i] = x;      // Copy the string
                       // You can do this in a single line
                       // inFile >> a[i]

        // You don't increment the `i`
        // That is why you only see the last word.

        // Whats the difference between `count` and `i`?
        count++;
    }
    // That was a nice loop but with a vector you can read the whole
    // file into the vector in a single line.
    // std::vector<std::string> a(std::istream_iterator<std::string>(inFile),
    //                            std::istream_iterator<std::string>());


    // Here `i` is normal and OK (single line loop variable).
    for (i = 0; i < 100; i++) {
        cout << a[i]; // No space between words?
    }

    // But you can declare it as part of the for loop and prevent it leaking
    // into the scope of the rest of your code.
    //     for(int i = 0; i < count; ++i) {
    //
    // Note 1: declare and initialize.
    // Note 2: the number of words read is not 100 but count.
    // Note 3: Prefer the prefix increment ++i
    //         It makes no difference here. But when using some objects it
    //         can. A lot of C++ code is changed simply by changing the type
    //         of the variables. So if you use the most efficient version of
    //         the code in all contexts then it will remain the most
    //         efficient even after maintenance.
    //
    // In C++ we usually loop over containers using begin() and end()
    // to get iterators. This make sit easy to convert to standard
    // algorithms if we need to. This is easier when you use a container
    // rather than an array as they maintain an accurate end. But it can
    // be done with arrays.
    //     for(auto loop = std::begin(a); loop != std::end(a); ++loop) {
    //
    // Also note that in modern C++ you can use `range based for`.
    // So it will find the begin and end of the array for you.
    //     for(auto const& obj: a) {
    //
    // More useful for std::vector than an array but worth mentioning.
    // It allows things like the trick I do with creating the vector
    // directly from the file as the vector can be constructed using
    // iterators and the iterator library has input iterators that
    // work on streams.


    // Not required in main()
    // If your application can not fail then prefer to not return
    // anything.
    return 0;
}

Я бы написал так:

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

int main()
{
    std::ifstream inFile("test.txt");

    if (!inFile) {
        std::cerr << "Error opening file" << "\n";
        exit(1);
    }

    std::vector<std::string> data(std::istream_iterator<std::string>(inFile),
                                  std::istream_iterator<std::string>());

    for(auto const& word: data) {
        std::cout << word << "\n";
    }
}
0 голосов
/ 18 октября 2019

Вам не нужно реализовывать все заново. Это уже реализовано в каталоге C ++

#include <iostream>
#include <fstream>

int main()
{
    std::ifstream f("file.txt");

    if (f.is_open())
        std::cout << f.rdbuf();
}

Надеюсь, что это работает !!

0 голосов
/ 18 октября 2019

В этой строке:

    a[i] = x;

Вы используете i, но оно никогда не увеличивается. Вместо этого сделайте:

    a[i++] = x;
0 голосов
/ 18 октября 2019

Другая часть, которая требует внимания, - это цикл , в то время как .

while( !inFile.eof() ) {
        inFile >> x;            (2)
        a[i]=x;
        i++; 
   }

Таким образом, последняя строка вашего входного файла будет записана дважды. Это потому, что ваш чек происходит до того, как вы схватите последнего x (2). Что вам нужно сделать, это,

 while( inFile >> x ) {
            a[i++] = x;
            count ++;
       }

Наконец, что произойдет, если во входном файле более 100 переменных? Ты их игнорируешь или подумала, как с этим справиться? В коде, который вы даете, вы просто получите ошибку сегментации.

0 голосов
/ 18 октября 2019

Вам необходимо увеличить i согласно ответу RoQuOTriX, но вы, вероятно, также хотите увеличить счетчик, чтобы знать, сколько слов у вас есть. Также вам следует избегать переполнения массива /

Попробуйте это:

int main() {

    ifstream inFile;
    inFile.open("test.txt");


    if(inFile.fail()) {

        cerr << "Error opening file"<< endl ;

        exit(1);
    }

    string x;
    string a[100];
    int count=0,i=0;

    while( (!inFile.eof()) && (count<100))   // avoid array overrun!
        inFile >> x;
        a[i]=x;
        i++; // i think you meant i++ not count++ (as per RoQuOTriX)
        count++;    // as per your original answer
    }

    for (i=0;i<count;i++){      //  only show values you actually read!
        cout<< a[i];
    }

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...