{ }codelper
字符串下标P0192

纸条里的字母编号

朋友发来一张纸条,上面是一个长字符串和一串字母编号。
第一行给出由小写英文字母组成的字符串 s,第二行给出编号个数 q,第三行给出用空格隔开的 q 个编号。
编号 k 为正数时,表示 s 从前往后第 k 个字母。
第一个字母是第 1 个。
编号 k 为负数时,表示 s 从后往前第 -k 个字母。
最后一个字母是 -1,它前面的字母是 -2。
编号不会是 0,并且总是指向 s 里的字母。
按给出的顺序把编号所指的字母连起来,在一行中输出这个字符串。

输入
1 ≤ s 的长度 ≤ 1,000,s 只含小写字母,1 ≤ q ≤ 1,000,1 ≤ |k| ≤ s 的长度
输出
一行,由 q 个字母组成的字符串
样例 1 · stdin
secretnote
4
3 -3 7 -1
stdout
cone
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

"从前往后第 k 个"是人从 1 开始数的编号,而八种语言的字符串下标都从 0 开始。
所以正数在所有语言里都是 s[k - 1](Java 是 s.charAt(k - 1))。
从后往前数的编号各语言不同。
Python 的 s[-1] 本身就是最后一个字母,负数可以直接用。
这时如果也像正数那样减 1(s[k - 1]),每个字母都会错开一位。
C# 有带 ^ 的从末尾数的下标,如 s[^1]。
JS/TS 的 s[-1] 不报错而是给出 undefined,拼接后会混进 "undefined" 这几个字母。
s.at(-1) 才会从后往前数。
Java 的 charAt(-1) 会抛异常,C 的 s[-1] 和 C++ 的 s[-1] 读到数组外,是未定义行为。
Craykon 的 s[-1] 会以"只有 0~n 号"的运行错误停止。
在这些语言中要加上长度,写成 s[len + k](Craykon 写 s[s.长度 + k])。

Pythonmain.py · 9 行
s = input().strip()q = int(input())out = []for k in map(int, input().split()):    if k > 0:        out.append(s[k - 1])  # 앞에서 k번째 → 번호는 k - 1    else:        out.append(s[k])      # Python은 s[-1]이 맨 끝 글자print("".join(out))
JavaScriptmain.js · 9 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const s = lines[0].trim();const ks = lines[2].trim().split(/\s+/).map(Number);let out = "";for (const k of ks) {  // s[-1]은 undefined라서 음수는 길이를 더해 번호로 바꾼다(s.at(k)도 된다)  out += k > 0 ? s[k - 1] : s[s.length + k];}console.log(out);
TypeScriptmain.ts · 10 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const s = lines[0].trim();const ks: number[] = lines[2].trim().split(/\s+/).map(Number);let out = "";for (const k of ks) {  // s[-1]은 undefined라서 음수는 길이를 더해 번호로 바꾼다(s.at(k)도 된다)  out += k > 0 ? s[k - 1] : s[s.length + k];}console.log(out);
JavaMain.java · 17 行
import java.io.BufferedReader;import java.io.InputStreamReader; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        String s = in.readLine().trim();        in.readLine();        StringBuilder out = new StringBuilder();        for (String t : in.readLine().trim().split("\\s+")) {            int k = Integer.parseInt(t);            // charAt은 0부터, 음수는 받지 않는다 → 뒤에서 세면 길이를 더한다            out.append(k > 0 ? s.charAt(k - 1) : s.charAt(s.length() + k));        }        System.out.println(out);    }}
C#Main.cs · 19 行
using System;using System.Text; class Program{    static void Main()    {        string s = Console.ReadLine().Trim();        Console.ReadLine();        var sb = new StringBuilder();        foreach (string t in Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries))        {            int k = int.Parse(t);            // s[^m]은 뒤에서 m번째 글자(C# 8 이후) — ^1이 맨 끝            sb.Append(k > 0 ? s[k - 1] : s[^(-k)]);        }        Console.WriteLine(sb);    }}
C++main.cpp · 16 行
#include <iostream>#include <string> int main() {    std::string s, out;    int q;    std::cin >> s >> q;    int len = (int)s.size();    for (int i = 0; i < q; i++) {        int k;        std::cin >> k;        // s[-1]은 정해지지 않은 동작 → 뒤에서 세면 길이를 더한다        out += k > 0 ? s[k - 1] : s[len + k];    }    std::cout << out << '\n';}
Cmain.c · 19 行
#include <stdio.h>#include <string.h> int main(void) {    static char s[1001];    static char out[1001];    int q;    scanf("%1000s %d", s, &q);    int len = (int)strlen(s);    for (int i = 0; i < q; i++) {        int k;        scanf("%d", &k);        /* C 배열은 0부터, 음수 번호는 배열 밖을 읽는다 → 길이를 더해 바꾼다 */        out[i] = k > 0 ? s[k - 1] : s[len + k];    }    out[q] = '\0';    puts(out);    return 0;}
Craykonmain.cray · 16 行
s = 控制台.读行().去空白();q = 控制台.读行().转数字();ks = 控制台.读数字();out = "";遍历 (k 在 ks){    如果 (k > 0)    {        out = out + s[k - 1]; // 앞에서 k번째 → 번호는 k - 1    }    否则    {        out = out + s[s.长度 + k]; // s[-1]은 오류라서 길이를 더한다    }}控制台.输出(out);