C ++文件读取程序在循环中递增变量错误
C++ File reading program incrementing variable wrong in loop
我正在做一个从文件中读取数据的作业,假定学生分数(我将在下面包括),然后我的程序应该输出 0-25、25 范围内的分数-50,依此类推,直到 200。当我 运行 我的代码时,我得到了疯狂的数字,例如,在 0-25 范围内有 120412409 个分数,但在 25-50 范围内有 none,并且75-100 大约 2000。我认为我的循环结构中存在错误,当它找到该范围的匹配项时错误地增加了变量,但我无法弄清楚。
我已经尝试过,但没有成功实现对函数范围的检查,但这似乎只会让事情变得更糟。
#include <iostream>
#include <fstream>
int main()
{
//Variable Declare
std::ifstream scores;
int tastyData;
int range0to24;
int range25to49;
int range50to74;
int range75to99;
int range100to124;
int range125to149;
int range150to174;
int range175to200;
//Opening File
scores.open("data.txt");
//Main Loop
while (scores.fail())
{
scores >> tastyData;
if (tastyData <= 24)
{
range0to24 = range0to24 + 1;
}
else if (tastyData <= 49 && tastyData > 24)
{
range25to49 = range25to49 + 1;
}
else if (tastyData <= 74 && tastyData > 49)
{
range50to74 = range50to74 + 1;
}
else if (tastyData <= 99 && tastyData > 74)
{
range75to99 = range75to99 + 1;
}
else if (tastyData <= 124 && tastyData > 99)
{
range100to124 = range100to124 + 1;
}
else if (tastyData <= 149 && tastyData > 124)
{
range125to149 = range125to149 + 1;
}
else if (tastyData <= 174 && tastyData > 149)
{
range150to174 = range150to174 + 1;
}
else if (tastyData <= 199 && tastyData > 174)
{
range175to200 = range175to200 + 1;
}
}
scores.close();
std::cout << range0to24 << "\n";
std::cout << range25to49 << "\n";
std::cout << range50to74 << "\n";
std::cout << range75to99 << "\n";
std::cout << range100to124 << "\n";
std::cout << range125to149 << "\n";
std::cout << range150to174 << "\n";
std::cout << range175to200 << "\n";
}
这是data.txt
76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167,
200, 175, 150, 87, 99, 129, 149, 176,
200, 87, 35, 157, 189
我希望程序输出每个范围内的条目数,例如
范围 0 到 24 = 1
范围 25 到 49 = 2
等等。
编辑:我的问题现已解决。初始化和解析是主要问题。感谢所有帮助过的人。
您还没有初始化您的变量,导致未定义的行为。由于您将它们用作计数器,因此您应该将它们显式初始化为零:
int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
int range75to99 = 0;
int range100to124 = 0;
int range125to149 = 0;
int range150to174 = 0;
int range175to200 = 0;
当你为一个变量分配内存而不给它一个值时,该值将是一个垃圾值。意思是你不能确定它。
在 C++ 中,你总是应该初始化你的变量。
此外,我猜你的意思是 while (!scores.fail())
而不是 while (scores.fail())
如果你想要另一种方式来排序你的分数,你可以这样做:
#include <iostream>
#include <map>
#include <vector>
int main()
{
int rangeStep = 10;
std::map<int, size_t> sortedScores;
std::vector<int> scores { 76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189 };
for (int score : scores)
{
++sortedScores[score / rangeStep];
}
for (const auto& element : sortedScores)
{
std::cout << "Range [" << element.first * rangeStep << "," << (element.first + 1) * rangeStep << "] => " << element.second << std::endl;
}
std::cin.get();
return 0;
}
输出
Range [10,20] => 1
Range [20,30] => 1
Range [30,40] => 1
Range [70,80] => 2
Range [80,90] => 3
Range [90,100] => 1
Range [100,110] => 1
Range [120,130] => 1
Range [130,140] => 1
Range [140,150] => 1
Range [150,160] => 4
Range [160,170] => 1
Range [170,180] => 3
Range [180,190] => 2
Range [200,210] => 3
你的文件解析也是错误的,你可以使用类似的东西:
std::vector<int> ReadScoresFromFile(const std::string& p_filename)
{
std::vector<int> result;
std::fstream file(p_filename);
std::string line;
while (getline(file, line))
{
std::stringstream linestream(line);
std::string value;
while (getline(linestream, value, ','))
{
result.push_back(std::atoi(value.c_str()));
}
}
return result;
}
并将结果存储到 std::vector<int> scores
变量中。
因为你不是在全局声明变量,所以你必须定义它们。
在您的计数器后添加 =0
或全局声明它们,但全局声明是不良编码习惯的一部分,因此请尽量避免它。
您的代码存在一些问题:
- 您的范围变量未初始化。您期望
? + 1
的结果是什么?
您可以通过在声明变量时初始化变量来解决此问题:
int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
...
- 您的 while 循环正在检查
scores.fail()
是否为真以继续,只有在打开文件失败时才会进入循环!
改用while (!scores.fail())
。
- 您的
if
else if
结构有一些冗余条件。
if (tastyData <= 24)
{
range0to24 = range0to24 + 1;
}
else if (tastyData <= 49 && tastyData > 24)
{
range25to49 = range25to49 + 1;
}
else if ...
如果输入第一个 if (tastyData <= 24)
,则将输入 else if
个块中的 none 个。如果第一个条件不成立,那么 tastyData
必然大于 24,因此下一个块的 tastyData > 24
条件是不必要的。这个逻辑一直向下级联,如果您使用 else if
.
,您只需要检查 tastyData
是否是下一个分数等级 <=
我还借此机会简化了您的代码,并展示了如何使用数组和一些整数数学来代替几个 hard-coded 分数变量和巨大的 if else if
结构。
#include <fstream>
#include <iostream>
#include <string>
int main()
{
// Set up the 'bins' for counting scores
int max = 200;
int binSize = 25;
int binCount = max / binSize;
int* bins = new int[binCount];
for (int i = 0; i < binCount; i++)
{
bins[i] = 0;
}
// Open the scores file
std::fstream scores("data.txt");
std::string line;
// Read each text line in the file
while (getline(scores, line))
{
std::stringstream linestream(line);
std::string value;
// Read each comma-separated value in a line
while (getline(linestream, value, ','))
{
int tastyData = std::atoi(value.c_str());
int index = (tastyData / binSize);
if (index >= binCount) continue;
bins[index]++;
}
}
scores.close();
for (int i = 0; i < binCount; i++)
{
std::cout << bins[i] << std::endl;
}
delete[] bins;
return 0;
}
*已更新以使用 Adrien Givry 的文件解析修复程序。
我正在做一个从文件中读取数据的作业,假定学生分数(我将在下面包括),然后我的程序应该输出 0-25、25 范围内的分数-50,依此类推,直到 200。当我 运行 我的代码时,我得到了疯狂的数字,例如,在 0-25 范围内有 120412409 个分数,但在 25-50 范围内有 none,并且75-100 大约 2000。我认为我的循环结构中存在错误,当它找到该范围的匹配项时错误地增加了变量,但我无法弄清楚。
我已经尝试过,但没有成功实现对函数范围的检查,但这似乎只会让事情变得更糟。
#include <iostream>
#include <fstream>
int main()
{
//Variable Declare
std::ifstream scores;
int tastyData;
int range0to24;
int range25to49;
int range50to74;
int range75to99;
int range100to124;
int range125to149;
int range150to174;
int range175to200;
//Opening File
scores.open("data.txt");
//Main Loop
while (scores.fail())
{
scores >> tastyData;
if (tastyData <= 24)
{
range0to24 = range0to24 + 1;
}
else if (tastyData <= 49 && tastyData > 24)
{
range25to49 = range25to49 + 1;
}
else if (tastyData <= 74 && tastyData > 49)
{
range50to74 = range50to74 + 1;
}
else if (tastyData <= 99 && tastyData > 74)
{
range75to99 = range75to99 + 1;
}
else if (tastyData <= 124 && tastyData > 99)
{
range100to124 = range100to124 + 1;
}
else if (tastyData <= 149 && tastyData > 124)
{
range125to149 = range125to149 + 1;
}
else if (tastyData <= 174 && tastyData > 149)
{
range150to174 = range150to174 + 1;
}
else if (tastyData <= 199 && tastyData > 174)
{
range175to200 = range175to200 + 1;
}
}
scores.close();
std::cout << range0to24 << "\n";
std::cout << range25to49 << "\n";
std::cout << range50to74 << "\n";
std::cout << range75to99 << "\n";
std::cout << range100to124 << "\n";
std::cout << range125to149 << "\n";
std::cout << range150to174 << "\n";
std::cout << range175to200 << "\n";
}
这是data.txt
76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189
我希望程序输出每个范围内的条目数,例如 范围 0 到 24 = 1 范围 25 到 49 = 2 等等。
编辑:我的问题现已解决。初始化和解析是主要问题。感谢所有帮助过的人。
您还没有初始化您的变量,导致未定义的行为。由于您将它们用作计数器,因此您应该将它们显式初始化为零:
int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
int range75to99 = 0;
int range100to124 = 0;
int range125to149 = 0;
int range150to174 = 0;
int range175to200 = 0;
当你为一个变量分配内存而不给它一个值时,该值将是一个垃圾值。意思是你不能确定它。 在 C++ 中,你总是应该初始化你的变量。
此外,我猜你的意思是 while (!scores.fail())
而不是 while (scores.fail())
如果你想要另一种方式来排序你的分数,你可以这样做:
#include <iostream>
#include <map>
#include <vector>
int main()
{
int rangeStep = 10;
std::map<int, size_t> sortedScores;
std::vector<int> scores { 76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189 };
for (int score : scores)
{
++sortedScores[score / rangeStep];
}
for (const auto& element : sortedScores)
{
std::cout << "Range [" << element.first * rangeStep << "," << (element.first + 1) * rangeStep << "] => " << element.second << std::endl;
}
std::cin.get();
return 0;
}
输出
Range [10,20] => 1
Range [20,30] => 1
Range [30,40] => 1
Range [70,80] => 2
Range [80,90] => 3
Range [90,100] => 1
Range [100,110] => 1
Range [120,130] => 1
Range [130,140] => 1
Range [140,150] => 1
Range [150,160] => 4
Range [160,170] => 1
Range [170,180] => 3
Range [180,190] => 2
Range [200,210] => 3
你的文件解析也是错误的,你可以使用类似的东西:
std::vector<int> ReadScoresFromFile(const std::string& p_filename)
{
std::vector<int> result;
std::fstream file(p_filename);
std::string line;
while (getline(file, line))
{
std::stringstream linestream(line);
std::string value;
while (getline(linestream, value, ','))
{
result.push_back(std::atoi(value.c_str()));
}
}
return result;
}
并将结果存储到 std::vector<int> scores
变量中。
因为你不是在全局声明变量,所以你必须定义它们。
在您的计数器后添加 =0
或全局声明它们,但全局声明是不良编码习惯的一部分,因此请尽量避免它。
您的代码存在一些问题:
- 您的范围变量未初始化。您期望
? + 1
的结果是什么?
您可以通过在声明变量时初始化变量来解决此问题:
int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
...
- 您的 while 循环正在检查
scores.fail()
是否为真以继续,只有在打开文件失败时才会进入循环!
改用while (!scores.fail())
。
- 您的
if
else if
结构有一些冗余条件。
if (tastyData <= 24)
{
range0to24 = range0to24 + 1;
}
else if (tastyData <= 49 && tastyData > 24)
{
range25to49 = range25to49 + 1;
}
else if ...
如果输入第一个 if (tastyData <= 24)
,则将输入 else if
个块中的 none 个。如果第一个条件不成立,那么 tastyData
必然大于 24,因此下一个块的 tastyData > 24
条件是不必要的。这个逻辑一直向下级联,如果您使用 else if
.
tastyData
是否是下一个分数等级 <=
我还借此机会简化了您的代码,并展示了如何使用数组和一些整数数学来代替几个 hard-coded 分数变量和巨大的 if else if
结构。
#include <fstream>
#include <iostream>
#include <string>
int main()
{
// Set up the 'bins' for counting scores
int max = 200;
int binSize = 25;
int binCount = max / binSize;
int* bins = new int[binCount];
for (int i = 0; i < binCount; i++)
{
bins[i] = 0;
}
// Open the scores file
std::fstream scores("data.txt");
std::string line;
// Read each text line in the file
while (getline(scores, line))
{
std::stringstream linestream(line);
std::string value;
// Read each comma-separated value in a line
while (getline(linestream, value, ','))
{
int tastyData = std::atoi(value.c_str());
int index = (tastyData / binSize);
if (index >= binCount) continue;
bins[index]++;
}
}
scores.close();
for (int i = 0; i < binCount; i++)
{
std::cout << bins[i] << std::endl;
}
delete[] bins;
return 0;
}
*已更新以使用 Adrien Givry 的文件解析修复程序。