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

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

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

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

Q&A

解決済

4回答

3415閲覧

コマンドライン引数のチェックについて

ken21

総合スコア17

C

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

0グッド

0クリップ

投稿2020/10/29 01:51

現在、C言語にて以下の機能を実装しようと試みています。

実現したい機能
・コマンドライン引数から入力した数値が正当かチェックを行う機能

機能の詳細
・チェック機能はmain関数とは別に関数を定義
・正当範囲の数字であれば0を返し、不正な値であれば1を返す。

動作
XX.exe 数字 のように実行した場合、入力情報をmain関数から引き取り、その数字がか正当な範囲(今回の場合は1~5の間)であれば上記の値を返す。

困っていること
上記の機能はif文やスイッチ文を羅列すれば実現できる機能かと思いますが、それではあまりにも冗長だと思いましたので↓のように配列とループ処理を使って実現しようと試みました。
しかしながら、1-5を入力した場合もそれ以外の数字を入力した場合のどちらも出力結果は
check =1」となってしまいます。
どのように変更すれば機能を実現できますでしょうか。

また、現在のコードに加えてもっと効率的な方法があればご教授いただけますでしょうか。

#include<stdio.h> #include<string.h> int checkArg(int argc, char *argv[]); int main(int argc, char *argv[]) { int check = checkArg(argc, argv); printf("check = %d\n", check); return 0; } int checkArg(int argc, char *argv[]){ int i; int check = 1; char op[5] = {'1', '2', '3', '4', '5'}; for (i = 0; i < 5; i++) { if (strcmp(argv[1], &op[i]) == 0) { check = 0; break; } } return check; }

以上になります。

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

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

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

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

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

kazuma-s

2020/10/29 02:13

+3 や 03 や 3.0 は不正な数値とするんですか?
fana

2020/10/29 02:27 編集

(正当範囲の"数字" だから,文字としての判断なんじゃないかなぁ,とか.) (とか思ったら混在しているのか)
ken21

2020/10/29 02:53

今回の場合、+3や03など不要な文字・数字がついているものは不正な値としています。
kazuma-s

2020/10/29 02:59

正当範囲が 1~99999 の場合も扱えるようなコードにしないといけないんですよね。
guest

回答4

0

こんなのはどうでしょうか?

C

1#include <stdio.h> // sprintf 2#include <stdlib.h> // atoi 3#include <string.h> // strcmp 4 5#define MIN_VAL 1 // 正当範囲の最小値 6#define MAX_VAL 5 // 正当範囲の最大値 (20 や 99999 でもOK) 7 8int checkArg(int argc, char *argv[]) 9{ 10 if (argc != 2) return 1; 11 int n = atoi(argv[1]); 12 char str[12]; 13 sprintf(str, "%d", n); 14 return strcmp(str, argv[1]) != 0 || n < MIN_VAL || n > MAX_VAL; 15}

投稿2020/10/29 04:16

kazuma-s

総合スコア8224

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

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

0

ベストアンサー

これじゃダメなの?

C

1int checkArg(int argc, char *argv[]){ 2 3 int i; 4 char op[5] = {'1', '2', '3', '4', '5'}; 5 6 if( argc < 2 )return 1; 7 if( argv[1][1] != '\0' )return 1; //(※1) 8 9 for (i = 0; i < 5; i++) { 10 if ( argv[1][0] == op[i] ) //単純に比較しちゃダメなの? 11 { return 0; } 12 } 13 14 return 1; 15}

[修正]
コメントにてご指摘の事項への対処として上記コード内(※1)の行を追加.

投稿2020/10/29 02:06

編集2020/10/29 02:12
fana

総合スコア11708

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

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

maisumakun

2020/10/29 02:07

それだと「15」でも通ってしまいますね。
fana

2020/10/29 02:09

ほんとですね.うっかり!
ken21

2020/10/29 02:43

回答ありがとうございます。 ↓の部分を確認させてください。 argv[1][0] == op[i] ・argv[][]という表記について →この表記は初めて見ましたがargvのポインタ先は文字列になっているからという理解でいます。その理解で行くと「argv[1][1] != '\0'」 というのは1文字の入力の確認という意味になりますよね? ・argv[1][0] == op[i]の表記について → == は整数比較かと思ってました。argv[1][0] もop[i]も格納されているのは文字情報になるので比較できるんでしょうか?
fana

2020/10/29 02:53 編集

argv は,文字列の配列の先頭を指す. 例えば, XX.exe Cat 18 とかして実行したら, argvは { "XX.exe", "Cat", "18" } という配列の先頭を指す(ものと想定して回答.最初の要素はフルパスになるかもしれんけどもここではどうでもいい). なので, argv[0] は,"XX.exe" argv[1] は,"Cat" argv[2] は,"18" --- 今, XX.exe 数字であってほしい文字列 みたいな実行の仕方を想定しているので, 調べたい対象は argv[1]. これが,数字であってほしい文字列(=文字の配列であって,末尾が'\0')の先頭を指すのだから, 数字であってほしい文字列の先頭の文字は argv[1][0] 数字であってほしい文字列の先頭から2番目の文字は argv[1][1]
fana

2020/10/29 02:56

なので, > 「argv[1][1] != '\0'」 というのは1文字の入力の確認という意味になりますよね? → Yes. > argv[1][0] もop[i]も格納されているのは文字情報になるので比較できるんでしょうか? → Yes.両者共にchar型なのでその値を比較している.
ken21

2020/10/29 02:58

丁寧にありがとうございます。 上の例で行くと argv[2]は argv[2][0] = '1' argv[2][1] = '8' argv[2][0] = '\0' という構成になっているということですよね?
fana

2020/10/29 03:01 編集

そうですね. (argv[2][2] = '\0' ← [2]のところが[0]になってるのがタイプミスっぽいですが.)
ken21

2020/10/29 03:01

回答中にすいません。 >>argv[2]は argv[2][0] = '1' argv[2][1] = '8' argv[2][0] = '\0' という構成になっているということですよね? →僕の認識であっていましたね。 > argv[1][0] もop[i]も格納されているのは文字情報になるので比較できるんでしょうか? → Yes.両者共にchar型なのでその値を比較している. →なるほど、実は最初はstrcmpではなくその方法で単純比較をしていましたが argv[1] == op[i]というような比較だったから駄目だったんですね。 一個目の回答でわかりました。 ありがとうございました。
guest

0

atoi strtol関数で数値に変換し、その値の範囲を調べれば良いかと思います。
学校の課題くさい雰囲気がするので、具体的なコードを書くのは差し控えます。


コメントでatoiのエラー検出が出来ないケースの指摘を頂いたので、strtolに修正しました。

投稿2020/10/29 02:05

編集2020/10/29 02:24
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

maisumakun

2020/10/29 02:07

atoi("1a")は1となるので、このような入力を除外したい場合には別な手段が必要となります。
退会済みユーザー

退会済みユーザー

2020/10/29 02:09

ああ、そうなんですね strtol の方がいいですかね
guest

0

char op[5] = {'1', '2', '3', '4', '5'};は、文字の配列なので、``char op[5] = "12345";`と書いたのと同じことになります。

末尾の\0すら入っていない文字列なので、これをstrcmpにかけてもまともな動作をしません。

文字列の配列を用意しましょう。

投稿2020/10/29 01:54

maisumakun

総合スコア145208

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

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

ken21

2020/10/29 02:26

ご指摘ありがとうございます 文字列の配列とは↓のような感じでしょうか char op[5][2] = {{'1'}, {'2'}, {'3'}, {'4'}, {'5'}}; for (i = 0; i < 5; i++) { if (strcmp(argv[1], &op[i][0]) == 0) { check = 0; break;
cateye

2020/10/29 02:46 編集

>文字列の配列とは↓のような感じでしょうか Cで言う“文字列”とは、文字の後に終端記号'\0'が付いた配列です。 従って、{{'1'}, {'2'}, {'3'}, {'4'}, {'5'}}ではなく、{'1', '2', '3', '4', '5','\0'}です。 ・・・char op[6] = "12345";あるいは、char op[] = "12345";と書くこと・・・
ken21

2020/10/29 02:51

その表記だと 「12345」が一塊になっている状態なのではないでしょうか? わかりにくくて申し訳ないですが、先の質問の意図は配列で数字を一文字ずつ区切って、strcmp関数で比較するにはどうすればよいかです。
cateye

2020/10/29 04:44 編集

終端文字のない文字配列には、strcmp()は使えません。 文字比較は、直に文字を比較します。argv[1][0]==op[i] 等 蛇足:'1' <= argv[1][0] && argv[1][0] <= '5' ・・・てのも有り?
cateye

2020/10/29 04:51 編集

>strcmp関数で比較 あえてやるなら、char *op[5] = {"1","2","3", "4","5"}; でしょうが・・・文字比較で済むものを、関数を使うメリットは?
fana

2020/10/29 04:52

> 文字列の配列 こういうことでは. char op[5][2] = {"1", "2", "3", "4", "5"}; (コメント欄でのシングルクォートとダブルクォートの見分けが難しい…乱視?)
ken21

2020/10/29 04:54

ということは配列に格納した数字とargv[]をstrcmpで比較することはできないという理解でよろしいでしょうか。 どうしても比較する場合は配列を使わずに strcmp(argv[1], '1')のように一つずつ行うほかないということでしょうか。
maisumakun

2020/10/29 04:55

> ということは配列に格納した数字とargv[]をstrcmpで比較することはできないという理解でよろしいでしょうか。 strcmpに投げるものは、ヌル文字で終端した「文字列」である必要があります。1文字だけでは正しく処理できません。
ken21

2020/10/29 05:00

ご回答ありがとうございます。 >>strcmpに投げるものは、ヌル文字で終端した「文字列」である必要があります。1文字だけでは正しく処理できません。 どうしてもやるのであればcateyeさんが言うように char *op[5] = {"1","2","3", "4","5"};を定義したうえで strcmp(argv[1], op[i])という比較の方法というがあるということですね。 今回の場合は単純な文字比較のほうがよさそうですね、、、
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問