我正在尝试从文本文件中读取并标记输入。我收到了一个分段错误,直到我意识到我忘了关闭我的ifstream。我添加了close调用,现在它无限循环。我现在只是想学习如何使用strtok,这就是为什么代码看起来并不完整。
void loadInstructions(char* fileName)
{
ifstream input;
input.open(fileName);
while(!input.eof());
{
string line;
getline (input,line);
char * lineChar = &line[0];
//instruction cmd; //This will be used later to store instructions from the parse
char * token;
token = strtok (lineChar," ");
// just trying to get the line number for now
int lineNumber = atoi(token);
cout << lineNumber << "\n";
}
input.close();
}
输入文件:(一行)
5 +8 0 0 25
答案 0 :(得分:5)
这while(input.good());
可能不是你想要的......
答案 1 :(得分:4)
使用此:
string line;
while(getline (input,line))
{
如果getline()有效,则输入循环 如果您尝试读取EOF,那么它将失败并且循环将退出。
所以这应该按预期说出来。
而不是使用不可移动的strtok()(损坏字符串)和atoi() 使用std :: stringstream
std::stringstream linestream(line);
int lineNumber;
linestream >> lineNumber; // reads a number from the line.
不要显式关闭()流(除非你想检测并纠正任何问题)。当对象在函数末尾超出范围时,文件将被关闭。
答案 2 :(得分:1)
您想使用eof()
而不是good()
。
答案 3 :(得分:0)
避免使用strtok
。还有其他方法来标记不需要被调用函数来修改字符串的字符串。它修改了它标记的字符串的事实也可能是导致循环的原因。
但更有可能的是,good()
成员不是正确的成员。请尝试!input.eof()
或类似,具体取决于您的需求。
答案 4 :(得分:0)
虽然你已经对你提出的问题得到了一些答案,但也许值得回答你应该关于你没有问过的代码的一些答案:
void loadInstructions(char* fileName)
由于该功能不会修改文件名,因此您几乎肯定希望将其更改为:
void loadInstructions(char const *fileName)
或
void loadInstructions(std::string const &fileName)
ifstream input;
input.open(fileName);
将这些结合起来要清晰得多:
ifstream input(fileName);
或(如果您传递了一个字符串):
ifstream input(fileName.c_str());
while(!input.eof());
这已经被涵盖了。
string line;
getline (input,line);
char * lineChar = &line[0];
//instruction cmd; //This will be used later to store instructions from the parse
char * token;
token = strtok (lineChar," ");
// just trying to get the line number for now
int lineNumber = atoi(token);
这大部分都是无关紧要的。您可以直接从原始输入转换atoi
:
string line;
getline(input, line);
int lineNumber = atoi(line);
如果您稍后要进行更多标记,则可以改为使用strtol
:
char *end_ptr;
int lineNumber = strtol(line, &end_ptr, 10);
这会将end_ptr
设置为刚好超过strtol
转换的部分的结尾。
我还考虑了另一种选择:将代码移动到一个类中读取和解析一行,并定义operator>>
来读取它们:
struct line {
int number;
operator int() { return number; }
};
std::istream &operator>>(std::istream &is, line &l) {
// Just for fun, we'll read the data in an alternative fashion.
// Instead of read a line into a buffer, then parse out the first number,
// we'll read a number from the stream, then ignore the rest of the line.
// I usually prefer the other way, but this is worth knowing as well.
is >> l.number;
// When you're ready to parse more, add the extra parsing code here.
is.ignore(std::numeric_limits<std::istream::pos_type>::max, '\n');
return is;
}
有了这个,我们可以很容易地打印出行号:
std::copy(std::istream_iterator<line>(input),
std::istream_iterator<line>(),
std::ostream_iterator<int>(std::cout, "\n"));
input.close();
我通常只是让它在超出范围时自动关闭。