質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

3564閲覧

配列の任意文字数のシフト

Natumeru

総合スコア5

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/09/10 03:38

編集2020/09/10 04:26
C言語

前提・実現したいこと

どちらにシフトするかと、いくつシフトするかを入力し、シフトした結果を表示させる。
このときに素数からはみ出ないようにしたい(0、またはここにない数字になる)

  • 左右どちらにシフト(移動)するか入力する
  • シフト数を入力する
  • シフト数は総素数を越えない

試したこと

/*  配列の一文字シフト *  要素数5の配列 */ #include<stdio.h> int main( void ) { int L[ 5 ] = { 5,8,1,3,4 }, R[ 5 ] = { 5,8,1,3,4 }; int i,wk=0; wk = L[ 0 ]; for( i = 0; i<5; i++) L[ i ] = L[i+1]; L[ 4 ] = wk; for( i=0;i<5;i++) { printf( "L[%d]:%d¥n", i, L[ i ] ); } printf( "---------¥n" ); wk=R[ 4 ]; for( i = 4; i >0; i-- ) R[ i ] = R[ i-1 ]; R[ 0 ] =wk ; for( i =0; i <5;i++) { printf( "R[%d]:%d¥n", i, R[ i ] ); } return 0; }

このプログラムをもとにシフトする方向とシフトする数を入れたプログラムを作成したい

実行結果

L[0]:8
L[1]:1
L[2]:3
L[3]:4
L[4]:5

R[0]:4
R[1]:5
R[2]:8
R[3]:1
R[4]:3

試したい実行結果

元の配列:1 2 3 4 5 6 7
どちらにシフトしますか(1:左 2:右):2
いくつシフトしますか(1~6):3

右に3文字シフトした結果
元の配列:1 2 3 4 5 6 7
シフト後:5 6 7 1 2 3 4
### 問題点
このプログラムでは左右に1文字しか移動できていません
実行したいのは左右どちらに何文字シフトさせるのかです
(if文だと記入しやすいです)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

1T2R3M4

2020/09/10 03:46

実行結果は動作しているように思えますが、問題点は何ですか。
Natumeru

2020/09/10 03:52

このプログラムだと、どちらにシフトするかといくつシフトするのかが記入されてないので 左に1文字シフトした結果と右に1文字シフトした結果が出るので作成したいプログラムが作成されていないという点が問題点だと思われます。
episteme

2020/09/10 04:09 編集

このコード、シフト(shift)じゃなくてローテート(rotate:回転)だよね... なんにせよひとつシフト/ローテートできれば、それをn回繰り返せばいい。
ttyp03

2020/09/10 04:17

実行結果と提示のコードあってます? 入力処理なんて見当たらないんですが。
Natumeru

2020/09/10 04:27

実行結果と試したい実行結果がごちゃごちゃになっていたみたいです。申し訳ございません
guest

回答3

0

ベストアンサー

{ 1, 2, 3, 4, 5 } を右へ 2シフトして、右からはみ出した分を左から入れると、
{ 4, 5, 1, 2, 3 }。
これは、元の配列の { 1, 2, 3 } と { 4, 5 } を交換したことになります。

{ 1, 2, 3, 4, 5 } を左へ 2シフトして、左からはみ出した分を右から入れると、
{ 3, 4, 5, 1, 2 }。
これは、元の配列の { 1, 2 } と { 3, 4, 5 } を交換したことになります。

長さ n の配列 int a[n]; があって、
左側の r 個と右側の (n - r)個を交換するのは、次の方法でできます。

C

1#include <stdio.h> 2 3void reverse(int *a, int i, int j) 4{ 5 while (i < --j) { 6 int t = a[i]; a[i++] = a[j]; a[j] = t; 7 } 8} 9int main(void) 10{ 11 enum { n = 5, r = 2 }; 12 int a[n] = { 1, 2, 3, 4, 5 }; 13 reverse(a, 0, r); 14 reverse(a, r, n); 15 reverse(a, 0, n); 16 for (int i = 0; i < n; i++) printf(" %d", a[i]); 17 putchar('\n'); 18}

追記

c

1#include <stdio.h> // printf, fgets, scanf 2#include <stdlib.h> // strtol 3 4#define N 500 5 6int main(void) 7{ 8 char buf[1024], *p = buf, *q; 9 int a[N], n, d, r; 10 printf("元の配列: "); 11 if (!fgets(buf, sizeof buf, stdin)) return 1; 12 for (n = 0; n < N; n++) { 13 a[n] = strtol(p, &q, 10); 14 if (q == p) break; 15 p = q; 16 } 17 if (n == 0) return 2; 18 printf("どちらにシフトしますか(1:左 2:右): "); 19 if (scanf("%d", &d) != 1 || d < 1 || d > 2) return 3; 20 printf("いくつシフトしますか(1~%d): ", n - 1); 21 if (scanf("%d", &r) != 1 || r < 1 || r >= n) return 4; 22 if (d == 2) r = n - r; 23 for (int i = 0; i < n; i++) printf(" %d", a[i]); 24 printf("\n n = %d, r = %d\n", n, r); 25}

実行例

text

1元の配列: 1 2 3 4 5 6 7 2どちらにシフトしますか(1:左 2:右): 2 3いくつシフトしますか(1~6): 3 4 1 2 3 4 5 6 7 5 n = 7, r = 4

疑問点があればコメントをお願いします。

投稿2020/09/10 09:25

編集2020/09/10 17:16
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Natumeru

2020/09/11 06:53

回答ありがとうございます。解答してくださったプログラムで実行できそうなので、こちらを参考に作成させていただきます!
guest

0

このときに素数からはみ出ないようにしたい(0、またはここにない数字になる)

要素数による剰余(% 要素数)を使用すればよいです。
注意点としては、負の値に対する剰余結果は負の値になります。
そのため、右にずらしたい場合は単純に引くのではなく要素数を足して正の値にする必要があります。

投稿2020/09/10 05:36

SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Natumeru

2020/09/10 05:39

ヒントありがとうございます!助かります
guest

0

C

1 wk = L[ 0 ]; 2 for( i = 0; i<5; i++) 3 L[ i ] = L[i+1]; 4 L[ 4 ] = wk;

上書きされてしまう先頭を保存しておいてから、
1つ後の要素で上書きし続け、
最後に保存しておいた先頭の要素を入れる。

という基本的な考え方そのものは間違っていません。
しかし、任意の数の配列に対して、任意の数のシフトを行うのに対して、
配列のサイズと、シフトする数を固定してしまっているのでうまく行きません。
(ついでに、int L[5]の時にi<5だとi=4の時に、L[i+1]L[5](6番目の要素)へのアクセスになってしまって、マズいです)

少なくとも配列の要素数に応じたループ数と、先頭のデータを書き戻す位置を考えないといけません。

任意の数のシフト自体は1つずつでも、それを必要回数繰り返せば、必要な数のシフトを行えば可能です。

(配列をもう一つ用意して一気にずらすのもあり)

投稿2020/09/10 03:52

amiya

総合スコア1218

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問