A 回答 (11件中1~10件)
- 最新から表示
- 回答順に表示
No.11
- 回答日時:
fgetsについて
>こちらは'\0'ターミネートが保証されます。
これは、此方の勘違いでした。
#strncpyあたりと勘違いしてたようです。
>strtolは現在主流のANSI-C(C89)では定義されていません。
これについては、JIS X3010-1993の7.10.1.5に定義されてます。
ANSI/ISOについてのソースが手元にないですが、原文ISO9899(C89)にも乗っているはずですが。
No.10
- 回答日時:
strtolは現在主流のANSI-C(C89)では定義されていません。
strtolのサポートはC99からで、Visual C++6.0はC89準拠です。
よって、
> ここまでくるとその処理系が本当にANSI Cかどうか疑いたくなる
「処理系のANSI-C準拠」と「strtolの挙動に対して予防線を張ること」に矛盾は生じません。
> strtolはpを走査の終了位置を示す文字へのポインタにするので、
> p == &str[strlen(str)] つまり *p == '\0'
>となり、p == NULL にはならないです。
前述のようにC89におけるstrtolの挙動は処理系依存である確率が高く、このような断言は危険です。
> fgetsはgetsのように'\n'を'\0'に変換しないのでチェックは必要ですよ?
そうですね。
カン違いでした。
> また、'\0'でターミネートされた値が確実に入るわけではないのでその辺も注意が必要です。
こちらは'\0'ターミネートが保証されます。
(C89,C99ともに)
No.9
- 回答日時:
> 質問の趣旨が「入力文字エラーチェック」ですから不正文字入力を認識するためにstrtol()を使うべきと考えました。
この点に付いてはどちらでも目的を達成できるので異論はないですが、
> pがNULLなら変換不能文字無し(=文字列は全て10進数に変換された)
strtolはpを走査の終了位置を示す文字へのポインタにするので、
p == &str[strlen(str)] つまり *p == '\0'
となり、p == NULL にはならないです。
> fgets()だから'\n'チェックは不要だし、
fgetsはgetsのように'\n'を'\0'に変換しないのでチェックは必要ですよ?
また、'\0'でターミネートされた値が確実に入るわけではないのでその辺も注意が必要です。
> '\0'を変換不能文字だと認識するようなstrtolの実装は見たことが無いのですが、
ここまでくるとその処理系が本当にANSI Cかどうか疑いたくなる。
No.8
- 回答日時:
2度目です。
質問の趣旨が「入力文字エラーチェック」ですから不正文字入力を認識するためにstrtol()を使うべきと考えました。
long strtol(char *, int, char **) ;
文字列を数値に変換
関数値:
変換後の数値。
文字列に変換不能文字があった場合、変換可能文字までを変換する(1zの場合、1)。
文字列が先頭から変換不能文字であった場合0。
第1引数:
変換対象の文字列。
第2引数:
変換の基数。
10→10進変換
16→16進変換
8 →8進変換
0 →C言語の定数記述規約に従い変換(0x=16進。0=8進)
第3引数:
変換不能文字を発見した場合、発見した変換不能文字のアドレスを設定する。
10XYZと文字列であれば'X'のアドレス。
この引数がNULLであった場合変換不能文字の報告を行わない
val[no] = strtol(str, 10, &p) ;
val[no]には変換できたところまでの数値が入ります。
pには変換不能だった文字のアドレスが設定されます。
pがNULLなら変換不能文字無し(=文字列は全て10進数に変換された)
*pが文字なら入力文字列に含まれた変換不能文字そのものへのアドレスです。
*p != '\0' && *p != '\n'の部分は「'\0'や'\n'が変換不能文字として報告されたら困る」という場合のチェックです。
fgets()だから'\n'チェックは不要だし、'\0'を変換不能文字だと認識するようなstrtolの実装は見たことが無いのですが、老婆心で常に入れるクセついてて…
エラールートなので(P!=NULLの時しか通らない)処理効率と関係ないので「nul文字と改行は無関係」という仕様を示す意味もあって入れてたりします。
sscanfやatoiは変換不能文字の報告を行わない(ssacnfでは可能だが、利用法が煩雑)ため、「エラーチェック」を趣旨とするこの質問には合致しないと考えます。
No.7
- 回答日時:
>ret = sscanf(buffer, "%d%[\n]", &data[i], &dummy);
↑の行間違い本当は↓
ret = sscanf(buffer, "%d%1[\n]", &data[i], &dummy);
どう違うかは考えてみてください。
No.6
- 回答日時:
何か問題を難しく考えすぎているようですが、
#1のやり方でgetsをfgetsにすれば一番単純では?
わざわざ一文字づつ調べる必要もないとけど。
とりあえずこんな感じ↓
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 10
#define BUFFER_SIZE 256
int main(void)
{
int ret, i;
int data[DATA_SIZE];
char buffer[BUFFER_SIZE];
char dummy;
for(i = 0; i < DATA_SIZE; i++)
{
printf("input data[%d] > ", i);
fgets(buffer, BUFFER_SIZE, stdin);
ret = sscanf(buffer, "%d%[\n]", &data[i], &dummy);
if(ret != 2)
{
printf("\ndata err!!\n\n");
--i;
}
}
for(i = 0; i < DATA_SIZE; i++)
printf("data[%d] = %d\n", i, data[i]);
return 0;
}
No.5
- 回答日時:
#4です。
>上記のサンプルは文字0から9の入力の場合には、配列に入力文字を格納するものですが、
>これでは126とか-46など、2桁以上の数字や、負の整数には対応できないようです。
先頭文字のチェックをしていませんの符号文字の入力には対応していません。
必要なら先頭文字のときに符号文字をチェックすればいいと思いますが。(ご自分でどうぞ)
2桁以上の数字には対応していませんか? どう読んだのでしょうか?
これは、1つの数値を文字列として格納する部分です。
これを数値データにして、数値配列に格納する部分は含まれていませんが。
尚、これがコンソールのアプリケーションの場合、
BSキーなどによる編集機能に対応するとか、
1文字入力関数もgetchar()でなく画面エコーしない関数を使うとか、
他にも考慮すべき点が多々ありますが、質問とかけ離れますので割愛しています。
要は、1文字ずつ入力して、都度チェックしてバッファにためる数値文字入力専用の関数を
作ればいいのではないでしょうか。
1行入力して、文字列の中身を検査して不適当な文字があれば再入力するようにするのが
一番簡単ですが、そういうものをご希望なんですか。
No.4
- 回答日時:
#3に方のご指摘のように、gets() は使用しないほうがいいですよ。
セキュリティホールの元凶になっている関数です。
文字数が制限できないので、バッファが溢れると弊害が出ます。
VCではどうか知りませんが、gccなどで"dangerous"というWarningが出ます。
ところでDOSアプリケーションでしたら、
getchar()で1文字入力が可能じゃなかったでしょうか。
で、こんな感じではどうでしょう。
int c, n=0;
char buf[BLEN+1];
while((c=getchar()) != '\r') {
if(('0' <= c) && (c <= '9')) {
buf[n++]=c;
if(n > BLEN)
break;
}
}
buf[n]='\0';
この回答への補足
回答頂きましてありがとうございます。
上記のサンプルは文字0から9の入力の場合には、
配列に入力文字を格納するものですが、
これでは126とか-46など、
2桁以上の数字や、負の整数には対応できないようです。
こちらの質問の方法が不充分だったようで、
申し訳ありませんでした。
No.3
- 回答日時:
私なら…
int val[MAX], no ;
char str[LEN] ;
char *p ;
for (no = 0 ; no < MAX && fgets(str, LEN, stdin) != NULL ; no++) {
val[no] = strtol(str, 10, &p) ;
if (p != NULL && (*p != '\0' && *p != '\n')) {
//10進数でない入力
//エラー処理
}
}
こんな感じにするかと…
gets関数の問題点:
入力文字数を制限できないのでエラー入力が想定できる場合は使用しないほうがよい。
この回答への補足
回答くださいましてありがとうございます。
読ませていただいたところ、
自分の知識不足で読み解けないコーディングがあります。
for (no = 0 ; no < MAX && fgets(str, LEN, stdin) != NULL ; no++) {
val[no] = strtol(str, 10, &p) ;
if (p != NULL && (*p != '\0' && *p != '\n')) {
//10進数でない入力
//エラー処理
恥ずかしながら、知らない関数があったりして、
論理構造が読み解けません。
人の好意に甘えて怠けすぎるのもいけないと思うので、
自分でも理解できるようもう少し調べてみようと思います。
ヒントをありがとうございます。
No.2
- 回答日時:
キー入力を原則的に文字列で入力します。
No.1のkyeongilさんの書かれているgets関数でchar型の配列に入れ、
これをisdigit関数で1文字ずつチェックして0~9までの文字であれば
そのまま正常にatoi関数で整数に変換して戻し値にして、0~9以外の
文字が含まれていたらエラーコードを返す関数を作っておきます。
なお、isdigit関数は#include<ctype.h>
atoi関数は #include<stdlib.h>
をインクルードいて置きます。
判らないときは、補足でレス下さい、サンプルコードを書きます。。
この回答への補足
回答していただきありがとうございます。
getsやgetcharでは、
一文字ずつしか読み込めず、
複数桁やマイナスの整数には対応できないようです。
その場合はどうすべきか、
自分でももうちょっと考えてみようと思います。
ヒントをくださり、ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセルのマイナス表示 3 2022/03/28 16:35
- C言語・C++・C# C#の問題です。 文字列型の配列 s[100] にキーボードから入力された100文字以内の文字列(単 2 2022/06/22 15:18
- その他(プログラミング・Web制作) プログラミングについて(Python) 添付した画像はC言語で簡単に作ったソースで、1つの配列に5つ 3 2022/09/10 19:15
- C言語・C++・C# [C言語] コメント文字列を無視して、数値データを読み込むプログラム部分について 5 2022/10/05 11:03
- C言語・C++・C# 至急お願いします。C言語で.imgのファイルを読み込んで1バイトづつ出力するプログラムを作りたいので 3 2023/01/16 22:49
- C言語・C++・C# c言語について array[i]-‘0’ これってどーゆー意味ですか? (ちなみに16進数を10進数 5 2022/12/06 18:39
- その他(プログラミング・Web制作) プログラミング pythonの問題について 2 2022/04/19 00:41
- SQL Server [SQLServer] テーブル名からカラム名を取得する 1 2022/08/23 21:20
- Visual Basic(VBA) 【再々投稿】VBAのプログラムで動作しなくて困っています 8 2022/10/14 09:06
- Excel(エクセル) capeofdragonと申します Excel2016を使っておりまして 半角又は全角の任意文字列が 2 2022/10/31 13:51
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
数値をASCII文字にする方法につ...
-
カンマの含まれる文字列の数値...
-
VB6 機種依存文字の変換
-
マクロで半角を全角に
-
1バイト文字の上位4ビット・...
-
エスケープ文字の復帰(¥r)と...
-
ソースコードの1行が長いとき...
-
ファイルから読み取った改行文...
-
VBAのコマンドボタンの文字列の...
-
メッセージボックスで1025文字...
-
全角括弧と全角読点の間隔を狭...
-
文字の入力で横バー上段、中断...
-
C言語について。
-
VBAでCSVをExcelに取り込む時に...
-
Excel関数「COUNTIF」で”文字”...
-
PHPで変数から1行目だけを取得...
-
JAVA System.out.println の ...
-
ラベル(スタティックテキスト)...
-
FORTRANで作成したテキストファ...
-
全角英数文字が嫌われる理由を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
数値をASCII文字にする方法につ...
-
16進数の文字列をアスキーコー...
-
カンマの含まれる文字列の数値...
-
VC++ マルチバイト文字とUniCod...
-
fgetws関数で読み込んだUNICODE...
-
マクロで半角を全角に
-
VB6.0 Base64のデコード方法を...
-
シフトJIS⇒MIMEエンコード(RFC2...
-
VBA ASC関数で変換できない文...
-
1バイト文字の上位4ビット・...
-
preg_replaceがうまくできない
-
サロゲートペア文字の半角カナ...
-
VB6 機種依存文字の変換
-
機種依存文字
-
エスケープされたunicodeのデコ...
-
エディットコントロールへのUni...
-
SQLインジェクション対策で、エ...
-
Movable Type 4で特殊な文字をH...
-
Perlで値が文字列か数値かを区...
-
ヌル文字とは一体何でしょうか
おすすめ情報