痔になりやすい生活習慣とは?

コンソールプログラムで
scanf("%s", buf);
を使用してユーザに入力された文字によって処理を行いたいのですが、このままではスペースを含む文字列がスペースの手前で切られてしまいます。
C:\Program Filesなどを入力可能にさせたい場合にはどのようにするのがベターですか?

A 回答 (3件)

お任せください!


そもそもscanfを使うというのはお勧めでは
ありません。scanfは文字+改行文字が入力
されないと完了しないためです。
が、それは良しとしましょう。
scanfの書式ですが、

int n = scanf("%[^\r\n]",buf);

という便利な書式があります。
perlでもおなじみの書式ですね。
上記の山文字"^"より前が読み込ませたい文字の集まりで、ハイフン指定が出来ます。
"^"より後ろが読込みを停止させたい文字の集まりです。上記の指定は復帰改行以外の文字が現れるまで読み込みます、という書式です。
下記のような指定も出来ます。

int n = scanf("%[a-zA-Z0-9\\: \t^\r\n]",buf);

なお、戻り値は読み込んだ項目数ですので、
if(n >= 1)
{
}
で判断できますね。
    • good
    • 3

コンソールからの入力は、fgets(buf,sizeof buf,stdin); を使います。


scanfは使い方が難しいので初心者は使わないほうがいいです。特にコンソール入力にはまず使いません。定型書式のファイルから読むときに使うくらいですが、その場合もfscanfかfgets+sscanfを使うでしょう。scanfの存在を忘れてしまってもかまわないです。
    • good
    • 0

fgetsを使うというのではだめですか?

    • good
    • 3

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

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が...続きを読む

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

Qfgetsなどのときのstdinのバッファを消すには?

こんにちは,今C(C++でない)を使用しています。
たとえば,
char str[20]
fgets(str,sizeof(str),stdin)
としたときに20字以上を打つと,stdinのバッファに20字以上の分が残ったままになります。

C++などでは
fflush(stdin)で,うまくいきますが,普通のCでは対応がされていないみたいでうまくいきません。

よろしくお願いします。

Aベストアンサー

あ,テキスト入力だからこんな大掛かりなことしなくてもいいんだ.
末尾に'\n'が出るまで掃出せばいいんですよね.

fgets(str, sizeof(str), stdin);
if ( str[strlen(str)-1] != '\n' ){
while( getchar() != '\n' );
}

でいいんだ.失礼しました.

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セグメンテーション違反

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

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

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

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

Aベストアンサー

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

Qc言語のポインタへの文字列入力についてです。

当方c言語初学者なのですがscanfを使ってポインタに文字列を入力したいのですがバグが発生して進みません・・・どういうことなのでしょうか?
#include <stdio.h>

int main(void)
{
char *a;

scanf("%s", a);
printf("%s", a);

return (0);
}

*aをa[128]; のように配列に変えるとうまくいくことはなんとかわかるのですが・・・助けてください(^_^;)

Aベストアンサー

ポインターというのは格納された値のアドレスのメモリーを指すための変数です。
一方、配列はデータを格納するためのメモリーを確保して、その先頭のアドレスが入っていますよ。

char *a;
scanf("%s", a);

と書くと、aを初期化せずにaの指す先にscanfで文字列を入れます。
大抵、プログラムが書き込むことを許されていないメモリーに書き込みを行おうとしたことを検出したOSからそのプログラムは強制終了されます。

char *a = "aaaaa";
scanf("%s", a);
となっているとどうなるか。
aは"aaaaa"が格納されているメモリーを指すように初期化されます。
ただ、大抵"aaaaa"は固定値を入れるために書き込みができないメモリーに格納されています。
よって、scanf("%s", a);も書き込みができないところに書こうとしたことをOSに検出され、強制終了となります。

2つ方向があると思います。
1. char a[128];のように宣言し、スタック上にメモリーを確保し、その先頭アドレスが入っているaを渡す方法。
2. mallocなどでヒープにメモリーを確保する方法。

1だと、
char a[128];
scanf("%127s", a);
のように書き、scanfで読み込んだ分をaから始まるメモリーに書くことになりますが、char a[128];で配列を確保しているので書き込みを行うことができ、強制終了はされません。

2だと、
char *a = malloc(128);
scanf("%127s", a);
printf("%s", a);
free(a);
のように書きます。
配列はスタック上に取られ、スタック上に取った値はプログラムがその関数を抜けるときに自動的に解放されますが、mallocで確保したメモリーは自動で解放されないので自分でfreeを呼んで開放する必要があります。

%127sがそろそろ気になっていると思います。
こうやって127文字までしか受け取らないようにscanfに指示しています。
C言語では文字列の最後は終了を示すNUL文字が入るので、確保したメモリーよりも1少ない値となっています。

というわけで、ちゃんとメモリーを確保してからscanfで書き込みましょう。ポインターはあくまでどこかのメモリーアドレスを指すだけで、指した先がちゃんと確保されているかどうかは知りませんから。

ポインターというのは格納された値のアドレスのメモリーを指すための変数です。
一方、配列はデータを格納するためのメモリーを確保して、その先頭のアドレスが入っていますよ。

char *a;
scanf("%s", a);

と書くと、aを初期化せずにaの指す先にscanfで文字列を入れます。
大抵、プログラムが書き込むことを許されていないメモリーに書き込みを行おうとしたことを検出したOSからそのプログラムは強制終了されます。

char *a = "aaaaa";
scanf("%s", a);
となっているとどうなるか。
aは"aaaaa"が格納されている...続きを読む

Qc言語 ファイルから数字を読み込む

c言語初心者です。
forループをつかって、
ファイルから空白で区切られた数字を一つずつ読み込む
プログラムを作りたいのですが、
forループの中をどう書いたらいいかわかりません。

#include <stdio.h>

int main (int argc, char *argv[])
{
char *fileName = argv[1];

FILE *fp = fopen("fileName", "r");

int num;
int i;

for(i=0; i<10; i++){
fscanf(fp, "%d", &num);
printf("%d\n", num);
}
fclose(fp);
}

ファイルの内容は、10個の数字が書かれている設定です。

Aベストアンサー

FILE *fp = fopen("fileName", "r");
は、
FILE *fp = fopen(fileName, "r");
でしょうね。
他はいいと思いますが。

細かいことを言うと、argv[1] を参照する前に、argcの値をチェックすべき。

Qcharと%c , %s の関係について

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下のプログラムの printf 関数については間違った使い方なのではないかと思っています。

scanf("%s", &c) は入力された文字のうち、終端文字の手前までの文字を引数のポインタが示すオブジェクトへ順に格納していく関数だと理解しているので、入力された文字が一文字だった場合、&cの示すオブジェクトに文字が代入されると考えたからです。

逆に printf("%s", &c) は、&cの示すオブジェクトから”ヌル文字”の手前までの文字列を順に表示する関数だと理解しているので、問題なく動作しているのは&cで示されるオブジェクトの後ろの領域が偶然'\0'だったからではないかと考えたからです。

何かの本で、未使用の領域は0である確率が高いという記述をみたことがあり、'\0'は0と同じだということなので問題なく動作する率が高いのではないかと思っています。


僕の考え方がどの程度正しくて、正確にはどうなのかを教えて欲しいです。


ちなみに、

-----------------------
char c;
char str[100];

scanf("%s", str);
scanf("%c", &c);
------------------------

と書くと c には改行文字が代入されてしまいます。
scanf("%s", str);
において"aasssdd "と最後に空白を入れると
c には空白文字が代入されます。

しかし、
--------------------------
char str1[100];
char str2[100];

scanf("%s", str1);
scanf("%s", str2);
--------------------------
においては、
scanf("%s", str1);
で "asdfg "と最後に空白を入れても次のstr2が空白で始まることはありません。


この辺りの処理がどのような法則で実行されているのかが分かりづらくて悩んでいます。
おそらく、
scanf("%s", str);
の場合には最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。


分かる方がいましたら回答をよろしくお願いします。

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下...続きを読む

Aベストアンサー

> char c;
> scanf("%s", &c);
char c では1文字分の領域しか確保されていないので、
1文字以上の文字列を無理矢理格納すると
他のデータが存在しているかもしれない領域を書き換えてしまいます。(メモリ破壊)

なお、'\0'はscanfが(本来書き込んではいけない領域に対してですが)書き込んでいます。


> と書くと c には改行文字が代入されてしまいます。
最初のscanfが改行文字を読み込んでいないからです。
以下のページに書かれている内容と本質的には同じ。
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-

> 最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。
そう考えて問題ないと思います。

QC言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。

QC言語のポインターに関する警告

line[100]で
「1」が格納されていたら「a」
「2」が格納されていたら「b」
「3」が格納されていたら「c」
とout[100]に代入する関数を作りたいのですが
コンパイルすると関数の部分で
warning: assignment makes integer from pointer without a cast
という警告がでます。
ポインターは使っていないのですが、ポインターに関する警告が出ているようで困っています。
どこが悪いのかまったくわからなくて作業が完全に止まってしまいました。
解決法をおしえてください。お願いします。

/*宣言*/
int=i; /*main関数内のfor文で使用*/
char line[100], out[100];
void change(int);

/*関数*/
void change(int i)
  {
   if(line[i]=='1'){
    out[10]="a\0"
   }if(line[i]=='2'){
    out[10]="b\0";
   }if(line[i]=='3'){
    out[10]="c\0"
}
}

line[100]で
「1」が格納されていたら「a」
「2」が格納されていたら「b」
「3」が格納されていたら「c」
とout[100]に代入する関数を作りたいのですが
コンパイルすると関数の部分で
warning: assignment makes integer from pointer without a cast
という警告がでます。
ポインターは使っていないのですが、ポインターに関する警告が出ているようで困っています。
どこが悪いのかまったくわからなくて作業が完全に止まってしまいました。
解決法をおしえてください。お願いします。

/*宣言*/
int...続きを読む

Aベストアンサー

>    out[10]="a\0"
>    out[10]="b\0";
>    out[10]="c\0"

"a\0"や"b\0"や"c\0"は「charへのポインタ」ですよ。

out[10]は「char」ですから「記憶域が小さい整数(つまり、charに)に、ポインタを代入すると、値が失われるぞ」と警告が出ます。

void change(int i)
  {
   if(line[i]=='1'){
    out[10]='a';
   }if(line[i]=='2'){
    out[10]='b';
   }if(line[i]=='3'){
    out[10]='c';
}
}
または
void change(int i)
  {
   if(line[i]=='1'){
    out[10]=0x61; /* aのASCIIコード */
   }if(line[i]=='2'){
    out[10]=0x62; /* bのASCIIコード */
   }if(line[i]=='3'){
    out[10]=0x63; /* cのASCIIコード */
}
}
と書きましょう。

>    out[10]="a\0"
>    out[10]="b\0";
>    out[10]="c\0"

"a\0"や"b\0"や"c\0"は「charへのポインタ」ですよ。

out[10]は「char」ですから「記憶域が小さい整数(つまり、charに)に、ポインタを代入すると、値が失われるぞ」と警告が出ます。

void change(int i)
  {
   if(line[i]=='1'){
    out[10]='a';
   }if(line[i]=='2'){
    out[10]='b';
   }if(line[i]=='3'){
    out[10]='c';
}
}
または
void change(int i)
  {
   if(l...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング