c++ - 如何获取C++中用逗号分隔的整数序列的最后一个整数?
问题描述
我要做的是从用逗号分隔的整数文件中获取每个整数并添加它们。例如,如果文件包含2,3,4,1
我的程序必须显示总和为 10。为此,我编写了以下代码。
int number_sum(const char* filename) {
std::ifstream file(filename);
if (file.is_open()) {
int sum = 0; //sum
char c; //Store each comma
int number = 0; //Store each number
while ( (file >> number >> c) && (c == ',') ) {
std::cout << "Adding up: " << number << " + " << sum << std::endl;
sum = sum + number;
}
std::cout << "Result is: " << sum << std::endl;
return sum;
}
else {
std::cout << "ERROR" << std::endl;
return -1;
}
这适用于除最后一位以外的所有数字。问题来了是因为最后一个后面没有逗号,所以程序没有搞定。我试图通过检查它是','还是EOF来区分“c”值,但这不起作用。有什么解决方案可以让我的程序获取最后一个数字并将其添加到其余数字中吗?(对不起我的英语,不是母语)。
非常感谢您提前。
解决方案
解析字符串比解析文件中的任意数据更容易。从文件中获取单行信息并将其存储到一个std::string
或读取所有文件并将内容保存到一个大文件buffer
或std::vector<std::string>>
. 然后在获得所需的所有信息后,关闭文件句柄,然后就可以进行解析了。
在一些人的帮助下,std libraries
您可以相当容易地做到这一点。我们还将使用辅助函数来分解文件中的文本行。
#include <numeric>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
std::vector<std::string> split( const std::string& s, char delimiter ) {
std::vector<std::string> tokens = {};
std::string token = {};
std::istringstream tokenStream( s ); // std::istringstream found in <sstream>
while( std::getline( tokenStream, token, delimiter ) ) {
tokens.push_back( token );
}
return tokens;
}
int number_sum( const char* filename ) {
// First try to open the file; if fails return -1
std::ifstream file;
file.open( filename );
if ( !file.is_open() ) {
std::cout << "failed to open file " << filename << '\n';
return -1;
}
// read a single line from the file and save it to a local string
std::string line = {};
std::getline( file, line );
// close the file
file.close();
// now parse the local string into string tokens and convert them to ints
std::vector<int> values = {};
std::vector<std::string> tokens = split( line, ',' );
for ( auto s : tokens ) {
values.push_back( std::stoi( s ) ); // std::stoi() found in <string>
}
// now that we have our vector of ints parsed from the strings we can add them together
// std::accumulate() found in <numeric>
return std::accumulate( values.begin(), values.end(), 0 );
}
int main() {
std::cout << number_sum( "test.txt" );
return 0;
}
测试.txt
2,3,4,1
输出
10
使用这种方法,您不必担心是否存在分隔符,这将适用于奇数和偶数类型的情况。stl
当您知道要使用哪些函数时,这就是库的力量。
现在这只会从您的输入文件中执行一行,但是可以扩展它以将文件中的多行与一个简单的 while 循环和一个额外的向量合并来存储每一行。不过,您可能必须更改此函数返回的内容。我会把这部分留给你作为练习。
在此答案的先前迭代中,我曾提到有一个错误并且我知道它是什么;当我最初发布它时,我正在编写一个辅助函数。只要逗号之间的值是单个数字字符,该程序对每个字符都可以正常工作,并且如果逗号之间有多个值,它将失败或中断。借助此辅助函数通过分隔符将字符串拆分为多个字符串,我们不必担心手动解析字符串中的每个字符,因为stl
库和函数将为我们完成此操作。此功能现在可以正常工作,并且适用于逗号之间的值超过一位的情况!
test.txt -第二次试用
23,32,46,11
输出
112
经过一番考虑,我清理了一下。我不喜欢这样一个事实,即进行累积的函数负责打开和读取文件中的内容,所以我将它移到了它自己的单独函数中。我还喜欢在运行时捕获错误并将它们显示到控制台的能力。最后,我重命名了一个函数,使其更具可读性。这是重构的程序:
#include <numeric>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <exception>
std::string readLineFromFile( const char* filename ) {
std::ifstream file( filename );
if ( !file ) {
std::stringstream stream;
stream << "failed to open file " << filename << '\n';
throw std::runtime_error( stream.str() );
}
std::string line;
std::getline( file, line );
file.close();
return line;
}
std::vector<std::string> splitString( const std::string& s, char delimiter ) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream( s );
while( std::getline( tokenStream, token, delimiter ) ) {
tokens.push_back( token );
}
return tokens;
}
int number_sum( const char* filename ) {
// Get contents from file
std::string line = readLineFromFile( filename );
// parse string
std::vector<int> values;
std::vector<std::string> tokens = splitString( line, ',' );
for( auto s : tokens ) {
values.push_back( std::stoi( s ) );
}
// return the accumulated value
return std::accumulate( values.begin(), values.end(), 0 );
}
int main() {
try {
std::cout << number_sum( "test.txt" ) << '\n';
// assuming there is no "test2.txt"
// this will throw a runtime error
// and display the appropriate message to the console
std::cout << number_sum( "test2.txt" ) << '\n';
} catch( const std::runtime_error& e ) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
推荐阅读
- python-3.x - 如何在同一行中获取 BeautifulSoup 信息?
- flutter - Inject Repository with BlocProvider in onGenerateRoute
- c# - .NET中奇怪的双减法结果
- sql - 我无法处理 SQL Server 中的 char(220) 或 SELECT 或 REPLACE 或任何其他函数
- xquery - arg1 不是 map:map marklogic 类型
- javascript - 在 $in 中使用变量
- java - Libgdx 动画内存泄漏
- google-analytics - Google Analytics (UA) 中的数据丢失了几天
- php - 从 JSON 获取数据并更新 CSV 文件的 PHP 脚本,CPU 使用率高
- python - 将 TensorFlow 和 Numpy 库添加到 osgeo/gdal docker 映像