C言語関係掲示板

過去ログ

No.343.比較する文字列をファイルから読み込む

[戻る] [ホームページ]
No.2183

比較する文字列をファイルから読み込む
投稿者---おかむん(2002/07/25 17:22:33)


標準関数strcmp()をポインタを使用して作成し、比較する文字列を用意しておいたファイルから読み込むようにするというところなんですが、ファイルから文字を取り込むときにstr2に取り込めません。
#include <stdio.h>
#define SIZE 128

int strcmp(char *str1, char *str2)
{
while(*str1 == *str2){
if(*str1 == NULL)
return 0;
str1++;
str2++;
}
return( *str1 - *str2 );
}
main()
{
 FILE *fp;
 char str1[SIZE];
char str2[SIZE];
int n;

 if ((fp = fopen("test.txt", "r")) == NULL) {
printf("file open error!!\n");
return(-1);
}
while (fgets(str1, SIZE, fp) != NULL) {

}

n = strcmp(str1,str2);

if(n == 0)
printf("等しい\n");
else if(n > 0)
printf("str1大\n");
else
printf("str2大\n");

return 0;
}

str1へはこれで読み込ませたのですが、str2へも同じ方法でやってみたのですが失敗しました。同じtest.txtファイルからstr2へ読み込ますにはどうしたらよいのでしょうか?ファイルはargv,argcのように引数で指定するべきなのでしょうか?
申し訳ないですが、どなたか助言お願い致します。


No.2184

Re:比較する文字列をファイルから読み込む
投稿者---超超超超初心者(2002/07/25 17:52:42)


"test.txt"のフォーマットが分からないので
(文字列1と文字列2は改行で区切られているのか、同じ行に書かれていて
 スペースで区切られているのか・・・等)
何とも言えないのですが

>str1へはこれで読み込ませたのですが
とあるので、改行で区切られていることを前提とさせていただきます。

その際には、fgets()を使用すると1行単位で読込みを行うと思うので
> while (fgets(str1, SIZE, fp) != NULL) {
>
> }
だと最後の1行しか読み込めないと思います。
ですから、strを2次元の配列として宣言して
while (fgets(str[i], SIZE, fp) != NULL) {
i++;
}
とすればいいのではないでしょうか?

私なりに作成したソースを載せさせていただきます。
*************************************************************
#include <stdio.h>
#define SIZE 128

int strcmp(char *str1, char *str2)
{
while(*str1 == *str2){
if(*str1 == NULL)
return 0;
str1++;
str2++;
}
return( *str1 - *str2 );
}
main()
{
FILE *fp;
char str[2][SIZE];
int n;
int i = 0;

if ((fp = fopen("test.txt", "r")) == NULL) {
printf("file open error!!\n");
return(-1);
}
while (fgets(str[i], SIZE, fp) != NULL) {
i++;
}

n = strcmp(str[0],str[1]);

if(n == 0)
printf("等しい\n");
else if(n > 0)
printf("str1大\n");
else
printf("str2大\n");

return 0;
}
***********************************************************
私も初心者のため、まだまだ見にくい点や
よくない書き方等あると思いますので
その点をご了承ください。




No.2192

Re:比較する文字列をファイルから読み込む
投稿者--- 2児のオヤジ です。(2002/07/25 23:54:01)



>#include <stdio.h>
>#define SIZE 128
>
>int strcmp(char *str1, char *str2)
>{
> while(*str1 == *str2){
> if(*str1 == NULL)
> return 0;
> str1++;
> str2++;
> }
> return( *str1 - *str2 );

このstrcmpの使い方を現在勉強中ですが、
ANSIC言語辞典によれば、
int strcmp(char *str1, char *str2)
{
while(*str1 == *str2){

str1++;
str2++;
if(*str1 == NULL)return 0;
}
return( *str1 - *str2 );
}


最後のreturnの使い方はちょっと違いますが、このようになってました。

それと、この場合、strcmpでなくとも良いと思うのですが?
strcmpの内容を関数で処理してると思うのですが??

この辺のところが悩んでるところですが、具体的な質問事項が見つからず、
試行錯誤している最中です。

No.2193

Re:比較する文字列をファイルから読み込む
投稿者---TDa(2002/07/26 00:24:07)


cygwinのソースの核の部分を上げます。

while (*s1 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
return (*(unsigned char *) s1) - (*(unsigned char *) s2);

それと本当に
if(*str1 == NULL)return 0;
      ^^^
こうなっていますか?そうだとしたらその本は燃やしてもいいです。
100歩譲って
if(*str1 == 0)return 0;
なら譲らないこともないけどNULLはだめです。
定数0, NULキャラクタ'\0', NULLポインタの区別を理解していない宣伝して
いるようなものです。

NULLがたまたま0にdefineされているのならそれでも「動いてしまう」のでしょうけど 。#define NULL ((void *) 0)な処理系だったらエラーになるでしょ
う。

No.2194

Re:比較する文字列をファイルから読み込む
投稿者---長月葵(2002/07/26 01:27:15)


>このstrcmpの使い方を現在勉強中ですが、
>ANSIC言語辞典によれば、
>
int strcmp(char *str1, char *str2)
{
while(*str1 == *str2){

str1++;
str2++;
if(*str1 == NULL)return 0;
}
return( *str1 - *str2 );
}

>
>最後のreturnの使い方はちょっと違いますが、このようになってました。

すいません、突っ込みだけなので申し訳ないのですが。
手持ちのANSI C言語辞典を見てみたらstrcmpは以下のようになっていました。
コメントは省略しています。
int strcmp(const char *s1, const char *s2)
{
  while(*s1 == *s2)
  {
    s1++;
    s2++;
    if(*s1 == '\0')return 0;
  }
  return (unsigned char)*s1 - (unsigned char)*s2;
}
ちなみに僕の持っている物は初版第5刷です。

No.2195

Re:比較する文字列をファイルから読み込む
投稿者--- 2児のオヤジ です。(2002/07/26 08:25:21)


>>最後のreturnの使い方はちょっと違いますが、このようになってました。
>
>すいません、突っ込みだけなので申し訳ないのですが。
>手持ちのANSI C言語辞典を見てみたらstrcmpは以下のようになっていました。
>コメントは省略しています。
>int strcmp(const char *s1, const char *s2)
>{
>  while(*s1 == *s2)
>  {
>    s1++;
>    s2++;
>    if(*s1 == '\0')return 0;
>  }
>  return (unsigned char)*s1 - (unsigned char)*s2;
>}
>ちなみに僕の持っている物は初版第5刷です。


すいません、コピーペースト使ってました。
 \0 で間違いありません。


No.2196

Re:比較する文字列をファイルから読み込む
投稿者--- 2児のオヤジ です。(2002/07/26 08:38:19)


>すいません、コピーペースト使ってました。
> \0 で間違いありません。

お礼忘れてました。
TDaさん 長月葵さんご指摘ありがとうございます。
教えて頂けるのは、大変にうれしいことだと思います。
感謝しております。


No.2198

Re:比較する文字列をファイルから読み込む
投稿者---おかむん(2002/07/26 10:42:22)


ご指摘下さったみなさまありがとうございました。
私の見た本は図書室の所蔵なので燃やせませんが、返却することにします。

>超超超超初心者さん
質問が不足していてすいません。test.txtの中身は以下のような記述です。

+----------------
|abc abd
|123 125
|zyx xyz
|abc z
| :

上に書いて頂いたソースをコンパイルしてみたのですが、"0x0a7a7978"の命令が"0x0a7a7978"のメモリを参照しました・・・というアプリケーションエラーを起こしてしまいました。
私の使用しているコンパイラはBorland C++ 5.5です。
すいませんが、またよろしければアドバイスお願い致します。

>2児の親父さん
strcmp関数と同じ仕様の関数を自分で作ってそれが正しく動作するかテストする。そして、比較する文字列をテストする際に、ファイルから文字列を読み込んでテストさせるっていう質問だったのです。質問がわかりにくかったみたいで申し訳ありません。
ポインタと関数の勉強のためにやってみてと言われたので、strcmp関数でなくてもいいと言えばいいのですが・・・。
よろしければ質問の件の助言お願い致します。

>TDaさん
他の文献を参考に見てみましたら'\0'と記述されていました。
貴重なご意見ありがとうございました。
間違ったまま進むところでした。



No.2200

Re:比較する文字列をファイルから読み込む
投稿者---TDa(2002/07/26 11:11:04)



>>超超超超初心者さん
>質問が不足していてすいません。test.txtの中身は以下のような記述です。
>
> +----------------
> |abc abd
> |123 125
> |zyx xyz
> |abc z
> | :
>
>上に書いて頂いたソースをコンパイルしてみたのですが、"0x0a7a7978"の命令が"0x0a7a7978"のメモリを参照しました・・・というアプリケーションエラーを起こしてしまいました。

それじゃポインタが変なところをさしているんでしょう。ちゃんとstr1, str2が
取り込めているか確認しましょう。
fgetsという関数は'\n'か設定サイズまで1行読み込む関数ですので上記のようなコードですとstr2が不定になっているのではないかと思います。

ふつうは次のようにします。ほかでも応用が利くので覚えておくといいでしょう。

fgets(buf, BUFSIZE, fp);
sscanf(buf, "%s %s", str1, str2);


No.2201

Re:比較する文字列をファイルから読み込む
投稿者---超超超超初心者さん(2002/07/26 12:18:36)


なるほど。
そいういうフォーマットだったんですね。
確かにそういうフォーマットで実行すると
私が記載したソースではエラーが出てしまうと思います。
(コンパイルは通ると思いますが・・・)
ということで、以下のように修正したソースを
記載させていただきます。
但し、
1.文字列と文字列の間はスペースで区切られている
2.文字列2の最後には改行コードがある
というのを前提条件として書かせていただきました。

それと、今回の質問として
「str2に文字列が取り込めない」という内容だったので
strcmp自体は何も修正してません。
(関数名だけは変更させていただきましたが)
何か問題点や不備などがありましたら
ご指摘いただけると幸いです。
よろしくお願い致します。

#include <stdio.h>
#include <string.h>
#define SIZE 256

int strcmp_t(char *str1, char *str2);
void judege(int n);


main()
{
        FILE *fp;
        char tmp_buf[SIZE];
        char *str1;
        char *str2; 
        int n;

        if ((fp = fopen("input.txt", "r")) == NULL) {
                printf("file open error!!\n");
                return(-1); 
        }
        
        while (fgets(tmp_buf, SIZE, fp) != NULL) {
                str1 = strtok(tmp_buf," ");
                str2 = strtok(NULL," ");
                str2[strlen(str2)-1] = '\0';

                n = strcmp_t(str1,str2);

                judege(n);
        }
        return 0;
}

int strcmp_t(char *str1, char *str2)
{
        while(*str1 == *str2){
                if(*str1 == NULL)
                        return 0;
                str1++;
                str2++;
        }
        return( *str1 - *str2 );
}

void judege(int n)
{
        if(n == 0)
                printf("等しい\n");
        else if(n > 0)
                printf("str1大\n");
        else
                printf("str2大\n");
}



No.2215

Re:比較する文字列をファイルから読み込む
投稿者---TDa(2002/07/26 18:51:48)


> str2&nbsp;=&nbsp;strtok(NULL,"&nbsp;");
> str2[strlen(str2)-1]&nbsp;=&nbsp;'\0';

ここは
str2 = strtok(NULL,"\n");
でいいんじゃないの。

ただstrtokにはポインタをstaticで押さえているという欠点があるのであまり
使いたくないです。

こんな感じで十分なのでは

while (fgets(buf, SIZE, fp) != NULL) {
if (sscanf(buf, "%s %s\n", str1, str2) != 2) {
fprintf(stderr, "フォーマットエラー\n");
exit(1);
}
n = strcmp(str1,str2);

if (n == 0)
printf("%s, %sは等しい\n", str1, str2);
else if (n > 0)
printf("%s, %sは %sが大\n", str1, str2, str1);
else
printf("%s, %sは %sが大\n", str1, str2, str2);
}


No.2223

Re:比較する文字列をファイルから読み込む
投稿者---かずま(2002/07/28 00:44:16)


>こんな感じで十分なのでは
>
>while (fgets(buf, SIZE, fp) != NULL) {
> if (sscanf(buf, "%s %s\n", str1, str2) != 2) {

確かに十分なんですが、おそらく scanf の書式中の " " と "\n" の意味を誤解
されていると思います。どちらも、ゼロ個以上の空白類文字(スペース、タブ、
改行など)を読み飛ばすという意味です。"%s" 自身に空白類文字を読み飛ばす
機能がありますから、"%s%s" と書いても良いのです。

No.2216

Re:比較する文字列をファイルから読み込む
投稿者---2児のオヤジ です。(2002/07/26 23:07:53)


>>2児の親父さん
>strcmp関数と同じ仕様の関数を自分で作ってそれが正しく動作するかテストする。そして、比較する文字列をテストする際に、ファイルから文字列を読み込んでテストさせるっていう質問だったのです。質問がわかりにくかったみたいで申し訳ありません。
>ポインタと関数の勉強のためにやってみてと言われたので、strcmp関数でなくてもいいと言えばいいのですが・・・。
>よろしければ質問の件の助言お願い致します。
>

助言と言うより、この前つまずいたところだったもんですから、気になって書き込みさせて頂きました。

while(*str1 == *str2){
if(*str1 == NULL)
return 0;
str1++;
str2++;
}
return( *str1 - *str2 );
}

がstrcmpの内容であり、このときに、#include <string.h>を入れてエラーがでて困っていました。
エラー内容が”再宣言で型が一致していない”でstring.hをはずして動いたのと、
strcmpの rcをはずして、stmpに変えても問題なく動き、なるほどと思った
次第です。(例文はちょっと違います。)

その他に、whileの中身をANSI C言語辞典から借用しても、問題なく動きました。

この辺のstrcmpの使い方が気になったものですから、、、便乗質問ですネ!!

No.2226

Re:比較する文字列をファイルから読み込む
投稿者---おかむん(2002/07/29 02:45:11)


みなさま多量のアドバイスに解説ありがとうございまいsた。