質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

9474閲覧

コンパイルエラー 整数型とポインタの比較

FumiakiNakao

総合スコア180

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/10/04 13:21

基礎的な質問でごめんなさい
textin.txt ファイルの空白、改行をすべて取り除いて、textout.txtファイルに出力したいです

c

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5int main(){ 6 7 FILE *fp,*fq; 8 char str[100]; 9 int i; 10 11 fp=fopen("textin.txt","r"); 12 if(fp==NULL){ 13 printf("File open error1\n"); 14 return 1; 15 }//File読み込みに失敗した場合 16 17 fq=fopen("textout.txt","w"); 18 if(fq==NULL){ 19 printf("File open error2\n"); 20 return 1; 21 }//File読み込みに失敗した場合 22 23 while(fscanf(fp,"%s",str)!=NULL){ 24 25 26 for(i=0;i<=strlen(str)-1;i++){ 27 fputc(str[i],fq); 28 } 29 30 } 31 32 fclose(fp); 33 fclose(fq); 34 35 return 0; 36}

このコードだとコンパイル時にwhile文の部分で「整数とポインタを比較しています」というエラーが出ます

疑問点は2つです
①なぜこのようなエラーがでるのか
(fscanfがint型としてNULLがポインタ型と見られてしまうのはなぜか)

②エラーが出ない書き方はどのようなものか

ご教授お願いしますm(__)m

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

>なぜこのようなエラーがでるのか
(fscanfがint型としてNULLがポインタ型と見られてしまうのはなぜか)

fscanf()の戻り値がintでNULLが(大抵)void*型だからです。

>エラーが出ない書き方はどのようなものか
fscanf()の戻り値を確認しましたか?・・・EOF(-1)あるいは読み取った項目数です。

[たとえば・・・]
文字列から空白と改行を取り除く関数を作って、fgets()で一行読んで処理をさせ書き出すようにします

時間があったので作ってみました。(stdin→stdoutです)

C

1~/test/ctst >cat tst08.c 2#include <stdio.h> 3#include <ctype.h> 4 5void DelSpace(char *strp); 6 7int main() 8{ 9 char buf[1024]; 10 // 11 while(fgets(buf, sizeof buf, stdin)){ 12 DelSpace(buf); 13 fputs(buf, stdout); 14 } 15 // 16 return 0; 17} 18 19 20void DelSpace(char *strp) 21{ 22 char *sop= strp; 23 char *dip= strp; 24 // 25 while(*sop){ 26 if(!isspace(*sop)){ 27 *dip++= *sop; 28 } 29 sop++; 30 } 31 *dip= '\0'; 32} 33 34~/test/ctst >./a.out <tst08.c 35#include<stdio.h>#include<ctype.h>voidDelSpace(char*strp);intmain(){charbuf[1024];//while(fgets(buf,sizeofbuf,stdin)){DelSpace(buf);fputs(buf,stdout);}//return0;}voidDelSpace(char*strp){char*sop=strp;char*dip=strp;//while(*sop){if(!isspace(*sop)){*dip++=*sop;}sop++;}*dip='\0';}~/test/ctst > 36

投稿2016/10/04 13:56

編集2016/10/05 04:35
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FumiakiNakao

2016/10/06 03:52

回答ありがとうございました NULLは*void型なのですね 勉強不足でした サンプルプログラムも大変参考になりました
guest

0

cateyeさんの回答が正鵠を射ていますが、補足。

fscanf関数は、scanf/printf系統に分類され、正常に入力された項目数(読み込みエラー時はEOF)を返します。

fgets関数は、gets/puts系統に分類され、入力された内容へのポインタ(エラー時はNULL)を返します。

要するに、似た目的で利用される関数ではあるが、返り値の仕様が違うわけです。昔からの伝統で規格化されたので、こういうもの、と割り切ってもらうしかありません。

本問では、条件式をwhile(fscanf(fp,"%s",str)>0)とすれば、正しく動作します。

以下蛇足:本問とは直接関係がないので、余裕があれば読んでください。

このプログラムには、あと2ヶ所、問題があります。
1つ目は、書き込み用ファイルが開けない場合の処理です。読み込み用ファイルが開いたままに、なりませんか?
2つ目は、長い単語入力があった場合です。もし101桁の数字が入力されたら、バッファオーバーフローが発生します。バッファオーバーフローは、時に深刻なセキュリティホールになります。修正方法ですが、while(fscanf(fp,"%99s",str)>0)と、fscanf関数の引数で桁数を指定すれば、この問題は回避されます。

投稿2016/10/05 01:04

編集2016/10/05 01:15
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FumiakiNakao

2016/10/06 03:51

回答ありがとうございました よくわかりました その他の問題点についてもご指摘ありがとうございます 次回からはそのことにも気をつけてプログラムを組んでいこうと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問