C言語プログラミング初心者のためのstrcmp()関数に代わる文字列比較プログラムの作成方法

このQ&Aのポイント
  • C言語プログラミング初心者のための文字列比較プログラム制作方法について相談です。strcmp()関数を使用せずに、2つの文字列を比較する方法を知りたいです。
  • 現在、2つの50文字以下の文字列を比較するプログラムを作成しています。しかし、文字列が等しい場合などにうまく動作しません。どのような条件を付ければ、正確に文字列が一致した場合のみ表示することができますか?
  • また、文字列の比較において、str1がaab、str2がaacの場合、str1 < str2となるのでしょうか?str1[2]にはヌル文字が入っており、それがstr2[2]のcと比較されたためなのでしょうか?分かる方がいれば、アドバイスをお願いします。
回答を見る
  • ベストアンサー

C言語プログラミング 初心者

現在2つの文字列を比較するstrcmp()関数と同じ動作をするプログラムを制作しています。 もちろん、strcmp()は一切用いません。 何とか作ってみたものの、文字列が等しいときなどにはうまく作動しません。 分かる方アドバイスお願いします。 以下のプログラムでは2つの50文字以下の文字列を入力することを想定しています。 #include<stdio.h> int main(void) { char str1[50],str2[50]; int a,b,i; printf("第1の文字列を入力してください: "); gets(str1); printf("第2の文字列を入力してください: "); gets(str2); /*文字列の長さを確認します*/ for(a = 0;str[a];a++) ; for(b = 0;str2[b];b++) ; printf("%s ha %d mozinonagasadesu\n",str1,a); printf("%s ha %d mozinonagasadesu\n",str2,b); /*文字列を比較します*/ for(i = 0;;i++){ if(str1[i] > str2[i]) printf("%s は %s より大きい\n"str1,str2); else if(str1[i] < str2[i]) printf("%s は %s より小さい\n"str1,str2); if(str1[i] > str2[i] || str1[i] <str2[i]) break; } for(i=0;str1[i] && str2[i];i++) if(str1[i] == str2[i] ) printf("文字列は等しい\n"); /*上のプログラミングだとstr1がaab、str2がaacのときも文字列が等しいと表示してしまうので、ぴったり等しいときのみ表示するにはどのように条件付けしたらよいでしょうか?*/ return 0; } ちなみにstr1[0]=a ,str1[1]=b, str2[0]=a, str[1]=b, str[2]=cが格納されていた場合、str1 < str2になると思うのですが正しいでしょうか? もし正しければこの場合str1[2]にはヌル文字が入っており、それがstr2[2]のcと比較されたためなのでしょうか? いろいろと質問してしまいましたが、分かる方解答お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

まず、最初のforループに終了条件がありません。 文字列に相違があればループを抜けますが、等しい場合は永遠に繰り返します。(実際は領域外のゴミを拾って相違となるか、アクセス禁止領域にアクセスしてエラーになるかしますが) どちらかの文字列が終端まで至ったところで比較を終了する必要があります。 次に、等しいかどうかの判定はループを出た時の文字の比較のままでいいのに、最初からループをやり直し、等しい時に抜け出てるので、1文字目が等しい文字列はすべて「等しい」となってしまいます。 以上のところに気を付ければ良いかと。

exymezxy09
質問者

お礼

forループの終了条件が抜けていましたか。気づきませんでした。 コンパイルできてしまったので。 プログラムが動いたのは解答していただいた理由によるものなんですね。 しっかり覚えておきたいと思います。 >次に、等しいかどうかの判定はループを出た時の文字の比較のままでいいのに、 そうですね。よく考えたらループを抜け出たものが等しければそれでいいんですよね。 大変分かりやすい説明ありがとうございました。

その他の回答 (4)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

タイトルはせめて「strcmpの自作」とかなんとか付けましょう。 すでに色々言われていますが、方針として 1.先頭から一つずつ要素を比較。いずれかの要素がヌル文字になるまで繰り返し 2.途中で異なる要素にヒットしたら、その大小により「大きい」もしくは「小さい」結果を返す 3.繰り返し終了まで到達したときに両方がヌル文字なら「等しい」、片方だけヌル文字ならそちらが「小さい」 という流れになります。 文字列長の差異と要素の差異でどちらが優先されるかはmanには書いてなかったのでとりあえず要素優先で書いてあります。

exymezxy09
質問者

お礼

解答ありがとうございます。 ご指摘を参考にして、何とかうまくプログラムを作り、実行することができました。

回答No.4

for(i = 0;str1[i] != \0 || str2[i] != \0;i++){ これって本当に動かしてみましたか? ...初頭でナルかどうかを判断しているんで、思うような判断処理はできないと思いますが。 for()を使ったサンプルプログラムを↓に示しておきます。 トレース付きにしてありますのでいろいろ試してみてください。そして、あなたのやり方とどこが違うのかを調べてください。 なお、片方がナル文字の場合はうまく処理してくれません。その理由とその処置に対処できれば、完成します。 #include<stdio.h> #define EQUAL "%s=%s\n" #define GREATE "%s>%s\n" #define SMALL "%s<%s\n" int main(void) { char str1[50],str2[50]; int i; printf("第1の文字列を入力してください: "); gets(str1); printf("第2の文字列を入力してください: "); gets(str2); for(i=0; i<50 && (str1[i] !='\0' || str2[i]!='\0'); i++) { printf("\ttrace(%d): %c, %c\n", i, str1[i], str2[i]); if(str1[i]>str2[i]){ printf(GREATE, str1,str2); break; } else if(str1[i]<str2[i]){ printf(SMALL, str1,str2); break; } else if(str1[i+1]=='\0') { printf("\ttrace(%d): %s, ", i+1, "NULL"); if(str2[i+1]=='\0') { printf("%s\n", "NULL"); printf(EQUAL, str1,str2); } else { printf("%c\n", str2[i+1]); printf(SMALL, str1,str2); } break; } else if(str2[i+1]=='\0') { if(str1[i+1]!='\0') { printf("\ttrace(%d): %c, %s\n", i+1, str1[i+1], "NULL"); printf(GREATE, str1, str2); } break; } } return 0; }

exymezxy09
質問者

お礼

>for(i = 0;str1[i] != \0 || str2[i] != \0;i++){ すいません。正しくは'\0'でした。 また、最後のprintfの部分ですが、うまく条件付けしたら、コンパイル出来てforループもきちんと成立しました。 ご指摘ありがとうございました。

回答No.3

#1 です。 > ちなみにstr1[0]=a ,str1[1]=b, str2[0]=a, str[1]=b, str[2]=cが格納されていた場合、str1 < str2になると思うのですが正しいでしょうか?  とくに条件が付けられているのでなければ、それで正しいと思います。 > もし正しければこの場合str1[2]にはヌル文字が入っており、それがstr2[2]のcと比較されたためなのでしょうか?  上記のプログラム上ではそうなります。

exymezxy09
質問者

お礼

再びの解答ありがとうございます。 解答していただいたことで、疑問は解消できました。 一応プログラムを変更してみたのですが、forの条件式はこれで大丈夫でしょうか? 何度も分かりやすく解答していただいているので、もう一度解答していただけると本当に助かります。 /*文字列を比較します*/ for(i = 0;str1[i] != \0 || str2[i] != \0;i++){ if(str1[i] > str2[i]) printf("%s ha %s yoriookii\n"str1,str2); else if(str1[i] < str2[i]) printf("%s ha %s yoritiisai\n"str1,str2); if(str1[i] > str2[i] || str1[i] <str2[i]) break; } printf("moziretuhahitosii\n");

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

まず日本語の問題から指摘しておこう. 最後に 「もし正しければこの場合str1[2]にはヌル文字が入っており、それがstr2[2]のcと比較されたためなのでしょうか?」 と書いているが, 「比較されたため」なんだといっている? あとはプログラムの問題: 比較のところで最初の for に終了条件がないのはなぜ? あと, 次の for で i をまた 0 から回す必然性が分からんし, なんで毎回表示するの?

exymezxy09
質問者

お礼

ご解答ありがとうございます。 forの終了条件が抜けていました。 修正したいと思います。 また、次のforループを修正したいと思います。

関連するQ&A

  • C言語で分からないところがあるのですが

    すみません。C言語のポインタで分からないことがあって来ました。 ポインタの理屈は理解してはいるのですが、いざソースコードを書いてみようということになると全く手がつけられずにいます。 以下のソースコードですが、strlen()と同じ働きをする関数mystrlen()と、strcmp()と同じ働きをする関数mystrcmpを、ポインタを使って作成するものです。どこをどうすればいいのか教えてくださいませんか。 #include <stdio.h> int main(void) { char str1[80], str2[80]; int i, j; int len1, len2; printf("第1の文字列を入力してください: "); gets(str1); printf("第2の文字列を入力してください: "); gets(str2); /* * 文字列の長さを確認する */ /* NULL文字(文字列の最後)まで読み飛ばす */ for (len1 = 0; len1 < 80 && str1[len1] != '\0'; len1++) ; /* ループ終了後、len1 に文字列の長さが入っている */ if (len1 < 80) { printf("%s は %d 文字の長さです\n", str1, len1); } else { printf ("第1の文字列が80字以上あります\n"); } /* str2 についても同様 */ for (len2 = 0; len2 < 80 && str2[len2] != '\0'; len2++) ; if (len2 < 80) { printf("%s は %d 文字の長さです\n", str2, len2); } else { printf ("第2の文字列が80字以上あります\n"); } if (len1 < 80 && len2 < 80) { for (i = 0; i < 80 && str1[i] != '\0' && str2[i] != '\0' && str1[i] == str2[i]; i++) ; if (str1[i] == str2[i]) { /* 両者同時に == '\0' のはず*/ printf("文字列は等しい\n"); } else if (str1[i] < str2[i]) { /* str1[i] == '\0' のはず*/ printf("%s は %s より小さい\n", str1, str2); } else { /* str2[i] == '\0' のはず*/ printf("%s は %s より大きい\n", str1, str2); } } /* * 十分なスペースがあれば、str2をstr1の最後に連結する */ if (len1 + len2 < 80) { /* str1 の末尾を探す */ for (i = 0; str1[i] != '\0'; i++) ; /* ループを抜けた段階では i は len1 と同じはずなので、 上記のループを作らず、i の代わりに len1 を用いるのも可 */ /* それ以降に str2 の中身をコピーする */ for (j = 0; str2[j] != '\0'; j++) { str1[i+j] = str2[j]; } str1[i+j] = '\0'; printf("%s\n", str1); } else { printf ("文字列をつなげた長さが80字以上あります\n"); } /* * str2をstr1にコピーする */ if (len1 + len2 < 80) { for (i = 0; str1[i] != '\0'; i++) { str1[i] = str2[i]; } str1[i] = '\0'; printf("%s %s\n", str1, str2); } return 0; }

  • C言語の文字列の取り扱いが分かりません

    こんにちは。 C言語で分からないことがあり、質問させていただきました。 学校で、文字列の取り扱いを習いました。 そこで質問なんですが、以下のソースコードをstrcpy , strcat , strcmp , strlen を使わずに書くことってできないですか? 先生に質問したところ、ポインタとかいうのを使うのだそうですが、それを使わずに書くことってできるんですか?もしよろしければお願いします。 以下のプログラムですが、ユーザーから2つの文字列を受けて、そこから4つの文字列関数を使ってみましょう、というやつです。実行結果も貼っておきますね。 #include <string.h> #include <stdio.h> int main(void) { char str1[80], str2[80]; int i; printf("INPUT 1st word-line. : "); gets(str1); printf("INPUT 2nd word-line. : "); gets(str2); /*文字列(word-line)の長さを確認します。*/ printf("%s is %d moji long.\n", str1, strlen(str1)); printf("%s is %d moji long.\n", str2, strlen(str2)); /*文字列を比較します。*/ i = strcmp(str1, str2); if (!i) printf("two word-lines are same length.\n"); else if (i < 0) printf("%s is smaller than %s.\n", str1, str2); else printf("%s is bigger than %s.\n", str1, str2); /*十分なスペースがあるのなら、str2をstr1の最後に結合させます。*/ if((strlen(str1) + strlen(str2)) < 80 ){ strcat(str1, str2); printf("%s\n", str1); } /*str2をstr1にコピーする*/ strcpy(str1, str2); printf("%s %s\n", str1, str2);

  • C言語について教えてください

    ファイルの文を読み込み、I、Weなどの定めた単語の数を数えるプログラムを作りたいのですが、うまくいきません。 具体的な問題点は、単語の数を数える際、一致する単語があった場合、再び最初から文を見直すため、無限ループしてしまう。 We,WE、weなど大文字小文字の違いで単語が数えられないなどです。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main( void ) { char filename[FILENAME_MAX]; int j=0; int k=0; int l=0; int m=0; int n=0; int o=0; int w; char str[50]; FILE *fp; gets(filename); fp = fopen(filename,"r"); { if(fp==NULL) { printf("ERROR"); return -1; } } fscanf(fp,"%50s",str); for(w=0;w<=j+k+l+m+n+o;w++) { if(strcmp("I",str)==0) { j++; } if(strcmp("We",str)==0) { k++; } if(strcmp("You",str)==0) { l++; } if(strcmp("He",str)==0) { m++; } if(strcmp("She",str)==0) { n++; } if(strcmp("They",str)==0) { o++; } } printf("I: %d\n",j); printf("We: %d\n",k); printf("You: %d\n",l); printf("He: %d\n",m); printf("She: %d\n",n); printf("They: %d",o); fclose(fp); return 0; }

  • C言語 strcmp 半角スペースがあるとだめ?

    C言語 strcmp 半角スペースが文字列に含まれている場合 文字列の比較がうまくいきません。半角スペースがあると比較できないのでしょうか? プログラム //strcmp #include <stdio.h> #include <string.h> int main(void){ char input[256]; char str[] = "HelloWorld!";   //char str[] = "Hello World!";だとうまくいかない。 printf("%s\n>", str); scanf("%s", input); if ( strcmp(input, str) == 0){ printf("同じです。\n"); }else{ printf("違います。\n"); } return 0; }

  • C言語のプログラミングですが、

    C言語のプログラミングですが、 255文字以内の文字列をキーボードから入力して、下記の各処理を行うプログラム(※入力した文字データは配列に入力)はどのようにしたらいいでしょうか?(入力例:acFNkeexFFg) ・入力した文字列の最後の文字を出力 ・入力した文字列⇒逆に並べ替えて出力 ・入力した文字列⇒縦に出力(1文字ずつ) ・入力した文字列の中に「F」が何個あるか ただし、使えるのはfor文・配列・if文ぐらいでそれ以上レベルの高いものは使わないで下さい。 … char str[255]; int i,n,na,nb,nc; printf("Input Strings= "); scanf("%s",str); for(i=0;str[i]!='¥0';i++){ n=i; } printf("The last character= %c",str[n]); くらいまでしか分かりません…

  • 作ったプログラミングC何だけど、評価していただけませんが?不足があれば、教えてください!

    文字列「abc」の各アルファベットを1文字ずらすと文字列「bcd 」になり、 文字列「nisidate」の各アルファベットを2文字ずらすと文字 列「pkukfcvg」となる。さらに、 文字列「kibishii」の各アルファベットを2文字ずらすと文字 列「mkdkujkk」となる。 このような、任意の文字列の各要素を任意の文字数ずらすプロ グラムを作成する、なお、zを1文字ずらしたとき のアルファベットはaとする。 #include <stdio.h> #include <string.h> int main(void) { char str[27]="abcdefghijklmnopqrstuvwxyz",str1[50], str2[50]; int x,i,j,len; printf("文字列を入力---> "); scanf("%s", str1); printf("何文字ずらすかを入力---> "); scanf("%d",&x); len=strlen(str1); for(i=0;i<len;i++) { for(j=0;j<27;j++) { if(str1[i]=='z') { str2[i]=str[x-1]; } if(!(str1[i]=='z')) { if(str1[i]==str[j]) { str2[i]=str[j+x]; } } } } printf("%d文字ずらした文字列は%sです\n", x, str2); return 0; } よろしくお願いします!!

  • C言語:配列の中の文字を。。。

    こんにちは。 閲覧していただきありがとうございます。 長文になりますが勉強がわからず困っているので、ご助力いただけると助かります。 C言語についてです。 文字列の中に、特定の文字が出てきたときにだけ改行して表示するプログラムを作りたくて、以下のようにしてみました。(文字はアルファベット小文字のみです) #include<stdio.h> #include<string.h> int main(){  char str[200];  int i;  int k;  puts("文字列を入力");  gets(str);  k = strlen(str);  for(i=0;i<k;i++){    if(strcmp(str[i],"n")==0)     printf("\n");    printf("%c",str[i]);    }   return 0; } このプログラムにより期待する結果は、例えば入力した文字列が「abcdne abcn d」だとすれば、nが来たときに改行が実行されて abcd ne abc n d と表示されるようにしたいのですが、strcmpにintは渡せないとか、ポインタを使ってみても、実力不足ゆえに、「移植性のないポインタ変換」とかのエラーしか出ません。 どのようにすれば、この結果を得ることができるのでしょうか? ぜひご教授ください。よろしくお願いします。

  • C言語

    入力した文字列と文字列'x'を受け取り、'x'の位置のポインタを返すのですが、例えば、saxcvと入力すると、xcvと表示されるのですが、このソースだと、saxcvと全部表示されてしまいます。分からないので、教えてください。宜しくお願いします。 #include <stdio.h> char *a(char *sew) { char *p=sew; while (*sew != 'x') { sew++; } return(p); } int main(void) { char str[21] ={'\0'}; int i=0,no=0; char ch; printf("文字を入力してください:"); while (i<21) { ch=getchar(); if (ch=='\n') {break;} else if (ch != '\0' && ch != '\0') { str[i] =ch; i++; } } for(i=0; i<20; i++) { if(str[i]=='x') { printf("'x'以降は%sです。\n", a(str)); no=1; break; } } if (no==0) printf("'x'は見つかりませんでした。"); return (0); }

  • プログラミングの問題で幾つか分からないことがあります。

    プログラミングの問題で幾つか分からないことがあります。 入力した文字列のアスキーコードを1上げて表示するというもので、 #include <stdio.h> int main(void){ char a[100]; int b, c; scanf("%s", a); for(b = 0; b <= 99; b++){ if(a[b] == '\n'){ break; } a[b] == a[b] + 1; } printf("%s", a); return 0; } というふうに作ったのですが、基の文字列がそのまま表示されてしまいます。 あと、文字列strの中にある文字列bagに含まれる文字と同じ文字を空白に置き換える関数を作り、文字列を与えて動かすというプログラムで、 #include <stdio.h> char str[100], bag[100]; int str_space(char str[], char bag[]){ int a, b, c, d; for(a = 0; a <= 99; a++){ if(str[a] == '\n'){ b = a; break; } } for(a = 0; a <= 99; a++){ if(bag[a] == '\n'){ c = a; break; } } for(a = 0; a <= b; a++){ for(d = 0; d <= c; d++){ if(str[a] == bag[d]){ str[a] = ' '; } } } return 0; } int main(void){ scanf("%s", str); scanf("%s", bag); str_space(str, bag); printf("%s", str); return 0; } というふうに作ったのですが、動きませんでした。 ヒントでもいいのでどなたかお教え下さい。

  • プログラミング ポインタを使った文字列比較

    プログラミング ポインタを使った文字列比較 2つの文字列str1, str2を入力し,それらが等しければ0,等しくなければ1を返す関数str_compareを作り、返り値によって以下のように表示するプログラムを作れ。ただし,関数strcmpを使ってはならない。 文字列の入出力はmain関数で行い,関数str_compareの仮引数にはポインタ変数を宣言し,ポインタと間接演算子*を用いた処理を行うこと。 % ./a.out input str1 = Worldcup input str2 = Worldcup same strings % ./a.out input str1 = World input str2 = cup different strings この問題に私は次のようにプログラミングしました。 #include <stdio.h> #define MAX 100 int str_compare(char *, char *); main() { char str1[MAX], str2[MAX]; printf("input str1 = %s", str1); scanf("%s", str1); printf("input str2 = %s", str2); scanf("%s", str2); str_compare(str1, str2); if (str_compare(str1, str2) == 0) printf("same strings\n"); else if (str_compare(str1, str2) == 1) printf("different strings\n"); } int str_compare(char *s1, char *s2) { int i; for (i = 0; s1[i] != '\0'; i++) { if (s1[i] != s2[i]) { break; } } if (s1[i] == s2[i]) { return 0; } else { return 1; } } これで実行したところ、「input str1 =」の右のスペースが文字化け?してしまいます。(半角カタカナや記号が出る)ただ、その後に文字列を入力すると、正しく機能します。 これは何が悪いなのでしょうか、どなたか教えてください。

専門家に質問してみよう