解析逗号分隔的数字(C++)
Parsing comma-delimited numbers in C++
我有一个简短的问题要问大家。我正在尝试编写一个简单的代码来从用户输入中提取数字并将它们保存到 int 数组中,但我很难弄清楚如何让它工作。下面显示的代码适用于个位数的数字,但不适用于超过 1 位的数字。
例如,如果用户输入:1,2,3,4,50,60,这就是我得到的:
Enter numbers (must be comma delimited): 1,2,3,4,50,60
My numbers are: 12345060
My parsed numbers are: 1
My parsed numbers are: 2
My parsed numbers are: 3
My parsed numbers are: 4
My parsed numbers are: 5
My parsed numbers are: 0
问题:如何修改这段简单的代码以准确捕获超过 1 位数字的数字?提前感谢!!
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
using namespace std;
// set up some variables
int numbers[100];
int main() {
// Enter numbers (comma delimited). Ex: 1,2,3,4,50,60<return>
cout << endl << endl << "Enter numbers (must be comma delimited): ";
string nums_in;
getline(cin, nums_in);
nums_in.erase(remove(nums_in.begin(), nums_in.end(), ','), nums_in.end()); // remove the unwanted commas
cout << "My numbers are: " << nums_in << endl;
// convert each char into int
for (int o = 0; o < 6; o++) {
istringstream buf(nums_in.substr(o,1));
buf >> numbers[o];
cout << "My parsed numbers are: " << numbers[o] << endl;
}
cout << endl << endl;
cout << "Done." << endl;
return 0;
}
在程序中,首先删除输入字符串中的"不需要的"逗号,然后遇到无法再区分输入行中的数字的问题。因此,似乎这些逗号毕竟不是不需要的。解决方案是逐步解析字符串,而无需先删除逗号,因为您需要它们来拆分输入字符串。下面是一个示例。
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
int main() {
// Enter numbers (comma delimited). Ex: 1,2,3,4,50,60<return>
std::cout << std::endl << std::endl << "Enter numbers (must be comma delimited): ";
std::string nums_in;
std::getline(std::cin, nums_in);
// Now parse
std::vector<int> data;
std::istringstream buf(nums_in);
while (!buf.eof()) {
int this_number;
buf >> this_number;
if (buf.bad()) {
std::cerr << "Number formatting error!n";
return 1;
}
data.push_back(this_number);
char comma = 0;
buf >> comma;
if (!buf.eof()) {
if (buf.fail()) {
std::cerr << "Could not read comma.n";
return 1;
}
if (comma!=',') {
std::cerr << "Found no comma but '" << comma << "' instead !n";
return 1;
}
}
}
std::cout << "My numbers are:";
for (auto a : data) {
std::cout << " " << a;
}
std::cout << std::endl;
std::cout << "Done." << std::endl;
return 0;
}
请注意,我没有使用"使用命名空间 std;",因为它被认为是不好的样式。此外,我使用了 C++11 功能来打印出值,并使用向量来存储数字 - 在您的代码中,键入包含 200 个数字的行会导致崩溃(或其他不良行为)。最后,解析错误处理尚未完成。使其完整和正确是留作练习。基于 istringstream 的方法的另一种方法是首先用逗号分隔行,然后使用 istringstreams 分别读取所有数字。
顺便说一句,你的问题非常实用,以至于它更适合标准的stackexchange站点 - 与计算机科学的联系非常弱。
要解决这类问题,您必须编写一个扫描仪。扫描程序将输入分解为令牌。一旦您能够将输入分解为令牌,您就可以检查令牌的顺序(请参阅解析器)。
在您的情况下,您有三个令牌: number
, comma
和 end
.有效输入的示例:number comma number end
。另一个例子:end
(空输入)。无效输入的示例:number number end
(数字之间没有逗号)。
下面是您问题的可能解决方案。 get_token
从输入中读取令牌,并将其存储在token
和number
全局中。 get_numbers
读取令牌,检查语法并将数字存储在numbers
中;数字计数存储在count
(也是全局变量)中。
#include <iostream>
#include <cctype>
enum { max_count = 100 };
int numbers[max_count];
int count;
enum token_type
{
token_unknwon,
token_end,
token_comma,
token_number
};
token_type token;
int number;
token_type get_token()
{
char c;
// get a character, but skip ws except newline
while ( std::cin.get( c ) && c != 'n' && std::isspace( c ) )
;
if ( ! std::cin || c == 'n' )
return token = token_end;
if ( c == ',' )
return token = token_comma;
if ( std::isdigit( c ) )
{
std::cin.unget();
std::cin >> number;
return token = token_number;
}
return token_unknwon;
}
enum error_type
{
error_ok,
error_number_expected,
error_too_many_numbers,
error_comma_expected
};
int get_numbers()
{
//
if ( get_token() == token_end )
return error_ok; // empty input
while ( true )
{
// number expected
if ( token != token_number )
return error_number_expected;
// store the number
if ( count >= max_count )
return error_too_many_numbers;
numbers[count++] = number;
// this might be the last number
if ( get_token() == token_end )
return error_ok;
// not the last number, comma expected
if ( token != token_comma )
return error_comma_expected;
// prepare next token
get_token();
}
}
int main()
{
//...
switch ( get_numbers() )
{
case error_ok: break;
case error_comma_expected: std::cout << "comma expected"; return -1;
case error_number_expected: std::cout << "number expected"; return -2;
case error_too_many_numbers: std::cout << "too many numbers"; return -3;
}
//
std::cout << count << " number(s): ";
for ( int i = 0; i < count; ++i )
std::cout << numbers[i] << ' ';
//...
return 0;
}
可以使用 std::getline 轻松完成此任务,以读取字符串中的整行,然后使用 std::istringstream 解析该字符串以提取单个数字并跳过逗号。
#include <iostream>
#include <sstream>
#include <vector>
using std::cout;
int main() {
// Enter numbers (comma delimited). Ex: 1,2,3,4,50,60<return>
cout << "nEnter numbers (must be comma delimited): ";
int x;
std::vector<int> v;
std::string str_in;
// read the whole line then use a stringstream buffer to extract the numbers
std::getline(std::cin, str_in);
std::istringstream str_buf{str_in};
while ( str_buf >> x ) {
v.push_back(x);
// If the next char in input is a comma, extract it. std::ws discards whitespace
if ( ( str_buf >> std::ws).peek() == ',' )
str_buf.ignore();
}
cout << "nMy parsed numbers are:n";
for ( int i : v ) {
cout << i << 'n';
}
cout << "nDone.n";
return 0;
}
嗯...在不删除逗号的情况下解析字符串怎么样?读取字符的字符串字符,将每个字符放在临时缓冲区中,直到点击逗号,然后将临时缓冲区转换为 int 并将其存储在向量中。清空临时缓冲区并重复。
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
// set up some variables
vector<int> numbers(0);
int main() {
// Enter numbers (comma delimited). Ex: 1,2,3,4,50,60<return>
cout << endl << endl << "Enter numbers (must be comma delimited): ";
string nums_in;
getline(cin, nums_in);
cout << "My numbers are: " << nums_in << endl;
string s_tmp = "";
int i_tmp;
for(vector<int>::size_type i = 0, len = nums_in.size(); i < len; i++){
if( nums_in[i] == ',' ){
if(s_tmp.size() > 0){
i_tmp = std::stoi(s_tmp);
numbers.push_back(i_tmp);
}
s_tmp = "";
}
else if( i == len-1){
s_tmp += nums_in[i];
i_tmp = std::stoi(s_tmp);
numbers.push_back(i_tmp);
cout << "My parsed numbers are:" << i_tmp << endl;
}
else {
s_tmp += nums_in[i];
}
}
cout << endl << endl;
cout << "Done." << endl;
return 0;
}
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 我想做一个彼此不同但重复出现的数字
- 将数字转换为字母(例如:123 转换为一二三)
- C++如何计算用户输入的数字中的偶数位数
- 如何在C++中确定文本文件中的元素是字符还是数字
- 打印数字图案
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 如何检查一个c++字符串中有多少相同的字符/数字
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 将数字打印成文字
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 在将数字随机生成为数组期间从内存输出随机数的数组