在C ++中循环遍历字符串

时间:2019-10-18 07:46:47

标签: c++ string loops

我有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 个答案:

答案 0 :(得分:3)

您没有在while循环中增加i变量,因此始终分配和覆盖第一个元素:

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 :(得分:1)

您的错误是您忘记在循环中增加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";
    }
}

答案 2 :(得分:0)

根据RoQuOTriX的答案,您需要增加i,但您可能还想增加计数,以便知道您有多少个单词。另外,您应该避免过度填充数组/

尝试一下:

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;
}

答案 3 :(得分:0)

在这一行:

    a[i] = x;

您使用i,但从未增加。而是:

    a[i++] = x;

答案 4 :(得分:-1)

另一个需要注意的部分是您的 while 循环。

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

这样,输入文件的最后一个字符串将被写入两次。这是因为您的检查发生在您抓住最后一个 x (2)之前。 您需要做的是

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

最后,如果输入文件中的变量超过100个,会发生什么?您是否忽略了它们,或者您是否想过一种解决方法?在您提供的代码中,您只会遇到分段错误。

答案 5 :(得分:-1)

您不需要再次实施所有操作。这已经在C ++目录中实现

#include <iostream>
#include <fstream>

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

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

希望这行得通!