• ベストアンサー

空文字列の中身

 C言語の初歩を勉強中のものです。  文字列入力の練習問題で、空文字を入力したら終了という構文があって、模範解答は下記のようになっています。 char buffer[ 81 ]; printf( "文字列入力(80字以内・空文字で終了 )___" ); fgets( buffer, 80, stdin ); if( strcmp( buffer, "" ) == 0 ) { break; }  または、 if( strlen( buffer ) == 0 ) { break; }  ところがこれでは正しく動作せず、bufferの中身を調べると、「 0x0A 」が入力され、文字列の長さは1となっています。実際 if( buffer[0] == 10 ) { break; }  とか、 if( strlen( buffer ) == 1 ) { break; } に書き直すとうまく動きました。  Enterキーだけを押した場合、長さ 0 の文字列 "" が入力されないのは極めて困ったことのような気がするのですが、打開策はあるのでしょうか。  ちなみに環境は、Windows XP と Borland C++ 5.5 および BCC Developer です。

  • nng2
  • お礼率100% (3/3)

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

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.1

ちょっと問題に疑問があります。 「空文字を入力したら終了」となっていますが、 解答を見たところ、「空の文字列を入力したら終了」 のように思えます。 「空文字」は、\0で表されるchar型のデータであり、 「空の文字列」は、\0を指すポインタです。 わかりにくいかもしれませんが、これはC言語的には違いがあります。 また、キーボードから「空文字」(\0を表す文字データ)を入力する方法は 聞いたことがないので、おそらく無いと思います。 それはともかく、 fgets()は、改行文字を含めて受け取るという仕様があります。 それと対をなすfputs()は、表示する文字列に、改行文字を付加しません。 だからfgets()で読み込んだ文字列をfputs()で表示するとちょうどいいことになります。 似たようなのにgets()とputs()というのがあります。 gets()は、改行文字を除いて読み込み、 puts()は改行文字を自動的に付加します。 だから、問題では、fgets()のかわりにgets()を使えば 望んだ動作になります。 (引数が異なるので書きかえるときは注意すること) 上記のことは、仕様で決まっているので、 模範解答は何か勘違いしているのだと思います。 もし解答を書いたのが身近にいる先生だった場合、 「ここはfgets()ではなくてgets()のまちがいではないでしょうか?」 と教えてあげてください。

nng2
質問者

お礼

 早速のご指導をありがとうございました。  まだ教科書1冊の途中までしか進んでいないので、問題の理解が十分でないまま安易に質問してしまったようです。  問題文は、「空の文字列を入力したら終了」が正しい表現でした。また、回答も   scanf( "%80s",buffer ); であったのですが、これでEnterを押しても画面で改行されるだけで入力されないので、自分で fgets に変えてしまっていたのでした。  ご指摘あったように gets に変えて試したところ正しく動作しました。入力関数の仕様についてこれから勉強していきたいと思います。お手数をおかけしました。

その他の回答 (1)

回答No.2

この出題者は、stdinから入力すれば改行は入力されないものと勘違いしているうえ、動作確認しないまま出題したようです。 でも、fgetsの仕様はNo1さんのおっしゃるとおり改行を含めて入力する関数だから、空文字のつもりで改行のみ入力すれば、改行コードが入ってきてあたりまえです。 stdinから改行ナシで入力するのであれば、fscanf()や、gets()関数を使用すべきです。

nng2
質問者

お礼

ありがとうございました。No.1の回答者の方へのお礼に書いたように、いろいろ理解が足りませんでした。

関連するQ&A

  • 文字列の検索

    プログラミングの勉強の際に下のプログラムを作りました。 最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 コンパイルは通るのですが、文字列を2つ入力すると 「セグメンテーション違反です」と表記されます… どこが悪いのでしょうか? どなたか解説・指摘・模範解答などおねがいします。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(*c!='\0'){ c=a; d=b; while(*c!='\0' && *d!='\0') if(*c!=*d) printf("0"); break; c++; d++; } if(*d='\0') printf("1"); a++; return a; return NULL; }

  • 文字列の検索

    先日同じ質問をして、プログラムの内容を修正したのですが、今度は2つ文字列を入力した後0が無限にでてきます… どなたか解説・指摘・模範解答などおねがいします。 内容は最初にある文字列を入力して、その後別の文字列を入力して、 後に入力した文字列が最初に入力した文字列に含まれていれば1、 含まれていなければ0と表示するプログラムです。 (使用するのは#include<stdio.h>のみ、ポインタ変数必須です) #include<stdio.h> char *mystrfin(char *a, char *b); int main(void) { char *c,*d; char str1[100],str2[100]; printf("1>>"); fgets(str1,100,stdin); printf("2>>"); fgets(str2,100,stdin); *mystrfin(c,d); } char *mystrfin(char *a,char *b){ char *c,*d; while(c!='\0'){ c=a; d=b; while(c!='\0' && d!='\0'){ if(c!=d) printf("0"); break; c++; d++; } } if(d='\0') printf("1"); a++; return a; return NULL; } 例 検索対象文字列:asdfghjkl 検索文字列:sdf 1と出力 検索対象文字列:asdfghjkl 検索文字列:qwer 0と出力

  • enterでループ終了

    #include <stdio.h> int main(void) { char str[255]; int i, len; while (1){ printf("文字列を入力してください:"); if (fgets(str, sizeof(str), stdin) == NULL) { break; } len = strlen(str); if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; if (str[0] == '\0') break; enterで終了するプログラムの例ですが、 if (fgets(str, sizeof(str), stdin) == NULL) のNULLはどういった理由で必要ですか? また、 if (len > 0 && str[len - 1] == '\n') str[len - 1] = '\0'; を消して、 if (str[0] == '\0') break; を、if (str[0] == '\n') break; と書き換えれば、終了すのではないですか?不適な理由がありますか?

  • fgets関数を使用したときの文字あふれについて

    fgets関数を用いて文字列を入力し、その長さを測るプログラムを作っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main ( int, char *[] ); int main ( argc, argv ) int argc; char *argv[]; { char buf[( MAX )]; while ( 1 ){ memset ( buf, 0, sizeof( buf )); fgets ( buf, MAX, stdin ); if( fgets == NULL ){ break; } printf("入力した文字列の長さは%dです\n" ,strlen( buf )); } return 0; } このプログラムでは、256までしか文字列の長さを測ることができません。 もしこのプログラムで256を超える文字列を入力してしまうと、文字のあふれが発生し、 「入力した文字列の長さは256です」 「入力した文字列の長さは(あふれた文字列の長さ)です」 とこのようになってしまいます。 このプログラムで256以上の文字を読み捨てて、 「入力した文字列の長さは(あふれた文字列の長さ)です」 を表示しないようにできるのでしょうか? また読み捨てた文字列の長さを知ることはできるのでしょうか? もしかしたらfgets関数を使用すると不可能なのではないか?と思っています。 分かる方が居ましたらどうか教えて下さい。 よろしくお願いします。

  • 長さ1の空文字列?

    タイトルの通り、長さ1の空文字列で困っています。 現在、Linux、Apache、MySQL、PHPを使って3階層アプリケーションを作っています。 予めMySQLでテーブルの形を決めておいて、CSVからデータを読み込ませておき、 PHPでSQL文を実行してレコードを取得することで、それらをユーザに表示という感じです。 複数あるカラムのうち、空文字列(CSV上でブランクだったもの)は表示させたくないので、 PHPで「 if(カラム=="")~ 」のように比較することで、空文字列だけ避けるつもりでした。 しかし上手くいかなかったので、strlen()で調べて見たところ、返り値が1でした。 本来は空文字列に対してstrlen()は0或いはfalseの返り値を返しますよね。 is_empty()でも空データ扱いにならず、当然NULLの扱いでもありません。 そのため、実データとの区別が出来ずに困っています。 何故、空文字列のカラムを除外したいかというと、 DB上のユニークなレコードを検索したいからです。 select * from where カラム='データ' and カラム='データ'… という風に。 「カラム=''」としてしまうと検索に引っかからなくなってしまいます。 どうすればよいでしょうか。 以下はそれぞれのバージョンです。 MySQL:5.0.95 PHP:5.1.6 Linux:RHEL5 Apache:2.2.3

    • ベストアンサー
    • PHP
  • C言語におけるfgetsを用いたループ処理について

    C言語において、文章を読み込むためにfgetsを用いて下記のプログラムを書いたのですが、*において入力を受け付けなくなります。 これを解消する方法はないでしょうか? ちなみにコンパイラはBBC、開発環境はVistaです。 なお、簡略のため#include,main等は省略しています。 //以下プログラム #define SIZE 16384 char moji[SIZE] = {""}; char buf[SIZE]; //EOF(^Z)になるまで、文字列を受け取る while(fgets(buf, sizeof(buf), stdin) != NULL){ if(sizeof(moji) < strlen(moji) + strlen(buf)) break; strcat(moji, buf); }; getchar(); //* //プログラムここまで

  • 文字列がNULLか空文字列かの判定

    Visual C++で、Cのプログラムを作成しているものです。(OS:WinNT 4.0) 文字列の扱いについて、質問します。 関数 int func(char *str) があると仮定します。 パラメータとして、strは以下のような状態あるとします。 (strは関数が呼ばれる前にcalloc()で領域確保済み)  シンボル名 値  str      0x00000001 "" 上記の状態で、strがNULLか空文字列("")であることを条件式にしたいのですが、str == NULL は偽となり、strcmp(str, "") を使用すると異常終了します。 どうしたらよいのでしょうか。アドバイスをお願いします。

  • fgetsとsscanf

    C言語の勉強をしております。 初歩的な質問なのかもしれないですが、 char buf[80]; char data[32]; fgets(buf,sizeof(buf),stdin); sscanf(data, "%s", buf); と、 fgets(data, sizeof(buf), stdin); は何が違うのでしょう? 他の質問内容やネットで探してみたんですが、基本的には組み合わせて使用されているみたいなんですが、必要性がわかりません・・・。 例えば、fgetsで構造体のメンバ(文字配列)へキーボードからデータを入力したい場合は、どちらで行うのが良いのでしょう? また、入力データが未入力かどうか判断させるには、 fgets(buf,sizeof(buf),stdin); if(buffer[0] == '\n'){   /* ループを抜ける */   break; } で良いですよね? ※関連している質問 http://oshiete1.goo.ne.jp/qa4438371.html あと、同じ処理内で、getsやscanfを混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか? 以上、よろしくお願いいたします。

  • c言語 文字列の比較

    ファイルから読み込んだ文字列と入力した文字列を比較して同じなら次の処理を行いたいんですが、入力が例えば同じ1212でもstrcmp()で181がかえってきます。原因は何なのでしょうか? #define BUFMAX=45;  char smsg[BUFMAX];  char pass[BUFMAX];  printf("pass=%s\n",pass); printf("smsg=%s\n",smsg); c=smsg; stc=strcmp(pass,c); passにはscanfで1212を読み込みます。 smsgにはfgetsでファイルから一行読み込みます。 テキストのなかみは1212が一行はいっています。 自分では全く見当がつかないので、回答していただける方がいれば、ヒントでもいいのでお願いします。

  • fgetsでバッファ残留文字列を無視して読み込む

    お世話になります。 早速質問させていただきます。 言語はC++です。 ファイルに、以下の文字列があったとします。 ============================ 123456789012 12345678901 1234567890 123456789 ============================ この時、 fgets( str, 10, fp); printf("str (%2d)= %s\n", strlen(str), str); を、EOFになるまで繰り返します。 すると、実施結果は ============================ 123456789 012 123456789 01 123456789 0 123456789 ============================ となります。 これは、fgetsで10というレングスを指定しているために、1行読み込んで、10文字以降の文字列はバッファに残ってしまっているため、 2度目のfgetsで、10文字以降の文字列が読み込まれ、書き出されているものと思われます。 この時、fgetsで1行読み込んだ後、バッファに残った文字列を無視し、2度目のfgetsで、2行目を読み込むにはどうしたらよいでしょうか? 有識者の方、ご教授ください。よろしくお願いします。

専門家に質問してみよう