{"id":"strings-parts","slug":"finding-parts","title":"Finding parts of a string","text":"`substring` cuts a piece out of a string. Like every String method, it gives back a new string and leaves the original whole.\n\n- `substring(start)` gives everything from the index `start` to the end.\n- `substring(start, end)` gives the characters from `start` up to, **but not including**, `end`.\n\n| Index | 0 | 1 | 2 | 3 | 4 | 5 |\n|---|---|---|---|---|---|---|\n| `\"carpet\"` | c | a | r | p | e | t |\n\n```java\nString word = \"carpet\";\nSystem.out.println(word.substring(3));\nSystem.out.println(word.substring(0, 3));\nSystem.out.println(word.substring(1, 4));\n```\n\n```output\npet\ncar\narp\n```\n\nBecause the end isn't included, `substring(start, end)` is always `end - start` characters long: `substring(1, 4)` has 3. An index past the end crashes the program with the same `StringIndexOutOfBoundsException` as `charAt`.\n\n### Searching in a string\n\n`indexOf` looks for a piece of text and returns the index where it first starts, or -1 when it isn't there. Together with `substring`, it cuts a string at a certain character, wherever that character happens to be:\n\n```java\nString email = \"ada@example.com\";\nint at = email.indexOf(\"@\");\nSystem.out.println(at);\nSystem.out.println(email.substring(0, at));\nSystem.out.println(email.substring(at + 1));\nSystem.out.println(email.indexOf(\"#\"));\n```\n\n```output\n3\nada\nexample.com\n-1\n```\n\nThree more methods answer yes-or-no questions with a `boolean`:\n\n```java\nString file = \"holiday-photo.jpg\";\nSystem.out.println(file.contains(\"photo\"));\nSystem.out.println(file.startsWith(\"holiday\"));\nSystem.out.println(file.endsWith(\".png\"));\n```\n\n```output\ntrue\ntrue\nfalse\n```\n\nAll of these count capitals: `\"Photo.JPG\".endsWith(\".jpg\")` is `false`. When capitals shouldn't matter, make the text small first: `file.toLowerCase().endsWith(\".jpg\")`.\n","task":"Fill in the numbers, so the program cuts `sun` and `flower` out of `sunflower`. It prints:\n\n```\nsun\nflower\n```\n","kind":"fill","seed":"public class Main {\n    public static void main(String[] args) {\n        String word = \"sunflower\";\n        System.out.println(word.substring([[0]], [[3]]));\n        System.out.println(word.substring([[3]]));\n    }\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        String word = \"sunflower\";\n        System.out.println(word.substring(0, 3));\n        System.out.println(word.substring(3));\n    }\n}\n","hints":["`sun` is at the indexes 0, 1 and 2. The end index is the first one that's *not* included.","`flower` starts at index 3 and goes on to the end, so it needs only the start."],"tests":[{"name":"Output","stdin":"","expect":"sun\nflower","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Read a file name with exactly one dot in it, such as `report.pdf`, and print the part before the dot and the part after it. For the input `report.pdf` the program prints:\n\n```\nName: report\nType: pdf\n```\n","kind":"code","seed":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        String file = scanner.nextLine();\n\n    }\n}\n","solution":"import java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        String file = scanner.nextLine();\n        int dot = file.indexOf(\".\");\n        System.out.println(\"Name: \" + file.substring(0, dot));\n        System.out.println(\"Type: \" + file.substring(dot + 1));\n    }\n}\n","hints":["`int dot = file.indexOf(\".\");` finds where the dot is.","The name is `file.substring(0, dot)`, and the type starts one after the dot: `file.substring(dot + 1)`."],"tests":[{"name":"Test 1","stdin":"report.pdf\n","expect":"Name: report\nType: pdf","hidden":false},{"name":"Test 2","stdin":"holiday.jpeg\n","expect":"Name: holiday\nType: jpeg","hidden":true},{"name":"Test 3","stdin":"a.b\n","expect":"Name: a\nType: b","hidden":true},{"name":"Test 4","stdin":"notes-2024.txt\n","expect":"Name: notes-2024\nType: txt","hidden":true}],"require":[{"pattern":"\\.indexOf\\s*\\(","message":"Find the dot with `indexOf`."},{"pattern":"\\.substring\\s*\\(","message":"Cut out the two parts with `substring`."}],"forbid":[]},{"task":"Write a method `fileKind(String fileName)` that returns `image` for names that end in `.jpg` or `.png`, `document` for names that end in `.pdf` or `.txt`, and `other` for anything else. Capitals don't matter: `Beach.JPG` is an image. The check runs `System.out.println(fileKind(\"Beach.JPG\"));` and expects:\n\n```\nimage\n```\n","kind":"code","seed":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(fileKind(\"Beach.JPG\"));\n    }\n\n    // Write the fileKind method here.\n}\n","solution":"public class Main {\n    public static void main(String[] args) {\n        System.out.println(fileKind(\"Beach.JPG\"));\n    }\n\n    public static String fileKind(String fileName) {\n        String name = fileName.toLowerCase();\n        if (name.endsWith(\".jpg\") || name.endsWith(\".png\")) {\n            return \"image\";\n        }\n        if (name.endsWith(\".pdf\") || name.endsWith(\".txt\")) {\n            return \"document\";\n        }\n        return \"other\";\n    }\n}\n","hints":["Make the name small first: `String name = fileName.toLowerCase();`. Then `.JPG` becomes `.jpg`.","`if (name.endsWith(\".jpg\") || name.endsWith(\".png\")) { return \"image\"; }`, the same for documents, and `return \"other\";` last."],"tests":[{"name":"System.out.println(fileKind(\"Beach.JPG\"));","stdin":"","call":"System.out.println(fileKind(\"Beach.JPG\"));\n","expect":"image","hidden":false},{"name":"System.out.println(fileKind(\"notes.txt\"));","stdin":"","call":"System.out.println(fileKind(\"notes.txt\"));\n","expect":"document","hidden":true},{"name":"System.out.println(fileKind(\"Report.PDF\"));","stdin":"","call":"System.out.println(fileKind(\"Report.PDF\"));\n","expect":"document","hidden":true},{"name":"System.out.println(fileKind(\"song.mp3\"));","stdin":"","call":"System.out.println(fileKind(\"song.mp3\"));\n","expect":"other","hidden":true},{"name":"System.out.println(fileKind(\"logo.png\"));","stdin":"","call":"System.out.println(fileKind(\"logo.png\"));\n","expect":"image","hidden":true},{"name":"System.out.println(fileKind(\"jpg-files.zip\"));","stdin":"","call":"System.out.println(fileKind(\"jpg-files.zip\"));\n","expect":"other","hidden":true}],"require":[{"pattern":"\\.endsWith\\s*\\(","message":"Check the end of the name with `endsWith`."}],"forbid":[]}]}