我正在用下面的代码为我的c++类做一个作业:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
string fileName;
string cheek,s;
long count;
ifstream input;
bool ask=1;
int main(){
while(ask){
cout<<"Enter a filename :n";
cin>>fileName;
cout<<"reading file...";
input.open(fileName);
if(input){
ask=0;
}
}
istringstream iss;
cout<<"dumping contents...";
while(getline(input,cheek)){
//
}
iss.str(cheek);
cout<<"parsing...";
while(iss.peek()!=EOF){
s=iss.peek();
if(s=="A"||s=="E"||s=="I"||s=="O"||s=="U"||s=="a"||s=="e"||s=="i"||s=="o"||s=="u"){
count++;
}
}
cout<<"nCOUNT="<<count<<"nresetting...n";
count=0;
iss.str("");
input.close();
fileName="";
cheek="";
s="";
}
由于某种原因,cin
无法识别当我清楚地按Enter键时。有解决这个问题的方法吗?
while(getline(input,cheek)){
只要while
循环条件计算为逻辑true
,这个while
循环将继续运行。每次调用getline()
时,读取文件中的下一行,并且getline()
返回true
。到达文件末尾后,getline()
最终返回false。
循环本身似乎没有发生任何事情:
//
}
就是这样。这就是整个循环。所以,用你自己的话,你能描述一下在这个循环中发生了什么吗?您可以给出的唯一答案是:在存储在cheek
变量中之后,已经读取了整个文件,并将其内容逐行丢弃。由于std::getline
所做的第一件事是擦除它作为参数获得的字符串,因此在整个过程结束时,您将始终以空cheek
结束,并且整个文件已被完全读取。
在这个循环之后,有一些代码似乎认为cheek
中有一些值得探索的东西,但是,由于上面概述的原因,那里没有任何东西。
这就是为什么所显示的代码没有完成任何任务。看起来您希望将后续逻辑放在中while
循环,而不是在它后面。要做到这一点,你所要做的就是遵循计算机编程的黄金法则:你的计算机总是精确地执行你让它做什么,而不是你想让它做什么"根据这条规则,您所要做的就是将逻辑的适当部分移到while循环本身中。
除了Sam回答中提到的问题之外,您还有许多其他问题。避免使用global变量。相反,声明所需范围内的所有变量。例如,你可以在main()
中包含所有的值,在while (getline ...
循环中包含一些值,例如
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(){
string fileName;
string cheek;
long count = 0, /* count must be initialized */
line = 0;
ifstream input;
正如评论中提到的,您的ask
变量是多余的。这没有错,但是你可以简单地通过不断循环来完成同样的事情,然后在收到良好的输入时break
读取循环,例如
while (true) {
cout << "Enter a filename : ";
cin >> fileName;
cout << "reading file...n";
input.open(fileName);
if (input){
break;
}
}
你的文件读取循环是相当笨拙的。您的循环条件是正确的,但是最好只是检查每行中的字符。您可以使用istringstream
,但不使用peek()
,而是简单地提取一个字符,然后根据元音列表检查该字符,例如
cout << "dumping contents...n";
while (getline(input, cheek)) {
char c;
istringstream iss (cheek);
cout << "parsing line " << (line++) << 'n';
while (iss >> c) {
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' ||
c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
}
你不会真的"抛弃";任何文件内容。如果您想转储每一行输入,请添加:
cout << input << 'n';
在cout << "parsing line ...
之前的文件读取循环中。
注意,增加了一个line
计数器,允许您报告检查的行数以及发现的元音数。行计数器可以用作简单的调试工具,以确认每行的解析,然后在不再需要时删除。最终输出可以是:
cout << "nLINES = " << line << " COUNT = " << count << 'n';
}
没有理由关闭文件或重置变量,因为您没有循环从另一个文件读取。
示例输入文件
$ cat dat/fleas2line.txt
my dog has fleas
my cat has none
使用/输出示例
$ ./bin/dumpfile
Enter a filename : dat/fleas2line.txt
reading file...
dumping contents...
parsing line 0
parsing line 1
LINES = 2 COUNT = 8
虽然在这个简短的赋值中没有什么区别,但请确保您阅读并理解为什么"使用命名空间std;"被认为是不好的实践?
如果你还有问题,请告诉我。完整的源代码如下:#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(){
string fileName;
string cheek;
long count = 0, /* count must be initialized */
line = 0;
ifstream input;
while (true) {
cout << "Enter a filename : ";
cin >> fileName;
cout << "reading file...n";
input.open(fileName);
if (input){
break;
}
}
cout << "dumping contents...n";
while (getline(input, cheek)) {
char c;
istringstream iss (cheek);
cout << "parsing line " << (line++) << 'n';
while (iss >> c) {
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' ||
c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
}
cout << "nLINES = " << line << " COUNT = " << count << 'n';
}