总结数字字符串输入的最佳方法
Best way of summing up an input of string of numbers
问题
目前,我在hackerrank上查看一个问题,其中输入的格式是:
4
6 7 8 9
基本上第一行指定输入整数的数量,第二行指定了以下所有整数。似乎很容易,但不确定为什么我的程序不起作用。
我的解决方案
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
int main(){
int n;
std::cin >> n;
// Get all the numbers
std::string rawInput;
std::cout << "we have reached here 1";
std::cin >> rawInput;
std::cout << "we have reached here 2";
std::vector<std::string> numbers;
std::string number = "";
for (int i = 0; i < rawInput.size(); i++) {
char c = rawInput[i];
if (c == ' ') {
numbers.push_back(number);
}
number += c;
}
// Get all the ints
int sum = 0;
std::cout << sum;
for (int j = 0; j < n; j++) {
sum += stoi(numbers[j]);
}
std::cout << sum;
return 0;
}
错误
现在我看不到调试cout
行:std::cout << "we have reached here 2";
。我不确定为什么是这种情况。
调试器输出
DB trace:
Reading symbols from solution...done.
[New LWP 18595]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000000000401042 in __gnu_cxx::__stoa<long, int, char, int> (
__idx=<optimized out>, __str=<optimized out>, __name=<optimized out>,
__convf=<optimized out>) at /usr/include/c++/6/ext/string_conversions.h:68
68 const _TRet __tmp = __convf(__str, &__endptr, __base...);
#0 0x0000000000401042 in __gnu_cxx::__stoa<long, int, char, int> (
__idx=<optimized out>, __str=<optimized out>, __name=<optimized out>,
__convf=<optimized out>) at /usr/include/c++/6/ext/string_conversions.h:68
#1 std::__cxx11::stoi (__base=10, __idx=0x0, __str=...)
at /usr/include/c++/6/bits/basic_string.h:5414
#2 main () at solution.cc:32
崩溃的直接原因是n
是正确的。您从未在代码中确认它,但是在numbers
迭代时继续使用它。然后,您覆盖numbers
并导致stoi
爆炸。
实际上,n
不是4!这只有1个,因为您的第二行输入被打破。只需打印出rawInput
的值,您就会看到。
要读取行6 7 8 9
,您需要std::getline(std::cin, rawInput)
。格式提取到std::string
(您现在正在使用(只会拔出第一个"令牌";即,仅6
。
但是,当切换到 std::getline
时,您 will 现在需要在拓扑排序的答案中探索的newline滑动滑稽动作,因为非格式提取不会以相同的方式跳过空格。
最后,将其添加到向量后,您永远不会清除number
,并且永远不会处理最终值。
我还建议在输出语句的末端添加一些新线。
这是一个固定程序:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
int main(){
int n;
std::cin >> n;
// Get all the numbers
std::string rawInput;
std::cin.ignore(256,'n');
std::getline(std::cin, rawInput);
std::vector<std::string> numbers;
std::string number = "";
for (size_t i = 0; i < rawInput.size(); i++) {
char c = rawInput[i];
if (c == ' ') {
numbers.push_back(number);
number = "";
}
number += c;
}
// One more! If there wasn't a space at the end of it.
if (!number.empty())
numbers.push_back(number);
// Get all the ints
int sum = 0;
for (size_t j = 0; j < numbers.size(); j++) {
sum += stoi(numbers[j]);
}
std::cout << sum << 'n';
}
(实时演示(
我实际上建议您只是坚持使用格式的提取,这要简单得多:
#include <vector>
#include <iostream>
#include <numeric>
#include <algorithm>
int main()
{
int n;
std::cin >> n;
// Get all the numbers
std::vector<int> numbers;
int temp;
while (std::cin >> temp)
numbers.push_back(temp);
const int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
std::cout << sum << 'n';
}
请注意,我们不再需要n
!但是,如果您想人为地将提取仅限于n
数字,则可以在while
循环中执行此操作。
(实时演示(
此行读取单个空间删除的令牌(请参阅文档(:
std::cin >> rawInput;
,此循环可用于该令牌中的每个字符一次,对于线上的每个整数(rawInput
都只包含第一个整数(
for (int i = 0; i < rawInput.size(); i++) {
最后,此循环没有检查n
和numbers.size()
是否完全相关:
for (int j = 0; j < n; j++) {
所以你:
- 使用错误的环条条件 覆盖
- 不了解或检查
rawInput
的内容 - 不了解或检查格式的输入操作员的工作方式。
numbers
的界限
仅打印您的变量值(或在GDB中检查它们(会显示 - 打印 we have reached here 1
不是的用处,而不是打印the value of rawInput is "6"
(这会给您一个非常强的提示(。
最重要的是,正确的代码实际上可以使用那些格式的输入操作员来完成大部分工作:
#include <iostream>
int main()
{
unsigned N = 0;
std::cin >> N;
if (!std::cin) return -1;
unsigned SUM = 0;
for (unsigned i = 0; i < N; ++i) {
unsigned val;
std::cin >> val;
if (!std::cin) return -2;
SUM += val;
}
std::cout << SUM << 'n';
}
我什至包括了样本错误检查,您可能可以从黑客测试中省略。它仍然比您的版本要短得多,更简单。
您使用的方法不正确!您假设该数字只有一个数字,而这可能总是不是这种情况。
您只需在for
循环中使用cin
,然后将所有数字存储在vector
中。
#include <iostream>
#include <vector>
int main() {
int n;
std::vector<int> numbers;
std::cin >> n;
for(int i=0;i<n;++i)
{
int no;
std::cin >> no;
numbers.push_back(no);
}
long sum = 0;
for (auto i : numbers)
sum += i;
std::cout << sum;
return 0;
}
输入
5
1 2 31 4 5
输出
43
哦,我一直都看到。微妙。
std::cin >> n;
仅在第一个int
中读取。它不会关注以后的结束。因此,当您准备在该字符串中阅读时,它将进入行的末端 - 第一行,其中有n
的一行。
修复:
std::cin >> n;
std::cin.ignore(256,'n'); //ignore up thru next 'n' or 256 chars, whichever is first
这跳过了线的结束,让您从下一个开始。
另一个修复程序,不太强大:
std::cin >> n;
std::cin.get(); //Gets the next char, which in this case happens to be 'n'
您还需要将std::cin >> rawInput;
更改为
char rawInputCharStar [SOMEBIGNUM];
std::cin.getline (rawInputCharStar,SOMEBIGNUM);
rawInput = rawInputCharStar
因此,它可以读取多个字符串。(我必须去char*,因为Getline期望char*。可能有一种更优雅的方式。(
当您进入for循环时,您会发现字符串中的数字不是字符串的 size ,因此您需要不同的界限。
(当然,我不知道您为什么不仅在ints中阅读它们,而且还必须有一个理由。(
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?