簡體   English   中英

遍歷 c++ 中的字符串

[英]Looping through strings in c++

我有包含 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;
}

您沒有在 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;
}

您的錯誤是您忘記在循環中增加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++;
    }
}

在這里你可以看到我們測試stream的state后讀取。 但這會將所有有意義的代碼放在 if 分支中。 為什么不把它推出一個級別。

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

在這里,我們從文件中讀取了一個單詞。 如果有效則進入循環,否則不要。

這應該可以修復小文件的所有錯誤,但值得通過文件的 rest 來尋找不良做法和改進。

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

根據 RoQuOTriX 的回答,您需要增加 i,但您可能還想增加 count 以便知道您有多少單詞。 你也應該避免過度填充你的數組/

嘗試這個:

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

在這條線上:

    a[i] = x;

你使用i但它永遠不會增加。 而是這樣做:

    a[i++] = x;

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

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

這樣,您輸入文件的最后一個字符串將被寫入兩次。 這是因為您的檢查發生在您抓住最后一個x (2) 之前。 你需要做的是,

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

最后,如果輸入文件中有超過 100 個變量會怎樣? 你是否忽略了它們,或者你有沒有想過解決這個問題的方法? 在您提供的代碼中,您只會遇到分段錯誤。

您不需要再次實現所有內容。 這已經在 C++ 目錄中實現

#include <iostream>
#include <fstream>

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

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

希望這有效!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM