(C言語)関数の中で文字列比較できない

このQ&Aのポイント
  • C言語の関数内で文字列比較ができない問題が発生しています。
  • 特定の文字列から助詞を取得しようとしている際、文字列比較が失敗してしまっています。
  • 助詞の番号を取得するための簡単な単体プログラムではうまく行くのですが、問題が発生しています。
回答を見る
  • ベストアンサー

(C言語)関数の中で文字列比較できない。

全体のソースコード省略させていただきます。 問題のある点だけあげたいと思います。 あるstr型:"初恋の人からの手紙" その文字列から助詞にあたるものを取得したいとする。 Phrase p_load(Phrase *p, char *str){ ....「省略」 str->particle[n] = get_jyoshi(js);//助詞番号取得 1。 printf("助詞:%d,jyoshi:%d\n", str->particle[n],get_jyoshi(js)); ===>>>get_jyoshiの関数はこんな感じです。 int get_jyoshi(char* js){ int num; if(strcmp(js,"の")==0){ return num = 1;} if(strcmp(js,"からの")==0){ return num = 2;} .......「省略」 else return 0; } 1。と書いてあるところに助詞の番号を表示しようとしたら助詞番号は"0"、つまりget_jyoshiの関数で文字列比較するときに失敗ということですね。。余談ですが、作ってるソースコードけっこう大きめですいくつかの再利用ソースコードと依存してます。そのため、試しで助詞番号を取得するための簡単な単体プログラムを作りました。そしたら、うまく行きましたが。問題はなんなんでしょうか?さっぱりわからないです。ご教授よろしくお願いします。

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

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.8

>もしかしたらファイル実体(emacsの方で)がなんらかの文字コードで保存されて、それで文字を比較できない、という可能性もあるんでしょうか? その可能性もあるような。 strstrだと一致したということですが、strstrの戻り値はポインタです。 つまり、==0で比較すると、不一致の時に、if文を通過します。 そもそも、strstrでも一致していなかったのではないですか?

g_loyd
質問者

お礼

長くなってしまってすみませんでした。 やっと解決しました。やはりemacsの文字コードの問題みたいです。 読み込みファイルと今回問題になるソースコードを全部最初から書き換えてみると、正常に動きました。-.-;; お騒がせしました。 ありがとうございました。

その他の回答 (7)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.7

>結果 >js : の >となるのです。 念のため、ですが、 { char *p=js; printf("["); while(*p){ printf("%02X ",*p++); } printf("]\n"); } だと、どう表示されるでしょうか。これならゴミがあってもわかります。

g_loyd
質問者

補足

アドバイス通りにやってみたら、このように結果が出ました:[FFFFFFA4FFFFFFCE] 言うのを忘れたんですが、このプログラムでファイル操作をやってます(最初から言うべきですね-.-;;)。あるテキストデータのファイルから文字列を読み込んで、処理をやってます。 昨日、思いついて、もしかしたらファイル実体(emacsの方で)がなんらかの文字コードで保存されて、それで文字を比較できない、という可能性もあるんでしょうか?

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

えぇと.... 最初に「プログラムを省略するのは構わないけど」と書いたけどやっぱり撤回. その現象が起きる, 「完全なプログラム」を出してください. 現状だとこちらで推測しなければならないことが多すぎるので, 実際にそのような現象が起きるのか, あるいはここに現れていない何かがおかしいのかを切り分けることができません. 今のままでは「群盲象をなでる」にしかなりません. たとえば, #1 の補足にある関数でもまだコンパイルエラーが出るはずだし, Phrase とかいうものがどのように定義されているのかわかりません.

g_loyd
質問者

補足

すみません、全体のコードをここであげられません。ここで挙げられないほどソースコードが大きいすぎです。はっきり言うと10以上のモジュールがあるので-.-;; 一応前言ってたように、全体をmakeするとコンパイルエラーになってないので、ソースコードは問題ないと思います。このプログラムでファイル操作やってますので、昨日、思いついてもしかしたらオープンするファイルの方に問題があるかもしれないです。(ファイル操作のこと最初から言うべきですね-.-;;;すみません)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.5

文字列からある特定の文字列を検索する、という行為と、 文字列どうしが一致しているかどうかを調べる、という行為が 全く別であることは理解できますね? 今回行ないたいのはどちらですか?strcmp関数を使うことが、目的に合致していますか?

g_loyd
質問者

補足

やりたいのは文字列同士が一致しているかどうかの方です。 そしたらstrcmpですよね。実際、ファイル操作やってますので、昨日思いついて、もしかしたら読み込むファイルのほうに問題があると。。。(ファイル操作のこと最初から言うべきですね-.-;; でも、ご意見ありがとうございます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.4

strstrというのは、文字列を検索する関数です。 ですので、 "なにぬねの" を入力した場合、 "の" と一致してしまいます。それでもいいのでしょうか?

g_loyd
質問者

お礼

今きづいたんです。やはりstrstrはダメ!!ですね。 get_jyoshiで"までの"、"についての"、"からの"という文字と比較してるので、もし"の"だけきたらこれらの文字と一致すると判定してしまった~~~~~~ (苦戦)なんでstrcmpうまく行かないだろうううう。。。-____-;;;

g_loyd
質問者

補足

本当はstrcmpのほうがいいですが、なぜか今のプログラムでうまくいかないです。ですのでstrstrにしました。もしかしたら、js の値を渡したときに何か見えないゴミが入って渡した"の"という文字を比較できないのでしょうか? でも、このように初期化もちゃんとやってましたが。。。 for(j=0;j<32;j++)js[j]='\0'; strncpy(js, &str[k], i-k); str->particle[n] = get_jyoshi(js)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

#2でう。 >実際表示できたんですが、jsの値は"0"と表示されたんです。 いや、戻り値じゃなくて、引数のほうですよ。

g_loyd
質問者

補足

引数の方はちゃんと文字列が入ってきました。 int get_jyoshi(char* js){ printf("js:%s\n",js); ......「省略」 でやったら 結果 js : の となるのです。 先ほどstrcmpではなくstrstrでやったら、うまくできました。 どうも、すみません。 解答ありがとうございます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

jsの値は表示させてみないのですか?

g_loyd
質問者

補足

実際表示できたんですが、jsの値は"0"と表示されたんです。 実際:"初恋_の_人_から_の_手紙" という文字列を処理して、 単語であるか助詞であるか判断する。 * "初恋" ときたら ==単語 * "の" と きたら ==助詞 しかし、"の"が来る時にget_jyoshiを呼出し、助詞の番号を取得しようとしたら返す値は"0"、つまり"の"は助詞番号がない、しかしget_jyoshiではこのように"の"であれば助詞番号は"1"です。 int get_jyoshi(char* js){ int num; if(strcmp(js,"の")==0){ return num = 1;}

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

プログラムを省略するのは構わないけど, 読み取るのに必要な文は残してください. 例えば, str の型は char * だから str->particle[n] は正しくありません. コンパイルエラーになるはずです. また, get_jyoshi に渡している js も宣言が現れていません. で, だけど, strcmp がどういう関数か理解できてますか? あなたがしたいのは「ある文字列の中から他の文字列を探す」ことであって, 「ある文字列が他の文字列と等しいかどうかを調べる」ことではないのではありませんか? 後者なら strcmp (や strncmp など) ですが, 前者では strstr あたりを使わないとダメですよ.

g_loyd
質問者

お礼

たった今strstrでやってみたらうまく行きました。すみません、ありがとうございました。 別のプログラムでstrcmpを使って、文字列の比較を上のやり方でやったらうまく行ったんですが、なぜでしょうか?strcmpについてもう一度勉強し直したいと思います。ありがとうございます。

g_loyd
質問者

補足

一応コンパイルエラーになっていないので省略しました。m(_ _)m すみませんでした。 実際、処理で使われる文字列はこんな形で:"初恋_の_人_から_の_手紙" Phrase* p(Phrase *str, char *buf){ int i, j, k, n, bun; char t[32],js[32]; /* 文字列の文節の数を数える */ n = 0; bun=0; for (i=0; i<strlen(buf); i++){ if (buf[i] == '_') bun++; } n = bun/2; str->num = n + 1; /* 文字列の単語と助詞の分割処理 */ i=0; k=0; while (buf[i]) { i++; if (buf[i] == '_'){ strncpy(str->basic_gainen[n],&buf[k], i-k); str->basic_gainen[n][i-k] = 0; k=i+1; i++; while(buf[i] != '_') i++; for(j=0;j<32;j++)js[j]='\0'; strncpy(js, &buf[k], i-k); str->particle[n] = get_jyoshi(js);//助詞番号取得 printf("n:%d,jyoshi :%d\n",n,get_jyoshi(js)); k=i+1; n--; } if(n==0){ //次が主部なら while (buf[i]) i++; strncpy(str->basic_gainen[n], &buf[k], i-k); str->basic_gainen[n][i-k] = 0; return c; } } return c; } 上の関数で一応文字列を分割したので、それぞれ、単語であるか助詞であるか処理を行う。分割した文字列をget_jyoshiにある文字列は等しいであれば助詞であると判断するという処理になっています。説明が下手ですみませんでした。伝わらない部分もあるかと思いますが、よろしくお願いします。

関連するQ&A

  • 関数の中のループについて

    typedef struct{ int num; char basic_gainen[MAX][32]; int particle[MAX]; }Gainen; int main (void){ Gainen g1, g2; char str1[256] = "外国_の_大型_の_船"; char str2[256] = "大型_の_船"; char buf[256]; divide(&g1, str1);//文字列の中から助詞と名詞を取得 divide(&g2,str2);//文字列の中から助詞と名詞を取得 printf("gainen:%s\n",print(&g1,buf)); printf("gainen:%s\n",print(&g2,buf)); if(hikaku(&g1,&g2)==1) printf("一部の単語は一致する\n"); } //二つの文字列を比較し、一部一致するかどうかの判定 int hikaku(Gainen *g1, Gainen *g2){ int n,i; if(g1->num != g2->num){ if(g1->num >= g2->num) n = g2->num; else n = g1->num; printf("n:%d\n",n); for(i=n;i>0;i--){ printf("inside loop i:%d\n",i); if(g1->particle[n] != g2->particle[n]) return 0; else if(strcmp(g1->basic_gainen[n],g2->basic_gainen[n]) != 0 ) return 0; } } return 1; } divide関数を省略させて頂きます。 hikaku関数のところで、二つの文字列の助詞と名詞が一致しなかったら0を返すその以外は1と返すというふうにしたいですが、実行したらhikaku関数から0の値wが返された。ループの数を表示したら、上のやり方でループがまわらないというのはわかったんです。上の条件判断はいけないですか?ご教授よろしくお願いします。

  • C言語 文字列操作

    トリム関数とリムーブ関数を作成してみました。改良点はありますでしょうか? ~~~~以下ソース~~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> char *Trim(char *str); char *Remove(char *str, char *rmv); void main(void) {  char str[10], rmv[10], *p;  int c;  /* " abcd "をトリムする */  strcpy(str, " abcd ");  printf("トリム前 |%s|\n", str);  p = Trim(str);  printf("トリム後 |%s|\n", str);  /* 指定文字列を削除する */  printf("削除する文字列を入力してください :");  scanf("%s", rmv);  Remove(str, rmv);  printf("削除後 |%s|\n", str);  exit(0); } char *Trim(char *str) {  char space[] = " ";  char null[] = "";  int index = 0;  while(1){   if(strcmp(&(str[index]), null) == 0){    index--;    if(strncmp(&(str[index]), space, 1) == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     break;    }   }else{    if(strncmp(&(str[index]), space, 1) == 0 && index == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     index++;    }   }  }  return str; } char *Remove(char *str, char *rmv) {  int c, size, i;  char *p;  c = '\0';  p = strchr(rmv, c);  size = p - rmv;  for(i = 0; i < size; i++){   c = (int)rmv[i];   p = strchr(str, c);   if (p != NULL) {    strcpy(&(str[p-str]), p + 1);   }   else{    printf("""%c""は見つかりませんでした\n", c);   }  }  return str; }

  • 文字列の引数を元に名前を変えて返す関数

    基本名と拡張子名と番号を引数として、連番ファイル名の文字列を返す関数を作っています。 例えばfor文で10回ループさせる場合、Name1に"画像"、Name2に".jpg"、Numにiを渡せば、文字列"画像00.jpg"~"画像10.jpg"が返ってくるという仕組みです。しかし、試行錯誤してもポインタの仕組みが根本的に理解できてないようなので、下に示すコードの修正と解説をお願いしてもよろしいでしょうか。ちなみにこのコードではstrcatの部分でエラーが起きます。 char FileRename(char *Name1,char *Name2,int Num) { char *FileNumber[100]; FileNumber[0] = "00"; FileNumber[1] = "01"; FileNumber[2] = "02"; FileNumber[3] = "03"; FileNumber[4] = "04"; FileNumber[5] = "05"; FileNumber[6] = "06"; FileNumber[7] = "07"; FileNumber[8] = "08"; FileNumber[9] = "09"; FileNumber[10] = "10"; FileNumber[11] = "11"; FileNumber[12] = "12"; FileNumber[13] = "13"; FileNumber[14] = "14"; FileNumber[15] = "15"; char *str; str = Name1; char *add = FileNumber[Num]; strncat(str,add,2); add[30] = *Name2; strncat(str,add,strlen(Name2)); return *str; }

  • C言語strcmpについて

    下記のプログラムでstrcmp動かしたところ、理論的には、68と表示されるところ、1と表示される理由を教えてください。詳細部分は、省略します、たとえば、include,const strcmp("ABCDE","ABC"); int strcmp(char *s1,char *s2){ while(*s1==*s2){ if(*s1=='\0') return (0); s1++; s2++; } return(( unsigned char)*s1 - (unsigned char)*s2);  

  • C言語での文字列ソート動作について

    任意の文字列を入力し、その文字列を昇順にソートするプログラムを作ったのですが、入力する文字の文字数が大きく異なると期待した結果が得られません。 文字数が少なくなったり、他の配列の文字が混ざったりと言う結果に成ってしまっています。 何が原因か分からない状態です。 以下にサンプルを記載させて頂きますので、助言よろしくお願いします。 /*----------------------------------------- 入力例 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC BBBBBBBBBBBBBBBB AAAAAA -----------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> void swapc(char *cx , char *cy){ char tmp[100]; strcpy(tmp, cx); strcpy(cx, cy); strcpy(cy, tmp); } int main(){ char *num[100]; char str_tmp[100]; //文字列一時格納 int moji_cnt; //入力した文字列のカウント int n , m; // 文字列入力処理開始 printf("文字列を入力してください\n"); for( moji_cnt = 0 ; moji_cnt != 3 ; moji_cnt++){ scanf("%s", str_tmp); *(num+moji_cnt) = (char *)malloc(sizeof(char) * (strlen(str_tmp)+1)); //メモリ確保 strcpy(*(num+moji_cnt), str_tmp); } puts("\n"); // 文字数ソート処理 for(n = 0 ; n < moji_cnt-1 ; n++){ for(m = 1 ; m < moji_cnt-n ; m++){ if(strcmp(*(num+n) , *(num+n+m)) > 0){ swapc(*(num+n) , *(num+n+m)); // 文字列入れ替え } } } puts("\n"); for(n = 0;n != moji_cnt;n++){ printf("%s\n" , *(num+n)); } free(num); }

  • 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言語 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; }

  • 文字列のコピーについて

    下記<コード1>と<コード2>はどちらも同じに思えますが、実際には<コード2>は”不正な処理”で終了してしまいます。 いろいろ考えたのですが、どうしても違いが理解できません。 理由がお分かりの方お願いいたします。 <コード1> char *str_copy(char *d , const char *s){ char *t=d; while(*d++=*s++) ; return (t); } int main(void) { char s1[128]="ABCD"; char s2[128]="EFGH"; str_copy(s2,s1); <コード2> char *str_copy(char *d , const char *s){ char *t=d; while(*d++=*s++) //不正な処理 ; return (t); } int main(void) { char s1[128]="ABCD"; char *ptr ="EFGH"; str_copy(ptr,s1);

  • 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言語について教えてください

    ファイルの文を読み込み、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; }

専門家に質問してみよう