我有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;
}
答案 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();
}
希望这行得通!