文字列終端でハマった

投稿者: | 2014年4月17日

こんにちは、Sayahamittです。

TLに流れてきたAOJの問題を解答しようとしたらあらぬ勘違いで1時間くらいハマったので

戒めを込めて書きます。

解いたのは次の問題

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0006&lang=jp

20文字までの半角英数字の文字列入力に対して、文字の順序を反転させて出力せよ。

という簡単な問題です。

ハマったクセに”簡単”と言うのもナンですが…(´Д`)

で、何をやらかしたかと言うと、文字列終端の処理を勘違いしていたのです。

まずヤらかしているコードがこれです。

#include "stdio.h"
#include "string.h"

int main(){
	char str[21];
	int i=0;
	int flag=0;

	memset(str,'0',21);

	fgets(str,sizeof(str),stdin);

	for(i=20,flag=0;i>=0;i--){
		if(str[i]==0){
			flag=1;
		}else if(flag==1){
			printf("%c",str[i]);
		}
	}
	printf("\n");
	return 0;
}

C言語で解答したのですが(Cくらいしか使えない(´・ω・`))

fgetsで20文字分入力を取って、その文字列を逆から辿って一文字ずつ表示してやろうという魂胆です。

さて、キーボードからの入力を取るのに一般的にはscanf()ではなくfgets()を使うと思います。

fgets関数では改行コードも文字列の一部として取得し、取得した文字列の終端にNULLターミネータを付加するわけですが、私はNULLターミネータと改行コードをなぜか混同していて二者の区別が判然としていませんでした。(理由は今も謎のまま)

もちろん、改行コードとターミネータが別物だということも分かってたし、fgetsが文字列の最後にターミネータを挿入することも知ってたんですけど、なぜか混同してました…orz

その結果…

fgetsで取得した文字列の終わりが “…\n\0” となっていることに気が付かず、ターミネータを起点にして一文字ずつ逆から表示していった結果、謎(思い込み)の改行が発生してしまった、というのが事の顛末です。

 

クズかよww

 

しかもこれAOJではOutputでの改行が読み飛ばされるらしく、合格してしまったんですよね^^;

 

訂正箇所は一箇所、else ifの条件にstr[i]!=10を追加するだけです。
こんなかんじ

  for(i=20,flag=0;i>=0;i--){
    if(str[i]==0){
      flag++;
    }else if(flag==1 && str[i]!=10){
      printf("%c",str[i]);
    }
  }

普通はハマるところじゃないハズなんでしょうけど、ターミネータと改行コードの区別がはっきりしていないという重罪を犯していた為に、ループの回数とか、バッファクリアとかを疑っていたせいで解決に一時間も掛かってしまったわけです(;´д`)

 

以上、ドジ記録でした。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください