{ }codelper
文字列の置換P0055

すべて置き換える

一行目に文章 text、二行目に探す語 a、三行目に置き換える語 b が与えられる。
text の中の a をすべて b に置き換えた文章を出力せよ。
探すのは元の text の左から行い、一度置き換えた部分は再び探さない。
そのため "aaa" の "aa" を "b" にすると "ba"、"banana" の "a" を "aa" にすると "baanaanaa" になる。
a と b に含まれる記号(.
$ ( \ など)は特別な意味を持たず、その文字そのものである。
a がなければ text をそのまま出力する。

入力
text は空白(先頭と末尾にはない)と記号を含む ASCII 文字(32〜126)、長さ 1〜1,000。
a と b は空白のない ASCII 文字、長さ 1〜10
出力
置き換えた文章一行
例 1 · stdin
I like cats. cats are cute.
cats
dogs
stdout
I like dogs. dogs are cute.
例 2 · stdin
a.b.c
.
$$
stdout
a$$b$$c
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

「すべてを文字どおり」置き換える関数:Python text.replace(a, b)、Java text.replace(a, b)、C# text.Replace(a, b)(序数比較)、Craykon text.置き換え(a, b)。
落とし穴が多いのは JS と Java です。
① JS・TS の text.replace("cats", "dogs") は文字列を渡すと最初の一つだけ置き換えます。
② すべて置き換える replaceAll(a, b) も、置き換える語の中の $&(見つけた語)・$$(ドル一つ)を特殊パターンとして読むので "$$" が "$" に縮みます。
文字どおり置き換えるには text.split(a).join(b) か関数 () => b を渡します。
③ Java の replaceAll は名前に反して最初の値を正規表現として読むので、. はどの文字にも一致し、( は PatternSyntaxException、置き換える語の $1 はグループ参照エラーになります。
単にすべて置き換えるのは replace です。
C と C++ には置き換え関数がないので、strstr/find で探して前の部分 + b をつなぎ、見つけた語のすぐ後ろからまた探します。
置き換えた結果を先頭から探し直すと、"banana" の a → aa のように置き換える語が探す語を含むとき終わりません。

Pythonmain.py · 4 行
text = input()a = input()b = input()print(text.replace(a, b))
JavaScriptmain.js · 3 行
const [text, a, b] = require("fs").readFileSync(0, "utf8").split("\n").map((x) => x.replace(/\r$/, ""));// split/join은 글자를 그대로 쓴다(replaceAll의 둘째 값은 $& $$ 같은 특수 패턴을 해석한다)console.log(text.split(a).join(b));
TypeScriptmain.ts · 4 行
import { readFileSync } from "node:fs";const [text, a, b]: string[] = readFileSync(0, "utf8").split("\n").map((x) => x.replace(/\r$/, ""));// split/join은 글자를 그대로 쓴다(replaceAll의 둘째 값은 $& $$ 같은 특수 패턴을 해석한다)console.log(text.split(a).join(b));
JavaMain.java · 13 行
import java.io.BufferedReader;import java.io.InputStreamReader; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        String text = br.readLine();        String a = br.readLine();        String b = br.readLine();        // replace(CharSequence, CharSequence)는 글자 그대로, 모두 바꾼다(replaceAll은 정규식)        System.out.println(text.replace(a, b));    }}
C#Main.cs · 12 行
using System; class Program{    static void Main()    {        string text = Console.ReadLine();        string a = Console.ReadLine();        string b = Console.ReadLine();        Console.WriteLine(text.Replace(a, b));    }}
C++main.cpp · 18 行
#include <iostream>#include <string> int main() {    std::string text, a, b;    std::getline(std::cin, text);    std::getline(std::cin, a);    std::getline(std::cin, b);    std::string out;    size_t from = 0;    for (size_t at = text.find(a); at != std::string::npos; at = text.find(a, from)) {        out.append(text, from, at - from);        out += b;        from = at + a.size();    }    out.append(text, from, std::string::npos);    std::cout << out << "\n";}
Cmain.c · 23 行
#include <stdio.h>#include <string.h> static void read_line(char *buf, int size) {    if (!fgets(buf, size, stdin)) buf[0] = '\0';    buf[strcspn(buf, "\r\n")] = '\0';} int main(void) {    char text[1005], a[16], b[16];    read_line(text, sizeof text);    read_line(a, sizeof a);    read_line(b, sizeof b);    size_t m = strlen(a);    const char *p = text;    for (const char *q = strstr(p, a); q != NULL; q = strstr(p, a)) {        fwrite(p, 1, (size_t)(q - p), stdout);  /* 찾은 곳 앞까지 */        fputs(b, stdout);        p = q + m;                              /* 찾은 말 다음부터 다시 */    }    puts(p);    return 0;}
Craykonmain.cray · 4 行
text = コンソール.行読み();a = コンソール.行読み();b = コンソール.行読み();コンソール.書く(text.置き換え(a, b));