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

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

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

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

Q&A

解決済

1回答

1337閲覧

文字列をうまい位置で区切って、共通に含まれる文字の種類数を最大化したい

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2018/05/28 06:46

前提・実現したいこと

https://beta.atcoder.jp/contests/abc098/tasks/abc098_b
この問題です。
方針は、入力した文字列sを、区切り文字の前と後でそれぞれsa,sbに
分けて、myJudge関数に渡して、それぞれにaからzまでの各文字が
含まれるかを判定して、どちらにもそのアルファベットが含まれた場合のみ
共通の文字があるとしてカウントしていって〜というものです。

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

発生している問題:aab|bcaの時にa,bが共通で、myJudge関数の 戻り値が2のはずなのに、printfすると1になっていること。 エラーメッセージはありません。

該当のソースコード

c

1#include<stdio.h> 2 3int myJudge(char *sa, char *sb); 4 5int main(void) 6{ 7 char s[100+1]={0}; 8 char sa[100+1]={0}; 9 char sb[100+1]={0}; 10 int n=0; 11 int ans=0; 12 int i=0; 13 int k=0; 14 int j=0; 15 int max=0; 16 17 scanf("%d", &n); 18 scanf("%s", s); 19 20 //kは仕切りの位置を表していて 21 //[i]と[i+1]の間にあるときk=iとしています 22 for(k=0; k<=n-2; k++){ 23 24 i=0; 25 j=0; 26 27 //saに入れる 28 while(i!=k+1){ 29 sa[i] = s[i]; 30 i++; 31 } 32 sa[i] = '\0'; 33 printf("sa:%s\n", sa); 34 //sbに入れる 35 while(i<=n-1){ 36 sb[j] = s[i]; 37 i++; 38 j++; 39 } 40 sb[j] = '\0'; 41 printf("sb:%s\n", sb); 42 43 ans = myJudge(sa, sb); 44 printf("ans:%d\n", ans); 45 46 if(ans > max){ 47 max = ans; 48 } 49 50 51 } 52 printf("%d\n", max); 53 54 return 0; 55} 56 57//aからzの文字を一つずつ、saとsbの両方に含まれるか判定する関数 58int myJudge(char *sa, char *sb) 59{ 60 char c; 61 int cnt=0; 62 int ans1=0,ans2=0; 63 64 for(c='a'; c<='z'; c++){ 65 ans1=0,ans2=0; 66 67 while(*sa != '\0'){ 68 if(*sa == c){ 69 ans1 = 1; 70 break; 71 } 72 sa = sa + 1; 73 } 74 while(*sb != '\0'){ 75 if(*sb == c){ 76 ans2 = 1; 77 break; 78 } 79 sb = sb + 1; 80 } 81 if(ans1==1 && ans2==1) 82 cnt++; 83 84 } 85 86 return cnt; 87} 88

試したこと

配列をsa,sbに分けれてるか、関数の戻り値の確認等

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

myJudge関数で、saとsbを直接インクリメントしているためですね。
forループの2周目は常にNULL文字から始まるので、while文が直ぐ抜けてしまうのでしょう。
インクリメント用の変数を用意すれば解決かと思います。

c

1int myJudge(char *sa, char *sb) 2{ 3 char c; 4 int cnt=0; 5 int ans1=0,ans2=0; 6 char *p; 7 8 for(c='a'; c<='z'; c++){ 9 ans1=0,ans2=0; 10 11 p = sa; 12 while(*p != '\0'){ 13 if(*p == c){ 14 ans1 = 1; 15 break; 16 } 17 p = p + 1; 18 } 19 p = sb; 20 while(*p != '\0'){ 21 if(*p == c){ 22 ans2 = 1; 23 break; 24 } 25 p = p + 1; 26 } 27 if(ans1==1 && ans2==1) 28 cnt++; 29 30 } 31 32 return cnt; 33}

投稿2018/05/28 07:21

ttyp03

総合スコア16996

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

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

退会済みユーザー

退会済みユーザー

2018/05/28 23:34

回答ありがとうございます。 forループの2周目は常にNULLから始まる、というところが理解できませんでした。saのみに注目して書かせていただきますが、 例えば、1周目でsa"a,\0"のアドレスが60のとき、forループを終えた後ではsaは61、つまりNULL文字を指していることはわかります。 しかし、2周目ではsaは新しい文字列"a,a,\0"の先頭のaを指していると思うのですが違いますか? 根拠は、myJudge関数のforループの直前にsaのアドレスを表示させると 何周目でも、saは60(1周目の文字列の先頭アドレス)を指していることです。 2周目でsaがNULL文字を指している⇔saの先頭アドレスが61で固定される と考えての意見なんですが、僕の意見はどこが勘違いしているか 教えていただけると幸いです。 よろしくお願いします。
ttyp03

2018/05/28 23:48

二周目と言っているのはforループの二周目です。 なのでforループの直前(ループ外)でアドレスを出力してもmainから渡されたsa配列の先頭アドレスを表示するだけですので、毎回同じ値になります。 簡単に説明するとこんな感じでしょうか。 main(){  char sa[] = "a,"; // 仮にアドレス0x100とする  myJudge(sa,sb); } myJudge(char *sa, char *sb){  printf("%p\n", sa); // ここでは0x100  for(省略){   printf("%p\n", sa); // 1周目は0x100、2周目は0x102   while(*sa != '\0'){    sa = sa + 1; // ここでアドレスを加算   }   printf("%p\n", sa); // 0x102 NULL文字の位置 このアドレスをforの2周目は引き継ぐ  } } 実際に動かして確認しているわけではないですし、mainの方は全然見ていないのでこちらも何か勘違いしているところがあるかもしれません。 不明点疑問点があればツッコミお願いします。
退会済みユーザー

退会済みユーザー

2018/05/29 04:22

回答ありがとうございます。 完全に理解しました。 毎回sa,sbをmain関数から渡したとしても、aで一致してbreakして '\0'までインクリメントして、そのままb以降の判定をするも、'\0'で 止まっててwhileを抜けて、結局どの組み合わせの文字列を渡しても 実質aの判定しかできない、ということですね! for文のところ勘違いしてて申し訳ありませんでした。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問