总结数字字符串输入的最佳方法

Best way of summing up an input of string of numbers

本文关键字:最佳 方法 输入 字符串 数字 数字字符      更新时间:2023-10-16

问题

目前,我在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++) {

最后,此循环没有检查nnumbers.size()是否完全相关:

for (int j = 0; j < n; j++) {

所以你:

  • 使用错误的环条条件
  • 覆盖numbers的界限
  • 不了解或检查rawInput的内容
  • 不了解或检查格式的输入操作员的工作方式。

仅打印您的变量值(或在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中阅读它们,而且还必须有一个理由。(