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

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

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

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

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Q&A

解決済

4回答

1606閲覧

ポインタ変数を利用したwhileの終了のさせかた

linkinpark

総合スコア42

C

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

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

0グッド

0クリップ

投稿2021/08/08 06:54

whileをポインタで回す際に範囲外にアクセスしたらループを終了させたいのですがNULLとしても終了してくれませんどのようにするとよいでしょうか?

C

1int luhn(char *ptr){ 2 char *head_ptr=ptr; 3 int i,current_number; 4 int index=1; 5 int sum=0; 6 7 while(*ptr !='\0')ptr++; 8 9 ptr--; 10 printf("ptr=%c",*ptr); 11 do{ 12 current_number=*ptr-'\0'; 13 if(index%2==0){ 14 current_number=current_number*2; 15 if(current_number>10){ 16 current_number=current_number-9; 17 } 18 } 19 sum+=current_number; 20 index++; 21 }while(ptr--!=NULL);ここの部分がおかしい 22 if(sum%10==0){ 23 return 1; 24 } 25 else{ 26 return 0; 27 } 28}

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

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

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

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

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

kazuma-s

2021/08/08 07:28

current_number=*ptr-'\0'; の '\0' は 0 です。 '0' の間違いではありませんか?
linkinpark

2021/08/08 09:07

すいません'0'ですね ご指摘ありがとうございます。
guest

回答4

0

} while (--ptr >= head_ptr);
これはほとんどすべての処理系でコンパイルエラーにもならず、
実行もできますが、規格上は未定義動作です。

ポインタを増減させるということは、そのポインタは配列の要素を指しています。
ポインタの値が配列の末尾の次の値になることは許されていますが、
配列の先頭の前を指すことは許されていません。

次のように書くと規格違反になりません。

C

1#include <stdio.h> 2 3int luhn(char *ptr) 4{ 5 char *head_ptr=ptr; 6 int i, current_number; 7 int index = 1; 8 int sum = 0; 9 10 while (*ptr !='\0') ptr++; 11 12 do { 13 current_number = *--ptr - '0'; // ★ ここで --ptr 14 if (index%2 == 0){ 15 current_number = current_number*2; 16 if (current_number > 10){ 17 current_number = current_number - 9; 18 } 19 } 20 sum += current_number; 21 printf("*ptr = '%c', current_number = %d, sum = %d\n", 22 *ptr, current_number, sum); 23 index++; 24 } while (ptr != head_ptr); // ★ まだ配列の先頭ではないか 25 if (sum%10 == 0) { 26 return 1; 27 } 28 else { 29 return 0; 30 } 31} 32 33int main(void) 34{ 35 char d[] = "9324"; 36 printf("%d\n", luhn(d)); 37}

ただし、luhn("") は未定義動作です。

投稿2021/08/08 07:42

kazuma-s

総合スコア8224

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

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

linkinpark

2021/08/08 07:53

ポインタの値が配列の末尾の次の値になることは許されていますが、 配列の先頭の前を指すことは許されていません。初めて知りました 未定義動作なのになぜ動くのでしょうか?配列の先頭の前を指すことは実質的にはokという ことなんですか?
int32_t

2021/08/08 07:58

確かに、回答を書いた後に「未定義動作だったかも?」と思った次第です。
guest

0

ベストアンサー

注意: 下記回答は未定義動作を含んでいます。他の回答を参照してください。


ポインタを1つずつ減らした場合、範囲外になったからといっていきなり NULL になることはありません。

文字列の先頭アドレスを超えたかどうかをチェックする必要があるので、

c

1 } while (--ptr >= head_ptr);

でしょうか。

投稿2021/08/08 07:01

編集2021/08/08 08:00
int32_t

総合スコア21695

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

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

linkinpark

2021/08/08 07:33

なるほどわかりやすい説明ありがとうございます!!
guest

0

head_ptr というのをわざわざ用意しているのだから,それを使えばよいのでは(というか,使うつもりだったのでは?)

投稿2021/08/08 06:59

fana

総合スコア11996

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

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

linkinpark

2021/08/08 07:34

そうですよね(笑)頭バグってました。 ありがとうございました。
guest

0

while(*ptr !='\0')ptr++;

この条件式を参考すれば。

どういう条件でループを終わらせるのかをよく考えよう

投稿2021/08/08 06:58

y_waiwai

総合スコア88042

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

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

linkinpark

2021/08/08 07:34

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問