I am currently doing an assignment in C++ in which I have to load a bunch of data from a .txt
file into a linked list:
我目前正在C ++中进行一项任务,我必须将.txt文件中的一堆数据加载到链表中:
Here is my load code:
这是我的加载代码:
void record::load( string fileName ) throw( recordException )
{
ifstream inFile( fileName.c_str() );
string c;
string t;
double p;
int q;
node *tail;
while (!isEmpty())
{
remove( 1 );
}
size = 0;
if ( getline(inFile, c) ||getline(inFile,t)||inFile >> p>> q) // Is file empty?
{ // File not empty:
try
{
head = new node;
// Add the first integer to the list.
head->cat = c;
head->title = t;
head->price = p;
head->qty = q;
head->next = NULL;
tail = head;
size = size + 1;
inFile.skipws;
// Add remaining items to linked list.
while ( getline(inFile, c)||getline(inFile ,t)||inFile >> p>> q)
// while(inFile.getline(c,50)||inFile.getline(t,50)||inFile>>p>>q)
{
tail->next = new node;
tail = tail->next;
tail->cat = c;
tail->title = t;
tail->price = p;
tail->qty = q;
tail->next = NULL;
size = size + 1;
inFile.skipws;
} // end while
} // end try
catch (bad_alloc e)
{
throw recordException(
"recordException: restore cannot allocate memory.");
} // end catch
} // end if
inFile.close();
}
It works great, except for one issue: I get really weird numbers when I try to display the data that is loaded in my linked list.
它工作得很好,除了一个问题:当我尝试显示链接列表中加载的数据时,我得到了非常奇怪的数字。
This is what it looks like when my program runs:
这是我的程序运行时的样子:
Can anyone help me? What can I do to remove those numbers? Why do these numbers occur anyway?
谁能帮我?我该怎么做才能删除这些数字?为什么这些数字仍然存在?
I am using C++ Codeblocks 16.01, if that is of any help.
我正在使用C ++ Codeblocks 16.01,如果有任何帮助的话。
2 个解决方案
#1
0
Next time, don't use images, always copy/paste the actual text into your post instead.
下次,请不要使用图片,而是将实际文本复制/粘贴到帖子中。
Your reading code does not match the format of your input data. When you call getline()
, it reads until it encounters a line break or EOF.
您的阅读代码与输入数据的格式不匹配。当你调用getline()时,它会一直读到它遇到换行符或EOF。
So, the first call to getline(inFile, c)
reads the ENTIRE first line in one go:
因此,第一次调用getline(inFile,c)一次性读取整个第一行:
" DVD Snow White 20 20"
Then getline(inFile,t)
reads the NEXT line in one go:
然后getline(inFile,t)一次读取NEXT行:
" VCD Cinderella 10 10"
Then inFile >> p >> q
tries to parse the NEXT line and fails:
然后inFile >> p >> q尝试解析NEXT行并失败:
" MT Wonderworld 20 30"
Since MT
is not a double
and Wonderworld
is not an int
.
由于MT不是双倍而且Wonderworld不是int。
You need to read the file line-by-line, parsing each line individually, for example:
您需要逐行读取文件,分别解析每一行,例如:
#include <string>
#include <sstream>
void record::load( std::string fileName ) throw( recordException )
{
while (!isEmpty())
remove( 1 );
size = 0;
std::ifstream inFile( fileName.c_str() );
if (!inFile.is_open())
return;
std::string line;
std::string c;
char t[25+1] = {0}; // <-- use whatever your max title length actually is...
double p;
int q;
node *newNode;
while (std::getline(inFile, line)) // Is file empty?
{
std::istringstream iss(line);
if ((iss >> c) && iss.get(t, sizeof(t)) && (iss >> p >> qty))
{
try
{
newNode = new node;
newNode->cat = c;
newNode->title = t;
newNode->price = p;
newNode->qty = q;
newNode->next = NULL;
if (!head)
head = newNode;
if (tail)
tail->next = newNode;
tail = newNode;
++size;
}
catch (const bad_alloc &e)
{
throw recordException(
"recordException: restore cannot allocate memory.");
}
}
}
}
#2
0
Regular Expression is much more suitable for task like this. You can use something like:
正则表达式更适合这样的任务。您可以使用以下内容:
std::string test = " DVD Snow White 20 20";
std::regex re("\\s*(\\S+)\\s+(\\S.*\\S)\\s+(\\d+)\\s+(\\d+)");
std::smatch match;
if (std::regex_match(test, match, re)) {
for (size_t i = 0; i < match.size(); ++i) {
std::cout << "submatch " << i << ": \"" << match[i] << "\"\n";
}
}
So you could read file line by line and split it using that RE:
因此,您可以逐行读取文件并使用该RE拆分它:
std::regex re("\\s*(\\S+)\\s+(\\S.*\\S)\\s+(\\d+)\\s+(\\d+)");
std::string line;
while( std::getline( inFile, line ) ) {
std::smatch match;
if (!std::regex_match(test, match, re)) continue;
std::string cat = match[1].str();
std::string title = match[2].str();
double price = std::stod( match[3].str() );
int qty = std::stoi( match[4].str() );
// you insert your node into list here
}
Note: I made RE pattern based on your input - price contains only digits, no dot. If it is not the case you would need to modify RE accordingly.
注意:我根据您的输入制作了RE模式 - 价格只包含数字,没有点数。如果不是这种情况,则需要相应地修改RE。
#1
0
Next time, don't use images, always copy/paste the actual text into your post instead.
下次,请不要使用图片,而是将实际文本复制/粘贴到帖子中。
Your reading code does not match the format of your input data. When you call getline()
, it reads until it encounters a line break or EOF.
您的阅读代码与输入数据的格式不匹配。当你调用getline()时,它会一直读到它遇到换行符或EOF。
So, the first call to getline(inFile, c)
reads the ENTIRE first line in one go:
因此,第一次调用getline(inFile,c)一次性读取整个第一行:
" DVD Snow White 20 20"
Then getline(inFile,t)
reads the NEXT line in one go:
然后getline(inFile,t)一次读取NEXT行:
" VCD Cinderella 10 10"
Then inFile >> p >> q
tries to parse the NEXT line and fails:
然后inFile >> p >> q尝试解析NEXT行并失败:
" MT Wonderworld 20 30"
Since MT
is not a double
and Wonderworld
is not an int
.
由于MT不是双倍而且Wonderworld不是int。
You need to read the file line-by-line, parsing each line individually, for example:
您需要逐行读取文件,分别解析每一行,例如:
#include <string>
#include <sstream>
void record::load( std::string fileName ) throw( recordException )
{
while (!isEmpty())
remove( 1 );
size = 0;
std::ifstream inFile( fileName.c_str() );
if (!inFile.is_open())
return;
std::string line;
std::string c;
char t[25+1] = {0}; // <-- use whatever your max title length actually is...
double p;
int q;
node *newNode;
while (std::getline(inFile, line)) // Is file empty?
{
std::istringstream iss(line);
if ((iss >> c) && iss.get(t, sizeof(t)) && (iss >> p >> qty))
{
try
{
newNode = new node;
newNode->cat = c;
newNode->title = t;
newNode->price = p;
newNode->qty = q;
newNode->next = NULL;
if (!head)
head = newNode;
if (tail)
tail->next = newNode;
tail = newNode;
++size;
}
catch (const bad_alloc &e)
{
throw recordException(
"recordException: restore cannot allocate memory.");
}
}
}
}
#2
0
Regular Expression is much more suitable for task like this. You can use something like:
正则表达式更适合这样的任务。您可以使用以下内容:
std::string test = " DVD Snow White 20 20";
std::regex re("\\s*(\\S+)\\s+(\\S.*\\S)\\s+(\\d+)\\s+(\\d+)");
std::smatch match;
if (std::regex_match(test, match, re)) {
for (size_t i = 0; i < match.size(); ++i) {
std::cout << "submatch " << i << ": \"" << match[i] << "\"\n";
}
}
So you could read file line by line and split it using that RE:
因此,您可以逐行读取文件并使用该RE拆分它:
std::regex re("\\s*(\\S+)\\s+(\\S.*\\S)\\s+(\\d+)\\s+(\\d+)");
std::string line;
while( std::getline( inFile, line ) ) {
std::smatch match;
if (!std::regex_match(test, match, re)) continue;
std::string cat = match[1].str();
std::string title = match[2].str();
double price = std::stod( match[3].str() );
int qty = std::stoi( match[4].str() );
// you insert your node into list here
}
Note: I made RE pattern based on your input - price contains only digits, no dot. If it is not the case you would need to modify RE accordingly.
注意:我根据您的输入制作了RE模式 - 价格只包含数字,没有点数。如果不是这种情况,则需要相应地修改RE。