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

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

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

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

Q&A

解決済

4回答

889閲覧

文字列について(仮引数)

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2021/05/25 16:58

編集2021/05/27 08:34

前提・実現したいこと

仮引数として文字列s1,s2を受け取り,s1からs2に含まれていない文字をすべて取り除く関数を作成したい.

発生している問題・エラーメッセージ

文字が一致していなければ消す,というコードを??の部分でどのように書けばよいのか分かりません.初心者なので,他に間違っている箇所はあるかもしれないです.

エラーメッセージ

該当のソースコード

c

1 2#include<stdio.h> 3#define NUMBER 101 4int delete(char s1[], char s2[]){ 5 int i, j; 6 for(i = 0; s1[i] != '\0'; i++){ 7 for(j = 0; s2[j] != '\0'; j++){ 8 if(s1[i] != s2[j]){ 9 ?? 10 } 11 } 12 } 13 printf("%s", s1); 14 15 printf("\n"); 16} 17 18int main(void){ 19 char str1[NUMBER]; 20 char str2[NUMBER]; 21 puts("100文字以内の半角文字列を2つ入力してください"); 22 printf("str1:\n"); 23 fgets(str1, NUMBER, stdin); 24 25 printf("str2:\n"); 26 fgets(str2, NUMBER, stdin); 27 28 printf("str1からstr2に含まれていない文字をすべて取り除いた結果、%sになる。\n", delete(str1, str2)); 29 30 return 0; 31} 32ソースコード

試したこと

??の部分でs1[i] = '';としてみたがエラーが出た.

補足情報(FW/ツールのバージョンなど)

emacsを利用しています.

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

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

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

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

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

hoshi-takanori

2021/05/25 19:18

s1 を破壊的に変更する場合、s1 からある文字を取り除くというのは、その文字の後ろにあるものをすべて一つずつ前にずらすことです。(他の言語では破壊的な変更は良くないと言われてますが、C 言語だからなぁ…。)
dodox86

2021/05/25 22:44

s1が"teratail"で、s2が"aert"だとすると、"il"はs2に含まれないので、"terata"になるのですよね。" そうだとすると、そもそも if(s1[i] != s2[j]){ ?? } のコードでは、s1の最初の文字't'から削除されようとしちゃうのでは? s1の各文字についてそれがs2に含まれているか、を判定していくのもひとつの方法だと思います。
guest

回答4

0

C

1#include <stdio.h> 2#define NUMBER 101 3 4char* delete(char* str, const char* pattern) { 5 char* wp = str; 6 // strにある各文字 *rp に対し 7 for ( char* rp = str; *rp; ++rp ) { 8 // *rp がpatternに含まれるかを調べ 9 char* p = pattern; 10 while ( *p ) { 11 if ( *p == *rp ) { break; } 12 ++p; 13 } 14 // 含まれているなら残す(書き込む) 15 if ( *p ) { 16 *wp++ = *rp; 17 } 18 } 19 *wp = '\0'; 20 return str; 21} 22 23int main(void) { 24 char str1[NUMBER]; 25 char str2[NUMBER]; 26 puts("100文字以内の半角文字列を2つ入力してください"); 27 printf("str1:\n"); 28 fgets(str1, NUMBER, stdin); 29 30 printf("str2:\n"); 31 fgets(str2, NUMBER, stdin); 32 33 printf("str1からstr2に含まれていない文字をすべて取り除いた結果、%sになる。\n", delete(str1, str2)); 34 35 return 0; 36}

投稿2021/05/25 23:13

編集2021/05/25 23:53
episteme

総合スコア16614

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

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

退会済みユーザー

退会済みユーザー

2021/05/27 07:46

知識不足で申し訳ないのですが,char*や,*rpの使い方をまだ習っていません.どういう意味なのかご教授願いたいです.
episteme

2021/05/27 07:53

char* wp; char* rp; いずれも"charを指すポインタ"です。
SaitoAtsushi

2021/05/27 09:47

補足。 関数の仮引数に配列形式の宣言があるとそれはポインタであるように自動的に調整されるルールです。 つまり質問者が書いているプログラムにおける関数 delete の int delete(char s1[], char s2[]) の部分は int delete(char *s1, char *s2) と書いたのと全く同じものであると解釈されます。 表記こそ違えども質問者はポインタを使っています。 肝心な点をあらためてまとめると ・ 関数の引数として配列 (文字の配列であるところの文字列も) を渡すことは出来ない ・ 配列の場所 (ポインタ) を渡すことで代わりにする ・ 仮引数を配列形式で書くと (どうせ配列は渡せないので) ポインタということに勝手に読み替える変則的なルール です。 C の理屈 (セマンティクス) は表面的な書き方でポインタを使わなかったとしてもポインタを軸にした理屈で定義されていたりするのでそこを避けて理解は出来ないです。
guest

0

s1から文字を取り除くと考えるから難しいのだと思います。
s1からs2に含まれる新しい文字列を作るというように考えを変える方が簡単です。

  • s1と同じ文字列長のバッファs1_workを用意する
  • s1の中にs2の文字と一致する文字を見つける
  • 一致する文字を見つけたらs1_workに追加する
  • s1の中身をすべてチェックし終えたらs1_workに終端文字'\0'を追加する
  • s1_workを表示する

投稿2021/05/25 17:22

TaroToyotomi

総合スコア1430

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

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

0

配列だけ習っていて、ポインタの表記が使えないなら、

C

1#include <stdio.h> // puts, printf, fgets 2 3#define NUMBER 101 4 5char *delete(char s1[], char s2[]) 6{ 7 int i, j, k = 0; 8 for (i = 0; s1[i] != '\0'; i++) { 9 for (j = 0; s2[j] != '\0' && s1[i] != s2[j]; j++) ; 10 if (s2[j] != '\0') s1[k++] = s2[j]; 11 } 12 s1[k] = '\0'; 13 return s1; 14} 15 16int main(void) 17{ 18 char str1[NUMBER]; 19 char str2[NUMBER]; 20 puts("100文字以内の半角文字列を2つ入力してください"); 21 printf("str1:\n"); 22 fgets(str1, NUMBER, stdin); 23 24 printf("str2:\n"); 25 fgets(str2, NUMBER, stdin); 26 27 printf("str1からstr2に含まれていない文字をすべて取り除いた結果、%sになる。\n", 28 delete(str1, str2)); 29 30 return 0; 31}

投稿2021/05/27 10:06

kazuma-s

総合スコア8224

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

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

0

ベストアンサー

基本的にはepistemeさんのものと同じですが、配列用に直してあります。
このコードではs1の内容そのものが変わってしまいますので、それが嫌であればstr1, str2以外に配列を作り、それを引数で渡す必要が(ポインタが判らない段階では)あります。

C

1#include<stdio.h> 2#define NUMBER 101 3 4void delete(char s1[], char s2[]){ // ポインタ習得後なら char* を返り値にしたりしたい 5 int i, j; 6 int wr = 0; // s1に上書きしていく番号 7 8 for(i = 0; s1[i] != '\0'; i++){ 9 for(j = 0; s2[j] != '\0'; j++){ 10 if(s1[i] == s2[j]){ 11 // s1の中にs2の要素が存在した。ここで抜ける場合、s2[j]は'\0'でない 12 break; 13 } 14 } 15 if (s2[j] != '\0') 16 { // s1の中にs2の要素が存在しなかった時、その文字をs1の最初(wr=0)から上書きしていく 17 s1[wr] = s1[i]; 18 wr++; 19 } 20 } 21 s1[wr] = '\0'; // 最後にヌル文字を入れる 22 23 printf("%s", s1); 24 25 printf("\n"); 26} 27 28int main(void){ 29 char str1[NUMBER]; 30 char str2[NUMBER]; 31 puts("100文字以内の半角文字列を2つ入力してください"); 32 printf("str1:\n"); 33 fgets(str1, NUMBER, stdin); 34 35 printf("str2:\n"); 36 fgets(str2, NUMBER, stdin); 37 38 /* ポインタをまだ学習していない場合は、deleteの返り値をそのままprintfすることは難しいでしょうから、 39 一度delete関数を走らせてからprintfするようにしましょう */ 40 delete (str1, str2); 41 printf("str1からstr2に含まれていない文字をすべて取り除いた結果、%sになる。\n", str1); 42 43 return 0; 44}

投稿2021/05/27 09:57

WoodenHamlet

総合スコア306

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問