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

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

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

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

2回答

1738閲覧

文字列を比較して任意の単語が含まれているかを検出するプログラム

naki_a

総合スコア6

C

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2021/05/18 14:42

C言語で、文章と英単語を入力し,大文字/小文字を区別せず英単語が文章中に含まれていれば,その旨を表示するプログラムを作成しなさい、という課題に取り組んでいます。
strlen,toupper(tolower),strncomp関数を必ず使わなければいけません。

strtok関数を使って半角スペースで文字列を区切って表示させるところまではできたのですがコアダンプというエラーが出て動かなくなってしまいます。

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

egg apple
egg

ans0 = 2
Segmentation fault (コアダンプ)

該当のソースコード

c

1#include <string.h> 2#include <stdio.h> 3#include<stdio.h> 4#include<ctype.h> 5 6int main(void) 7{ 8 int str_len, word_len, n, ans; 9 char in_str[50] = {}; 10 char in_word[15]; 11 char large_str[50] = {}; 12 char large_word[15] = {}; 13 char *p, *w; 14 15 str_len = strlen(in_str); 16 word_len = strlen(in_word); 17 18 printf(">>"); 19 scanf("%[^\n]",in_str); 20 printf(">>"); 21 scanf("%[^\n]",in_word); 22 for(n = 0; n < str_len; n++) { 23 large_str[n] = toupper(in_str[n]); 24 } 25 for(n = 0; n < word_len; n++) { 26 large_word[n] = toupper(in_word[n]); 27 } 28 29 w = large_word; 30 p = strtok(large_str," "); 31 32 //1つ目のトークン表示 33 ans = strncmp(p, w, word_len); 34 if(ans == 0) 35 printf("Hit!!\n"); 36 puts(p); 37 38 //トークンがNULLになるまでループ 39 while(p!=NULL){ 40 41 //2回目以降は第一引数はNULL 42 p = strtok(NULL," "); 43 if(p!=NULL){ 44 ans = strncmp(p, w, word_len); 45 if(ans == 0) 46 printf("Hit!!\n"); 47 puts(p); 48 } 49 } 50 return 0; 51}

試したこと

c

1//1つ目のトークン表示 2 ans = strncmp(p, w, word_len); 3 if(ans == 0) 4 printf("Hit!!\n"); 5 puts(p);

ansへの代入の後にprintf関数を入れてansを表示させたところ、一回目のstrncmp関数で何が入ってきても0が代入されていました。
これでは比較できていないのでしょうか?

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

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

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

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

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

guest

回答2

0

ベストアンサー

ansへの代入の後にprintf関数を入れてansを表示させたところ、一回目のstrncmp関数で何が入ってきても0が代入されていました。

ans だけでなく、str_len、word_len、n、in_str、in_word、large_str、
large_word、p、w を表示して何が入っているか見てください。

追記

C

1#include <stdio.h> // scanf, printf, puts 2#include <string.h> // strlen, strncmp, strtok 3#include <ctype.h> // toupper 4 5int main(void) 6{ 7 char str[50], word[15]; 8 9 printf(">>"), scanf("%[^\n]", str); 10 printf(">>"), scanf(" %[^\n]", word); 11 for (int i = 0; str[i]; i++) str[i] = toupper(str[i]); 12 int len = strlen(word); 13 for (int i = 0; i < len; i++) word[i] = toupper(word[i]); 14 char *p = strtok(str," "); 15 while (p && strncmp(p, word, len)) p = strtok(NULL, " "); 16 puts(p ? "その英単語は、英文に含まれています。" 17 : "その英単語は、英文に含まれていません。"); 18}

追記2
次のように書いても実行結果は同じです。

C

1#include <stdio.h> // scanf, printf, puts 2#include <string.h> // strlen, strncmp, strtok 3#include <ctype.h> // toupper 4 5int main(void) 6{ 7 char str[50], word[15]; 8 9 printf(">>"); 10 scanf("%[^\n]", str); 11 printf(">>"); 12 scanf("%s", word); 13 for (int i = 0; str[i] != '\0'; i++) 14 str[i] = toupper(str[i]); 15 int len = strlen(word); 16 for (int i = 0; i < len; i++) 17 word[i] = toupper(word[i]); 18 char *p = strtok(str," "); 19 while (p != NULL && strncmp(p, word, len) != 0) 20 p = strtok(NULL, " "); 21 if (p != NULL) 22 puts("その英単語は、英文に含まれています。"); 23 else 24 puts("その英単語は、英文に含まれていません。"); 25}

!= '\0'!= NULL!= 0 はすべて省略できます。
これらは != の左の項が 0 ではないかどうかを判定しています。
for の第2式も while や if の式もその式の値が 0 でないかどうかで判定します。

投稿2021/05/18 15:49

編集2021/05/23 17:31
kazuma-s

総合スコア8224

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

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

naki_a

2021/05/19 13:54

起床してからアドバイスに従い全部表示させたところ、ここ3日ほど自分がとんでもないことをしているのに気づきました。ありがとうございます。
kazuma-s

2021/05/19 14:47

どのようにして解決したですか? コードを質問に追記してください。
naki_a

2021/05/22 10:32

追記いたしました、ご指摘ありがとうございます。
guest

0

このように解決しました。

C言語

1#include <string.h> 2#include <stdio.h> 3#include<stdio.h> 4#include<ctype.h> 5 6int main(void) 7{ 8 int str_len, word_len, n, ans; 9 char in_str[50] = {}; 10 char in_word[15]; 11 char large_str[50] = {}; 12 char large_word[15] = {}; 13 char *p, *w; 14 15 printf(">>"); 16 scanf("%[^\n]",in_str); 17 printf(">>"); 18 scanf("%s",in_word); 19 20 str_len = strlen(in_str); 21 word_len = strlen(in_word); 22 printf("str_len = %d\nword_len = %d\n", str_len, word_len); 23 24 for(n = 0; n < str_len; n++) { 25 large_str[n] = toupper(in_str[n]); 26 } 27 printf("large_str = %s\n",large_str); 28 for(n = 0; n < word_len; n++) { 29 large_word[n] = toupper(in_word[n]); 30 } 31 printf("large_word = %s\n",large_word); 32 33 w = large_word; 34 puts(w); 35 p = strtok(large_str," "); 36 37 ans = strncmp(p, w, word_len); 38 if(ans == 0) 39 printf("その英単語は、英文に含まれています。\n"); 40 else{ 41 while(p!=NULL){ 42 p = strtok(NULL," "); 43 if(p!=NULL){ 44 ans = strncmp(p, w, word_len); 45 if(ans == 0){ 46 printf("その英単語は、英文に含まれています。\n"); 47 break; 48 } 49 puts(p); 50 } 51 } 52 } 53 if(ans != 0) { 54 printf("その英単語は、英文に含まれていません。\n"); 55 } 56 57 return 0; 58}

投稿2021/05/22 10:31

naki_a

総合スコア6

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

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

kazuma-s

2021/05/22 16:06

2つめの scanf の "%[^\n]" をどうするんだろうと思っていましたが、"%s" にしたんですね。 " %[^\n]" のように % の前にスペースを置くという手もあります。 ちょっと気になるのが strncmp を使っていることで、 これだと、str = "I am a teacher."、word = "tea" が 「含まれています」になってしまいます。
kazuma-s

2021/05/22 16:11

#include <stdio.h> が 2つあることはまあいいとして、 = {}; のように空の初期化子は標準の C では許されていません。 また、in_word 以外の文字配列はすべて初期化して、これだけ初期化しないのはなぜでしょうか? strncmp が 2回あって、同じ printf も 2回あるのはもっと簡単に書けます。 私の回答に追記します。
naki_a

2021/05/23 03:32

#include<stdio.h>が2個あるのは多分コピペしたりしてるうちに重複してしまったんだと思います……。 in_wordをしてないのもおそらくこの配列は後でつけ加えたため初期化を忘れていたのだと思うので特に意味は無いです、= {}; がダメなのも初めて知りました。 追記拝見しました。私のプログラムの半分以下程度の長さで実装されていてここまでコンパクトになるんだと驚きました。 よろしければお答え頂けると嬉しいのですが、(p && strncmp(p, word, len)はどういう処理をしているんでしょうか? strncmp関数は文字列が一致すれば0が返ってくるという挙動だと理解しているのですが、pとandをとっているのはどういう意味があるんでしょうか??
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問