[RC-02] 求和

GitHub跳转原题关系图返回列表

逐行扫描字符串,按“后面是数字且前面不是数字”的规则识别负号并提取所有整数求和。

OJ: luogu

题目 ID: P6051

难度:普及-

标签:字符串模拟

日期: 2026-06-19 10:38

题意

给出若干行字符串,每行中可能夹杂着一些整数。

要求对每一行分别求出其中所有整数的和;如果某一行没有整数,就不输出这一行。

思路

这题最关键的是判断 - 是负号还是分隔符。

最直接的教学版写法如下:

cpp
// brute.cpp:逐字符扫描每一行,识别其中的整数并求和,作为教学版和对拍基准程序。
#include <bits/stdc++.h>
using namespace std;

bool is_digit_char(char ch) {
    return ch >= '0' && ch <= '9';
}

// 只有“-后面紧跟数字,且前面不是数字”时,才把它看成负号。
bool is_negative_sign(const string &s, int i) {
    if (s[i] != '-') {
        return false;
    }
    if (i + 1 >= (int) s.size() || !is_digit_char(s[i + 1])) {
        return false;
    }
    if (i > 0 && is_digit_char(s[i - 1])) {
        return false;
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string line;
    while (getline(cin, line)) {
        if (!line.empty() && line.back() == '\r') {
            line.pop_back();
        }

        long long sum = 0;
        bool has_number = false;
        int n = (int) line.size();
        int i = 0;

        while (i < n) {
            if (is_digit_char(line[i]) || is_negative_sign(line, i)) {
                int sign = 1;
                if (line[i] == '-') {
                    sign = -1;
                    i++;
                }

                long long value = 0;
                while (i < n && is_digit_char(line[i])) {
                    value = value * 10 + (line[i] - '0');
                    i++;
                }

                sum += sign * value;
                has_number = true;
            }
            else {
                i++;
            }
        }

        if (has_number) {
            cout << sum << '\n';
        }
    }

    return 0;
}

一个 - 只有在下面这种情况下才算负号:

  1. 后面紧跟数字;
  2. 前面不是数字。

于是我们逐行扫描字符串:

  • 如果当前位置是数字,开始读一个正整数;
  • 如果当前位置是合法负号,开始读一个负整数;
  • 读完后加入当前行总和。

扫描结束时,如果这行至少出现过一个整数,就输出总和。

代码

cpp
#include <bits/stdc++.h>
using namespace std;

bool is_digit_char(char ch) {
    return ch >= '0' && ch <= '9';
}

bool is_negative_sign(const string &s, int i) {
    if (s[i] != '-') {
        return false;
    }
    if (i + 1 >= (int) s.size() || !is_digit_char(s[i + 1])) {
        return false;
    }
    if (i > 0 && is_digit_char(s[i - 1])) {
        return false;
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string line;
    while (getline(cin, line)) {
        if (!line.empty() && line.back() == '\r') {
            line.pop_back();
        }

        long long sum = 0;
        bool has_number = false;
        int n = (int) line.size();
        int i = 0;

        while (i < n) {
            if (is_digit_char(line[i]) || is_negative_sign(line, i)) {
                int sign = 1;
                if (line[i] == '-') {
                    sign = -1;
                    i++;
                }

                long long value = 0;
                while (i < n && is_digit_char(line[i])) {
                    value = value * 10 + (line[i] - '0');
                    i++;
                }

                sum += sign * value;
                has_number = true;
            }
            else {
                i++;
            }
        }

        if (has_number) {
            cout << sum << '\n';
        }
    }

    return 0;
}

复杂度

  • 时间复杂度:O(n)O(n)n 为总字符数
  • 空间复杂度:O(1)O(1)(不计输入存储)

总结

这题是典型的字符串提取整数问题。

关键不是加法本身,而是把整数边界和负号规则判断准确。