利用規約の変更について

C言語標準入力でquitを入力で終わるプログラムを作っているのですが
うまくいきません

#include <stdio.h>

int main(void) {

int i, n;
double data[100];

printf("数字を入力してください。\n");
printf("入力を終えるときにはCtrl-dを押してください。\n");

n = 0;
while (scanf("%lf", &data[n]) != EOF) {
n++;
}

for (i=0; i<n; i++) {
printf("data[%d] = %f\n", i, data[i]);
}

return (0);
}

と今はとりあえづ作ってみたのですが
今のままではCtrl-dでループから抜ける形になっています
strcmp関数を使うとは思うのですが
strcmp関数はchar型なのでエラーが出てしまいます;
このやり方じゃないchar型にしてやり直さないといけないでしょうか;
Linux CentOS gcc
でやっています

標準入力で数字を入力しそれを格納
quitを入力するまで繰り返す
quitを入力で終了、これまで格納していた文字列の表示

簡単なプログラムの流れとしては上記の感じです
よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (13件中1~10件)

終了しますね。

>#12

hogehog12345670000004quit

とか入力すると妙な挙動に見えるかも知れませんね。
標準入力に残る関係上しょうもないですかね。
まぁ、エラーケース考えるのは質問者さんに任せるとします。
# 勉強用だとエラー処理とか入っていなかったりとか多いですし。
# fgets()の戻り値もチェックしていなかったなぁ、そういえば…。
    • good
    • 0

起動した直後に


hogehogquit
を入力するといきなり終了しちゃうような気がします>#11.

まあ「そ~いう仕様」だと思えばいいだけですが.
    • good
    • 0

こんな感じですかねぇ……


インデントを全角空白でやっているのでコピペする場合はご注意を。
一応、CentOS6.5で動作確認はしましけど。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MCH 8
#define N 20

int main()
{
 int data[N];
 int nc = 0, i, flag;
 char bff[MCH];

 do
 {
  /* 入力 */
  printf("data%d?:", (nc + 1));
  fgets(bff,MCH,stdin);
  /* "quit"だったら抜け */
  if(strcmp(bff,"quit\n") == 0)
  {
   break;
  }
  /* 数字以外があるか確認 */
  for(i = 0,flag = 1;bff[i] != '\n' && bff[i] != '\0';i++)
  {
   if(!isdigit(bff[i]))
   {
    flag = 0;
   }
  }
  if(flag != 1)
  {
   printf("error:数字のみでお願いします。\n");
   continue;
  }
  /* 5桁以上ならエラー(先のforループの結果、iは入力した文字数になっている) */
  if(i > 5)
  {
   printf("error:5桁以内でお願いします。\n");
   continue;
  }
  /* データ格納 */
  if(i != 0)
  {
   data[nc++] = atoi(bff);
  }
 }while(nc < N);

 /* 結果表示 */
 printf("データ:\n");
 for(i = 0;i < nc;i++)
 {
  printf("data[%d]=%d\n", i, data[i]);
 }
 return 0;
}
    • good
    • 0

先は長そうですねぇ……



>:27: error: ‘else’ without a previous ‘if’

>else if(!isdigit(bff))
のelseに流れる為のif文はどれでしょう?

>:33: 警告: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast …

>strcpy(a,bff);

char型に「文字列」は入れられません。
というか、この場合変数aに入っている謎の値がアドレスとして処理されます。(型が違うので怒られてますが)

>:35: 警告: passing argument 1 of ‘atoi’ makes pointer from integer without a cast …

>i=atoi(nc);

atoi()の引数はchar *かと。ncでは…アドレス0~10に数字が入っていることになります。
# 型がおかしいからやっぱり怒られる。

>:48: error: expected ‘while’ at end of input

久しぶりに「{」と「}」の対応が取れていません。
do {に対応する}は一番最後のものです。
よって、main()が閉じていませんので…
>:48: error: expected declaration or statement at end of input
こう言われます。


さて、他のツッコミ満載を消化しましょうかね。

>if(!(strcmp(bff,"quit\n")==0||nc==N))
ncがNだった時に…
>ch[nc++] = bff[0];
バッファオーバーフロー達成です。
ch[20]は安全に使える領域でしたか?

>char ch[N],a;

char型では値が入らない…と指摘済みですよね?

>scanf("%5d",bff);

%dで指定する場合は、結果を格納するアドレスを渡す必要があります。
bffはアドレスなのでまぁ、OKでしょう。
想定する動作はしませんが。
# bffからの連続する4バイトに「数値」が入ります。「数字」ではありませんのでご注意を。
# どう格納されるかは…エンディアン次第ですかね。(4バイトである保証もありませんが…まぁ、この場合どうでもいい話)

>else if(!isdigit(bff))

「isdigit()で1文字ずつ」と書いたかと思われますが……
何より引数の型が違うかと。(char *がintになったんですかねぇ…)

>printf("@ bff=%s",bff);
>printf("@ atoi(bff)=%d\n",atoi(bff));

入力のループの外にありますよ?
それで正しいのですか??

>fget(bff,MCH,stdin);
で数字を入力した場合は、まるっと捨てます。
# 後でscanf()しているから。
というかfgets()…ですよね??




なんというか、そろそろ回答例なコードでも乗せて強制終了した方がいいんじゃないか?
とか思い始めてきた……。
勉強にはたぶんならないけど。
    • good
    • 0
この回答へのお礼

すいません
長々付き合ってもらってしまって…

申し訳な過ぎるので
もお解答例を頂いて自分で勉強しようかと思ったのですが…

ご迷惑じゃなければ解答例を頂けないでしょうか

本当に長々付き合わせてすいませんでした

お礼日時:2014/09/10 14:53

>→数値=コンピュータで計算できる数字


>数字=人間語でコンピュータで計算できない
>って言う認識なんですが…;

おおむね合っている…かなぁ。
念のため、「数値 数字」などでWeb検索してください。

>→条件:数字以外入力時はエラー表示し、再入力・全角数字の場合入力時はエラー表示し、再入力
>というのもあるので

エラー判定の追加があるようなので…
イメージとして掲示した中の
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
の前で、入力した文字列が数字のみかどうかの判定処理を追加してください。

http://linux.die.net/man/3/isdigit
のisdigit()で「1文字ずつ」判定していけばよいでしょう。
# 数字=>数値変換でエラーになったら…とかいう手もありますけどね。
# ただしatof()は使えないですが。sscanf()でもダメ…かなぁ…(先頭が数字だと…ね)
    • good
    • 0
この回答へのお礼

とりあえず
大まかな流れとしてはこんな感じですかね?


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MCH 8
#define N 20

int main(){
char ch[N],a;
int nc,quit,ic,b;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;

do{
fget(bff,MCH,stdin);
if(!(strcmp(bff,"quit\n")==0||nc==N))
{
ch[nc++] = bff[0];
break;
}
else
{
scanf("%5d",bff);
printf("error:5桁以内でお願いします。\n");
}
else if(!isdigit(bff))
{
puts("error");
}
else
{
strcpy(a,bff);
ch[nc]=a;
i=atoi(nc);
}
while(!quit);
printf("@ bff=%s",bff);
printf("@ atoi(bff)=%d\n",atoi(bff));
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
b = ch[ic];
printf("ch[%d]=%d\n",ic,b);
/*printf("ch[%d] = %f\n",ic,ch[ic]);*/
}
return 0;
}


: In function ‘main’:
:27: error: ‘else’ without a previous ‘if’
:33: 警告: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast
/usr/include/string.h:128: note: expected ‘char * __restrict__’ but argument is of type ‘char’
:35: 警告: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
/usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘int’
:48: error: expected ‘while’ at end of input
:48: error: expected declaration or statement at end of input

めっちゃエラー出てしまったんですけどね…
これでも半分まで減らしましたが今出てるエラーは意味がわからなくて…

お礼日時:2014/09/10 13:51

>ch[]の値はどこでどんな感じで入れたら良いですか?;



数値で入れたいのか、文字で入れたいのか…どちらです?
# とりあえず、「数値」と「数字」の区別はつきますか?

>charじゃないほうが良いということはdoubleとかにしないとってことですかね…?

数値…であれば、int型の配列でいいんじゃないですかね?
文字として…ということならばchar型の二次元配列なりになると思いますが。

>あと条件で
>5文字以上の場合入力時はエラー表示し、再入力
>というのがありまして

nc=0;
do{
 fgets(bff,MCH,stdin);
 bffがquitじゃないか判定。
 =>quitだったらループ脱出フラグ設定
 else
  bffが5文字(5桁?)以内か判定
  =>5文字以上ならエラーメッセージ表示
  else
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
   nc加算
   ncが10か?
   =>10だったらループ脱出フラグ設定
}while(!quit);

って感じですかね。
数字=>数値変換でエラーになる可能性もありますけど。
「"wktk"を数値にせよ。」とか言われても困るでしょう?
    • good
    • 0
この回答へのお礼

# とりあえず、「数値」と「数字」の区別はつきますか?

→数値=コンピュータで計算できる数字
数字=人間語でコンピュータで計算できない
って言う認識なんですが…;

数値…であれば、int型の配列でいいんじゃないですかね?
文字として…ということならばchar型の二次元配列なりになると思いますが。

→条件:数字以外入力時はエラー表示し、再入力・全角数字の場合入力時はエラー表示し、再入力
というのもあるので
intですかね;

nc=0;
do{
 fgets(bff,MCH,stdin);
 bffがquitじゃないか判定。
 =>quitだったらループ脱出フラグ設定
 else
  bffが5文字(5桁?)以内か判定
  =>5文字以上ならエラーメッセージ表示
  else
   入力内容をコピー(ch[nc]=入力内容(数値で保持なら数字=>数値変換))
   nc加算
   ncが10か?
   =>10だったらループ脱出フラグ設定
}while(!quit);

って感じですかね。

→ありがとうございます。ちょっとそのやり方でやってみますね;

お礼日時:2014/09/09 16:39

>データ:


>ch[0] = ?
>ch[1] = A
>となって値が出てこなかったです;

出てきたら恐怖です。

>do{
>fgets(bff,MCH,stdin);
>if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
>nc++;
>}
>}
>while(!quit);
のどこで、ch[]に値を入れているのでしょうか?

あと…ch[]はchar型なので、入力した内容を数値として持つつもりなら
>234
>345
234はともかく345は入りません。(char型には255まで…でしょう。signed charだったら127)

さらに…
>printf("ch[%d] = %c\n",ic,ch[ic]);
%cで出力すると入力値によっては画面壊れたりしますよ。
# 表示できない文字コードだった…とか、コントロールコードだった…とか……。
    • good
    • 0
この回答へのお礼

ch[]の値はどこでどんな感じで入れたら良いですか?;

あと条件で
5文字以上の場合入力時はエラー表示し、再入力
というのがありまして…記載するのを忘れていましたが…
charじゃないほうが良いということはdoubleとかにしないとってことですかね…?

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

#define MCH 8
#define N 20

int main(){
char ch[N];
int nc,quit,ic,b;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;
do{
fgets(bff,MCH,stdin);
if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
ch[nc++] = bff[0];
}
}while(!quit);
printf("@ bff=%s",bff);
printf("@ atoi(bff)=%d\n",atoi(bff));
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
b = ch[ic];
printf("ch[%d]=%d\n",ic,b);
/*printf("ch[%d] = %f\n",ic,ch[ic]);*/
}
return 0;
}

お礼日時:2014/09/09 15:03

指摘漏れ。



>printf("str[%s] = %s\n",i,str[i]);

最初の%sで、アドレス0からの文字列を表示。
gccってことだからたぶん"(null)"で済むでしょう。
が、その次の%sで…str[0]の値がアドレスとして使用されて…ここでもセグメンテーションフォルト発動…でしょうね。

>char str[10];
では、入力された情報を保持し続けるには足りません。

>while(scanf("%s",str[n])){
>if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))

でnが10になっていた時には手遅れです。
配列の添え字の範囲について再度勉強し直してください。
# char str[10];
# で確保された配列は…
# str[0]~str[10]まで使えますか?
# str[1]~str[10]でしったけ?
    • good
    • 0
この回答へのお礼

指摘と自分なりに考えて下記のようにしてみました。


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

#define MCH 8
#define N 20

int main(){
char ch[N];
int nc,quit,ic;
char bff[MCH];

printf("入力(quit by quit):\n");
nc=0;
do{
fgets(bff,MCH,stdin);
if(!(quit=strcmp(bff,"quit\n")==0||nc==N)){
nc++;
}
}
while(!quit);
printf("データ:\n");
for(ic=0;ic<nc;ic++)
{
printf("ch[%d] = %c\n",ic,ch[ic]);
}
return 0;
}


gccでコンパイラ時のエラーはありませんでした

実行
入力(quit by quit):
234
345
quit
データ:
ch[0] = ?
ch[1] = A

となって値が出てこなかったです;

お礼日時:2014/09/08 16:04

>error: expected declaration or statement at end of input



14行目と16行目が対。(問題なし)
18行目と22行目が対。(だけど途中のreturnで終了)
5行目のmain()開始の「{」と、12行目のwhile()ループ開始の「{」が片思い中です。

あと……
>char str[10];
>scanf("%s",str[n])

入力された文字列を、どっか判らないアドレス(str[]は未初期化の変数なので入っている値は不定)に入れてね♪
ということで、コンパイルエラーを修正しても実行して入力した段階でセグメンテーションフォルトの魔法が発動でプロセス殺人事件が発生します。
犯人は……OSだっ!!
# 真犯人は仕組んだプログラマーだ。
    • good
    • 0

>passing argument 1 of 'strcmp' from incompatible pointer type



strとした時とstr[n]とした時で型が異なりますが、その辺りは理解してます?

>while(scanf("%s",str[n]));
>if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))

scanf()で入力を受け取ったのはstr[n][0]からstr[n][9]の範囲。
strcmp()で比較したいのはどこですか?
# あと、scanf()で受け取った時に改行文字入っていますか??

>error: expected 'while' at end of input

while()の後にセミコロンありますが、正しいですか?

というか、12行目にあるdoに対応するwhile()ってどれです?

>error: expected declaration or statement at end of input

「{」と「}」の対応が取れていません。
main()の「{」(5行目)に対応する「}」がありません。
vimでも対応する括弧は色を変えて表示してくれるオプションがあったと思いますのでその辺り確認しましょう。

ちなみに、16行目と18行目が対、
20行目と22行目が対、
13行目と24行目が対になっています。
# 24行目の対がmain()の開始…なのでしょうから、13行目の対が無い(というかdoに対応するwhile()が不明)というのが問題なのでしょう。
    • good
    • 0
この回答へのお礼

すいません;
少し直してみました;;;

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

int main(void)
{
int i,n,quit;
char str[10];

printf("プログラムを終了するにはquitを入力してください\n");
n = 0;

while(scanf("%s",str[n])){
if(!(quit=strcmp(str,"quit\n") == 0 || n == 10))
{
n++;
}
for(i=0;i<n;i++)
{
printf("str[%s] = %s\n",i,str[i]);

return 0;
}

gcc後のエラー↓

#ファイル名: In function 'main'*
#ファイル名#:22: error: expected declaration or statement at end of input

お礼日時:2014/09/08 14:25

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語 While文(ループ)内の文字入力

While文で、1文字入力をやれば思うようにうまくいかない。数字(データ)入力や、文字列入力の場合(%d 及び %s)ならうまくいく。文面で説明するより実際のプログラムを見た方が分かりやすいと思うので、以下にプログラムとその実行結果、実行結果に対する私が意図している結果とを示します。

【プログラム部分】
#include<stdio.h>

int main(void)
{
   char a;

   while(1)
   {
   printf("1文字を入力:");
   scanf("%c",&a);

   if(a == 'x')
     break;

   printf("入力したのは %c です。\n",a);
   }

   return 0;
}

【実行結果(キーボードからは「 e 」と入力」)】
1文字を入力:e
入力したのは e です。
1文字を入力:入力したのは
です。
1文字を入力:

【私が意図している結果】
1文字を入力:e
入力したのは e です。
1文字を入力:


 ちなみにC言語の環境は、インターネットで無料で入手できる試食版です。(LSI C-86 Ver3.30c 試食版)
 上記プログラムを見てもらえればお分かりだと思いますが、「xを入力するまで、永遠と1文字入力とその表示を行う」ことを意図しています。しかし実際の結果は意図に反しています。
 1回目は正常に動作しているようですが、問題は2回目以降。scnafで入力待ちをすることなく、なぜかscanfをスルーする形で3回目のscanf入力待ちとなっています。この理由を教えてください。お願いします。

While文で、1文字入力をやれば思うようにうまくいかない。数字(データ)入力や、文字列入力の場合(%d 及び %s)ならうまくいく。文面で説明するより実際のプログラムを見た方が分かりやすいと思うので、以下にプログラムとその実行結果、実行結果に対する私が意図している結果とを示します。

【プログラム部分】
#include<stdio.h>

int main(void)
{
   char a;

   while(1)
   {
   printf("1文字を入力:");
   scanf("%c",&a);

   if(a == ...続きを読む

Aベストアンサー

>1文字を入力:入力したのは
>です。

は、[Enter]キーの入力によるためです。
[Enter]キーをスルーする必要があります。

   char a;
char dummy; /*[Enter]キー用*/

   while(1)
   {
   printf("1文字を入力:");
   scanf("%c",&a);
scanf("%c",&dummy); /*[Enter]キー用*/

   if(a == 'x')
     break;

   printf("入力したのは %c です。\n",a);
   }


で、どうでしょうか?

Q数値の連続入力終了条件について

C言語初心者です。よろしくお願いします。

早速質問なのですが、while文を使ったscanf()関数による数値連続入力で、
◎1----------------------------------------------
#include<stdio.h>
int main(void)
{
     double dt,sum=0.0;
     while(scanf("%lf",&dt) !=EOF){
  sum=sum+dt;
}
  printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎1のようにすれば、Ctrl+ZでEOFが返されたら終了とわかるのですが、今度は「0」が入力されたら処理を終了するというプログラムで、
◎2----------------------------------------------
#include<stdio.h>
int main(void)
{
     double dt,sum=0.0;
     while(scanf("%lf",&dt) !=0.0){
  sum=sum+dt;
}
  printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎2のようにすると「0」が入力されても、終了せず、以下に示す◎3のように、しないと終了出来ません。
◎3----------------------------------------------
#include<stdio.h>
int main(void)
{
     double dt,sum=0.0;
   
     scanf("%lf",&dt);
     while(dt!=0.0){
  sum=sum+dt;
scanf("%lf",&dt);
}
  printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎2で何故、◎1のように出来ず、◎3のようなscanf()を1回目、2回目と判定を入れなければならないか教えて下さい。

C言語初心者です。よろしくお願いします。

早速質問なのですが、while文を使ったscanf()関数による数値連続入力で、
◎1----------------------------------------------
#include<stdio.h>
int main(void)
{
     double dt,sum=0.0;
     while(scanf("%lf",&dt) !=EOF){
  sum=sum+dt;
}
  printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎1のようにすれば、Ctrl+ZでEOFが返されたら終了とわかるのですが、今度は「0」が入力されたら...続きを読む

Aベストアンサー

◎1の書き方では、無限ループする場合があります。

scanfは「正しく変換を行った回数、または、入力が尽きた場合にEOF」を返します。

例えば
1.2[Enter]
3.5[Enter]
kkk[Enter]
と入力すると、kkkを入力してEnterを押した瞬間、無限ループします。

scanfは「kkkは%lfに合わないので、0個を変換しました」と0を返し、入力バッファにkkkを残したままにします。

0はEOFとは違うので、そのままループを繰り返します。

入力バッファにはkkkが残ったまま消費されないので、次の回も、次の次の回も、scanfは永久に0を返し続けます。

そして、プログラムを止める事が出来なくなります。

◎2の書き方でも、やはり無限ループする場合があります。

今度は「kkk」とか「@@@」とか「abcdefgh」とか、実数に変換できない物を入力する事で止まります。

しかし「Ctrl+Z」などを打ち込み「入力が尽きた状態」にすると、scanfはEOFを返します。

0はEOFとは違うので、そのままループを繰り返します。

キーボード入力は「入力が尽きた状態」のままなので、次の回も、次の次の回も、scanfは永久にEOFを返し続けます。

そして、プログラムを止める事が出来なくなります。

◎3の書き方でも、やはり無限ループする場合があります。

今度は「0」を入力する事で止まります。

しかし「Ctrl+Z」などを打ち込み「入力が尽きた状態」にすると、scanfはEOFを返します。

この時、dtはscanfによって値を変更されませんから、dtは前回入力したままの「0以外の値」になっています。

dtが0以外では、ループを終了しません。そのままループを繰り返します。

キーボード入力は「入力が尽きた状態」のままなので、次の回も、次の次の回も、scanfは永久にEOFを返し続けます。

そして、プログラムを止める事が出来なくなります。

そう言った訳で、質問者さんの書いた3つのプログラムはどれも「無限ループする、大変に危険なプログラム」です。

下記のようなプログラムが「無限ループしない、安全なプログラム」です。
#include<stdio.h>
int main(void)
{
  double dt,sum=0.0;
  while(scanf("%lf",&dt) != 1){ // EOFや0を返したらやめる
    if (dt == 0.0) // 正しい入力でも、入力が「0」ならやめる
    sum=sum+dt;
  }
  printf("合計=%f\n",sum);
  return 0;
}
もちろん、scanfは1個しかありません。

◎1の書き方では、無限ループする場合があります。

scanfは「正しく変換を行った回数、または、入力が尽きた場合にEOF」を返します。

例えば
1.2[Enter]
3.5[Enter]
kkk[Enter]
と入力すると、kkkを入力してEnterを押した瞬間、無限ループします。

scanfは「kkkは%lfに合わないので、0個を変換しました」と0を返し、入力バッファにkkkを残したままにします。

0はEOFとは違うので、そのままループを繰り返します。

入力バッファにはkkkが残ったまま消費されないので、次の回も、次の次の...続きを読む

Qセグメンテーション違反

C言語を使用しています。

構造体に値をいれようとしたら、コンパイルは出来るのですが、実行時に
「セグメンテーション違反です (core dumped)」
となってしまい、それ以上行えません。

構造体と代入したい変数との型は、合っています。

いろいろ本などで見ましたが、何が原因かわからず困っています。
教えてください。
宜しくお願いします。

Aベストアンサー

OSは何でしょうか。コンパイラは何を使用していますか?
通常、デバッグオプションをつけて実行すると、異常の発生したソースの箇所で止まりますので、それが手がかりになります。またNo1の方が言われてますように、ソースが公開できるのであれば、ソースを提示するのが良いかと思います。

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

QC言語で文字列をかえす正しい書き方が知りたいです?

C言語で次の警告が表示されます。
文字列を返したいのですが、正しい書き方はどのようにすれば良いのでしょうか?


jci.h(20) : warning C4172; ローカル変数またはテンポラリのアドレスを返します。


char *test(char *a, int b)
{
char str[BUFSIZ];
return str; <------

}

Aベストアンサー

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び出し元でちゃんとfreeしましょう。

B-2.呼び出し元でメモリを確保するケース
(注意:同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{

...

return str;
}
これは#1の方の回答と同じです。

B-3.B-1/B-2の複合
(注意:NULL以外の同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{
if(str == NULL)
{
str = malloc(BUFSIZ);
if(str == NULL) return NULL; //エラー
}

...

return str;
}

こんなところですかね。

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び...続きを読む

Q数字以外が入力されたらエラー文を出したい。

scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、無限ループが発生してしまいます。
エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを作りたいのですが、どうすれば出来るでしょうか。

Aベストアンサー

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を strtod() 関数で整数に変換します。
・このときグローバル変数の errno を調べて ERANGE なら整数値のオーバーフローが起きたとか、
 第2引数で私のポインタに変換できなくなった位置をセットしますので、このポインタが \0 文字
 以外なら数字以外(アルファベットや記号)が混ざっていることになります。
・下にそのサンプルを載せます。

サンプル:
char buff[ 256 ];
char *argp;
int value;

// 文字列で入力
scanf( "%s", buff );
value = strtol( buff, &argp, 10 ); ←10進数で変換

// ここでチェック
if ( (errno != ERANGE) && (*argp != '\0') ){
 printf( "変換不可能な文字が入力されています。\n" );
 exit( 1 );
}

その他:
・上記のサンプルを使うには errno.h をインクルードして下さい。
 このヘッダに ERANGE 定数が定義されています。
 あと stdlib.h もインクルードしないと strtol() 関数が利用できません。
・以上。下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strtol.html

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を str...続きを読む

Qファイルの中身検索と表示

Cでの作成についてなんですが、
fopenでテキストファイルを開き、テキストの中身の
特定文字が含まれている行を新に作ったファイルの中に
書き込みたいんですが、テキストの中身の検索と
抽出方法がいろいろ試してみましたがわかりません。
よろしくお願いします。

Aベストアンサー

★文字列の検索関数を使えば良い。
・テキストの中身の検索は、行単位で文字列を取得(fgets)してから、この文字列内に
 検索文字列の有無をチェックします。この有無は文字列から文字列を検索する関数
 『strstr』関数を使うのが便利です。また、文字列から1文字の検索を行う場合は
 『strchr』関数を使います。質問では、特定の文字が含まれている行となっていますが
・検索するのは1文字、文字群、文字列のどれですか?
 これによっていろいろと代わりますよ。処理が…。
・とりあえず文字列から特定の文字列を含まれた行を抽出するサンプルを下に載せます。

サンプル:
char buff[ 256 ];
char *find = "検索文字列";
FILE *fp; ←読み込み用
FILE *fo; ←抽出用

省略(fopen×2つ)

while ( fgets(buff,sizeof(buff),fp) != NULL ){
 if ( strstr(buff,find) != NULL ){
  fputs( buff, fo );
 }
}

省略(fclose×2つ)

解説:
・上記のサンプルでは、行単位でテキストの中身を取得して、この文字列から検索文字列(find)が
 含まれるか『strstr()』関数でチェックしています。見つかると『NULL』以外を返します。
・そして、見つかったらば行単位で『fputs』関数で出力しています。
 これで見つかった行だけが、新たに作ったファイルに書き込まれていきます。→抽出です。
・また『strstr()』関数の部分を
 『if ( strchr(buff,'a') != NULL ){ … }』とすると『a』の文字が含まれる行のみを抽出します。
 『if ( strspn(buff,"+-*/") != 0 ){ … }』とすると『+-*/』の文字群が含まれる行のみを抽出します。
 検索する文字とは、1文字、文字群、文字列のどれですか?
・以上。おわり。→上記のを参考にして下さい。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strspn.html,http://www9.plala.or.jp/sgwr-t/c/sec17.html

★文字列の検索関数を使えば良い。
・テキストの中身の検索は、行単位で文字列を取得(fgets)してから、この文字列内に
 検索文字列の有無をチェックします。この有無は文字列から文字列を検索する関数
 『strstr』関数を使うのが便利です。また、文字列から1文字の検索を行う場合は
 『strchr』関数を使います。質問では、特定の文字が含まれている行となっていますが
・検索するのは1文字、文字群、文字列のどれですか?
 これによっていろいろと代わりますよ。処理が…。
・とりあえず文字列から特定...続きを読む

QEnterキーを押されたら次の処理に移るという事をしたい。

コンソールアプリケーション上で文字列を表示させた後、ユーザーがエンターキーを押したら次の文字列を表示するという仕様にしたいのですが、エンターキーだけ入力待ちにするっていうのはどのように書けばいいんでしょうか?

Aベストアンサー

#include <stdio.h>

int main(void)
{
char *str[] = {"abc", "def", "ghi", "jkl"};
int i;

for(i = 0; i < 4; i ++){
while(getchar() != '\n') ;
puts(str[i]);
}
return 0;
}

Qnullと""、\0とEOFの違いについて。

いつも気になっていたのですが、
(1)nullと""、(2)\0とEOFは、同じなのでしょうか、
違うのでしょうか。
(1)については、違う気がします。しかし、""は、
なにを表しているのか分かりません(0バイトなのか、
空文字にも文字コードがあるのか、""と空白" "は
違うのか)。
(2)は、同じだと思うのですが・・。
文字を数えたりすると、これらが気になります。
お願いします。

Aベストアンサー

意味が違ってくるんです。

(1) NULL と ""
同じ事です。NULLとは「未定、未知、不明」ですので
まだ文字列が決まってない(設定しない)と言うことで
未定(=NULL)です。

(2)\0 と EOF
こちらは違います。文字列の終端文字としての'\0'は
NULLの事で、確定している文字が無くなった=文字列の終わり
と判断しているのです。
EOFは文字列ではなくファイルの終端です。
処理系によって変わってきますが、Windowsでは
NULL = 0
EOF = -1
と定義されてる事からも違うのは明らかです。

QコマンドプロンプトからのEOFの入力方法について

#include <stdio.h>

main(){
int cnt[10];
int c;
int i;
for(i=0; i<10; i++){
cnt[i] = 0;
}
while((c=getchar())!=EOF){
if(c>='0' && c<='9'){
cnt[c-'0']++;
}
}
for(i=0; i<10; i++){
printf("%d : %d", i, cnt[i]);
}
}

という、キーボードから入力した数値の個数を
表示するプログラムを、VisualC++で、Win32consoleアプリケーションで作ったのですが、
コマンドプロンプトから何個かの数値を入力したあと、Enterキーを押しても
何の反応もありません。
キーボードから「EOF」を入力するにはどうすればよいのでしょうか。
または、どういう状態をEOFと言うのでしょうか。

Aベストアンサー

くわしかないですが。
・Windowsのコマンドプロンプトでも^Zで入力終了です
#って違うことを訊いていたり?

・^ZはASCIIだと0x1aなのはその通りですが、getcharでそのキャラクタを
受け取るわけではありません。#3の回答にあるとおりです。
#(ストリームがバイナリの場合は別)

・テキストモードでファイルをオープンして読み込んでいる場合、
・・データの中に0x1aがあってそこに到達した
・・ファイルの終端に到達した
ときにEOFが返ってきます。


人気Q&Aランキング

おすすめ情報