[英]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.