アプリ版:「スタンプのみでお礼する」機能のリリースについて

int main(void){
....
while(!(i==EOF)){
num=0;
while((i=fgetc(stream))!='\n'){
if(i==EOF) break;
str[num]=i;
num++;
}
kannsuu1();
kannsuu2();
}
return 0;
void kannsuu1(void){

printf("出力されない");
for(i=0;str[i]!=NULL;i=i+2){
printf("%c%c",str[i],str[i+1]);/*これも出力されない*/
}
}
void kannsuu2(void){
....
}

簡単に上記のように記述したプログラムがあるのですが、コンパイラの警告はまったくかかりませんでしたが、関数の中のprintfがdosプロンプトに出力されないのですよ。だれか心あたりがありましたらおしえてもらえないでしょうか?
お願いいたします。

A 回答 (9件)

出力できるようになったのですね?ヨカッタヨカッタ!



原因が分からない事なんて多々あります(笑)
そのうち原因に気が付くこともあるしね。

とりあえずmarkの位置修正などでソースとのにらめっこなどが続くと思います。
頑張ってください。
    • good
    • 0
この回答へのお礼

どうも今までありがとうございました。

お礼日時:2001/05/08 14:26

 うーん、、、Nickeeさんのソース丸々コピーして、divide()とcall_di()だけコメントにして実行したら、ちゃんと動きましたよ?(全角SPは消しましたが…)



OSはWin98、コンパイラはBorland C/C++ 5.5です。

↓これが使用したテストデータです。
あいうえお\n
さしすEOF

↓これが実行結果です。(DOS窓よりコピーしました)
ここからあいうえお
ここからさしす

・Nickeeさんの方の実行結果の画面って、どうなってます?できたらDOS窓のコピーをお願いします。
・とりあえずresult()以外の2つの関数呼び出しをコメントにして、↑のような超単純データでテストしてみてもらえますか?
・またresult()の代わりにputs(str)を実行してみてもらえますか?

#要求ばかり多くてゴメンなさい。。

以上、よろしくお願いします。
    • good
    • 0
この回答へのお礼

?????????????????????????????
( ? 0 ? )
なんか、いわれたとおりに、コメントにしたら、出力ができて、コメントを消してもう一度実行したら、プログラムが動きました。ちょっと、markの位置が微妙にづれていましたが。。。
うーーん?なぜ?
putsもうごきました。
とりあえず、直ったのでいいのですが、とりあえず、これで、締め切りたいのですが、leaz024さんにこれまで、付き合ってもらって、一方的に切るのは悪いと思いましたので、leaz024さんのご意見を聞かせてもらってから、切ろうと思います。
もし、なかったら、"ない"でもよろしいので。
ちなみに、僕は、原因がわかりません。メモリとか、関係あるんですかね。。

お礼日時:2001/05/08 10:03

 コンパイルでエラーが出たということですが、もしかしてNo.5のサンプルから、コピーしたりしました?



 サンプルはブラウザでの見栄えをよくするために、半角スペースやタブを使うところを「全角スペース」で書いています。文字列内などでない場所で全角文字を使用すると、「無効な文字がありました」のようなエラーになります。

 お使いのテキストエディタに「全角スペースを何らかの記号で表示する機能」などがあれば、有効にしておく便利ですよ。
 またソース全体を選択し、「全角スペース→半角スペース2個」の置換を実行してみるとよいでしょう。


#もし上記が見当違いの回答だとしたら、次の補足をお願いします。

>rewindを使用したら、コンパイルエラーがでて
このときに追加したコードを、そのまま見せていただけますか?

>rewindだけをけして
とは、どのようなことをされたのでしょうか?

この回答への補足

どうやら、コンパイラエラーは全角スペースが原因だったようです。leaz024さんのいうとおり、コピーをしてはりつけてしまいましたから。。
まだ、rewindをsetvbufをつかっても出力されないんですよ。もう、お手上げです。
下記にソースプログラムをのせておくので、leaz024さんもお忙しいと思われるので、暇で、気が向いた時でよろしいのですので、目を通してもらえれば、幸いです。結構長いので。。。

ちなみに、このプログラムは、あるテキストからdictionary.txtにある文字を探して、その部分だけ、||で囲もうとしたものです。文字はすべて、全角をいう設定で。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int mark[100];
char str[200];
char com[10][200][20];
char moji[100];

void divide(void);
void call_di(void);
void compare(char *moji);
void result(void);

/*======================================================================*/

int main(int argc,char *argv[]){

  FILE *stream;
int i=0,k,num;

for(i=0;i<=99;i++) mark[i]=0;

setvbuf(stdout,NULL,_IONBF,0);
if(argc!=2) {
printf("使用法:<プログラム名><ファイル名>\n");
exit(1);
}
if((stream=fopen(argv[1], "r"))==NULL){
printf("can't open\n");
exit(1);
}


while(!(i==EOF)){
num=0;
while((i=fgetc(stream))!='\n'){
if(i==EOF) break;
str[num]=i;
num++;
}
str[num]=NULL;
str[num+1]=NULL;

divide();
call_di();
result();
printf("\n");

}

fclose(stream);

return 0;
}

/*======================================================================*/
void divide(void){

int k,num,m;

for(k=1;k<11;k++){
for(num=0;num<strlen(str)/2;num++){
for(m=0;m<k*2;m++){
com[k][num][m]=str[num*2+m];
}
com[k][num][m+1]='\0';
}
}
}
/*======================================================================*/
void call_di(void){

  FILE *stream2;
int i,num=0;

if((stream2=fopen("dictionary.txt","r"))==NULL){
printf("can't_open_error\n");
exit(1);
}

while((i=fgetc(stream2))!=EOF){
moji[num]=i;

if(moji[num]=='\n') {
moji[num]=NULL;
num=-1;
compare(moji);
}
num++;
}

fclose(stream2);
}
/*======================================================================*/
void compare(char *moji){

int i;

for(i=0;i<strlen(str)/2;i++){
if(strcmp(moji,com[strlen(moji)/2][i])==0){
mark[i]=1;
mark[strlen(moji)/2+i]=1;
}
}

}

/*======================================================================*/
void result(void){

int i;

/*ここからの出力ができない*/
printf("ここから");
for(i=0;str[i]!='\0';i=i+2){
printf("%c%c",str[i],str[i+1]);
if(mark[i/2]) printf(" | ");
}
rewind(stdout);
}

補足日時:2001/05/06 13:09
    • good
    • 0

>>memset(str, '\0', strlen(str));  /* これしないと、まずくない? */


>これは文字列の最後にNULLをいれるということでしょうか?いちおう、単純にstr[n]=NULL;ってしてあります.

 例には書いてないだけで、他の雑用的な処理はなされているのですね。もしかしたら、その延長で処理してあるのかも知れませんが、一応気になったので・・・

  str[n] = NULL;

 これって、main関数内の処理の方にあるってことですよね?
kansuu1内では、strの中を1個おきにしか調べていないので、奇数番目にヌルが入っていると、そのままループが継続されてしまう可能性があります。
(前回の入力よりも入力した文字数が少なく、文字列長が奇数の場合)

 kansuu1の処理が3個単位になっても、1個単位になってもOKなように、2個のヌルを入れるのではなく、memsetでクリアするようにしてみました。

 それからヌルの使い方なんですが、ヌルを表すNULLと'\0'には
  ・NULL … 無効ポインタ
  ・'\0' … 文字列の終端記号
という、意味の違いがあります。
(Cでは
  #define NULL ((void *)0)
という処理系もあるので、この場合は'\0'とは全くの別物です。)

 使ってしまえばどちらも0なので問題はないのですが、人にソースを公開する場合には解読の助けにもなるので、このような使い分けは大事ですよ。
(特に集団開発などでは、人のコードを読まされる場合なんて多々あります。)

この回答への補足

すいません何度も。。
rewindを使用したら、コンパイルエラーがでて、

不正な文字 'character' (0x'value')
入力ファイルの中に無効な文字がありました。

その文字の 16 進値が出力されます。
これは,関数マクロに余分な引数が渡されたことが原因であることもあります。

.....なんて警告がでてしまい、しまったとおもって、rewindだけをけして、もう一度コンパイルしたら、この警告が消えなくなってしまいました。何か思い当たるふしがあるようであれば、もう一度アドバイスを願いたいのですが。。

補足日時:2001/05/05 19:24
    • good
    • 0

 そもそもコンパイラの警告やエラーというのは


  ・プログラム自体が間違っている場合
   (セミコロン抜けや括弧の不整合、文法ミスなど)
  ・間違いではないが、プログラマのミスではないかと思われるような記述を見つけた場合
   (ifやwhileなどの条件式内で、代入のみが行われているなど)
などに発せられるもので、動作の不具合を教えてくれるものではありません。
(このような実行時の不具合を一般に「バグ」と呼びます。バグを警告してくれるコンパイラなんてあったら、世の中つまんなくなっちゃうでしょ?)

 で本題ですが、a-kumaさんがおっしゃられているように、printf関数の出力先である「標準出力(stdout)」は、デフォルトでバッファリングを行うように設定されています。
 バッファリング付き出力先に対して出力を行う際は、バッファが満タンになるか、改行('\n')が出力されるかまで、実際の出力は行われません。

 途中途中で改行してやるのがベターなのですが、スクロールできないDOS窓プログラムなので、大量の情報を表示するために改行をしていないのでしょう。

 こういう場合、バッファリングを切ったりするのも手なんですが、バッファリングを切らずに、しかも改行しないで出力を実行させる関数があります。
 【書式】
   #include <stdio.h>
   void rewind(FILE *fp);
 この関数を使えば、その時点でバッファの中身が出力先デバイスに送られます。
引数には、<stdio.h>内で定義されているstdoutを指定すればOKです。

 例のリストは少し見にくかったので、少々手直しをしたサンプルを載せておきます。

#include <stdio.h>
#include <string.h>

/* main()内部 */
     :
  do {
    n = fgetc(stream);
    if (n != EOF && n != '\n') {
      str[num++] = (char)n;
    } else {
      kannsuu1();
      kannsuu2();
      num = 0;
      memset(str, '\0', strlen(str));  /* これしないと、まずくない? */
    }
  } while (n != EOF);
     :

/* kansuu1()内部 */
     :
  printf("表示されない?");
  for (i = 0; str[i] != NULL; i += 2) {
    printf("%c%c", str[i], str[i+1]);
  }
  rewind(stdout);    /* この関数実行後、画面に出力される */
     :

 とりあえずはrewindの行を追加するだけでも動きますので、お試しください。

この回答への補足

memset(str, '\0', strlen(str));  /* これしないと、まずくない? */
これは文字列の最後にNULLをいれるということでしょうか?いちおう、単純にstr[n]=NULL;ってしてあります.
とりあえず,rewindをつかってみます。ありがとうございました。

補足日時:2001/05/05 14:00
    • good
    • 0

まず、コンパイル環境くらいは書きましょう。


32bit Windowsなら「Win32コンソール」アプリ
ケーションにすればprintfの出力が見れます。

「関数のプロトタイプ宣言」が先であることは
分かっていますよね。

それと、
while(!(i==EOF)){
 num=0;
 while((i=fgetc(stream))!='\n'){
の使い方はあまり感心しません。

通常File I/Oでは
 while((i=fgetc(stream))!=EOF){
  //必要な処理を書く
 }
の様に書くのが普通ではないでしょうか?

今回のケースだと、
 num=0;
 while((i=fgetc(stream))!=EOF){
  if(i=='\n'){
   kannsuu1();
   kannsuu2();
   num=0;
   //ここでstr[]の中身をpaddingする必要がある
  }
  else{
   str[num]=(char)i;
   num++;
  }
 }
 if(num>0){//これがないと最後の1行が処理されない
  kannsuu1();
  kannsuu2();
 }
の様になるでしょう。

この回答への補足

 コンパイルの環境って。うーん、よくわかりませんけど、OSはwin98でBorlandの
TurboC++をインストールしています。
 関数のプロトタイプ宣言もちゃんとしています。

>while(!(i==EOF)){
 num=0;
 while((i=fgetc(stream))!='\n'){
の使い方はあまり感心しません。

通常File I/Oでは
 while((i=fgetc(stream))!=EOF){
  //必要な処理を書く
 }
の様に書くのが普通ではないでしょうか?

いや、一行づつ処理をしたかったので。。。

>今回のケースだと、
 num=0;
 while((i=fgetc(stream))!=EOF){
  if(i=='\n'){
   kannsuu1();
   kannsuu2();
   num=0;
   //ここでstr[]の中身をpaddingする必要がある
  }
  else{
   str[num]=(char)i;
   num++;
  }
 }
 if(num>0){//これがないと最後の1行が処理されない
  kannsuu1();
  kannsuu2();
 }
うーーーん、プログラムの処理のしかたが違っているような気がする。。

参考にさせてもらいます。ありがとうございました。

補足日時:2001/05/05 13:45
    • good
    • 0

int main(void){


....
  while(!(i==EOF)){
    while((i=fgetc(stream))!='\n'){
      if(i==EOF) break;
    }
    kannsuu1();
  }
  return 0;


void kannsuu1(void)
{
  printf("出力されない");



勝手にまとめさせてもらうとこんなプログラムになりますが
これで”出力されない”が出力されないなら
素人の私では回答できません。

もしよかったら
このプログラムがどのように終了するのか
教えてください。
    • good
    • 0
この回答へのお礼

int main(void){
....
  while(!(i==EOF)){
    while((i=fgetc(stream))!='\n'){
      if(i==EOF) break;
    }
    kannsuu1();
  }
  fclose(stream); 
  return 0;


void kannsuu1(void)
{
  printf("出力されない");


って具合で同じなのですけれど、勉強不足のため、どのようにプログラムが終了するかっていうのが、わからないのですけども。
 たとえを書いてもらえるわかるのですが。

お礼日時:2001/05/05 13:43

「出力されない」というのは、その関数を呼び出したタイミングで、ということ


なのでしょうね。

printf() は、普通、出力をバッファリング、つまり、関数の中で一時貯めておきます。
その貯めた中身を吐き出す、つまり、出力するのは、バッファが一杯になるか、改行(\n)に
当たったときです。

「dosプロンプトに」とあるので、勝手に Visual C/C++ だと想像しますが、関数の
リファレンスに書いてあります。

これを避けるためには、方法はふたつ。

ひとつは、バッファリングされていない stderr を使うこと。printf() を
fprintf(stderr, ...) に置き換えます。

もうひとつは、setvbuf() 関数を使って、バッファリングをしない指定をすること。
stdout に対して、バッファリングしない指定 _IONBF を指定します。

詳細は、関数のリファレンスを見て欲しいのですが、多分こんな感じの関数呼び出しを
最初に一発だけしておけば良いです。

  setvbuf(stdout, NULL, _IONBF, 0);

バッファリングをしない指定なので、バッファのアドレスやそのサイズは、
NULL と 0 を指定しておけば良いです。
    • good
    • 0
この回答へのお礼

 うーーん、わからない、何をいっているのか。。まあ、一行ずつ解読しつつ、読み進めていきます。ありがとうございました。

お礼日時:2001/05/05 14:06

printfの中に\nの改行マークを入れてないというのはどうでしょうか?


古い、unixならためておくこともあると思います。

あと、13行目のreturnの後ろに}で閉じてないのは、
省略しているだけですよね。
    • good
    • 0
この回答へのお礼

windowsなので、13行目はわすれていました。参考にさせてもらいます。ありがとうございました。

お礼日時:2001/05/05 13:38

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!