回答編集履歴

2

ご指摘を受けての修正

2021/09/16 08:38

投稿

BeatStar
BeatStar

スコア4962

test CHANGED
@@ -232,7 +232,15 @@
232
232
 
233
233
 
234
234
 
235
- 要するに「nextメソッドは『次の空白まで』か『改行まで』」ですね。(空白無しだと改行まで)
235
+ ~~要するに「nextメソッドは『次の空白まで』か『改行まで』」ですね。(空白無しだと改行まで)~~
236
+
237
+
238
+
239
+ > 完全なトークンの前後には、区切り文字パターンに一致する入力が配置されます
240
+
241
+
242
+
243
+ とあるので、「次の区切り文字まで」となりますね。
236
244
 
237
245
 
238
246
 
@@ -240,7 +248,7 @@
240
248
 
241
249
 
242
250
 
243
- ```xoxxoxo``` のように、『空白を含んでいない』ですね。そうなると、やっぱり『改行までを一つとして読み込む』という感じになってしまいます。
251
+ ```xoxxoxo``` のように、『区切り文字を含んでいない』ですね。そうなると、やっぱり『改行までを一つとして読み込む』という感じになってしまいます。
244
252
 
245
253
 
246
254
 

1

質問本文にあるコードが修正されたので、それに対しての本回答の修正と追記

2021/09/16 08:38

投稿

BeatStar
BeatStar

スコア4962

test CHANGED
@@ -18,35 +18,45 @@
18
18
 
19
19
  public static void main(String[] args){
20
20
 
21
- // char型配列sを要素数7で確保
21
+   // char型配列sを宣言し、要素数7とする
22
22
 
23
23
  char[] s = new char[7];
24
24
 
25
+ // Scannerクラスのオブジェクトを生成(つまり, コンソールから読み込めるようにする)
26
+
27
+ Scanner scan = new Scanner(System.in);
28
+
29
+ // コンソールから整数一個を取り出す
30
+
31
+ int n = scan.nextInt();
32
+
33
+
34
+
25
- // 7回ループ
35
+ // 7回繰り返す
26
36
 
27
37
  for(int i=0; i<7; i++){
28
38
 
29
-   // 取得
39
+ // 現在のsの場所に入れていく
30
40
 
31
41
  s[i] = scan.next().charAt(0);
32
42
 
33
43
  }
34
44
 
35
-   // char型配列に設定
45
+
36
-
37
- char[] s = scan.next().toCharArray();
46
+
38
-
39
-  // n-1番目の値がoなら
47
+ // (n-1)番目が 'o'なら
40
48
 
41
49
  if(s[n-1] == 'o'){
42
50
 
43
-   // Yes表示
51
+ // "Yes"と表示
44
52
 
45
53
  System.out.println("Yes");
46
54
 
47
- }else{ // それ以外なら
55
+ // それ以外なら
56
+
48
-
57
+ }else{
58
+
49
-   // No表示
59
+ // "No"と表示
50
60
 
51
61
  System.out.println("No");
52
62
 
@@ -64,47 +74,29 @@
64
74
 
65
75
 
66
76
 
67
- …あれ、これ、本当にこのコードでしょうか。そもそも実行時どころか、コンパイルエラーになるはずですが。
68
-
69
-
70
-
71
- 少なくとも、char[] s が2回宣言されている。これだとコンパイラとかがどっちを呼んでいるのかわからなくなるため、エラーになるはず。
72
-
73
-
74
-
75
- それに、n-1 番目にアクセスしようとしているが、どこにもnらしきものが無いし、
76
-
77
- 読み込んでもいない。
78
-
79
-
80
-
81
- 仮にこれらを解決しても、別の問題がある。
82
-
83
-
84
-
85
- まずはそこを考えてください。
86
-
87
-
88
-
89
- そして、先程のコメントを書き出す。それを**擬似コード**とでも呼びましょうか。
77
+ そして、のコメントを書き出す。それを**擬似コード**とでも呼びましょうか。
90
78
 
91
79
 
92
80
 
93
81
  ```ここに言語を入力
94
82
 
95
- 1. 配列sを宣言し、要素数は7
83
+ 1. 配列sを用意し、要素数は7とする
84
+
96
-
85
+ 2. Scannerのオブジェクトを生成(= コンソールから読み込めるようにする)
86
+
87
+ 3. コンソールから整数一個分を取り出す
88
+
97
- 2. 配列に突っ込んでいく
89
+ 4. 以下を7回繰り返す
98
-
90
+
99
- 3. 配列sに入れ
91
+ 4.1. コンソールから読み取って、現在のsの場所に入れていく
100
-
92
+
101
- 4. n-1番目がoなら
93
+ 5. n-1番目が'o'なら
102
-
94
+
103
- 4.1. Yes
95
+ 5.1. "Yes"と表示
104
-
96
+
105
- 5. それ以外なら
97
+ 6. それ以外( 'o'以外 )なら
106
-
98
+
107
- 5.1. No
99
+ 6.1. "No"と表示
108
100
 
109
101
  ```
110
102
 
@@ -123,3 +115,217 @@
123
115
 
124
116
 
125
117
  「**プログラムは魔法でもなんでもなく、現実世界でのシミュレーションである**」です。
118
+
119
+
120
+
121
+ で、この疑似コードではなんら問題がなさそうです。
122
+
123
+ でも明らかに問題がある。
124
+
125
+
126
+
127
+ ということで、コードに戻ってみましょうか。
128
+
129
+
130
+
131
+ 疑似コードでいう(1)~(3)はなんら問題がありませんね。
132
+
133
+
134
+
135
+ で、今回は(4)辺りでエラーが起きているようです。
136
+
137
+ では、その(4)辺りを抜き出してみましょう。
138
+
139
+
140
+
141
+ ```Java
142
+
143
+ for(int i=0; i<7; i++){
144
+
145
+ s[i] = scan.next().charAt(0);
146
+
147
+ }
148
+
149
+ ```
150
+
151
+
152
+
153
+ ですね。こういう場合は条件式とかが間違っている可能性があります。
154
+
155
+ なので、とりあえず条件式とその周辺を見てみましょう。
156
+
157
+
158
+
159
+ ```
160
+
161
+ for( int i = 0; i < 7; i++ )...
162
+
163
+ ```
164
+
165
+
166
+
167
+ …これを数直線で考えてみると、そんなに問題はなさそうですね。
168
+
169
+
170
+
171
+ では、次は(4.1) にフォーカスしてみましょうか。
172
+
173
+
174
+
175
+ ```Java
176
+
177
+ s[i] = scan.next().charAt(0);
178
+
179
+ ```
180
+
181
+
182
+
183
+ これはどういう意味でしょうか。分解してみると、
184
+
185
+
186
+
187
+ ```Java
188
+
189
+ String tmp = scan.next();
190
+
191
+ s[i] = tmp.charAt(0);
192
+
193
+ ```
194
+
195
+
196
+
197
+ となるはずです。
198
+
199
+
200
+
201
+ で、こういう場合は[公式ドキュメント](https://docs.oracle.com/javase/jp/8/docs/api/) (あるいは公式リファレンスとも) を読んでみましょう。
202
+
203
+ これは原本に当たるので、正確です。
204
+
205
+
206
+
207
+ とりあえず、公式リファレンス(ドキュメント)の「Scannerクラス」を見てみましょう。
208
+
209
+ バージョンによって異なるようですが、Java Platform SE 8の場合、[ここ](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Scanner.html)ですね。
210
+
211
+
212
+
213
+ 使っているのは Scannerクラスの nextメソッドですから、[ここ](https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#next())ですね。
214
+
215
+
216
+
217
+ 上記によると、nextメソッドは**一行レベルで読み取る**ような感じでしょうか。
218
+
219
+ あー、でもnextLineメソッドもあるので、どう違うのでしょうか。
220
+
221
+
222
+
223
+ そういうときは『違い』を付けて検索するといいかもしれません。
224
+
225
+
226
+
227
+ 例:「Java Scanner next nextLine 違い」
228
+
229
+
230
+
231
+ そうすると、私の環境では[ここ](https://qiita.com/Terry3/items/4f4c253c24ecd5f4d302)や[ここ](https://mikado.hatenablog.jp/entry/2014/05/29/231135)がヒットしました。
232
+
233
+
234
+
235
+ 要するに「nextメソッドは『次の空白まで』か『改行まで』」ですね。(空白無しだと改行まで)
236
+
237
+
238
+
239
+ 今回の入力値を見てください。
240
+
241
+
242
+
243
+ ```xoxxoxo``` のように、『空白を含んでいない』ですね。そうなると、やっぱり『改行までを一つとして読み込む』という感じになってしまいます。
244
+
245
+
246
+
247
+ では、この状態で再度、現実世界でシミュレーションしてみてください。
248
+
249
+
250
+
251
+ そうすると、
252
+
253
+
254
+
255
+ (4)に来た時に、
256
+
257
+
258
+
259
+ ```
260
+
261
+ 一行レベルで読み込む( tmp = "xoxxoxo" )
262
+
263
+ → そのtmpから 0番目を取得する ( s[0] = 'x' )
264
+
265
+ → また一行レベルで読み込む( ただしもう入力値がないので...? )
266
+
267
+ →→ 『エラー!!!!!!』
268
+
269
+ ```
270
+
271
+
272
+
273
+ と言う風になっていますね。
274
+
275
+
276
+
277
+ ありゃ、なんで複数行読み込もうとしているのでしょうか。
278
+
279
+
280
+
281
+ ……と考えると、わかるはずです。
282
+
283
+
284
+
285
+ こういう場合はとりあえず、プログラミングは置いといて、「**現実世界でならどうするか**」を考えましょう。
286
+
287
+
288
+
289
+ 今回の場合、
290
+
291
+
292
+
293
+ ```
294
+
295
+ [依頼]
296
+
297
+ ある人(Aさん)が数字(= n ) と oとxからなる単語(= s )をあなたに言います。
298
+
299
+ このsは、'o' が 晴れ、'x' が 雨という意味です。
300
+
301
+ あなたは、Aさんが言った単語sの n番目の文字が 'o' なら「晴れ」、
302
+
303
+ 'x'なら「雨」と言いましょう。
304
+
305
+ ```
306
+
307
+
308
+
309
+ 的なものでしょうか。
310
+
311
+
312
+
313
+ そうすると、「単純にnとsを受けって s[n] の場所を調べればよくね?」的な感じになりますよね。
314
+
315
+ (まあ、実際には 配列は0からはじまるので n-1 番目ですが)
316
+
317
+
318
+
319
+ で、xoxxoxoとかは一つの文字列と見なせますね。
320
+
321
+ "o x o x x ..." のように半角スペースとかで区切られている場合はアレですが。
322
+
323
+
324
+
325
+ なので、「文字列として受け取る -> s[n-1] を調べる」ってだけでいいはずです。
326
+
327
+
328
+
329
+ C言語だと 文字列は 文字の配列版です。ですがこの配列版だと文字列操作が面倒なので、**JavaとかではStringクラスとかでくるんでいるだけです**。
330
+
331
+ 中身はおそらく、charの配列とかでしょうね。(厳密にはワイド文字列とかだろうけど)